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