1//===-- TargetMachine.cpp -------------------------------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the LLVM-C part of TargetMachine.h
11//
12//===----------------------------------------------------------------------===//
13
14#include "llvm-c/TargetMachine.h"
15#include "llvm-c/Core.h"
16#include "llvm-c/Target.h"
17#include "llvm/IR/DataLayout.h"
18#include "llvm/IR/Module.h"
19#include "llvm/PassManager.h"
20#include "llvm/Support/CodeGen.h"
21#include "llvm/Support/FormattedStream.h"
22#include "llvm/Support/TargetRegistry.h"
23#include "llvm/Support/raw_ostream.h"
24#include "llvm/Target/TargetMachine.h"
25#include <cassert>
26#include <cstdlib>
27#include <cstring>
28
29using namespace llvm;
30
31inline DataLayout *unwrap(LLVMTargetDataRef P) {
32  return reinterpret_cast<DataLayout*>(P);
33}
34
35inline LLVMTargetDataRef wrap(const DataLayout *P) {
36  return reinterpret_cast<LLVMTargetDataRef>(const_cast<DataLayout*>(P));
37}
38
39inline TargetLibraryInfo *unwrap(LLVMTargetLibraryInfoRef P) {
40  return reinterpret_cast<TargetLibraryInfo*>(P);
41}
42
43inline LLVMTargetLibraryInfoRef wrap(const TargetLibraryInfo *P) {
44  TargetLibraryInfo *X = const_cast<TargetLibraryInfo*>(P);
45  return reinterpret_cast<LLVMTargetLibraryInfoRef>(X);
46}
47
48inline TargetMachine *unwrap(LLVMTargetMachineRef P) {
49  return reinterpret_cast<TargetMachine*>(P);
50}
51inline Target *unwrap(LLVMTargetRef P) {
52  return reinterpret_cast<Target*>(P);
53}
54inline LLVMTargetMachineRef wrap(const TargetMachine *P) {
55  return
56    reinterpret_cast<LLVMTargetMachineRef>(const_cast<TargetMachine*>(P));
57}
58inline LLVMTargetRef wrap(const Target * P) {
59  return reinterpret_cast<LLVMTargetRef>(const_cast<Target*>(P));
60}
61
62LLVMTargetRef LLVMGetFirstTarget() {
63   const Target* target = &*TargetRegistry::begin();
64   return wrap(target);
65}
66LLVMTargetRef LLVMGetNextTarget(LLVMTargetRef T) {
67  return wrap(unwrap(T)->getNext());
68}
69
70const char * LLVMGetTargetName(LLVMTargetRef T) {
71  return unwrap(T)->getName();
72}
73
74const char * LLVMGetTargetDescription(LLVMTargetRef T) {
75  return unwrap(T)->getShortDescription();
76}
77
78LLVMBool LLVMTargetHasJIT(LLVMTargetRef T) {
79  return unwrap(T)->hasJIT();
80}
81
82LLVMBool LLVMTargetHasTargetMachine(LLVMTargetRef T) {
83  return unwrap(T)->hasTargetMachine();
84}
85
86LLVMBool LLVMTargetHasAsmBackend(LLVMTargetRef T) {
87  return unwrap(T)->hasMCAsmBackend();
88}
89
90LLVMTargetMachineRef LLVMCreateTargetMachine(LLVMTargetRef T, char* Triple,
91  char* CPU, char* Features, LLVMCodeGenOptLevel Level, LLVMRelocMode Reloc,
92  LLVMCodeModel CodeModel) {
93  Reloc::Model RM;
94  switch (Reloc){
95    case LLVMRelocStatic:
96      RM = Reloc::Static;
97      break;
98    case LLVMRelocPIC:
99      RM = Reloc::PIC_;
100      break;
101    case LLVMRelocDynamicNoPic:
102      RM = Reloc::DynamicNoPIC;
103      break;
104    default:
105      RM = Reloc::Default;
106      break;
107  }
108
109  CodeModel::Model CM = unwrap(CodeModel);
110
111  CodeGenOpt::Level OL;
112  switch (Level) {
113    case LLVMCodeGenLevelNone:
114      OL = CodeGenOpt::None;
115      break;
116    case LLVMCodeGenLevelLess:
117      OL = CodeGenOpt::Less;
118      break;
119    case LLVMCodeGenLevelAggressive:
120      OL = CodeGenOpt::Aggressive;
121      break;
122    default:
123      OL = CodeGenOpt::Default;
124      break;
125  }
126
127  TargetOptions opt;
128  return wrap(unwrap(T)->createTargetMachine(Triple, CPU, Features, opt, RM,
129    CM, OL));
130}
131
132
133void LLVMDisposeTargetMachine(LLVMTargetMachineRef T) {
134  delete unwrap(T);
135}
136
137LLVMTargetRef LLVMGetTargetMachineTarget(LLVMTargetMachineRef T) {
138  const Target* target = &(unwrap(T)->getTarget());
139  return wrap(target);
140}
141
142char* LLVMGetTargetMachineTriple(LLVMTargetMachineRef T) {
143  std::string StringRep = unwrap(T)->getTargetTriple();
144  return strdup(StringRep.c_str());
145}
146
147char* LLVMGetTargetMachineCPU(LLVMTargetMachineRef T) {
148  std::string StringRep = unwrap(T)->getTargetCPU();
149  return strdup(StringRep.c_str());
150}
151
152char* LLVMGetTargetMachineFeatureString(LLVMTargetMachineRef T) {
153  std::string StringRep = unwrap(T)->getTargetFeatureString();
154  return strdup(StringRep.c_str());
155}
156
157LLVMTargetDataRef LLVMGetTargetMachineData(LLVMTargetMachineRef T) {
158  return wrap(unwrap(T)->getDataLayout());
159}
160
161static LLVMBool LLVMTargetMachineEmit(LLVMTargetMachineRef T, LLVMModuleRef M,
162  formatted_raw_ostream &OS, LLVMCodeGenFileType codegen, char **ErrorMessage) {
163  TargetMachine* TM = unwrap(T);
164  Module* Mod = unwrap(M);
165
166  PassManager pass;
167
168  std::string error;
169
170  const DataLayout* td = TM->getDataLayout();
171
172  if (!td) {
173    error = "No DataLayout in TargetMachine";
174    *ErrorMessage = strdup(error.c_str());
175    return true;
176  }
177  pass.add(new DataLayout(*td));
178
179  TargetMachine::CodeGenFileType ft;
180  switch (codegen) {
181    case LLVMAssemblyFile:
182      ft = TargetMachine::CGFT_AssemblyFile;
183      break;
184    default:
185      ft = TargetMachine::CGFT_ObjectFile;
186      break;
187  }
188  if (TM->addPassesToEmitFile(pass, OS, ft)) {
189    error = "TargetMachine can't emit a file of this type";
190    *ErrorMessage = strdup(error.c_str());
191    return true;
192  }
193
194  pass.run(*Mod);
195
196  OS.flush();
197  return false;
198}
199
200LLVMBool LLVMTargetMachineEmitToFile(LLVMTargetMachineRef T, LLVMModuleRef M,
201  char* Filename, LLVMCodeGenFileType codegen, char** ErrorMessage) {
202  std::string error;
203  raw_fd_ostream dest(Filename, error, sys::fs::F_Binary);
204  formatted_raw_ostream destf(dest);
205  if (!error.empty()) {
206    *ErrorMessage = strdup(error.c_str());
207    return true;
208  }
209  bool Result = LLVMTargetMachineEmit(T, M, destf, codegen, ErrorMessage);
210  dest.flush();
211  return Result;
212}
213
214LLVMBool LLVMTargetMachineEmitToMemoryBuffer(LLVMTargetMachineRef T,
215  LLVMModuleRef M, LLVMCodeGenFileType codegen, char** ErrorMessage,
216  LLVMMemoryBufferRef *OutMemBuf) {
217  std::string CodeString;
218  raw_string_ostream OStream(CodeString);
219  formatted_raw_ostream Out(OStream);
220  bool Result = LLVMTargetMachineEmit(T, M, Out, codegen, ErrorMessage);
221  OStream.flush();
222
223  std::string &Data = OStream.str();
224  *OutMemBuf = LLVMCreateMemoryBufferWithMemoryRangeCopy(Data.c_str(),
225                                                     Data.length(), "");
226  return Result;
227}
228