1234285Sdim//===-- TargetMachine.cpp -------------------------------------------------===//
2234285Sdim//
3234285Sdim//                     The LLVM Compiler Infrastructure
4234285Sdim//
5234285Sdim// This file is distributed under the University of Illinois Open Source
6234285Sdim// License. See LICENSE.TXT for details.
7234285Sdim//
8234285Sdim//===----------------------------------------------------------------------===//
9234285Sdim//
10234285Sdim// This file implements the LLVM-C part of TargetMachine.h
11234285Sdim//
12234285Sdim//===----------------------------------------------------------------------===//
13234285Sdim
14252723Sdim#include "llvm-c/TargetMachine.h"
15234285Sdim#include "llvm-c/Core.h"
16234285Sdim#include "llvm-c/Target.h"
17252723Sdim#include "llvm/IR/DataLayout.h"
18252723Sdim#include "llvm/IR/Module.h"
19252723Sdim#include "llvm/PassManager.h"
20252723Sdim#include "llvm/Support/CodeGen.h"
21252723Sdim#include "llvm/Support/FormattedStream.h"
22234285Sdim#include "llvm/Support/TargetRegistry.h"
23234285Sdim#include "llvm/Support/raw_ostream.h"
24263509Sdim#include "llvm/Support/Host.h"
25252723Sdim#include "llvm/Target/TargetMachine.h"
26234285Sdim#include <cassert>
27234285Sdim#include <cstdlib>
28234285Sdim#include <cstring>
29234285Sdim
30234285Sdimusing namespace llvm;
31234285Sdim
32252723Sdiminline DataLayout *unwrap(LLVMTargetDataRef P) {
33252723Sdim  return reinterpret_cast<DataLayout*>(P);
34252723Sdim}
35234285Sdim
36252723Sdiminline LLVMTargetDataRef wrap(const DataLayout *P) {
37252723Sdim  return reinterpret_cast<LLVMTargetDataRef>(const_cast<DataLayout*>(P));
38252723Sdim}
39234285Sdim
40252723Sdiminline TargetLibraryInfo *unwrap(LLVMTargetLibraryInfoRef P) {
41252723Sdim  return reinterpret_cast<TargetLibraryInfo*>(P);
42252723Sdim}
43252723Sdim
44252723Sdiminline LLVMTargetLibraryInfoRef wrap(const TargetLibraryInfo *P) {
45252723Sdim  TargetLibraryInfo *X = const_cast<TargetLibraryInfo*>(P);
46252723Sdim  return reinterpret_cast<LLVMTargetLibraryInfoRef>(X);
47252723Sdim}
48252723Sdim
49252723Sdiminline TargetMachine *unwrap(LLVMTargetMachineRef P) {
50252723Sdim  return reinterpret_cast<TargetMachine*>(P);
51252723Sdim}
52252723Sdiminline Target *unwrap(LLVMTargetRef P) {
53252723Sdim  return reinterpret_cast<Target*>(P);
54252723Sdim}
55252723Sdiminline LLVMTargetMachineRef wrap(const TargetMachine *P) {
56252723Sdim  return
57252723Sdim    reinterpret_cast<LLVMTargetMachineRef>(const_cast<TargetMachine*>(P));
58252723Sdim}
59252723Sdiminline LLVMTargetRef wrap(const Target * P) {
60252723Sdim  return reinterpret_cast<LLVMTargetRef>(const_cast<Target*>(P));
61252723Sdim}
62252723Sdim
63234285SdimLLVMTargetRef LLVMGetFirstTarget() {
64263509Sdim  if(TargetRegistry::begin() == TargetRegistry::end()) {
65263509Sdim    return NULL;
66263509Sdim  }
67263509Sdim
68263509Sdim  const Target* target = &*TargetRegistry::begin();
69263509Sdim  return wrap(target);
70234285Sdim}
71234285SdimLLVMTargetRef LLVMGetNextTarget(LLVMTargetRef T) {
72234285Sdim  return wrap(unwrap(T)->getNext());
73234285Sdim}
74234285Sdim
75263509SdimLLVMTargetRef LLVMGetTargetFromName(const char *Name) {
76263509Sdim  StringRef NameRef = Name;
77263509Sdim  for (TargetRegistry::iterator IT = TargetRegistry::begin(),
78263509Sdim                                IE = TargetRegistry::end(); IT != IE; ++IT) {
79263509Sdim    if (IT->getName() == NameRef)
80263509Sdim      return wrap(&*IT);
81263509Sdim  }
82263509Sdim
83263509Sdim  return NULL;
84263509Sdim}
85263509Sdim
86263509SdimLLVMBool LLVMGetTargetFromTriple(const char* TripleStr, LLVMTargetRef *T,
87263509Sdim                                 char **ErrorMessage) {
88263509Sdim  std::string Error;
89263509Sdim
90263509Sdim  *T = wrap(TargetRegistry::lookupTarget(TripleStr, Error));
91263509Sdim
92263509Sdim  if (!*T) {
93263509Sdim    if (ErrorMessage)
94263509Sdim      *ErrorMessage = strdup(Error.c_str());
95263509Sdim
96263509Sdim    return 1;
97263509Sdim  }
98263509Sdim
99263509Sdim  return 0;
100263509Sdim}
101263509Sdim
102234285Sdimconst char * LLVMGetTargetName(LLVMTargetRef T) {
103234285Sdim  return unwrap(T)->getName();
104234285Sdim}
105234285Sdim
106234285Sdimconst char * LLVMGetTargetDescription(LLVMTargetRef T) {
107234285Sdim  return unwrap(T)->getShortDescription();
108234285Sdim}
109234285Sdim
110234285SdimLLVMBool LLVMTargetHasJIT(LLVMTargetRef T) {
111234285Sdim  return unwrap(T)->hasJIT();
112234285Sdim}
113234285Sdim
114234285SdimLLVMBool LLVMTargetHasTargetMachine(LLVMTargetRef T) {
115234285Sdim  return unwrap(T)->hasTargetMachine();
116234285Sdim}
117234285Sdim
118234285SdimLLVMBool LLVMTargetHasAsmBackend(LLVMTargetRef T) {
119234285Sdim  return unwrap(T)->hasMCAsmBackend();
120234285Sdim}
121234285Sdim
122263509SdimLLVMTargetMachineRef LLVMCreateTargetMachine(LLVMTargetRef T,
123263509Sdim        const char* Triple, const char* CPU, const char* Features,
124263509Sdim        LLVMCodeGenOptLevel Level, LLVMRelocMode Reloc,
125263509Sdim        LLVMCodeModel CodeModel) {
126234285Sdim  Reloc::Model RM;
127234285Sdim  switch (Reloc){
128234285Sdim    case LLVMRelocStatic:
129234285Sdim      RM = Reloc::Static;
130234285Sdim      break;
131234285Sdim    case LLVMRelocPIC:
132234285Sdim      RM = Reloc::PIC_;
133234285Sdim      break;
134234285Sdim    case LLVMRelocDynamicNoPic:
135234285Sdim      RM = Reloc::DynamicNoPIC;
136234285Sdim      break;
137234285Sdim    default:
138234285Sdim      RM = Reloc::Default;
139234285Sdim      break;
140234285Sdim  }
141234285Sdim
142252723Sdim  CodeModel::Model CM = unwrap(CodeModel);
143252723Sdim
144234285Sdim  CodeGenOpt::Level OL;
145234285Sdim  switch (Level) {
146234285Sdim    case LLVMCodeGenLevelNone:
147234285Sdim      OL = CodeGenOpt::None;
148234285Sdim      break;
149234285Sdim    case LLVMCodeGenLevelLess:
150234285Sdim      OL = CodeGenOpt::Less;
151234285Sdim      break;
152234285Sdim    case LLVMCodeGenLevelAggressive:
153234285Sdim      OL = CodeGenOpt::Aggressive;
154234285Sdim      break;
155234285Sdim    default:
156234285Sdim      OL = CodeGenOpt::Default;
157234285Sdim      break;
158234285Sdim  }
159234285Sdim
160234285Sdim  TargetOptions opt;
161234285Sdim  return wrap(unwrap(T)->createTargetMachine(Triple, CPU, Features, opt, RM,
162234285Sdim    CM, OL));
163234285Sdim}
164234285Sdim
165234285Sdim
166234285Sdimvoid LLVMDisposeTargetMachine(LLVMTargetMachineRef T) {
167234285Sdim  delete unwrap(T);
168234285Sdim}
169234285Sdim
170234285SdimLLVMTargetRef LLVMGetTargetMachineTarget(LLVMTargetMachineRef T) {
171234285Sdim  const Target* target = &(unwrap(T)->getTarget());
172234285Sdim  return wrap(target);
173234285Sdim}
174234285Sdim
175234285Sdimchar* LLVMGetTargetMachineTriple(LLVMTargetMachineRef T) {
176234285Sdim  std::string StringRep = unwrap(T)->getTargetTriple();
177234285Sdim  return strdup(StringRep.c_str());
178234285Sdim}
179234285Sdim
180234285Sdimchar* LLVMGetTargetMachineCPU(LLVMTargetMachineRef T) {
181234285Sdim  std::string StringRep = unwrap(T)->getTargetCPU();
182234285Sdim  return strdup(StringRep.c_str());
183234285Sdim}
184234285Sdim
185234285Sdimchar* LLVMGetTargetMachineFeatureString(LLVMTargetMachineRef T) {
186234285Sdim  std::string StringRep = unwrap(T)->getTargetFeatureString();
187234285Sdim  return strdup(StringRep.c_str());
188234285Sdim}
189234285Sdim
190234285SdimLLVMTargetDataRef LLVMGetTargetMachineData(LLVMTargetMachineRef T) {
191245431Sdim  return wrap(unwrap(T)->getDataLayout());
192234285Sdim}
193234285Sdim
194263509Sdimvoid LLVMSetTargetMachineAsmVerbosity(LLVMTargetMachineRef T,
195263509Sdim                                      LLVMBool VerboseAsm) {
196263509Sdim  unwrap(T)->setAsmVerbosityDefault(VerboseAsm);
197263509Sdim}
198263509Sdim
199252723Sdimstatic LLVMBool LLVMTargetMachineEmit(LLVMTargetMachineRef T, LLVMModuleRef M,
200252723Sdim  formatted_raw_ostream &OS, LLVMCodeGenFileType codegen, char **ErrorMessage) {
201234285Sdim  TargetMachine* TM = unwrap(T);
202234285Sdim  Module* Mod = unwrap(M);
203234285Sdim
204234285Sdim  PassManager pass;
205234285Sdim
206234285Sdim  std::string error;
207234285Sdim
208245431Sdim  const DataLayout* td = TM->getDataLayout();
209234285Sdim
210234285Sdim  if (!td) {
211245431Sdim    error = "No DataLayout in TargetMachine";
212234285Sdim    *ErrorMessage = strdup(error.c_str());
213234285Sdim    return true;
214234285Sdim  }
215245431Sdim  pass.add(new DataLayout(*td));
216234285Sdim
217234285Sdim  TargetMachine::CodeGenFileType ft;
218234285Sdim  switch (codegen) {
219234285Sdim    case LLVMAssemblyFile:
220234285Sdim      ft = TargetMachine::CGFT_AssemblyFile;
221234285Sdim      break;
222234285Sdim    default:
223234285Sdim      ft = TargetMachine::CGFT_ObjectFile;
224234285Sdim      break;
225234285Sdim  }
226252723Sdim  if (TM->addPassesToEmitFile(pass, OS, ft)) {
227252723Sdim    error = "TargetMachine can't emit a file of this type";
228234285Sdim    *ErrorMessage = strdup(error.c_str());
229234285Sdim    return true;
230234285Sdim  }
231234285Sdim
232252723Sdim  pass.run(*Mod);
233252723Sdim
234252723Sdim  OS.flush();
235252723Sdim  return false;
236252723Sdim}
237252723Sdim
238252723SdimLLVMBool LLVMTargetMachineEmitToFile(LLVMTargetMachineRef T, LLVMModuleRef M,
239252723Sdim  char* Filename, LLVMCodeGenFileType codegen, char** ErrorMessage) {
240252723Sdim  std::string error;
241263509Sdim  raw_fd_ostream dest(Filename, error, sys::fs::F_Binary);
242252723Sdim  if (!error.empty()) {
243234285Sdim    *ErrorMessage = strdup(error.c_str());
244234285Sdim    return true;
245234285Sdim  }
246263509Sdim  formatted_raw_ostream destf(dest);
247252723Sdim  bool Result = LLVMTargetMachineEmit(T, M, destf, codegen, ErrorMessage);
248252723Sdim  dest.flush();
249252723Sdim  return Result;
250252723Sdim}
251234285Sdim
252252723SdimLLVMBool LLVMTargetMachineEmitToMemoryBuffer(LLVMTargetMachineRef T,
253252723Sdim  LLVMModuleRef M, LLVMCodeGenFileType codegen, char** ErrorMessage,
254252723Sdim  LLVMMemoryBufferRef *OutMemBuf) {
255252723Sdim  std::string CodeString;
256252723Sdim  raw_string_ostream OStream(CodeString);
257252723Sdim  formatted_raw_ostream Out(OStream);
258252723Sdim  bool Result = LLVMTargetMachineEmit(T, M, Out, codegen, ErrorMessage);
259252723Sdim  OStream.flush();
260234285Sdim
261252723Sdim  std::string &Data = OStream.str();
262252723Sdim  *OutMemBuf = LLVMCreateMemoryBufferWithMemoryRangeCopy(Data.c_str(),
263252723Sdim                                                     Data.length(), "");
264252723Sdim  return Result;
265234285Sdim}
266263509Sdim
267263509Sdimchar *LLVMGetDefaultTargetTriple(void) {
268263509Sdim  return strdup(sys::getDefaultTargetTriple().c_str());
269263509Sdim}
270