blob: b830ec26242cc4087c62e4771451f84465d4f246 [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
22#include <llvm/Support/CodeGen.h>
23
24#include <utils/StopWatch.h>
25
Stephen Hines2f6a4932012-05-03 12:27:13 -070026#include "DebugHelper.h"
27#include "Initialization.h"
28#include "RSExecutable.h"
29#include "RSScript.h"
30#include "Sha1Helper.h"
31#include "Source.h"
Stephen Hines7dfc4d82012-05-03 12:25:21 -070032
33#include "bcc_internal.h"
Stephen Hines2f6a4932012-05-03 12:27:13 -070034#include <bcinfo/BitcodeWrapper.h>
Stephen Hines7dfc4d82012-05-03 12:25:21 -070035
36using namespace bcc;
37
38namespace llvm {
39 class Module;
40}
41
42static bool bccBuildStampPrinted = false;
43
44static void bccPrintBuildStamp() {
45 if (!bccBuildStampPrinted) {
46 ALOGI("LIBBCC build time: %s", bccGetBuildTime());
47 ALOGI("LIBBCC build revision: %s", bccGetBuildRev());
48 bccBuildStampPrinted = true;
49 }
50}
51
52extern "C" BCCScriptRef bccCreateScript() {
Stephen Hines5b948192012-05-03 12:26:56 -070053 BCC_FUNC_LOGGER();
Stephen Hines7dfc4d82012-05-03 12:25:21 -070054 bccPrintBuildStamp();
55 init::Initialize();
56 RSScriptContext *rsctx = new (std::nothrow) RSScriptContext();
57 if (rsctx != NULL) {
58 rsctx->script = NULL;
59 rsctx->result = NULL;
60 }
61 return wrap(rsctx);
62}
63
64
65extern "C" void bccDisposeScript(BCCScriptRef script) {
Stephen Hines5b948192012-05-03 12:26:56 -070066 BCC_FUNC_LOGGER();
Stephen Hines7dfc4d82012-05-03 12:25:21 -070067 RSScriptContext *rsctx = unwrap(script);
68 if (rsctx != NULL) {
69 delete rsctx->script;
70 delete rsctx->result;
71 }
72 delete rsctx;
73}
74
75
76extern "C" int bccRegisterSymbolCallback(BCCScriptRef script,
77 BCCSymbolLookupFn pFn,
78 void *pContext) {
Stephen Hines5b948192012-05-03 12:26:56 -070079 BCC_FUNC_LOGGER();
Stephen Hines7dfc4d82012-05-03 12:25:21 -070080 unwrap(script)->driver.setRSRuntimeLookupFunction(pFn);
81 unwrap(script)->driver.setRSRuntimeLookupContext(pContext);
82 return BCC_NO_ERROR;
83}
84
85
86extern "C" int bccGetError(BCCScriptRef script) {
Stephen Hines5b948192012-05-03 12:26:56 -070087 BCC_FUNC_LOGGER();
Stephen Hines7dfc4d82012-05-03 12:25:21 -070088 return BCC_DEPRECATED_API;
89}
90
91static bool helper_add_source(RSScriptContext *pCtx,
92 char const *pName,
93 char const *pBitcode,
94 size_t pBitcodeSize,
95 unsigned long pFlags,
96 bool pIsLink) {
97 bool need_dependency_check = !(pFlags & BCC_SKIP_DEP_SHA1);
98 if (!pName && need_dependency_check) {
99 pFlags |= BCC_SKIP_DEP_SHA1;
100
101 ALOGW("It is required to give resName for sha1 dependency check.\n");
102 ALOGW("Sha1sum dependency check will be skipped.\n");
103 ALOGW("Set BCC_SKIP_DEP_SHA1 for flags to surpress this warning.\n");
104 }
105
106 Source *source = Source::CreateFromBuffer(pCtx->context, pName,
107 pBitcode, pBitcodeSize);
108 if (source == NULL) {
109 return false;
110 }
111
112 if (pCtx->script == NULL) {
113 pCtx->script = new (std::nothrow) RSScript(*source);
114 if (pCtx->script == NULL) {
115 ALOGE("Out of memory during script creation.");
116 return false;
117 }
118 } else {
119 bool result;
120 if (pIsLink) {
121 result = pCtx->script->mergeSource(*source);
122 } else {
123 result = pCtx->script->reset(*source);
124 }
125 if (!result) {
126 return false;
127 } else {
128 bcinfo::BitcodeWrapper wrapper(pBitcode, pBitcodeSize);
129 pCtx->script->setCompilerVersion(wrapper.getCompilerVersion());
130 pCtx->script->setOptimizationLevel(
131 static_cast<RSScript::OptimizationLevel>(
132 wrapper.getOptimizationLevel()));
133 }
134 }
135
136 if (need_dependency_check) {
Stephen Hines6975a662012-05-03 12:26:44 -0700137 uint8_t sha1[20];
138 calcSHA1(sha1, pBitcode, pBitcodeSize);
139 if (!pCtx->script->addSourceDependency(pName, sha1)) {
Stephen Hines7dfc4d82012-05-03 12:25:21 -0700140 return false;
141 }
142 }
143
144 return true;
145}
146
147static bool helper_add_source(RSScriptContext *pCtx,
148 llvm::Module *pModule,
149 bool pIsLink) {
150 if (pModule == NULL) {
151 ALOGE("Cannot add null module to script!");
152 return false;
153 }
154
155 Source *source = Source::CreateFromModule(pCtx->context, *pModule, true);
156 if (source == NULL) {
157 return false;
158 }
159
160 if (pCtx->script == NULL) {
161 pCtx->script = new (std::nothrow) RSScript(*source);
162 if (pCtx->script == NULL) {
163 ALOGE("Out of memory during script creation.");
164 return false;
165 }
166 } else {
167 bool result;
168 if (pIsLink) {
169 result = pCtx->script->mergeSource(*source);
170 } else {
171 result = pCtx->script->reset(*source);
172 }
173 if (!result) {
174 return false;
175 }
176 }
177
178 return true;
179}
180
181static bool helper_add_source(RSScriptContext *pCtx,
182 char const *pPath,
183 unsigned long pFlags,
184 bool pIsLink) {
185 bool need_dependency_check = !(pFlags & BCC_SKIP_DEP_SHA1);
186
187 Source *source = Source::CreateFromFile(pCtx->context, pPath);
188 if (source == NULL) {
189 return false;
190 }
191
192 if (pCtx->script == NULL) {
193 pCtx->script = new (std::nothrow) RSScript(*source);
194 if (pCtx->script == NULL) {
195 ALOGE("Out of memory during script creation.");
196 return false;
197 }
198 } else {
199 bool result;
200 if (pIsLink) {
201 result = pCtx->script->mergeSource(*source);
202 } else {
203 result = pCtx->script->reset(*source);
204 }
205 if (!result) {
206 return false;
207 }
208 }
209
210 if (need_dependency_check) {
Stephen Hines6975a662012-05-03 12:26:44 -0700211 uint8_t sha1[20];
212 calcFileSHA1(sha1, pPath);
213 if (!pCtx->script->addSourceDependency(pPath, sha1)) {
Stephen Hines7dfc4d82012-05-03 12:25:21 -0700214 return false;
215 }
216 }
217
218 return true;
219}
220
221extern "C" int bccReadBC(BCCScriptRef script,
222 char const *resName,
223 char const *bitcode,
224 size_t bitcodeSize,
225 unsigned long flags) {
Stephen Hines5b948192012-05-03 12:26:56 -0700226 BCC_FUNC_LOGGER();
Stephen Hines7dfc4d82012-05-03 12:25:21 -0700227 return (helper_add_source(unwrap(script), resName,
228 bitcode, bitcodeSize,
229 flags, /* pIsLink */false) == false);
230}
231
232
233extern "C" int bccReadModule(BCCScriptRef script,
234 char const *resName /* deprecated */,
235 LLVMModuleRef module,
236 unsigned long flags) {
Stephen Hines5b948192012-05-03 12:26:56 -0700237 BCC_FUNC_LOGGER();
Stephen Hines7dfc4d82012-05-03 12:25:21 -0700238 return (helper_add_source(unwrap(script), unwrap(module),
239 /* pIsLink */false) == false);
240}
241
242
243extern "C" int bccReadFile(BCCScriptRef script,
244 char const *path,
245 unsigned long flags) {
Stephen Hines5b948192012-05-03 12:26:56 -0700246 BCC_FUNC_LOGGER();
Stephen Hines7dfc4d82012-05-03 12:25:21 -0700247 return (helper_add_source(unwrap(script), path,
248 flags, /* pIsLink */false) == false);
249}
250
251
252extern "C" int bccLinkBC(BCCScriptRef script,
253 char const *resName,
254 char const *bitcode,
255 size_t bitcodeSize,
256 unsigned long flags) {
Stephen Hines5b948192012-05-03 12:26:56 -0700257 BCC_FUNC_LOGGER();
Stephen Hines7dfc4d82012-05-03 12:25:21 -0700258 return (helper_add_source(unwrap(script), resName,
259 bitcode, bitcodeSize,
260 flags, /* pIsLink */true) == false);
261}
262
263
264extern "C" int bccLinkFile(BCCScriptRef script,
265 char const *path,
266 unsigned long flags) {
Stephen Hines5b948192012-05-03 12:26:56 -0700267 BCC_FUNC_LOGGER();
Stephen Hinesc4fba312012-05-03 12:25:37 -0700268 return (helper_add_source(unwrap(script), path,
269 flags, /* pIsLink */true) == false);
Stephen Hines7dfc4d82012-05-03 12:25:21 -0700270}
271
272
273extern "C" void bccMarkExternalSymbol(BCCScriptRef script, char const *name) {
Stephen Hines5b948192012-05-03 12:26:56 -0700274 BCC_FUNC_LOGGER();
Stephen Hines7dfc4d82012-05-03 12:25:21 -0700275 return /* BCC_DEPRECATED_API */;
276}
277
278
279extern "C" int bccPrepareRelocatable(BCCScriptRef script,
280 char const *objPath,
281 bccRelocModelEnum RelocModel,
282 unsigned long flags) {
Stephen Hines5b948192012-05-03 12:26:56 -0700283 BCC_FUNC_LOGGER();
Stephen Hines7dfc4d82012-05-03 12:25:21 -0700284 return BCC_DEPRECATED_API;
285}
286
287
288extern "C" int bccPrepareSharedObject(BCCScriptRef script,
289 char const *objPath,
290 char const *dsoPath,
291 unsigned long flags) {
Stephen Hines5b948192012-05-03 12:26:56 -0700292 BCC_FUNC_LOGGER();
Stephen Hines7dfc4d82012-05-03 12:25:21 -0700293 return BCC_DEPRECATED_API;
294}
295
296
297extern "C" int bccPrepareExecutable(BCCScriptRef script,
298 char const *cacheDir,
299 char const *cacheName,
300 unsigned long flags) {
Stephen Hines5b948192012-05-03 12:26:56 -0700301 BCC_FUNC_LOGGER();
302
Stephen Hines7dfc4d82012-05-03 12:25:21 -0700303 android::StopWatch compileTimer("bcc: PrepareExecutable time");
304
305 RSScriptContext *rsctx = unwrap(script);
306
307 if (rsctx->script == NULL) {
308 return 1;
309 }
310
311 // Construct the output path.
312 std::string output_path(cacheDir);
313 if (!output_path.empty() && (*output_path.rbegin() != '/')) {
314 output_path.append(1, '/');
315 }
316 output_path.append(cacheName);
317 output_path.append(".o");
318
319 // Make sure the result container is clean.
320 if (rsctx->result != NULL) {
321 delete rsctx->result;
322 rsctx->result = NULL;
323 }
324
325 rsctx->result = rsctx->driver.build(*rsctx->script, output_path);
326
327 return (rsctx->result == NULL);
328}
329
330
331extern "C" void *bccGetFuncAddr(BCCScriptRef script, char const *funcname) {
Stephen Hines5b948192012-05-03 12:26:56 -0700332 BCC_FUNC_LOGGER();
Stephen Hines7dfc4d82012-05-03 12:25:21 -0700333
334 RSScriptContext *rsctx = unwrap(script);
335
336 void *addr = NULL;
337 if (rsctx->result != NULL) {
338 addr = rsctx->result->getSymbolAddress(funcname);
339 }
340
341#if DEBUG_BCC_REFLECT
342 ALOGD("Function Address: %s --> %p\n", funcname, addr);
343#endif
344
345 return addr;
346}
347
348
349extern "C" void bccGetExportVarList(BCCScriptRef script,
350 size_t varListSize,
351 void **varList) {
Stephen Hines5b948192012-05-03 12:26:56 -0700352 BCC_FUNC_LOGGER();
353
Stephen Hines7dfc4d82012-05-03 12:25:21 -0700354 const RSScriptContext *rsctx = unwrap(script);
355 if (varList && rsctx->result) {
356 const android::Vector<void *> &export_var_addrs =
357 rsctx->result->getExportVarAddrs();
358 size_t count = export_var_addrs.size();
359
360 if (count > varListSize) {
361 count = varListSize;
362 }
363
364 for (size_t i = 0; i < count; ++i) {
365 varList[i] = export_var_addrs[i];
366 }
367
368#if DEBUG_BCC_REFLECT
369 ALOGD("ExportVarCount = %lu\n",
370 static_cast<unsigned long>(export_var_addrs.size()));
371
372 for (size_t i = 0; i < count; ++i) {
373 ALOGD("ExportVarList[%lu] = %p\n", static_cast<unsigned long>(i),
374 varList[i]);
375 }
376#endif
377 }
378}
379
380
381extern "C" void bccGetExportFuncList(BCCScriptRef script,
382 size_t funcListSize,
383 void **funcList) {
Stephen Hines5b948192012-05-03 12:26:56 -0700384 BCC_FUNC_LOGGER();
385
Stephen Hines7dfc4d82012-05-03 12:25:21 -0700386 const RSScriptContext *rsctx = unwrap(script);
387 if (funcList && rsctx->result) {
388 const android::Vector<void *> &export_func_addrs =
389 rsctx->result->getExportFuncAddrs();
390 size_t count = export_func_addrs.size();
391
392 if (count > funcListSize) {
393 count = funcListSize;
394 }
395
396 for (size_t i = 0; i < count; ++i) {
397 funcList[i] = export_func_addrs[i];
398 }
399
400#if DEBUG_BCC_REFLECT
401 ALOGD("ExportFuncCount = %lu\n",
402 static_cast<unsigned long>(export_var_addrs.size()));
403
404 for (size_t i = 0; i < count; ++i) {
405 ALOGD("ExportFuncList[%lu] = %p\n", static_cast<unsigned long>(i),
406 varList[i]);
407 }
408#endif
409 }
410}
411
412
413extern "C" void bccGetExportForEachList(BCCScriptRef script,
414 size_t forEachListSize,
415 void **forEachList) {
Stephen Hines5b948192012-05-03 12:26:56 -0700416 BCC_FUNC_LOGGER();
417
Stephen Hines7dfc4d82012-05-03 12:25:21 -0700418 const RSScriptContext *rsctx = unwrap(script);
419 if (forEachList && rsctx->result) {
420 const android::Vector<void *> &export_foreach_func_addrs =
421 rsctx->result->getExportForeachFuncAddrs();
422 size_t count = export_foreach_func_addrs.size();
423
424 if (count > forEachListSize) {
425 count = forEachListSize;
426 }
427
428 for (size_t i = 0; i < count; ++i) {
429 forEachList[i] = export_foreach_func_addrs[i];
430 }
431
432#if DEBUG_BCC_REFLECT
433 ALOGD("ExportForEachCount = %lu\n",
434 static_cast<unsigned long>(export_foreach_func_addrs.size()));
435
436 for (size_t i = 0; i < count; ++i) {
437 ALOGD("ExportForEachList[%lu] = %p\n", static_cast<unsigned long>(i),
438 forEachList[i]);
439 }
440#endif
441 }
442}