brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.9 KiB · 29a310a Raw
177 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// Converts CIR directly to LLVM IR, similar to mlir-translate or LLVM llc.10//11//===----------------------------------------------------------------------===//12 13#include "mlir/Dialect/DLTI/DLTI.h"14#include "mlir/Dialect/Func/IR/FuncOps.h"15#include "mlir/Dialect/LLVMIR/LLVMDialect.h"16#include "mlir/IR/BuiltinOps.h"17#include "mlir/IR/MLIRContext.h"18#include "mlir/InitAllTranslations.h"19#include "mlir/Support/LogicalResult.h"20#include "mlir/Target/LLVMIR/Dialect/All.h"21#include "mlir/Target/LLVMIR/Import.h"22#include "mlir/Tools/mlir-translate/MlirTranslateMain.h"23#include "mlir/Tools/mlir-translate/Translation.h"24 25#include "llvm/IR/Module.h"26#include "llvm/TargetParser/Host.h"27 28#include "clang/Basic/Diagnostic.h"29#include "clang/Basic/DiagnosticIDs.h"30#include "clang/Basic/DiagnosticOptions.h"31#include "clang/Basic/TargetInfo.h"32#include "clang/CIR/Dialect/IR/CIRDialect.h"33#include "clang/CIR/Dialect/Passes.h"34#include "clang/CIR/LowerToLLVM.h"35#include "clang/CIR/MissingFeatures.h"36 37namespace cir {38namespace direct {39extern void registerCIRDialectTranslation(mlir::DialectRegistry &registry);40} // namespace direct41 42namespace {43 44/// The goal of this option is to ensure that the triple and data layout specs45/// are always available in the ClangIR module. With this requirement met, the46/// behavior of this option is designed to be as intuitive as possible, as shown47/// in the table below:48///49/// +--------+--------+-------------+-----------------+-----------------------+50/// | Option | Triple | Data Layout | Behavior Triple | Behavior Data Layout  |51/// +========+========+=============+=================+=======================+52/// | T      | T      | T           | Overwrite       | Derive from triple    |53/// | T      | T      | F           | Overwrite       | Derive from triple    |54/// | T      | F      | T           | Overwrite       | Derive from triple    |55/// | T      | F      | F           | Overwrite       | Derive from triple    |56/// | F      | T      | T           |                 |                       |57/// | F      | T      | F           |                 | Derive from triple    |58/// | F      | F      | T           | Set default     | Derive from triple    |59/// | F      | F      | F           | Set default     | Derive from triple    |60/// +--------+--------+-------------+-----------------+-----------------------+61llvm::cl::opt<std::string>62    targetTripleOption("target",63                       llvm::cl::desc("Specify a default target triple when "64                                      "it's not available in the module"),65                       llvm::cl::init(""));66 67std::string prepareCIRModuleTriple(mlir::ModuleOp mod) {68  std::string triple = targetTripleOption;69 70  // Treat "" as the default target machine.71  if (triple.empty()) {72    triple = llvm::sys::getDefaultTargetTriple();73 74    mod.emitWarning() << "no target triple provided, assuming " << triple;75  }76 77  mod->setAttr(cir::CIRDialect::getTripleAttrName(),78               mlir::StringAttr::get(mod.getContext(), triple));79  return triple;80}81 82llvm::LogicalResult prepareCIRModuleDataLayout(mlir::ModuleOp mod,83                                               llvm::StringRef rawTriple) {84  auto *context = mod.getContext();85 86  // Data layout is fully determined by the target triple. Here we only pass the87  // triple to get the data layout.88  llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> diagID(89      new clang::DiagnosticIDs);90  clang::DiagnosticOptions diagOpts;91  llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> diagnostics =92      new clang::DiagnosticsEngine(diagID, diagOpts,93                                   new clang::IgnoringDiagConsumer());94  llvm::Triple triple(rawTriple);95  // TODO: Need to set various target options later to populate96  // 'TargetInfo' properly.97  clang::TargetOptions targetOptions;98  targetOptions.Triple = rawTriple;99  llvm::IntrusiveRefCntPtr<clang::TargetInfo> targetInfo =100      clang::TargetInfo::CreateTargetInfo(*diagnostics, targetOptions);101  if (!targetInfo) {102    mod.emitError() << "error: invalid target triple '" << rawTriple << "'\n";103    return llvm::failure();104  }105  std::string layoutString = targetInfo->getDataLayoutString();106 107  // Registered dialects may not be loaded yet, ensure they are.108  context->loadDialect<mlir::DLTIDialect, mlir::LLVM::LLVMDialect>();109 110  mlir::DataLayoutSpecInterface dlSpec =111      mlir::translateDataLayout(llvm::DataLayout(layoutString), context);112  mod->setAttr(mlir::DLTIDialect::kDataLayoutAttrName, dlSpec);113 114  return llvm::success();115}116 117/// Prepare requirements like cir.triple and data layout.118llvm::LogicalResult prepareCIRModuleForTranslation(mlir::ModuleOp mod) {119  auto modTriple = mod->getAttrOfType<mlir::StringAttr>(120      cir::CIRDialect::getTripleAttrName());121  auto modDataLayout = mod->getAttr(mlir::DLTIDialect::kDataLayoutAttrName);122  bool hasTargetOption = targetTripleOption.getNumOccurrences() > 0;123 124  // Skip the situation where nothing should be done.125  if (!hasTargetOption && modTriple && modDataLayout)126    return llvm::success();127 128  std::string triple;129 130  if (!hasTargetOption && modTriple) {131    // Do nothing if it's already set.132    triple = modTriple.getValue();133  } else {134    // Otherwise, overwrite or set default.135    triple = prepareCIRModuleTriple(mod);136  }137 138  // If the data layout is not set, derive it from the triple.139  return prepareCIRModuleDataLayout(mod, triple);140}141} // namespace142} // namespace cir143 144void registerToLLVMTranslation() {145  static llvm::cl::opt<bool> disableCCLowering(146      "disable-cc-lowering",147      llvm::cl::desc("Disable calling convention lowering pass"),148      llvm::cl::init(false));149 150  mlir::TranslateFromMLIRRegistration registration(151      "cir-to-llvmir", "Translate CIR to LLVMIR",152      [](mlir::Operation *op, mlir::raw_ostream &output) {153        auto cirModule = llvm::dyn_cast<mlir::ModuleOp>(op);154 155        if (mlir::failed(cir::prepareCIRModuleForTranslation(cirModule)))156          return mlir::failure();157 158        llvm::LLVMContext llvmContext;159        std::unique_ptr<llvm::Module> llvmModule =160            cir::direct::lowerDirectlyFromCIRToLLVMIR(cirModule, llvmContext);161        if (!llvmModule)162          return mlir::failure();163        llvmModule->print(output, nullptr);164        return mlir::success();165      },166      [](mlir::DialectRegistry &registry) {167        registry.insert<mlir::DLTIDialect, mlir::func::FuncDialect>();168        mlir::registerAllToLLVMIRTranslations(registry);169        cir::direct::registerCIRDialectTranslation(registry);170      });171}172 173int main(int argc, char **argv) {174  registerToLLVMTranslation();175  return failed(mlir::mlirTranslateMain(argc, argv, "CIR Translation Tool"));176}177