1bb8507e6SMatthias Braun //===-- TargetMachine.cpp -------------------------------------------------===// 2bb8507e6SMatthias Braun // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6bb8507e6SMatthias Braun // 7bb8507e6SMatthias Braun //===----------------------------------------------------------------------===// 8bb8507e6SMatthias Braun // 9bb8507e6SMatthias Braun // This file implements the LLVM-C part of TargetMachine.h 10bb8507e6SMatthias Braun // 11bb8507e6SMatthias Braun //===----------------------------------------------------------------------===// 12bb8507e6SMatthias Braun 13bb8507e6SMatthias Braun #include "llvm-c/Core.h" 14bb8507e6SMatthias Braun #include "llvm-c/Target.h" 15bb8507e6SMatthias Braun #include "llvm-c/TargetMachine.h" 16bb8507e6SMatthias Braun #include "llvm/Analysis/TargetTransformInfo.h" 17bb8507e6SMatthias Braun #include "llvm/IR/DataLayout.h" 18bb8507e6SMatthias Braun #include "llvm/IR/LegacyPassManager.h" 19bb8507e6SMatthias Braun #include "llvm/IR/Module.h" 201ae61a61Swhitequark #include "llvm/MC/SubtargetFeature.h" 21bb8507e6SMatthias Braun #include "llvm/Support/FileSystem.h" 22bb8507e6SMatthias Braun #include "llvm/Support/FormattedStream.h" 23bb8507e6SMatthias Braun #include "llvm/Support/Host.h" 24bb8507e6SMatthias Braun #include "llvm/Support/TargetRegistry.h" 25bb8507e6SMatthias Braun #include "llvm/Support/raw_ostream.h" 26bf121cf4SDavid Blaikie #include "llvm/Target/CodeGenCWrappers.h" 27bb8507e6SMatthias Braun #include "llvm/Target/TargetMachine.h" 28bb8507e6SMatthias Braun #include <cassert> 29bb8507e6SMatthias Braun #include <cstdlib> 30bb8507e6SMatthias Braun #include <cstring> 31bb8507e6SMatthias Braun 32bb8507e6SMatthias Braun using namespace llvm; 33bb8507e6SMatthias Braun 34bb8507e6SMatthias Braun static TargetMachine *unwrap(LLVMTargetMachineRef P) { 35bb8507e6SMatthias Braun return reinterpret_cast<TargetMachine *>(P); 36bb8507e6SMatthias Braun } 37bb8507e6SMatthias Braun static Target *unwrap(LLVMTargetRef P) { 38bb8507e6SMatthias Braun return reinterpret_cast<Target*>(P); 39bb8507e6SMatthias Braun } 40bb8507e6SMatthias Braun static LLVMTargetMachineRef wrap(const TargetMachine *P) { 41bb8507e6SMatthias Braun return reinterpret_cast<LLVMTargetMachineRef>(const_cast<TargetMachine *>(P)); 42bb8507e6SMatthias Braun } 43bb8507e6SMatthias Braun static LLVMTargetRef wrap(const Target * P) { 44bb8507e6SMatthias Braun return reinterpret_cast<LLVMTargetRef>(const_cast<Target*>(P)); 45bb8507e6SMatthias Braun } 46bb8507e6SMatthias Braun 47bb8507e6SMatthias Braun LLVMTargetRef LLVMGetFirstTarget() { 48bb8507e6SMatthias Braun if (TargetRegistry::targets().begin() == TargetRegistry::targets().end()) { 49bb8507e6SMatthias Braun return nullptr; 50bb8507e6SMatthias Braun } 51bb8507e6SMatthias Braun 52bb8507e6SMatthias Braun const Target *target = &*TargetRegistry::targets().begin(); 53bb8507e6SMatthias Braun return wrap(target); 54bb8507e6SMatthias Braun } 55bb8507e6SMatthias Braun LLVMTargetRef LLVMGetNextTarget(LLVMTargetRef T) { 56bb8507e6SMatthias Braun return wrap(unwrap(T)->getNext()); 57bb8507e6SMatthias Braun } 58bb8507e6SMatthias Braun 59bb8507e6SMatthias Braun LLVMTargetRef LLVMGetTargetFromName(const char *Name) { 60bb8507e6SMatthias Braun StringRef NameRef = Name; 61bb8507e6SMatthias Braun auto I = find_if(TargetRegistry::targets(), 62bb8507e6SMatthias Braun [&](const Target &T) { return T.getName() == NameRef; }); 63bb8507e6SMatthias Braun return I != TargetRegistry::targets().end() ? wrap(&*I) : nullptr; 64bb8507e6SMatthias Braun } 65bb8507e6SMatthias Braun 66bb8507e6SMatthias Braun LLVMBool LLVMGetTargetFromTriple(const char* TripleStr, LLVMTargetRef *T, 67bb8507e6SMatthias Braun char **ErrorMessage) { 68bb8507e6SMatthias Braun std::string Error; 69bb8507e6SMatthias Braun 70bb8507e6SMatthias Braun *T = wrap(TargetRegistry::lookupTarget(TripleStr, Error)); 71bb8507e6SMatthias Braun 72bb8507e6SMatthias Braun if (!*T) { 73bb8507e6SMatthias Braun if (ErrorMessage) 74bb8507e6SMatthias Braun *ErrorMessage = strdup(Error.c_str()); 75bb8507e6SMatthias Braun 76bb8507e6SMatthias Braun return 1; 77bb8507e6SMatthias Braun } 78bb8507e6SMatthias Braun 79bb8507e6SMatthias Braun return 0; 80bb8507e6SMatthias Braun } 81bb8507e6SMatthias Braun 82bb8507e6SMatthias Braun const char * LLVMGetTargetName(LLVMTargetRef T) { 83bb8507e6SMatthias Braun return unwrap(T)->getName(); 84bb8507e6SMatthias Braun } 85bb8507e6SMatthias Braun 86bb8507e6SMatthias Braun const char * LLVMGetTargetDescription(LLVMTargetRef T) { 87bb8507e6SMatthias Braun return unwrap(T)->getShortDescription(); 88bb8507e6SMatthias Braun } 89bb8507e6SMatthias Braun 90bb8507e6SMatthias Braun LLVMBool LLVMTargetHasJIT(LLVMTargetRef T) { 91bb8507e6SMatthias Braun return unwrap(T)->hasJIT(); 92bb8507e6SMatthias Braun } 93bb8507e6SMatthias Braun 94bb8507e6SMatthias Braun LLVMBool LLVMTargetHasTargetMachine(LLVMTargetRef T) { 95bb8507e6SMatthias Braun return unwrap(T)->hasTargetMachine(); 96bb8507e6SMatthias Braun } 97bb8507e6SMatthias Braun 98bb8507e6SMatthias Braun LLVMBool LLVMTargetHasAsmBackend(LLVMTargetRef T) { 99bb8507e6SMatthias Braun return unwrap(T)->hasMCAsmBackend(); 100bb8507e6SMatthias Braun } 101bb8507e6SMatthias Braun 102bb8507e6SMatthias Braun LLVMTargetMachineRef LLVMCreateTargetMachine(LLVMTargetRef T, 103bb8507e6SMatthias Braun const char *Triple, const char *CPU, const char *Features, 104bb8507e6SMatthias Braun LLVMCodeGenOptLevel Level, LLVMRelocMode Reloc, 105bb8507e6SMatthias Braun LLVMCodeModel CodeModel) { 106bb8507e6SMatthias Braun Optional<Reloc::Model> RM; 107bb8507e6SMatthias Braun switch (Reloc){ 108bb8507e6SMatthias Braun case LLVMRelocStatic: 109bb8507e6SMatthias Braun RM = Reloc::Static; 110bb8507e6SMatthias Braun break; 111bb8507e6SMatthias Braun case LLVMRelocPIC: 112bb8507e6SMatthias Braun RM = Reloc::PIC_; 113bb8507e6SMatthias Braun break; 114bb8507e6SMatthias Braun case LLVMRelocDynamicNoPic: 115bb8507e6SMatthias Braun RM = Reloc::DynamicNoPIC; 116bb8507e6SMatthias Braun break; 1177882b283SRobert Widmann case LLVMRelocROPI: 1187882b283SRobert Widmann RM = Reloc::ROPI; 1197882b283SRobert Widmann break; 1207882b283SRobert Widmann case LLVMRelocRWPI: 1217882b283SRobert Widmann RM = Reloc::RWPI; 1227882b283SRobert Widmann break; 1237882b283SRobert Widmann case LLVMRelocROPI_RWPI: 1247882b283SRobert Widmann RM = Reloc::ROPI_RWPI; 1257882b283SRobert Widmann break; 126bb8507e6SMatthias Braun default: 127bb8507e6SMatthias Braun break; 128bb8507e6SMatthias Braun } 129bb8507e6SMatthias Braun 130bb8507e6SMatthias Braun bool JIT; 131bb8507e6SMatthias Braun Optional<CodeModel::Model> CM = unwrap(CodeModel, JIT); 132bb8507e6SMatthias Braun 133bb8507e6SMatthias Braun CodeGenOpt::Level OL; 134bb8507e6SMatthias Braun switch (Level) { 135bb8507e6SMatthias Braun case LLVMCodeGenLevelNone: 136bb8507e6SMatthias Braun OL = CodeGenOpt::None; 137bb8507e6SMatthias Braun break; 138bb8507e6SMatthias Braun case LLVMCodeGenLevelLess: 139bb8507e6SMatthias Braun OL = CodeGenOpt::Less; 140bb8507e6SMatthias Braun break; 141bb8507e6SMatthias Braun case LLVMCodeGenLevelAggressive: 142bb8507e6SMatthias Braun OL = CodeGenOpt::Aggressive; 143bb8507e6SMatthias Braun break; 144bb8507e6SMatthias Braun default: 145bb8507e6SMatthias Braun OL = CodeGenOpt::Default; 146bb8507e6SMatthias Braun break; 147bb8507e6SMatthias Braun } 148bb8507e6SMatthias Braun 149bb8507e6SMatthias Braun TargetOptions opt; 150bb8507e6SMatthias Braun return wrap(unwrap(T)->createTargetMachine(Triple, CPU, Features, opt, RM, CM, 151bb8507e6SMatthias Braun OL, JIT)); 152bb8507e6SMatthias Braun } 153bb8507e6SMatthias Braun 154bb8507e6SMatthias Braun void LLVMDisposeTargetMachine(LLVMTargetMachineRef T) { delete unwrap(T); } 155bb8507e6SMatthias Braun 156bb8507e6SMatthias Braun LLVMTargetRef LLVMGetTargetMachineTarget(LLVMTargetMachineRef T) { 157bb8507e6SMatthias Braun const Target* target = &(unwrap(T)->getTarget()); 158bb8507e6SMatthias Braun return wrap(target); 159bb8507e6SMatthias Braun } 160bb8507e6SMatthias Braun 161bb8507e6SMatthias Braun char* LLVMGetTargetMachineTriple(LLVMTargetMachineRef T) { 162bb8507e6SMatthias Braun std::string StringRep = unwrap(T)->getTargetTriple().str(); 163bb8507e6SMatthias Braun return strdup(StringRep.c_str()); 164bb8507e6SMatthias Braun } 165bb8507e6SMatthias Braun 166bb8507e6SMatthias Braun char* LLVMGetTargetMachineCPU(LLVMTargetMachineRef T) { 167*adcd0268SBenjamin Kramer std::string StringRep = std::string(unwrap(T)->getTargetCPU()); 168bb8507e6SMatthias Braun return strdup(StringRep.c_str()); 169bb8507e6SMatthias Braun } 170bb8507e6SMatthias Braun 171bb8507e6SMatthias Braun char* LLVMGetTargetMachineFeatureString(LLVMTargetMachineRef T) { 172*adcd0268SBenjamin Kramer std::string StringRep = std::string(unwrap(T)->getTargetFeatureString()); 173bb8507e6SMatthias Braun return strdup(StringRep.c_str()); 174bb8507e6SMatthias Braun } 175bb8507e6SMatthias Braun 176bb8507e6SMatthias Braun void LLVMSetTargetMachineAsmVerbosity(LLVMTargetMachineRef T, 177bb8507e6SMatthias Braun LLVMBool VerboseAsm) { 178bb8507e6SMatthias Braun unwrap(T)->Options.MCOptions.AsmVerbose = VerboseAsm; 179bb8507e6SMatthias Braun } 180bb8507e6SMatthias Braun 181bb8507e6SMatthias Braun LLVMTargetDataRef LLVMCreateTargetDataLayout(LLVMTargetMachineRef T) { 182bb8507e6SMatthias Braun return wrap(new DataLayout(unwrap(T)->createDataLayout())); 183bb8507e6SMatthias Braun } 184bb8507e6SMatthias Braun 185bb8507e6SMatthias Braun static LLVMBool LLVMTargetMachineEmit(LLVMTargetMachineRef T, LLVMModuleRef M, 186bb8507e6SMatthias Braun raw_pwrite_stream &OS, 187bb8507e6SMatthias Braun LLVMCodeGenFileType codegen, 188bb8507e6SMatthias Braun char **ErrorMessage) { 189bb8507e6SMatthias Braun TargetMachine* TM = unwrap(T); 190bb8507e6SMatthias Braun Module* Mod = unwrap(M); 191bb8507e6SMatthias Braun 192bb8507e6SMatthias Braun legacy::PassManager pass; 193bb8507e6SMatthias Braun 194bb8507e6SMatthias Braun std::string error; 195bb8507e6SMatthias Braun 196bb8507e6SMatthias Braun Mod->setDataLayout(TM->createDataLayout()); 197bb8507e6SMatthias Braun 1981dfede31SReid Kleckner CodeGenFileType ft; 199bb8507e6SMatthias Braun switch (codegen) { 200bb8507e6SMatthias Braun case LLVMAssemblyFile: 2011dfede31SReid Kleckner ft = CGFT_AssemblyFile; 202bb8507e6SMatthias Braun break; 203bb8507e6SMatthias Braun default: 2041dfede31SReid Kleckner ft = CGFT_ObjectFile; 205bb8507e6SMatthias Braun break; 206bb8507e6SMatthias Braun } 2079a45114bSPeter Collingbourne if (TM->addPassesToEmitFile(pass, OS, nullptr, ft)) { 208bb8507e6SMatthias Braun error = "TargetMachine can't emit a file of this type"; 209bb8507e6SMatthias Braun *ErrorMessage = strdup(error.c_str()); 210bb8507e6SMatthias Braun return true; 211bb8507e6SMatthias Braun } 212bb8507e6SMatthias Braun 213bb8507e6SMatthias Braun pass.run(*Mod); 214bb8507e6SMatthias Braun 215bb8507e6SMatthias Braun OS.flush(); 216bb8507e6SMatthias Braun return false; 217bb8507e6SMatthias Braun } 218bb8507e6SMatthias Braun 219bb8507e6SMatthias Braun LLVMBool LLVMTargetMachineEmitToFile(LLVMTargetMachineRef T, LLVMModuleRef M, 220bb8507e6SMatthias Braun char* Filename, LLVMCodeGenFileType codegen, char** ErrorMessage) { 221bb8507e6SMatthias Braun std::error_code EC; 222d9b948b6SFangrui Song raw_fd_ostream dest(Filename, EC, sys::fs::OF_None); 223bb8507e6SMatthias Braun if (EC) { 224bb8507e6SMatthias Braun *ErrorMessage = strdup(EC.message().c_str()); 225bb8507e6SMatthias Braun return true; 226bb8507e6SMatthias Braun } 227bb8507e6SMatthias Braun bool Result = LLVMTargetMachineEmit(T, M, dest, codegen, ErrorMessage); 228bb8507e6SMatthias Braun dest.flush(); 229bb8507e6SMatthias Braun return Result; 230bb8507e6SMatthias Braun } 231bb8507e6SMatthias Braun 232bb8507e6SMatthias Braun LLVMBool LLVMTargetMachineEmitToMemoryBuffer(LLVMTargetMachineRef T, 233bb8507e6SMatthias Braun LLVMModuleRef M, LLVMCodeGenFileType codegen, char** ErrorMessage, 234bb8507e6SMatthias Braun LLVMMemoryBufferRef *OutMemBuf) { 235bb8507e6SMatthias Braun SmallString<0> CodeString; 236bb8507e6SMatthias Braun raw_svector_ostream OStream(CodeString); 237bb8507e6SMatthias Braun bool Result = LLVMTargetMachineEmit(T, M, OStream, codegen, ErrorMessage); 238bb8507e6SMatthias Braun 239bb8507e6SMatthias Braun StringRef Data = OStream.str(); 240bb8507e6SMatthias Braun *OutMemBuf = 241bb8507e6SMatthias Braun LLVMCreateMemoryBufferWithMemoryRangeCopy(Data.data(), Data.size(), ""); 242bb8507e6SMatthias Braun return Result; 243bb8507e6SMatthias Braun } 244bb8507e6SMatthias Braun 245bb8507e6SMatthias Braun char *LLVMGetDefaultTargetTriple(void) { 246bb8507e6SMatthias Braun return strdup(sys::getDefaultTargetTriple().c_str()); 247bb8507e6SMatthias Braun } 248bb8507e6SMatthias Braun 2497c4a0745Swhitequark char *LLVMNormalizeTargetTriple(const char* triple) { 2507c4a0745Swhitequark return strdup(Triple::normalize(StringRef(triple)).c_str()); 2517c4a0745Swhitequark } 2527c4a0745Swhitequark 2531ae61a61Swhitequark char *LLVMGetHostCPUName(void) { 2541ae61a61Swhitequark return strdup(sys::getHostCPUName().data()); 2551ae61a61Swhitequark } 2561ae61a61Swhitequark 2571ae61a61Swhitequark char *LLVMGetHostCPUFeatures(void) { 2581ae61a61Swhitequark SubtargetFeatures Features; 2591ae61a61Swhitequark StringMap<bool> HostFeatures; 2601ae61a61Swhitequark 2611ae61a61Swhitequark if (sys::getHostCPUFeatures(HostFeatures)) 2621ae61a61Swhitequark for (auto &F : HostFeatures) 2631ae61a61Swhitequark Features.AddFeature(F.first(), F.second); 2641ae61a61Swhitequark 2651ae61a61Swhitequark return strdup(Features.getString().c_str()); 2661ae61a61Swhitequark } 2671ae61a61Swhitequark 268bb8507e6SMatthias Braun void LLVMAddAnalysisPasses(LLVMTargetMachineRef T, LLVMPassManagerRef PM) { 269bb8507e6SMatthias Braun unwrap(PM)->add( 270bb8507e6SMatthias Braun createTargetTransformInfoWrapperPass(unwrap(T)->getTargetIRAnalysis())); 271bb8507e6SMatthias Braun } 272