//===-- TargetMachine.cpp -------------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file implements the LLVM-C part of TargetMachine.h // //===----------------------------------------------------------------------===// #include "llvm-c/TargetMachine.h" #include "llvm-c/Core.h" #include "llvm-c/Target.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Module.h" #include "llvm/PassManager.h" #include "llvm/Support/CodeGen.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/Host.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetMachine.h" #include <cassert> #include <cstdlib> #include <cstring> using namespace llvm; inline TargetMachine *unwrap(LLVMTargetMachineRef P) { return reinterpret_cast<TargetMachine*>(P); } inline Target *unwrap(LLVMTargetRef P) { return reinterpret_cast<Target*>(P); } inline LLVMTargetMachineRef wrap(const TargetMachine *P) { return reinterpret_cast<LLVMTargetMachineRef>(const_cast<TargetMachine*>(P)); } inline LLVMTargetRef wrap(const Target * P) { return reinterpret_cast<LLVMTargetRef>(const_cast<Target*>(P)); } LLVMTargetRef LLVMGetFirstTarget() { if(TargetRegistry::begin() == TargetRegistry::end()) { return nullptr; } const Target* target = &*TargetRegistry::begin(); return wrap(target); } LLVMTargetRef LLVMGetNextTarget(LLVMTargetRef T) { return wrap(unwrap(T)->getNext()); } LLVMTargetRef LLVMGetTargetFromName(const char *Name) { StringRef NameRef = Name; for (TargetRegistry::iterator IT = TargetRegistry::begin(), IE = TargetRegistry::end(); IT != IE; ++IT) { if (IT->getName() == NameRef) return wrap(&*IT); } return nullptr; } LLVMBool LLVMGetTargetFromTriple(const char* TripleStr, LLVMTargetRef *T, char **ErrorMessage) { std::string Error; *T = wrap(TargetRegistry::lookupTarget(TripleStr, Error)); if (!*T) { if (ErrorMessage) *ErrorMessage = strdup(Error.c_str()); return 1; } return 0; } const char * LLVMGetTargetName(LLVMTargetRef T) { return unwrap(T)->getName(); } const char * LLVMGetTargetDescription(LLVMTargetRef T) { return unwrap(T)->getShortDescription(); } LLVMBool LLVMTargetHasJIT(LLVMTargetRef T) { return unwrap(T)->hasJIT(); } LLVMBool LLVMTargetHasTargetMachine(LLVMTargetRef T) { return unwrap(T)->hasTargetMachine(); } LLVMBool LLVMTargetHasAsmBackend(LLVMTargetRef T) { return unwrap(T)->hasMCAsmBackend(); } LLVMTargetMachineRef LLVMCreateTargetMachine(LLVMTargetRef T, const char* Triple, const char* CPU, const char* Features, LLVMCodeGenOptLevel Level, LLVMRelocMode Reloc, LLVMCodeModel CodeModel) { Reloc::Model RM; switch (Reloc){ case LLVMRelocStatic: RM = Reloc::Static; break; case LLVMRelocPIC: RM = Reloc::PIC_; break; case LLVMRelocDynamicNoPic: RM = Reloc::DynamicNoPIC; break; default: RM = Reloc::Default; break; } CodeModel::Model CM = unwrap(CodeModel); CodeGenOpt::Level OL; switch (Level) { case LLVMCodeGenLevelNone: OL = CodeGenOpt::None; break; case LLVMCodeGenLevelLess: OL = CodeGenOpt::Less; break; case LLVMCodeGenLevelAggressive: OL = CodeGenOpt::Aggressive; break; default: OL = CodeGenOpt::Default; break; } TargetOptions opt; return wrap(unwrap(T)->createTargetMachine(Triple, CPU, Features, opt, RM, CM, OL)); } void LLVMDisposeTargetMachine(LLVMTargetMachineRef T) { delete unwrap(T); } LLVMTargetRef LLVMGetTargetMachineTarget(LLVMTargetMachineRef T) { const Target* target = &(unwrap(T)->getTarget()); return wrap(target); } char* LLVMGetTargetMachineTriple(LLVMTargetMachineRef T) { std::string StringRep = unwrap(T)->getTargetTriple(); return strdup(StringRep.c_str()); } char* LLVMGetTargetMachineCPU(LLVMTargetMachineRef T) { std::string StringRep = unwrap(T)->getTargetCPU(); return strdup(StringRep.c_str()); } char* LLVMGetTargetMachineFeatureString(LLVMTargetMachineRef T) { std::string StringRep = unwrap(T)->getTargetFeatureString(); return strdup(StringRep.c_str()); } LLVMTargetDataRef LLVMGetTargetMachineData(LLVMTargetMachineRef T) { return wrap(unwrap(T)->getDataLayout()); } void LLVMSetTargetMachineAsmVerbosity(LLVMTargetMachineRef T, LLVMBool VerboseAsm) { unwrap(T)->setAsmVerbosityDefault(VerboseAsm); } static LLVMBool LLVMTargetMachineEmit(LLVMTargetMachineRef T, LLVMModuleRef M, formatted_raw_ostream &OS, LLVMCodeGenFileType codegen, char **ErrorMessage) { TargetMachine* TM = unwrap(T); Module* Mod = unwrap(M); PassManager pass; std::string error; const DataLayout* td = TM->getDataLayout(); if (!td) { error = "No DataLayout in TargetMachine"; *ErrorMessage = strdup(error.c_str()); return true; } Mod->setDataLayout(td); pass.add(new DataLayoutPass(Mod)); TargetMachine::CodeGenFileType ft; switch (codegen) { case LLVMAssemblyFile: ft = TargetMachine::CGFT_AssemblyFile; break; default: ft = TargetMachine::CGFT_ObjectFile; break; } if (TM->addPassesToEmitFile(pass, OS, ft)) { error = "TargetMachine can't emit a file of this type"; *ErrorMessage = strdup(error.c_str()); return true; } pass.run(*Mod); OS.flush(); return false; } LLVMBool LLVMTargetMachineEmitToFile(LLVMTargetMachineRef T, LLVMModuleRef M, char* Filename, LLVMCodeGenFileType codegen, char** ErrorMessage) { std::string error; raw_fd_ostream dest(Filename, error, sys::fs::F_None); if (!error.empty()) { *ErrorMessage = strdup(error.c_str()); return true; } formatted_raw_ostream destf(dest); bool Result = LLVMTargetMachineEmit(T, M, destf, codegen, ErrorMessage); dest.flush(); return Result; } LLVMBool LLVMTargetMachineEmitToMemoryBuffer(LLVMTargetMachineRef T, LLVMModuleRef M, LLVMCodeGenFileType codegen, char** ErrorMessage, LLVMMemoryBufferRef *OutMemBuf) { std::string CodeString; raw_string_ostream OStream(CodeString); formatted_raw_ostream Out(OStream); bool Result = LLVMTargetMachineEmit(T, M, Out, codegen, ErrorMessage); OStream.flush(); std::string &Data = OStream.str(); *OutMemBuf = LLVMCreateMemoryBufferWithMemoryRangeCopy(Data.c_str(), Data.length(), ""); return Result; } char *LLVMGetDefaultTargetTriple(void) { return strdup(sys::getDefaultTargetTriple().c_str()); } void LLVMAddAnalysisPasses(LLVMTargetMachineRef T, LLVMPassManagerRef PM) { unwrap(T)->addAnalysisPasses(*unwrap(PM)); }