blob: f8ddfc4b65eb5f95b3fea9d2d0e9425ca4bec9cb [file] [log] [blame]
Shih-wei Liao52aefd82012-07-27 03:12:56 -07001/*
2 * Copyright 2012, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "bcc/AndroidBitcode/ABCCompilerDriver.h"
18
19#include <llvm/Module.h>
20#include <llvm/Support/MemoryBuffer.h>
21#include <llvm/Support/raw_ostream.h>
Shih-wei Liao56de4e82012-08-16 01:05:08 -070022#include <mcld/Config/Config.h>
Shih-wei Liao3928c622012-08-16 00:23:15 -070023
Shih-wei Liao52aefd82012-07-27 03:12:56 -070024#include "bcc/Config/Config.h"
25#include "bcc/Script.h"
26#include "bcc/Source.h"
27#include "bcc/Support/CompilerConfig.h"
28#include "bcc/Support/LinkerConfig.h"
29#include "bcc/Support/Log.h"
30#include "bcc/Support/OutputFile.h"
31#include "bcc/Support/TargetLinkerConfigs.h"
32#include "bcc/Support/TargetCompilerConfigs.h"
33
Shih-wei Liao56de4e82012-08-16 01:05:08 -070034#if defined(PROVIDE_ARM_CODEGEN)
35# include "ARM/ARMABCCompilerDriver.h"
36#endif
37#if defined(PROVIDE_MIPS_CODEGEN)
38# include "Mips/MipsABCCompilerDriver.h"
39#endif
40#if defined(PROVIDE_X86_CODEGEN)
41# include "X86/X86ABCCompilerDriver.h"
42#endif
Shih-wei Liao52aefd82012-07-27 03:12:56 -070043
44namespace bcc {
45
Shih-wei Liao3928c622012-08-16 00:23:15 -070046ABCCompilerDriver::ABCCompilerDriver(const std::string &pTriple)
Shih-wei Liao52aefd82012-07-27 03:12:56 -070047 : mContext(), mCompiler(), mLinker(),
48 mCompilerConfig(NULL), mLinkerConfig(NULL),
Shih-wei Liao3928c622012-08-16 00:23:15 -070049 mTriple(pTriple), mAndroidSysroot("/") {
Shih-wei Liao52aefd82012-07-27 03:12:56 -070050}
51
52ABCCompilerDriver::~ABCCompilerDriver() {
53 delete mCompilerConfig;
54 delete mLinkerConfig;
55}
56
57bool ABCCompilerDriver::configCompiler() {
58 if (mCompilerConfig != NULL) {
59 return true;
60 }
61
62 mCompilerConfig = new (std::nothrow) CompilerConfig(mTriple);
63 if (mCompilerConfig == NULL) {
64 ALOGE("Out of memory when create the compiler configuration!");
65 return false;
66 }
67
68 // Set PIC mode for relocatables.
69 mCompilerConfig->setRelocationModel(llvm::Reloc::PIC_);
70
71 // Set optimization level to -O1.
72 mCompilerConfig->setOptimizationLevel(llvm::CodeGenOpt::Less);
73
74 Compiler::ErrorCode result = mCompiler.config(*mCompilerConfig);
75
76 if (result != Compiler::kSuccess) {
77 ALOGE("Failed to configure the compiler! (detail: %s)",
78 Compiler::GetErrorString(result));
79 return false;
80 }
81
82 return true;
83}
84
85bool ABCCompilerDriver::configLinker() {
86 if (mLinkerConfig != NULL) {
87 return true;
88 }
89
90 mLinkerConfig = new (std::nothrow) LinkerConfig(mTriple);
91 if (mLinkerConfig == NULL) {
92 ALOGE("Out of memory when create the linker configuration!");
93 return false;
94 }
95
96 // FIXME: how can we get the soname if input/output is file descriptor?
97 mLinkerConfig->setSOName("");
98
99 mLinkerConfig->setDyld("/system/bin/linker");
100 mLinkerConfig->setSysRoot(mAndroidSysroot);
101 mLinkerConfig->addSearchDir("=/system/lib");
102
103 // Add non-portable function list. For each function X, linker will rename
104 // it to X_portable. And X_portable" is implemented in libportable to solve
105 // portable issues.
Shih-wei Liao31b7c562012-08-16 00:56:04 -0700106 const char **non_portable_func = getNonPortableList();
107 if (non_portable_func != NULL) {
108 while (*non_portable_func != NULL) {
109 mLinkerConfig->addPortable(*non_portable_func);
110 non_portable_func++;
111 }
112 }
Shih-wei Liao52aefd82012-07-27 03:12:56 -0700113
114 // -shared
115 mLinkerConfig->setShared(true);
116
117 // -Bsymbolic.
118 mLinkerConfig->setBsymbolic(true);
119
120 // Config the linker.
121 Linker::ErrorCode result = mLinker.config(*mLinkerConfig);
122 if (result != Linker::kSuccess) {
123 ALOGE("Failed to configure the linker! (%s)",
124 Linker::GetErrorString(result));
125 return false;
126 }
127
128 return true;
129}
130
131//------------------------------------------------------------------------------
132
133Script *ABCCompilerDriver::prepareScript(int pInputFd) {
134 Source *source = Source::CreateFromFd(mContext, pInputFd);
135 if (source == NULL) {
136 ALOGE("Failed to load LLVM module from file descriptor `%d'", pInputFd);
137 return NULL;
138 }
139
140 Script *script = new (std::nothrow) Script(*source);
141 if (script == NULL) {
142 ALOGE("Out of memory when create script for file descriptor `%d'!",
143 pInputFd);
144 delete source;
145 return NULL;
146 }
147
148 return script;
149}
150
151bool ABCCompilerDriver::compile(Script &pScript, llvm::raw_ostream &pOutput) {
152 // Config the compiler.
153 if (!configCompiler()) {
154 return false;
155 }
156
157 // Run the compiler.
158 Compiler::ErrorCode result = mCompiler.compile(pScript, pOutput);
159 if (result != Compiler::kSuccess) {
160 ALOGE("Fatal error during compilation (%s)!",
161 Compiler::GetErrorString(result));
162 return false;
163 }
164
165 return true;
166}
167
168bool ABCCompilerDriver::link(const Script &pScript,
169 const std::string &input_relocatable,
170 int pOutputFd) {
171 // Config the linker.
172 if (!configLinker()) {
173 return false;
174 }
175
176 // Prepare output file.
177 Linker::ErrorCode result = mLinker.setOutput(pOutputFd);
178
179 if (result != Linker::kSuccess) {
180 ALOGE("Failed to open the output file! (file descriptor `%d': %s)",
181 pOutputFd, Linker::GetErrorString(result));
182 return false;
183 }
184
185 mLinker.addObject(mAndroidSysroot + "/system/lib/crtbegin_so.o");
186
187 // Prepare the relocatables.
188 //
189 // FIXME: Ugly const_cast here.
190 mLinker.addObject(const_cast<char *>(input_relocatable.data()),
191 input_relocatable.size());
192
193 // Read dependent library list.
194 const Source &source = pScript.getSource();
195 for (llvm::Module::lib_iterator lib_iter = source.getModule().lib_begin(),
196 lib_end = source.getModule().lib_end(); lib_iter != lib_end;
197 ++lib_iter) {
198 mLinker.addNameSpec(*lib_iter);
199 }
200
201 // TODO: Refactor libbcc/runtime/ to libcompilerRT.so and use it.
202 mLinker.addNameSpec("bcc");
203
204 mLinker.addObject(mAndroidSysroot + "/system/lib/crtend_so.o");
205
206 // Perform linking.
207 result = mLinker.link();
208 if (result != Linker::kSuccess) {
209 ALOGE("Failed to link the shared object (detail: %s)",
210 Linker::GetErrorString(result));
211 return false;
212 }
213
214 return true;
215}
216
217//------------------------------------------------------------------------------
218
Shih-wei Liao3928c622012-08-16 00:23:15 -0700219ABCCompilerDriver *ABCCompilerDriver::Create(const std::string &pTriple) {
220 std::string error;
221 const llvm::Target *target =
222 llvm::TargetRegistry::lookupTarget(pTriple, error);
223
224 if (target == NULL) {
225 ALOGE("Unsupported target '%s' (detail: %s)!", pTriple.c_str(),
226 error.c_str());
227 return NULL;
228 }
229
230 switch (llvm::Triple::getArchTypeForLLVMName(target->getName())) {
Shih-wei Liao56de4e82012-08-16 01:05:08 -0700231#if defined(PROVIDE_ARM_CODEGEN)
Shih-wei Liao3928c622012-08-16 00:23:15 -0700232 case llvm::Triple::arm:
233 case llvm::Triple::thumb: {
234 return new ARMABCCompilerDriver(pTriple);
235 }
Shih-wei Liao56de4e82012-08-16 01:05:08 -0700236#endif
237#if defined(PROVIDE_MIPS_CODEGEN)
Shih-wei Liao3928c622012-08-16 00:23:15 -0700238 case llvm::Triple::mipsel: {
239 return new MipsABCCompilerDriver(pTriple);
240 }
Shih-wei Liao56de4e82012-08-16 01:05:08 -0700241#endif
242#if defined(PROVIDE_X86_CODEGEN)
Shih-wei Liao3928c622012-08-16 00:23:15 -0700243 case llvm::Triple::x86: {
244 return new X86ABCCompilerDriver(pTriple);
245 }
Shih-wei Liao56de4e82012-08-16 01:05:08 -0700246#endif
Shih-wei Liao3928c622012-08-16 00:23:15 -0700247 default: {
248 ALOGE("Unknown architecture '%s' supplied in %s!", target->getName(),
249 pTriple.c_str());
250 break;
251 }
252 }
253
254 return NULL;
255}
256
Shih-wei Liao52aefd82012-07-27 03:12:56 -0700257bool ABCCompilerDriver::build(int pInputFd, int pOutputFd) {
258 //===--------------------------------------------------------------------===//
259 // Prepare the input.
260 //===--------------------------------------------------------------------===//
261 Script *script = prepareScript(pInputFd);
262 if (script == NULL) {
263 return false;
264 }
265
266 //===--------------------------------------------------------------------===//
267 // Prepare the output.
268 //===--------------------------------------------------------------------===//
269 std::string output_relocatable;
270 llvm::raw_ostream *output =
271 new (std::nothrow) llvm::raw_string_ostream(output_relocatable);
272 if (output == NULL) {
273 ALOGE("Failed to prepare the output for compile the input from %d into "
274 "relocatable object!", pInputFd);
275 delete script;
276 return false;
277 }
278
279 //===--------------------------------------------------------------------===//
280 // Compile.
281 //===--------------------------------------------------------------------===//
282 if (!compile(*script, *output)) {
283 delete output;
284 delete script;
285 return false;
286 }
287
288 //===--------------------------------------------------------------------===//
289 // Close the output.
290 //===--------------------------------------------------------------------===//
291 delete output;
292
293 //===--------------------------------------------------------------------===//
294 // Link.
295 //===--------------------------------------------------------------------===//
296 if (!link(*script, output_relocatable, pOutputFd)) {
297 delete script;
298 return false;
299 }
300
301 //===--------------------------------------------------------------------===//
302 // Clean up.
303 //===--------------------------------------------------------------------===//
304 delete script;
305
306 return true;
307}
308
309} // namespace bcc