377 lines · cpp
1//===-- TargetMachine.cpp -------------------------------------------------===//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// This file implements the LLVM-C part of TargetMachine.h10//11//===----------------------------------------------------------------------===//12 13#include "llvm-c/Core.h"14#include "llvm-c/TargetMachine.h"15#include "llvm/Analysis/TargetTransformInfo.h"16#include "llvm/IR/DataLayout.h"17#include "llvm/IR/LegacyPassManager.h"18#include "llvm/IR/Module.h"19#include "llvm/MC/TargetRegistry.h"20#include "llvm/Support/CBindingWrapping.h"21#include "llvm/Support/FileSystem.h"22#include "llvm/Support/raw_ostream.h"23#include "llvm/Target/CodeGenCWrappers.h"24#include "llvm/Target/TargetMachine.h"25#include "llvm/TargetParser/Host.h"26#include "llvm/TargetParser/SubtargetFeature.h"27#include <cstring>28#include <optional>29 30using namespace llvm;31 32namespace llvm {33 34/// Options for LLVMCreateTargetMachine().35struct LLVMTargetMachineOptions {36 std::string CPU;37 std::string Features;38 std::string ABI;39 CodeGenOptLevel OL = CodeGenOptLevel::Default;40 std::optional<Reloc::Model> RM;41 std::optional<CodeModel::Model> CM;42 bool JIT;43};44 45} // namespace llvm46 47DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLVMTargetMachineOptions,48 LLVMTargetMachineOptionsRef)49 50static TargetMachine *unwrap(LLVMTargetMachineRef P) {51 return reinterpret_cast<TargetMachine *>(P);52}53static Target *unwrap(LLVMTargetRef P) {54 return reinterpret_cast<Target*>(P);55}56static LLVMTargetMachineRef wrap(const TargetMachine *P) {57 return reinterpret_cast<LLVMTargetMachineRef>(const_cast<TargetMachine *>(P));58}59static LLVMTargetRef wrap(const Target * P) {60 return reinterpret_cast<LLVMTargetRef>(const_cast<Target*>(P));61}62 63LLVMTargetRef LLVMGetFirstTarget() {64 if (TargetRegistry::targets().begin() == TargetRegistry::targets().end()) {65 return nullptr;66 }67 68 const Target *target = &*TargetRegistry::targets().begin();69 return wrap(target);70}71LLVMTargetRef LLVMGetNextTarget(LLVMTargetRef T) {72 return wrap(unwrap(T)->getNext());73}74 75LLVMTargetRef LLVMGetTargetFromName(const char *Name) {76 StringRef NameRef = Name;77 auto I = find_if(TargetRegistry::targets(),78 [&](const Target &T) { return T.getName() == NameRef; });79 return I != TargetRegistry::targets().end() ? wrap(&*I) : nullptr;80}81 82LLVMBool LLVMGetTargetFromTriple(const char* TripleStr, LLVMTargetRef *T,83 char **ErrorMessage) {84 std::string Error;85 86 Triple TT(TripleStr);87 *T = wrap(TargetRegistry::lookupTarget(TT, Error));88 89 if (!*T) {90 if (ErrorMessage)91 *ErrorMessage = strdup(Error.c_str());92 93 return 1;94 }95 96 return 0;97}98 99const char * LLVMGetTargetName(LLVMTargetRef T) {100 return unwrap(T)->getName();101}102 103const char * LLVMGetTargetDescription(LLVMTargetRef T) {104 return unwrap(T)->getShortDescription();105}106 107LLVMBool LLVMTargetHasJIT(LLVMTargetRef T) {108 return unwrap(T)->hasJIT();109}110 111LLVMBool LLVMTargetHasTargetMachine(LLVMTargetRef T) {112 return unwrap(T)->hasTargetMachine();113}114 115LLVMBool LLVMTargetHasAsmBackend(LLVMTargetRef T) {116 return unwrap(T)->hasMCAsmBackend();117}118 119LLVMTargetMachineOptionsRef LLVMCreateTargetMachineOptions(void) {120 return wrap(new LLVMTargetMachineOptions());121}122 123void LLVMDisposeTargetMachineOptions(LLVMTargetMachineOptionsRef Options) {124 delete unwrap(Options);125}126 127void LLVMTargetMachineOptionsSetCPU(LLVMTargetMachineOptionsRef Options,128 const char *CPU) {129 unwrap(Options)->CPU = CPU;130}131 132void LLVMTargetMachineOptionsSetFeatures(LLVMTargetMachineOptionsRef Options,133 const char *Features) {134 unwrap(Options)->Features = Features;135}136 137void LLVMTargetMachineOptionsSetABI(LLVMTargetMachineOptionsRef Options,138 const char *ABI) {139 unwrap(Options)->ABI = ABI;140}141 142void LLVMTargetMachineOptionsSetCodeGenOptLevel(143 LLVMTargetMachineOptionsRef Options, LLVMCodeGenOptLevel Level) {144 CodeGenOptLevel OL;145 146 switch (Level) {147 case LLVMCodeGenLevelNone:148 OL = CodeGenOptLevel::None;149 break;150 case LLVMCodeGenLevelLess:151 OL = CodeGenOptLevel::Less;152 break;153 case LLVMCodeGenLevelAggressive:154 OL = CodeGenOptLevel::Aggressive;155 break;156 case LLVMCodeGenLevelDefault:157 OL = CodeGenOptLevel::Default;158 break;159 }160 161 unwrap(Options)->OL = OL;162}163 164void LLVMTargetMachineOptionsSetRelocMode(LLVMTargetMachineOptionsRef Options,165 LLVMRelocMode Reloc) {166 std::optional<Reloc::Model> RM;167 168 switch (Reloc) {169 case LLVMRelocStatic:170 RM = Reloc::Static;171 break;172 case LLVMRelocPIC:173 RM = Reloc::PIC_;174 break;175 case LLVMRelocDynamicNoPic:176 RM = Reloc::DynamicNoPIC;177 break;178 case LLVMRelocROPI:179 RM = Reloc::ROPI;180 break;181 case LLVMRelocRWPI:182 RM = Reloc::RWPI;183 break;184 case LLVMRelocROPI_RWPI:185 RM = Reloc::ROPI_RWPI;186 break;187 case LLVMRelocDefault:188 break;189 }190 191 unwrap(Options)->RM = RM;192}193 194void LLVMTargetMachineOptionsSetCodeModel(LLVMTargetMachineOptionsRef Options,195 LLVMCodeModel CodeModel) {196 auto CM = unwrap(CodeModel, unwrap(Options)->JIT);197 unwrap(Options)->CM = CM;198}199 200LLVMTargetMachineRef201LLVMCreateTargetMachineWithOptions(LLVMTargetRef T, const char *TripleStr,202 LLVMTargetMachineOptionsRef Options) {203 auto *Opt = unwrap(Options);204 TargetOptions TO;205 TO.MCOptions.ABIName = Opt->ABI;206 return wrap(unwrap(T)->createTargetMachine(Triple(TripleStr), Opt->CPU,207 Opt->Features, TO, Opt->RM,208 Opt->CM, Opt->OL, Opt->JIT));209}210 211LLVMTargetMachineRef212LLVMCreateTargetMachine(LLVMTargetRef T, const char *Triple, const char *CPU,213 const char *Features, LLVMCodeGenOptLevel Level,214 LLVMRelocMode Reloc, LLVMCodeModel CodeModel) {215 auto *Options = LLVMCreateTargetMachineOptions();216 217 LLVMTargetMachineOptionsSetCPU(Options, CPU);218 LLVMTargetMachineOptionsSetFeatures(Options, Features);219 LLVMTargetMachineOptionsSetCodeGenOptLevel(Options, Level);220 LLVMTargetMachineOptionsSetRelocMode(Options, Reloc);221 LLVMTargetMachineOptionsSetCodeModel(Options, CodeModel);222 223 auto *Machine = LLVMCreateTargetMachineWithOptions(T, Triple, Options);224 225 LLVMDisposeTargetMachineOptions(Options);226 return Machine;227}228 229void LLVMDisposeTargetMachine(LLVMTargetMachineRef T) { delete unwrap(T); }230 231LLVMTargetRef LLVMGetTargetMachineTarget(LLVMTargetMachineRef T) {232 const Target* target = &(unwrap(T)->getTarget());233 return wrap(target);234}235 236char* LLVMGetTargetMachineTriple(LLVMTargetMachineRef T) {237 std::string StringRep = unwrap(T)->getTargetTriple().str();238 return strdup(StringRep.c_str());239}240 241char* LLVMGetTargetMachineCPU(LLVMTargetMachineRef T) {242 std::string StringRep = std::string(unwrap(T)->getTargetCPU());243 return strdup(StringRep.c_str());244}245 246char* LLVMGetTargetMachineFeatureString(LLVMTargetMachineRef T) {247 std::string StringRep = std::string(unwrap(T)->getTargetFeatureString());248 return strdup(StringRep.c_str());249}250 251void LLVMSetTargetMachineAsmVerbosity(LLVMTargetMachineRef T,252 LLVMBool VerboseAsm) {253 unwrap(T)->Options.MCOptions.AsmVerbose = VerboseAsm;254}255 256void LLVMSetTargetMachineFastISel(LLVMTargetMachineRef T, LLVMBool Enable) {257 unwrap(T)->setFastISel(Enable);258}259 260void LLVMSetTargetMachineGlobalISel(LLVMTargetMachineRef T, LLVMBool Enable) {261 unwrap(T)->setGlobalISel(Enable);262}263 264void LLVMSetTargetMachineGlobalISelAbort(LLVMTargetMachineRef T,265 LLVMGlobalISelAbortMode Mode) {266 GlobalISelAbortMode AM = GlobalISelAbortMode::Enable;267 switch (Mode) {268 case LLVMGlobalISelAbortDisable:269 AM = GlobalISelAbortMode::Disable;270 break;271 case LLVMGlobalISelAbortEnable:272 AM = GlobalISelAbortMode::Enable;273 break;274 case LLVMGlobalISelAbortDisableWithDiag:275 AM = GlobalISelAbortMode::DisableWithDiag;276 break;277 }278 279 unwrap(T)->setGlobalISelAbort(AM);280}281 282void LLVMSetTargetMachineMachineOutliner(LLVMTargetMachineRef T,283 LLVMBool Enable) {284 unwrap(T)->setMachineOutliner(Enable);285}286 287LLVMTargetDataRef LLVMCreateTargetDataLayout(LLVMTargetMachineRef T) {288 return wrap(new DataLayout(unwrap(T)->createDataLayout()));289}290 291static LLVMBool LLVMTargetMachineEmit(LLVMTargetMachineRef T, LLVMModuleRef M,292 raw_pwrite_stream &OS,293 LLVMCodeGenFileType codegen,294 char **ErrorMessage) {295 TargetMachine* TM = unwrap(T);296 Module* Mod = unwrap(M);297 298 legacy::PassManager pass;299 300 std::string error;301 302 Mod->setDataLayout(TM->createDataLayout());303 304 CodeGenFileType ft;305 switch (codegen) {306 case LLVMAssemblyFile:307 ft = CodeGenFileType::AssemblyFile;308 break;309 default:310 ft = CodeGenFileType::ObjectFile;311 break;312 }313 if (TM->addPassesToEmitFile(pass, OS, nullptr, ft)) {314 error = "TargetMachine can't emit a file of this type";315 *ErrorMessage = strdup(error.c_str());316 return true;317 }318 319 pass.run(*Mod);320 321 OS.flush();322 return false;323}324 325LLVMBool LLVMTargetMachineEmitToFile(LLVMTargetMachineRef T, LLVMModuleRef M,326 const char *Filename,327 LLVMCodeGenFileType codegen,328 char **ErrorMessage) {329 std::error_code EC;330 raw_fd_ostream dest(Filename, EC, sys::fs::OF_None);331 if (EC) {332 *ErrorMessage = strdup(EC.message().c_str());333 return true;334 }335 bool Result = LLVMTargetMachineEmit(T, M, dest, codegen, ErrorMessage);336 dest.flush();337 return Result;338}339 340LLVMBool LLVMTargetMachineEmitToMemoryBuffer(LLVMTargetMachineRef T,341 LLVMModuleRef M, LLVMCodeGenFileType codegen, char** ErrorMessage,342 LLVMMemoryBufferRef *OutMemBuf) {343 SmallString<0> CodeString;344 raw_svector_ostream OStream(CodeString);345 bool Result = LLVMTargetMachineEmit(T, M, OStream, codegen, ErrorMessage);346 347 StringRef Data = OStream.str();348 *OutMemBuf =349 LLVMCreateMemoryBufferWithMemoryRangeCopy(Data.data(), Data.size(), "");350 return Result;351}352 353char *LLVMGetDefaultTargetTriple(void) {354 return strdup(sys::getDefaultTargetTriple().c_str());355}356 357char *LLVMNormalizeTargetTriple(const char* triple) {358 return strdup(Triple::normalize(StringRef(triple)).c_str());359}360 361char *LLVMGetHostCPUName(void) {362 return strdup(sys::getHostCPUName().data());363}364 365char *LLVMGetHostCPUFeatures(void) {366 SubtargetFeatures Features;367 for (const auto &[Feature, IsEnabled] : sys::getHostCPUFeatures())368 Features.AddFeature(Feature, IsEnabled);369 370 return strdup(Features.getString().c_str());371}372 373void LLVMAddAnalysisPasses(LLVMTargetMachineRef T, LLVMPassManagerRef PM) {374 unwrap(PM)->add(375 createTargetTransformInfoWrapperPass(unwrap(T)->getTargetIRAnalysis()));376}377