1dff0c46cSDimitry Andric //===-- TargetMachine.cpp -------------------------------------------------===//
2dff0c46cSDimitry Andric //
3dff0c46cSDimitry Andric // The LLVM Compiler Infrastructure
4dff0c46cSDimitry Andric //
5dff0c46cSDimitry Andric // This file is distributed under the University of Illinois Open Source
6dff0c46cSDimitry Andric // License. See LICENSE.TXT for details.
7dff0c46cSDimitry Andric //
8dff0c46cSDimitry Andric //===----------------------------------------------------------------------===//
9dff0c46cSDimitry Andric //
10dff0c46cSDimitry Andric // This file implements the LLVM-C part of TargetMachine.h
11dff0c46cSDimitry Andric //
12dff0c46cSDimitry Andric //===----------------------------------------------------------------------===//
13dff0c46cSDimitry Andric
14dff0c46cSDimitry Andric #include "llvm-c/Core.h"
15dff0c46cSDimitry Andric #include "llvm-c/Target.h"
16db17bf38SDimitry Andric #include "llvm-c/TargetMachine.h"
17ff0cc061SDimitry Andric #include "llvm/Analysis/TargetTransformInfo.h"
18139f7f9bSDimitry Andric #include "llvm/IR/DataLayout.h"
19ff0cc061SDimitry Andric #include "llvm/IR/LegacyPassManager.h"
20db17bf38SDimitry Andric #include "llvm/IR/Module.h"
214ba319b5SDimitry Andric #include "llvm/MC/SubtargetFeature.h"
2291bc56edSDimitry Andric #include "llvm/Support/FileSystem.h"
23dff0c46cSDimitry Andric #include "llvm/Support/FormattedStream.h"
2491bc56edSDimitry Andric #include "llvm/Support/Host.h"
25139f7f9bSDimitry Andric #include "llvm/Support/TargetRegistry.h"
26139f7f9bSDimitry Andric #include "llvm/Support/raw_ostream.h"
274ba319b5SDimitry Andric #include "llvm/Target/CodeGenCWrappers.h"
28139f7f9bSDimitry Andric #include "llvm/Target/TargetMachine.h"
29dff0c46cSDimitry Andric #include <cassert>
30dff0c46cSDimitry Andric #include <cstdlib>
31dff0c46cSDimitry Andric #include <cstring>
32dff0c46cSDimitry Andric
33dff0c46cSDimitry Andric using namespace llvm;
34dff0c46cSDimitry Andric
unwrap(LLVMTargetMachineRef P)357d523365SDimitry Andric static TargetMachine *unwrap(LLVMTargetMachineRef P) {
36284c1978SDimitry Andric return reinterpret_cast<TargetMachine *>(P);
37284c1978SDimitry Andric }
unwrap(LLVMTargetRef P)387d523365SDimitry Andric static Target *unwrap(LLVMTargetRef P) {
39284c1978SDimitry Andric return reinterpret_cast<Target*>(P);
40284c1978SDimitry Andric }
wrap(const TargetMachine * P)417d523365SDimitry Andric static LLVMTargetMachineRef wrap(const TargetMachine *P) {
427d523365SDimitry Andric return reinterpret_cast<LLVMTargetMachineRef>(const_cast<TargetMachine *>(P));
43284c1978SDimitry Andric }
wrap(const Target * P)447d523365SDimitry Andric static LLVMTargetRef wrap(const Target * P) {
45284c1978SDimitry Andric return reinterpret_cast<LLVMTargetRef>(const_cast<Target*>(P));
46284c1978SDimitry Andric }
47dff0c46cSDimitry Andric
LLVMGetFirstTarget()48dff0c46cSDimitry Andric LLVMTargetRef LLVMGetFirstTarget() {
49ff0cc061SDimitry Andric if (TargetRegistry::targets().begin() == TargetRegistry::targets().end()) {
5091bc56edSDimitry Andric return nullptr;
51f785676fSDimitry Andric }
52f785676fSDimitry Andric
53ff0cc061SDimitry Andric const Target *target = &*TargetRegistry::targets().begin();
54dff0c46cSDimitry Andric return wrap(target);
55dff0c46cSDimitry Andric }
LLVMGetNextTarget(LLVMTargetRef T)56dff0c46cSDimitry Andric LLVMTargetRef LLVMGetNextTarget(LLVMTargetRef T) {
57dff0c46cSDimitry Andric return wrap(unwrap(T)->getNext());
58dff0c46cSDimitry Andric }
59dff0c46cSDimitry Andric
LLVMGetTargetFromName(const char * Name)60f785676fSDimitry Andric LLVMTargetRef LLVMGetTargetFromName(const char *Name) {
61f785676fSDimitry Andric StringRef NameRef = Name;
62d88c1a5aSDimitry Andric auto I = find_if(TargetRegistry::targets(),
63ff0cc061SDimitry Andric [&](const Target &T) { return T.getName() == NameRef; });
64ff0cc061SDimitry Andric return I != TargetRegistry::targets().end() ? wrap(&*I) : nullptr;
65f785676fSDimitry Andric }
66f785676fSDimitry Andric
LLVMGetTargetFromTriple(const char * TripleStr,LLVMTargetRef * T,char ** ErrorMessage)67f785676fSDimitry Andric LLVMBool LLVMGetTargetFromTriple(const char* TripleStr, LLVMTargetRef *T,
68f785676fSDimitry Andric char **ErrorMessage) {
69f785676fSDimitry Andric std::string Error;
70f785676fSDimitry Andric
71f785676fSDimitry Andric *T = wrap(TargetRegistry::lookupTarget(TripleStr, Error));
72f785676fSDimitry Andric
73f785676fSDimitry Andric if (!*T) {
74f785676fSDimitry Andric if (ErrorMessage)
75f785676fSDimitry Andric *ErrorMessage = strdup(Error.c_str());
76f785676fSDimitry Andric
77f785676fSDimitry Andric return 1;
78f785676fSDimitry Andric }
79f785676fSDimitry Andric
80f785676fSDimitry Andric return 0;
81f785676fSDimitry Andric }
82f785676fSDimitry Andric
LLVMGetTargetName(LLVMTargetRef T)83dff0c46cSDimitry Andric const char * LLVMGetTargetName(LLVMTargetRef T) {
84dff0c46cSDimitry Andric return unwrap(T)->getName();
85dff0c46cSDimitry Andric }
86dff0c46cSDimitry Andric
LLVMGetTargetDescription(LLVMTargetRef T)87dff0c46cSDimitry Andric const char * LLVMGetTargetDescription(LLVMTargetRef T) {
88dff0c46cSDimitry Andric return unwrap(T)->getShortDescription();
89dff0c46cSDimitry Andric }
90dff0c46cSDimitry Andric
LLVMTargetHasJIT(LLVMTargetRef T)91dff0c46cSDimitry Andric LLVMBool LLVMTargetHasJIT(LLVMTargetRef T) {
92dff0c46cSDimitry Andric return unwrap(T)->hasJIT();
93dff0c46cSDimitry Andric }
94dff0c46cSDimitry Andric
LLVMTargetHasTargetMachine(LLVMTargetRef T)95dff0c46cSDimitry Andric LLVMBool LLVMTargetHasTargetMachine(LLVMTargetRef T) {
96dff0c46cSDimitry Andric return unwrap(T)->hasTargetMachine();
97dff0c46cSDimitry Andric }
98dff0c46cSDimitry Andric
LLVMTargetHasAsmBackend(LLVMTargetRef T)99dff0c46cSDimitry Andric LLVMBool LLVMTargetHasAsmBackend(LLVMTargetRef T) {
100dff0c46cSDimitry Andric return unwrap(T)->hasMCAsmBackend();
101dff0c46cSDimitry Andric }
102dff0c46cSDimitry Andric
LLVMCreateTargetMachine(LLVMTargetRef T,const char * Triple,const char * CPU,const char * Features,LLVMCodeGenOptLevel Level,LLVMRelocMode Reloc,LLVMCodeModel CodeModel)103f785676fSDimitry Andric LLVMTargetMachineRef LLVMCreateTargetMachine(LLVMTargetRef T,
104f785676fSDimitry Andric const char *Triple, const char *CPU, const char *Features,
105f785676fSDimitry Andric LLVMCodeGenOptLevel Level, LLVMRelocMode Reloc,
106dff0c46cSDimitry Andric LLVMCodeModel CodeModel) {
1073ca95b02SDimitry Andric Optional<Reloc::Model> RM;
108dff0c46cSDimitry Andric switch (Reloc){
109dff0c46cSDimitry Andric case LLVMRelocStatic:
110dff0c46cSDimitry Andric RM = Reloc::Static;
111dff0c46cSDimitry Andric break;
112dff0c46cSDimitry Andric case LLVMRelocPIC:
113dff0c46cSDimitry Andric RM = Reloc::PIC_;
114dff0c46cSDimitry Andric break;
115dff0c46cSDimitry Andric case LLVMRelocDynamicNoPic:
116dff0c46cSDimitry Andric RM = Reloc::DynamicNoPIC;
117dff0c46cSDimitry Andric break;
118*b5893f02SDimitry Andric case LLVMRelocROPI:
119*b5893f02SDimitry Andric RM = Reloc::ROPI;
120*b5893f02SDimitry Andric break;
121*b5893f02SDimitry Andric case LLVMRelocRWPI:
122*b5893f02SDimitry Andric RM = Reloc::RWPI;
123*b5893f02SDimitry Andric break;
124*b5893f02SDimitry Andric case LLVMRelocROPI_RWPI:
125*b5893f02SDimitry Andric RM = Reloc::ROPI_RWPI;
126*b5893f02SDimitry Andric break;
127dff0c46cSDimitry Andric default:
128dff0c46cSDimitry Andric break;
129dff0c46cSDimitry Andric }
130dff0c46cSDimitry Andric
1312cab237bSDimitry Andric bool JIT;
1322cab237bSDimitry Andric Optional<CodeModel::Model> CM = unwrap(CodeModel, JIT);
133dff0c46cSDimitry Andric
134284c1978SDimitry Andric CodeGenOpt::Level OL;
135dff0c46cSDimitry Andric switch (Level) {
136dff0c46cSDimitry Andric case LLVMCodeGenLevelNone:
137dff0c46cSDimitry Andric OL = CodeGenOpt::None;
138dff0c46cSDimitry Andric break;
139dff0c46cSDimitry Andric case LLVMCodeGenLevelLess:
140dff0c46cSDimitry Andric OL = CodeGenOpt::Less;
141dff0c46cSDimitry Andric break;
142dff0c46cSDimitry Andric case LLVMCodeGenLevelAggressive:
143dff0c46cSDimitry Andric OL = CodeGenOpt::Aggressive;
144dff0c46cSDimitry Andric break;
145dff0c46cSDimitry Andric default:
146dff0c46cSDimitry Andric OL = CodeGenOpt::Default;
147dff0c46cSDimitry Andric break;
148dff0c46cSDimitry Andric }
149dff0c46cSDimitry Andric
150dff0c46cSDimitry Andric TargetOptions opt;
1512cab237bSDimitry Andric return wrap(unwrap(T)->createTargetMachine(Triple, CPU, Features, opt, RM, CM,
1522cab237bSDimitry Andric OL, JIT));
153dff0c46cSDimitry Andric }
154dff0c46cSDimitry Andric
LLVMDisposeTargetMachine(LLVMTargetMachineRef T)1557d523365SDimitry Andric void LLVMDisposeTargetMachine(LLVMTargetMachineRef T) { delete unwrap(T); }
156dff0c46cSDimitry Andric
LLVMGetTargetMachineTarget(LLVMTargetMachineRef T)157dff0c46cSDimitry Andric LLVMTargetRef LLVMGetTargetMachineTarget(LLVMTargetMachineRef T) {
158dff0c46cSDimitry Andric const Target* target = &(unwrap(T)->getTarget());
159dff0c46cSDimitry Andric return wrap(target);
160dff0c46cSDimitry Andric }
161dff0c46cSDimitry Andric
LLVMGetTargetMachineTriple(LLVMTargetMachineRef T)162dff0c46cSDimitry Andric char* LLVMGetTargetMachineTriple(LLVMTargetMachineRef T) {
1638f0fd8f6SDimitry Andric std::string StringRep = unwrap(T)->getTargetTriple().str();
164dff0c46cSDimitry Andric return strdup(StringRep.c_str());
165dff0c46cSDimitry Andric }
166dff0c46cSDimitry Andric
LLVMGetTargetMachineCPU(LLVMTargetMachineRef T)167dff0c46cSDimitry Andric char* LLVMGetTargetMachineCPU(LLVMTargetMachineRef T) {
168dff0c46cSDimitry Andric std::string StringRep = unwrap(T)->getTargetCPU();
169dff0c46cSDimitry Andric return strdup(StringRep.c_str());
170dff0c46cSDimitry Andric }
171dff0c46cSDimitry Andric
LLVMGetTargetMachineFeatureString(LLVMTargetMachineRef T)172dff0c46cSDimitry Andric char* LLVMGetTargetMachineFeatureString(LLVMTargetMachineRef T) {
173dff0c46cSDimitry Andric std::string StringRep = unwrap(T)->getTargetFeatureString();
174dff0c46cSDimitry Andric return strdup(StringRep.c_str());
175dff0c46cSDimitry Andric }
176dff0c46cSDimitry Andric
LLVMSetTargetMachineAsmVerbosity(LLVMTargetMachineRef T,LLVMBool VerboseAsm)177f785676fSDimitry Andric void LLVMSetTargetMachineAsmVerbosity(LLVMTargetMachineRef T,
178f785676fSDimitry Andric LLVMBool VerboseAsm) {
179ff0cc061SDimitry Andric unwrap(T)->Options.MCOptions.AsmVerbose = VerboseAsm;
180f785676fSDimitry Andric }
181f785676fSDimitry Andric
LLVMCreateTargetDataLayout(LLVMTargetMachineRef T)1823ca95b02SDimitry Andric LLVMTargetDataRef LLVMCreateTargetDataLayout(LLVMTargetMachineRef T) {
1833ca95b02SDimitry Andric return wrap(new DataLayout(unwrap(T)->createDataLayout()));
1843ca95b02SDimitry Andric }
1853ca95b02SDimitry Andric
LLVMTargetMachineEmit(LLVMTargetMachineRef T,LLVMModuleRef M,raw_pwrite_stream & OS,LLVMCodeGenFileType codegen,char ** ErrorMessage)186284c1978SDimitry Andric static LLVMBool LLVMTargetMachineEmit(LLVMTargetMachineRef T, LLVMModuleRef M,
187ff0cc061SDimitry Andric raw_pwrite_stream &OS,
188ff0cc061SDimitry Andric LLVMCodeGenFileType codegen,
189ff0cc061SDimitry Andric char **ErrorMessage) {
190dff0c46cSDimitry Andric TargetMachine* TM = unwrap(T);
191dff0c46cSDimitry Andric Module* Mod = unwrap(M);
192dff0c46cSDimitry Andric
193ff0cc061SDimitry Andric legacy::PassManager pass;
194dff0c46cSDimitry Andric
195dff0c46cSDimitry Andric std::string error;
196dff0c46cSDimitry Andric
1977d523365SDimitry Andric Mod->setDataLayout(TM->createDataLayout());
198dff0c46cSDimitry Andric
199dff0c46cSDimitry Andric TargetMachine::CodeGenFileType ft;
200dff0c46cSDimitry Andric switch (codegen) {
201dff0c46cSDimitry Andric case LLVMAssemblyFile:
202dff0c46cSDimitry Andric ft = TargetMachine::CGFT_AssemblyFile;
203dff0c46cSDimitry Andric break;
204dff0c46cSDimitry Andric default:
205dff0c46cSDimitry Andric ft = TargetMachine::CGFT_ObjectFile;
206dff0c46cSDimitry Andric break;
207dff0c46cSDimitry Andric }
2084ba319b5SDimitry Andric if (TM->addPassesToEmitFile(pass, OS, nullptr, ft)) {
209139f7f9bSDimitry Andric error = "TargetMachine can't emit a file of this type";
210dff0c46cSDimitry Andric *ErrorMessage = strdup(error.c_str());
211dff0c46cSDimitry Andric return true;
212dff0c46cSDimitry Andric }
213dff0c46cSDimitry Andric
214dff0c46cSDimitry Andric pass.run(*Mod);
215dff0c46cSDimitry Andric
216284c1978SDimitry Andric OS.flush();
217dff0c46cSDimitry Andric return false;
218dff0c46cSDimitry Andric }
219284c1978SDimitry Andric
LLVMTargetMachineEmitToFile(LLVMTargetMachineRef T,LLVMModuleRef M,char * Filename,LLVMCodeGenFileType codegen,char ** ErrorMessage)220284c1978SDimitry Andric LLVMBool LLVMTargetMachineEmitToFile(LLVMTargetMachineRef T, LLVMModuleRef M,
221284c1978SDimitry Andric char* Filename, LLVMCodeGenFileType codegen, char** ErrorMessage) {
22239d628a0SDimitry Andric std::error_code EC;
22339d628a0SDimitry Andric raw_fd_ostream dest(Filename, EC, sys::fs::F_None);
22439d628a0SDimitry Andric if (EC) {
22539d628a0SDimitry Andric *ErrorMessage = strdup(EC.message().c_str());
226284c1978SDimitry Andric return true;
227284c1978SDimitry Andric }
228ff0cc061SDimitry Andric bool Result = LLVMTargetMachineEmit(T, M, dest, codegen, ErrorMessage);
229284c1978SDimitry Andric dest.flush();
230284c1978SDimitry Andric return Result;
231284c1978SDimitry Andric }
232284c1978SDimitry Andric
LLVMTargetMachineEmitToMemoryBuffer(LLVMTargetMachineRef T,LLVMModuleRef M,LLVMCodeGenFileType codegen,char ** ErrorMessage,LLVMMemoryBufferRef * OutMemBuf)233284c1978SDimitry Andric LLVMBool LLVMTargetMachineEmitToMemoryBuffer(LLVMTargetMachineRef T,
234284c1978SDimitry Andric LLVMModuleRef M, LLVMCodeGenFileType codegen, char** ErrorMessage,
235284c1978SDimitry Andric LLVMMemoryBufferRef *OutMemBuf) {
236ff0cc061SDimitry Andric SmallString<0> CodeString;
237ff0cc061SDimitry Andric raw_svector_ostream OStream(CodeString);
238ff0cc061SDimitry Andric bool Result = LLVMTargetMachineEmit(T, M, OStream, codegen, ErrorMessage);
239284c1978SDimitry Andric
240ff0cc061SDimitry Andric StringRef Data = OStream.str();
241ff0cc061SDimitry Andric *OutMemBuf =
242ff0cc061SDimitry Andric LLVMCreateMemoryBufferWithMemoryRangeCopy(Data.data(), Data.size(), "");
243284c1978SDimitry Andric return Result;
244284c1978SDimitry Andric }
245f785676fSDimitry Andric
LLVMGetDefaultTargetTriple(void)246f785676fSDimitry Andric char *LLVMGetDefaultTargetTriple(void) {
247f785676fSDimitry Andric return strdup(sys::getDefaultTargetTriple().c_str());
248f785676fSDimitry Andric }
24991bc56edSDimitry Andric
LLVMNormalizeTargetTriple(const char * triple)2504ba319b5SDimitry Andric char *LLVMNormalizeTargetTriple(const char* triple) {
2514ba319b5SDimitry Andric return strdup(Triple::normalize(StringRef(triple)).c_str());
2524ba319b5SDimitry Andric }
2534ba319b5SDimitry Andric
LLVMGetHostCPUName(void)2544ba319b5SDimitry Andric char *LLVMGetHostCPUName(void) {
2554ba319b5SDimitry Andric return strdup(sys::getHostCPUName().data());
2564ba319b5SDimitry Andric }
2574ba319b5SDimitry Andric
LLVMGetHostCPUFeatures(void)2584ba319b5SDimitry Andric char *LLVMGetHostCPUFeatures(void) {
2594ba319b5SDimitry Andric SubtargetFeatures Features;
2604ba319b5SDimitry Andric StringMap<bool> HostFeatures;
2614ba319b5SDimitry Andric
2624ba319b5SDimitry Andric if (sys::getHostCPUFeatures(HostFeatures))
2634ba319b5SDimitry Andric for (auto &F : HostFeatures)
2644ba319b5SDimitry Andric Features.AddFeature(F.first(), F.second);
2654ba319b5SDimitry Andric
2664ba319b5SDimitry Andric return strdup(Features.getString().c_str());
2674ba319b5SDimitry Andric }
2684ba319b5SDimitry Andric
LLVMAddAnalysisPasses(LLVMTargetMachineRef T,LLVMPassManagerRef PM)26991bc56edSDimitry Andric void LLVMAddAnalysisPasses(LLVMTargetMachineRef T, LLVMPassManagerRef PM) {
270ff0cc061SDimitry Andric unwrap(PM)->add(
271ff0cc061SDimitry Andric createTargetTransformInfoWrapperPass(unwrap(T)->getTargetIRAnalysis()));
27291bc56edSDimitry Andric }
273