blob: 4eb33e69bae63e189fab609dfb782071ea1e522b [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>
Shih-wei Liao42b88c32012-08-16 01:18:46 -070020#include <llvm/Pass.h>
Shih-wei Liao52aefd82012-07-27 03:12:56 -070021#include <llvm/Support/MemoryBuffer.h>
22#include <llvm/Support/raw_ostream.h>
Shih-wei Liao56de4e82012-08-16 01:05:08 -070023#include <mcld/Config/Config.h>
Shih-wei Liao3928c622012-08-16 00:23:15 -070024
Shih-wei Liao52aefd82012-07-27 03:12:56 -070025#include "bcc/Config/Config.h"
26#include "bcc/Script.h"
27#include "bcc/Source.h"
28#include "bcc/Support/CompilerConfig.h"
29#include "bcc/Support/LinkerConfig.h"
30#include "bcc/Support/Log.h"
31#include "bcc/Support/OutputFile.h"
32#include "bcc/Support/TargetLinkerConfigs.h"
33#include "bcc/Support/TargetCompilerConfigs.h"
34
Shih-wei Liao56de4e82012-08-16 01:05:08 -070035#if defined(PROVIDE_ARM_CODEGEN)
36# include "ARM/ARMABCCompilerDriver.h"
37#endif
38#if defined(PROVIDE_MIPS_CODEGEN)
39# include "Mips/MipsABCCompilerDriver.h"
40#endif
41#if defined(PROVIDE_X86_CODEGEN)
42# include "X86/X86ABCCompilerDriver.h"
43#endif
Shih-wei Liao52aefd82012-07-27 03:12:56 -070044
45namespace bcc {
46
Shih-wei Liao3928c622012-08-16 00:23:15 -070047ABCCompilerDriver::ABCCompilerDriver(const std::string &pTriple)
Shih-wei Liao42b88c32012-08-16 01:18:46 -070048 : mContext(), mCompiler(*this), mLinker(),
Shih-wei Liao52aefd82012-07-27 03:12:56 -070049 mCompilerConfig(NULL), mLinkerConfig(NULL),
Shih-wei Liao3928c622012-08-16 00:23:15 -070050 mTriple(pTriple), mAndroidSysroot("/") {
Shih-wei Liao52aefd82012-07-27 03:12:56 -070051}
52
53ABCCompilerDriver::~ABCCompilerDriver() {
54 delete mCompilerConfig;
55 delete mLinkerConfig;
56}
57
58bool ABCCompilerDriver::configCompiler() {
59 if (mCompilerConfig != NULL) {
60 return true;
61 }
62
63 mCompilerConfig = new (std::nothrow) CompilerConfig(mTriple);
64 if (mCompilerConfig == NULL) {
65 ALOGE("Out of memory when create the compiler configuration!");
66 return false;
67 }
68
69 // Set PIC mode for relocatables.
70 mCompilerConfig->setRelocationModel(llvm::Reloc::PIC_);
71
72 // Set optimization level to -O1.
73 mCompilerConfig->setOptimizationLevel(llvm::CodeGenOpt::Less);
74
75 Compiler::ErrorCode result = mCompiler.config(*mCompilerConfig);
76
77 if (result != Compiler::kSuccess) {
78 ALOGE("Failed to configure the compiler! (detail: %s)",
79 Compiler::GetErrorString(result));
80 return false;
81 }
82
83 return true;
84}
85
86bool ABCCompilerDriver::configLinker() {
87 if (mLinkerConfig != NULL) {
88 return true;
89 }
90
91 mLinkerConfig = new (std::nothrow) LinkerConfig(mTriple);
92 if (mLinkerConfig == NULL) {
93 ALOGE("Out of memory when create the linker configuration!");
94 return false;
95 }
96
97 // FIXME: how can we get the soname if input/output is file descriptor?
98 mLinkerConfig->setSOName("");
99
100 mLinkerConfig->setDyld("/system/bin/linker");
101 mLinkerConfig->setSysRoot(mAndroidSysroot);
102 mLinkerConfig->addSearchDir("=/system/lib");
103
104 // Add non-portable function list. For each function X, linker will rename
105 // it to X_portable. And X_portable" is implemented in libportable to solve
106 // portable issues.
Shih-wei Liao31b7c562012-08-16 00:56:04 -0700107 const char **non_portable_func = getNonPortableList();
108 if (non_portable_func != NULL) {
109 while (*non_portable_func != NULL) {
110 mLinkerConfig->addPortable(*non_portable_func);
111 non_portable_func++;
112 }
113 }
Shih-wei Liao52aefd82012-07-27 03:12:56 -0700114
115 // -shared
116 mLinkerConfig->setShared(true);
117
118 // -Bsymbolic.
119 mLinkerConfig->setBsymbolic(true);
120
121 // Config the linker.
122 Linker::ErrorCode result = mLinker.config(*mLinkerConfig);
123 if (result != Linker::kSuccess) {
124 ALOGE("Failed to configure the linker! (%s)",
125 Linker::GetErrorString(result));
126 return false;
127 }
128
129 return true;
130}
131
132//------------------------------------------------------------------------------
133
134Script *ABCCompilerDriver::prepareScript(int pInputFd) {
135 Source *source = Source::CreateFromFd(mContext, pInputFd);
136 if (source == NULL) {
137 ALOGE("Failed to load LLVM module from file descriptor `%d'", pInputFd);
138 return NULL;
139 }
140
141 Script *script = new (std::nothrow) Script(*source);
142 if (script == NULL) {
143 ALOGE("Out of memory when create script for file descriptor `%d'!",
144 pInputFd);
145 delete source;
146 return NULL;
147 }
148
149 return script;
150}
151
152bool ABCCompilerDriver::compile(Script &pScript, llvm::raw_ostream &pOutput) {
153 // Config the compiler.
154 if (!configCompiler()) {
155 return false;
156 }
157
158 // Run the compiler.
159 Compiler::ErrorCode result = mCompiler.compile(pScript, pOutput);
160 if (result != Compiler::kSuccess) {
161 ALOGE("Fatal error during compilation (%s)!",
162 Compiler::GetErrorString(result));
163 return false;
164 }
165
166 return true;
167}
168
169bool ABCCompilerDriver::link(const Script &pScript,
170 const std::string &input_relocatable,
171 int pOutputFd) {
172 // Config the linker.
173 if (!configLinker()) {
174 return false;
175 }
176
177 // Prepare output file.
178 Linker::ErrorCode result = mLinker.setOutput(pOutputFd);
179
180 if (result != Linker::kSuccess) {
181 ALOGE("Failed to open the output file! (file descriptor `%d': %s)",
182 pOutputFd, Linker::GetErrorString(result));
183 return false;
184 }
185
186 mLinker.addObject(mAndroidSysroot + "/system/lib/crtbegin_so.o");
187
188 // Prepare the relocatables.
189 //
190 // FIXME: Ugly const_cast here.
191 mLinker.addObject(const_cast<char *>(input_relocatable.data()),
192 input_relocatable.size());
193
194 // Read dependent library list.
195 const Source &source = pScript.getSource();
196 for (llvm::Module::lib_iterator lib_iter = source.getModule().lib_begin(),
197 lib_end = source.getModule().lib_end(); lib_iter != lib_end;
198 ++lib_iter) {
199 mLinker.addNameSpec(*lib_iter);
200 }
201
202 // TODO: Refactor libbcc/runtime/ to libcompilerRT.so and use it.
203 mLinker.addNameSpec("bcc");
204
205 mLinker.addObject(mAndroidSysroot + "/system/lib/crtend_so.o");
206
207 // Perform linking.
208 result = mLinker.link();
209 if (result != Linker::kSuccess) {
210 ALOGE("Failed to link the shared object (detail: %s)",
211 Linker::GetErrorString(result));
212 return false;
213 }
214
215 return true;
216}
217
218//------------------------------------------------------------------------------
219
Shih-wei Liao3928c622012-08-16 00:23:15 -0700220ABCCompilerDriver *ABCCompilerDriver::Create(const std::string &pTriple) {
221 std::string error;
222 const llvm::Target *target =
223 llvm::TargetRegistry::lookupTarget(pTriple, error);
224
225 if (target == NULL) {
226 ALOGE("Unsupported target '%s' (detail: %s)!", pTriple.c_str(),
227 error.c_str());
228 return NULL;
229 }
230
231 switch (llvm::Triple::getArchTypeForLLVMName(target->getName())) {
Shih-wei Liao56de4e82012-08-16 01:05:08 -0700232#if defined(PROVIDE_ARM_CODEGEN)
Shih-wei Liao3928c622012-08-16 00:23:15 -0700233 case llvm::Triple::arm:
234 case llvm::Triple::thumb: {
235 return new ARMABCCompilerDriver(pTriple);
236 }
Shih-wei Liao56de4e82012-08-16 01:05:08 -0700237#endif
238#if defined(PROVIDE_MIPS_CODEGEN)
Shih-wei Liao3928c622012-08-16 00:23:15 -0700239 case llvm::Triple::mipsel: {
240 return new MipsABCCompilerDriver(pTriple);
241 }
Shih-wei Liao56de4e82012-08-16 01:05:08 -0700242#endif
243#if defined(PROVIDE_X86_CODEGEN)
Shih-wei Liao3928c622012-08-16 00:23:15 -0700244 case llvm::Triple::x86: {
245 return new X86ABCCompilerDriver(pTriple);
246 }
Shih-wei Liao56de4e82012-08-16 01:05:08 -0700247#endif
Shih-wei Liao3928c622012-08-16 00:23:15 -0700248 default: {
249 ALOGE("Unknown architecture '%s' supplied in %s!", target->getName(),
250 pTriple.c_str());
251 break;
252 }
253 }
254
255 return NULL;
256}
257
Shih-wei Liao52aefd82012-07-27 03:12:56 -0700258bool ABCCompilerDriver::build(int pInputFd, int pOutputFd) {
259 //===--------------------------------------------------------------------===//
260 // Prepare the input.
261 //===--------------------------------------------------------------------===//
262 Script *script = prepareScript(pInputFd);
263 if (script == NULL) {
264 return false;
265 }
266
267 //===--------------------------------------------------------------------===//
268 // Prepare the output.
269 //===--------------------------------------------------------------------===//
270 std::string output_relocatable;
271 llvm::raw_ostream *output =
272 new (std::nothrow) llvm::raw_string_ostream(output_relocatable);
273 if (output == NULL) {
274 ALOGE("Failed to prepare the output for compile the input from %d into "
275 "relocatable object!", pInputFd);
276 delete script;
277 return false;
278 }
279
280 //===--------------------------------------------------------------------===//
281 // Compile.
282 //===--------------------------------------------------------------------===//
283 if (!compile(*script, *output)) {
284 delete output;
285 delete script;
286 return false;
287 }
288
289 //===--------------------------------------------------------------------===//
290 // Close the output.
291 //===--------------------------------------------------------------------===//
292 delete output;
293
294 //===--------------------------------------------------------------------===//
295 // Link.
296 //===--------------------------------------------------------------------===//
297 if (!link(*script, output_relocatable, pOutputFd)) {
298 delete script;
299 return false;
300 }
301
302 //===--------------------------------------------------------------------===//
303 // Clean up.
304 //===--------------------------------------------------------------------===//
305 delete script;
306
307 return true;
308}
309
310} // namespace bcc