blob: 7425d0a668379e4cfcbc5aca12bd356ebe694133 [file] [log] [blame]
Stephen Hines7dfc4d82012-05-03 12:25:21 -07001/*
2 * Copyright 2010-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// Bitcode compiler (bcc) for Android:
18// This is an eager-compilation JIT running on Android.
19
Stephen Hines2f6a4932012-05-03 12:27:13 -070020#include <bcc/bcc.h>
Stephen Hines7dfc4d82012-05-03 12:25:21 -070021
Stephen Hines4a68b1c2012-05-03 12:28:14 -070022#include <string>
Stephen Hines7dfc4d82012-05-03 12:25:21 -070023
24#include <utils/StopWatch.h>
25
Stephen Hines4a68b1c2012-05-03 12:28:14 -070026#include "Config.h"
27
28#include <bcc/bcc_mccache.h>
29#include "bcc_internal.h"
30
31#include "BCCContext.h"
32#include "Compiler.h"
Stephen Hines2f6a4932012-05-03 12:27:13 -070033#include "DebugHelper.h"
Stephen Hines2f6a4932012-05-03 12:27:13 -070034#include "RSScript.h"
35#include "Sha1Helper.h"
36#include "Source.h"
Stephen Hines7dfc4d82012-05-03 12:25:21 -070037
Stephen Hines7dfc4d82012-05-03 12:25:21 -070038using namespace bcc;
39
40namespace llvm {
41 class Module;
42}
43
44static bool bccBuildStampPrinted = false;
45
46static void bccPrintBuildStamp() {
47 if (!bccBuildStampPrinted) {
48 ALOGI("LIBBCC build time: %s", bccGetBuildTime());
49 ALOGI("LIBBCC build revision: %s", bccGetBuildRev());
50 bccBuildStampPrinted = true;
51 }
52}
53
54extern "C" BCCScriptRef bccCreateScript() {
Stephen Hines5b948192012-05-03 12:26:56 -070055 BCC_FUNC_LOGGER();
Stephen Hines7dfc4d82012-05-03 12:25:21 -070056 bccPrintBuildStamp();
Stephen Hines4a68b1c2012-05-03 12:28:14 -070057 // FIXME: This is a workaround for this API: use global BCC context and
58 // create an empty source to create a Script object.
59 BCCContext *context = BCCContext::GetOrCreateGlobalContext();
60 if (context == NULL) {
61 return NULL;
Stephen Hines7dfc4d82012-05-03 12:25:21 -070062 }
Stephen Hines4a68b1c2012-05-03 12:28:14 -070063
64 Source *source = Source::CreateEmpty(*context, "empty");
65 return wrap(new RSScript(*source));
Stephen Hines7dfc4d82012-05-03 12:25:21 -070066}
67
68
69extern "C" void bccDisposeScript(BCCScriptRef script) {
Stephen Hines5b948192012-05-03 12:26:56 -070070 BCC_FUNC_LOGGER();
Stephen Hines4a68b1c2012-05-03 12:28:14 -070071 delete unwrap(script);
Stephen Hines7dfc4d82012-05-03 12:25:21 -070072}
73
74
75extern "C" int bccRegisterSymbolCallback(BCCScriptRef script,
76 BCCSymbolLookupFn pFn,
77 void *pContext) {
Stephen Hines5b948192012-05-03 12:26:56 -070078 BCC_FUNC_LOGGER();
Stephen Hines4a68b1c2012-05-03 12:28:14 -070079 return unwrap(script)->registerSymbolCallback(pFn, pContext);
Stephen Hines7dfc4d82012-05-03 12:25:21 -070080}
81
82
83extern "C" int bccGetError(BCCScriptRef script) {
Stephen Hines5b948192012-05-03 12:26:56 -070084 BCC_FUNC_LOGGER();
Stephen Hines4a68b1c2012-05-03 12:28:14 -070085 return unwrap(script)->getError();
Stephen Hines7dfc4d82012-05-03 12:25:21 -070086}
87
Stephen Hines4a68b1c2012-05-03 12:28:14 -070088static bool helper_add_source(RSScript *pScript,
Stephen Hines7dfc4d82012-05-03 12:25:21 -070089 char const *pName,
90 char const *pBitcode,
91 size_t pBitcodeSize,
92 unsigned long pFlags,
93 bool pIsLink) {
94 bool need_dependency_check = !(pFlags & BCC_SKIP_DEP_SHA1);
95 if (!pName && need_dependency_check) {
96 pFlags |= BCC_SKIP_DEP_SHA1;
97
98 ALOGW("It is required to give resName for sha1 dependency check.\n");
99 ALOGW("Sha1sum dependency check will be skipped.\n");
100 ALOGW("Set BCC_SKIP_DEP_SHA1 for flags to surpress this warning.\n");
101 }
102
Stephen Hines4a68b1c2012-05-03 12:28:14 -0700103 BCCContext *context = BCCContext::GetOrCreateGlobalContext();
104 if (context == NULL) {
105 return false;
106 }
107
108 Source *source = Source::CreateFromBuffer(*context, pName,
Stephen Hines7dfc4d82012-05-03 12:25:21 -0700109 pBitcode, pBitcodeSize);
110 if (source == NULL) {
111 return false;
112 }
113
Stephen Hines7dfc4d82012-05-03 12:25:21 -0700114 if (need_dependency_check) {
Stephen Hines6975a662012-05-03 12:26:44 -0700115 uint8_t sha1[20];
116 calcSHA1(sha1, pBitcode, pBitcodeSize);
Stephen Hines0f6b1d32012-05-03 12:29:33 -0700117 if (!pScript->addSourceDependency(BCC_APK_RESOURCE, pName, sha1)) {
Stephen Hines7dfc4d82012-05-03 12:25:21 -0700118 return false;
119 }
120 }
121
Stephen Hines4a68b1c2012-05-03 12:28:14 -0700122 return ((pIsLink) ? pScript->mergeSource(*source) : pScript->reset(*source));
Stephen Hines7dfc4d82012-05-03 12:25:21 -0700123}
124
Stephen Hines4a68b1c2012-05-03 12:28:14 -0700125static bool helper_add_source(RSScript *pScript,
Stephen Hines7dfc4d82012-05-03 12:25:21 -0700126 llvm::Module *pModule,
127 bool pIsLink) {
Stephen Hines4a68b1c2012-05-03 12:28:14 -0700128 if (pModule == NULL)
129 return false;
130
131 BCCContext *context = BCCContext::GetOrCreateGlobalContext();
132 if (context == NULL) {
133 return false;
134 }
135
Stephen Hines7dfc4d82012-05-03 12:25:21 -0700136 if (pModule == NULL) {
137 ALOGE("Cannot add null module to script!");
138 return false;
139 }
140
Stephen Hines4a68b1c2012-05-03 12:28:14 -0700141 Source *source = Source::CreateFromModule(*context, *pModule, true);
Stephen Hines7dfc4d82012-05-03 12:25:21 -0700142 if (source == NULL) {
143 return false;
144 }
145
Stephen Hines4a68b1c2012-05-03 12:28:14 -0700146 return ((pIsLink) ? pScript->mergeSource(*source) : pScript->reset(*source));
Stephen Hines7dfc4d82012-05-03 12:25:21 -0700147}
148
Stephen Hines4a68b1c2012-05-03 12:28:14 -0700149static bool helper_add_source(RSScript *pScript,
Stephen Hines7dfc4d82012-05-03 12:25:21 -0700150 char const *pPath,
151 unsigned long pFlags,
152 bool pIsLink) {
153 bool need_dependency_check = !(pFlags & BCC_SKIP_DEP_SHA1);
Stephen Hines4a68b1c2012-05-03 12:28:14 -0700154 BCCContext *context = BCCContext::GetOrCreateGlobalContext();
155 if (context == NULL) {
Stephen Hines7dfc4d82012-05-03 12:25:21 -0700156 return false;
157 }
158
Stephen Hines4a68b1c2012-05-03 12:28:14 -0700159 Source *source = Source::CreateFromFile(*context, pPath);
160 if (source == NULL) {
161 return false;
Stephen Hines7dfc4d82012-05-03 12:25:21 -0700162 }
163
164 if (need_dependency_check) {
Stephen Hines6975a662012-05-03 12:26:44 -0700165 uint8_t sha1[20];
166 calcFileSHA1(sha1, pPath);
Stephen Hines0f6b1d32012-05-03 12:29:33 -0700167 if (!pScript->addSourceDependency(BCC_APK_RESOURCE, pPath, sha1)) {
Stephen Hines7dfc4d82012-05-03 12:25:21 -0700168 return false;
169 }
170 }
171
Stephen Hines4a68b1c2012-05-03 12:28:14 -0700172 return ((pIsLink) ? pScript->mergeSource(*source) : pScript->reset(*source));
Stephen Hines7dfc4d82012-05-03 12:25:21 -0700173}
174
175extern "C" int bccReadBC(BCCScriptRef script,
176 char const *resName,
177 char const *bitcode,
178 size_t bitcodeSize,
179 unsigned long flags) {
Stephen Hines5b948192012-05-03 12:26:56 -0700180 BCC_FUNC_LOGGER();
Stephen Hines7dfc4d82012-05-03 12:25:21 -0700181 return (helper_add_source(unwrap(script), resName,
182 bitcode, bitcodeSize,
183 flags, /* pIsLink */false) == false);
184}
185
186
187extern "C" int bccReadModule(BCCScriptRef script,
188 char const *resName /* deprecated */,
189 LLVMModuleRef module,
190 unsigned long flags) {
Stephen Hines5b948192012-05-03 12:26:56 -0700191 BCC_FUNC_LOGGER();
Stephen Hines7dfc4d82012-05-03 12:25:21 -0700192 return (helper_add_source(unwrap(script), unwrap(module),
193 /* pIsLink */false) == false);
194}
195
196
197extern "C" int bccReadFile(BCCScriptRef script,
198 char const *path,
199 unsigned long flags) {
Stephen Hines5b948192012-05-03 12:26:56 -0700200 BCC_FUNC_LOGGER();
Stephen Hines7dfc4d82012-05-03 12:25:21 -0700201 return (helper_add_source(unwrap(script), path,
202 flags, /* pIsLink */false) == false);
203}
204
205
206extern "C" int bccLinkBC(BCCScriptRef script,
207 char const *resName,
208 char const *bitcode,
209 size_t bitcodeSize,
210 unsigned long flags) {
Stephen Hines5b948192012-05-03 12:26:56 -0700211 BCC_FUNC_LOGGER();
Stephen Hines7dfc4d82012-05-03 12:25:21 -0700212 return (helper_add_source(unwrap(script), resName,
213 bitcode, bitcodeSize,
214 flags, /* pIsLink */true) == false);
215}
216
217
218extern "C" int bccLinkFile(BCCScriptRef script,
219 char const *path,
220 unsigned long flags) {
Stephen Hines5b948192012-05-03 12:26:56 -0700221 BCC_FUNC_LOGGER();
Stephen Hinesc4fba312012-05-03 12:25:37 -0700222 return (helper_add_source(unwrap(script), path,
223 flags, /* pIsLink */true) == false);
Stephen Hines7dfc4d82012-05-03 12:25:21 -0700224}
225
226
227extern "C" void bccMarkExternalSymbol(BCCScriptRef script, char const *name) {
Stephen Hines5b948192012-05-03 12:26:56 -0700228 BCC_FUNC_LOGGER();
Stephen Hines4a68b1c2012-05-03 12:28:14 -0700229 unwrap(script)->markExternalSymbol(name);
Stephen Hines7dfc4d82012-05-03 12:25:21 -0700230}
231
232
233extern "C" int bccPrepareRelocatable(BCCScriptRef script,
234 char const *objPath,
235 bccRelocModelEnum RelocModel,
236 unsigned long flags) {
Stephen Hines5b948192012-05-03 12:26:56 -0700237 BCC_FUNC_LOGGER();
Stephen Hines4a68b1c2012-05-03 12:28:14 -0700238 llvm::Reloc::Model RM;
239
240 switch (RelocModel) {
241 case bccRelocDefault: {
242 RM = llvm::Reloc::Default;
243 break;
244 }
245 case bccRelocStatic: {
246 RM = llvm::Reloc::Static;
247 break;
248 }
249 case bccRelocPIC: {
250 RM = llvm::Reloc::PIC_;
251 break;
252 }
253 case bccRelocDynamicNoPIC: {
254 RM = llvm::Reloc::DynamicNoPIC;
255 break;
256 }
257 default: {
258 ALOGE("Unrecognized relocation model for bccPrepareObject!");
259 return BCC_INVALID_VALUE;
260 }
261 }
262
263 return unwrap(script)->prepareRelocatable(objPath, RM, flags);
Stephen Hines7dfc4d82012-05-03 12:25:21 -0700264}
265
266
267extern "C" int bccPrepareSharedObject(BCCScriptRef script,
268 char const *objPath,
269 char const *dsoPath,
270 unsigned long flags) {
Stephen Hines5b948192012-05-03 12:26:56 -0700271 BCC_FUNC_LOGGER();
Stephen Hines4a68b1c2012-05-03 12:28:14 -0700272 return unwrap(script)->prepareSharedObject(objPath, dsoPath, flags);
Stephen Hines7dfc4d82012-05-03 12:25:21 -0700273}
274
275
276extern "C" int bccPrepareExecutable(BCCScriptRef script,
277 char const *cacheDir,
278 char const *cacheName,
279 unsigned long flags) {
Stephen Hines5b948192012-05-03 12:26:56 -0700280 BCC_FUNC_LOGGER();
281
Stephen Hines7dfc4d82012-05-03 12:25:21 -0700282 android::StopWatch compileTimer("bcc: PrepareExecutable time");
283
Stephen Hines4a68b1c2012-05-03 12:28:14 -0700284 return unwrap(script)->prepareExecutable(cacheDir, cacheName, flags);
Stephen Hines7dfc4d82012-05-03 12:25:21 -0700285}
286
287
288extern "C" void *bccGetFuncAddr(BCCScriptRef script, char const *funcname) {
Stephen Hines5b948192012-05-03 12:26:56 -0700289 BCC_FUNC_LOGGER();
Stephen Hines7dfc4d82012-05-03 12:25:21 -0700290
Stephen Hines4a68b1c2012-05-03 12:28:14 -0700291 void *addr = unwrap(script)->lookup(funcname);
Stephen Hines7dfc4d82012-05-03 12:25:21 -0700292
293#if DEBUG_BCC_REFLECT
294 ALOGD("Function Address: %s --> %p\n", funcname, addr);
295#endif
296
297 return addr;
298}
299
300
301extern "C" void bccGetExportVarList(BCCScriptRef script,
302 size_t varListSize,
303 void **varList) {
Stephen Hines5b948192012-05-03 12:26:56 -0700304 BCC_FUNC_LOGGER();
305
Stephen Hines4a68b1c2012-05-03 12:28:14 -0700306 if (varList) {
307 unwrap(script)->getExportVarList(varListSize, varList);
308
309#if DEBUG_BCC_REFLECT
310 size_t count = unwrap(script)->getExportVarCount();
311 ALOGD("ExportVarCount = %lu\n", (unsigned long)count);
Stephen Hines7dfc4d82012-05-03 12:25:21 -0700312
313 if (count > varListSize) {
314 count = varListSize;
315 }
316
317 for (size_t i = 0; i < count; ++i) {
Stephen Hines4a68b1c2012-05-03 12:28:14 -0700318 ALOGD("ExportVarList[%lu] = %p\n", (unsigned long)i, varList[i]);
Stephen Hines7dfc4d82012-05-03 12:25:21 -0700319 }
320#endif
321 }
322}
323
324
325extern "C" void bccGetExportFuncList(BCCScriptRef script,
326 size_t funcListSize,
327 void **funcList) {
Stephen Hines5b948192012-05-03 12:26:56 -0700328 BCC_FUNC_LOGGER();
329
Stephen Hines4a68b1c2012-05-03 12:28:14 -0700330 if (funcList) {
331 unwrap(script)->getExportFuncList(funcListSize, funcList);
332
333#if DEBUG_BCC_REFLECT
334 size_t count = unwrap(script)->getExportFuncCount();
335 ALOGD("ExportFuncCount = %lu\n", (unsigned long)count);
Stephen Hines7dfc4d82012-05-03 12:25:21 -0700336
337 if (count > funcListSize) {
338 count = funcListSize;
339 }
340
341 for (size_t i = 0; i < count; ++i) {
Stephen Hines4a68b1c2012-05-03 12:28:14 -0700342 ALOGD("ExportFuncList[%lu] = %p\n", (unsigned long)i, funcList[i]);
Stephen Hines7dfc4d82012-05-03 12:25:21 -0700343 }
344#endif
345 }
346}
347
348
349extern "C" void bccGetExportForEachList(BCCScriptRef script,
350 size_t forEachListSize,
351 void **forEachList) {
Stephen Hines5b948192012-05-03 12:26:56 -0700352 BCC_FUNC_LOGGER();
353
Stephen Hines4a68b1c2012-05-03 12:28:14 -0700354 if (forEachList) {
355 unwrap(script)->getExportForEachList(forEachListSize, forEachList);
356
357#if DEBUG_BCC_REFLECT
358 size_t count = unwrap(script)->getExportForEachCount();
359 ALOGD("ExportForEachCount = %lu\n", (unsigned long)count);
Stephen Hines7dfc4d82012-05-03 12:25:21 -0700360
361 if (count > forEachListSize) {
362 count = forEachListSize;
363 }
364
365 for (size_t i = 0; i < count; ++i) {
Stephen Hines4a68b1c2012-05-03 12:28:14 -0700366 ALOGD("ExportForEachList[%lu] = %p\n", (unsigned long)i, forEachList[i]);
Stephen Hines7dfc4d82012-05-03 12:25:21 -0700367 }
368#endif
369 }
370}