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 ®istry);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 ®istry) {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