main.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. /*
  2. * Copyright 2011-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. #include <bcinfo/BitcodeTranslator.h>
  17. #include <bcinfo/BitcodeWrapper.h>
  18. #include <bcinfo/MetadataExtractor.h>
  19. #include <llvm/ADT/StringRef.h>
  20. #include <llvm/Bitcode/ReaderWriter.h>
  21. #include <llvm/IR/AssemblyAnnotationWriter.h>
  22. #include <llvm/IR/LLVMContext.h>
  23. #include <llvm/IR/Module.h>
  24. #include <llvm/Support/FileSystem.h>
  25. #include <llvm/Support/ManagedStatic.h>
  26. #include <llvm/Support/MemoryBuffer.h>
  27. #include <llvm/Support/ToolOutputFile.h>
  28. #include <ctype.h>
  29. #include <dlfcn.h>
  30. #include <stdarg.h>
  31. #include <stdint.h>
  32. #include <stdio.h>
  33. #include <stdlib.h>
  34. #include <string.h>
  35. #include <getopt.h>
  36. #include <errno.h>
  37. #include <sys/stat.h>
  38. #include <sys/types.h>
  39. #include <unistd.h>
  40. #include <string>
  41. #include <vector>
  42. // This file corresponds to the standalone bcinfo tool. It prints a variety of
  43. // information about a supplied bitcode input file.
  44. std::string inFile;
  45. std::string outFile;
  46. std::string infoFile;
  47. extern int opterr;
  48. extern int optind;
  49. bool translateFlag = false;
  50. bool infoFlag = false;
  51. bool verbose = true;
  52. static int parseOption(int argc, char** argv) {
  53. int c;
  54. while ((c = getopt(argc, argv, "itv")) != -1) {
  55. opterr = 0;
  56. switch(c) {
  57. case '?':
  58. // ignore any error
  59. break;
  60. case 't':
  61. translateFlag = true;
  62. break;
  63. case 'i':
  64. // Turn off verbose so that we only generate the .info file.
  65. infoFlag = true;
  66. verbose = false;
  67. break;
  68. case 'v':
  69. verbose = true;
  70. break;
  71. default:
  72. // Critical error occurs
  73. return 0;
  74. break;
  75. }
  76. }
  77. if(optind >= argc) {
  78. fprintf(stderr, "input file required\n");
  79. return 0;
  80. }
  81. inFile = argv[optind];
  82. int l = inFile.length();
  83. if (l > 3 && inFile[l-3] == '.' && inFile[l-2] == 'b' && inFile[l-1] == 'c') {
  84. outFile = std::string(inFile.begin(), inFile.end() - 3) + ".ll";
  85. infoFile = std::string(inFile.begin(), inFile.end() - 3) + ".bcinfo";
  86. } else {
  87. outFile = inFile + ".ll";
  88. infoFile = inFile + ".bcinfo";
  89. }
  90. return 1;
  91. }
  92. static void dumpReduceInfo(FILE *info, const char *Kind, const char *Name) {
  93. if (Name)
  94. fprintf(info, " %s(%s)\n", Kind, Name);
  95. }
  96. static int dumpInfo(bcinfo::MetadataExtractor *ME) {
  97. if (!ME) {
  98. return 1;
  99. }
  100. FILE *info = fopen(infoFile.c_str(), "w");
  101. if (!info) {
  102. fprintf(stderr, "Could not open info file %s\n", infoFile.c_str());
  103. return 2;
  104. }
  105. fprintf(info, "exportVarCount: %zu\n", ME->getExportVarCount());
  106. const char **varNameList = ME->getExportVarNameList();
  107. for (size_t i = 0; i < ME->getExportVarCount(); i++) {
  108. fprintf(info, "%s\n", varNameList[i]);
  109. }
  110. fprintf(info, "exportFuncCount: %zu\n", ME->getExportFuncCount());
  111. const char **funcNameList = ME->getExportFuncNameList();
  112. for (size_t i = 0; i < ME->getExportFuncCount(); i++) {
  113. fprintf(info, "%s\n", funcNameList[i]);
  114. }
  115. fprintf(info, "exportForEachCount: %zu\n",
  116. ME->getExportForEachSignatureCount());
  117. const char **nameList = ME->getExportForEachNameList();
  118. const uint32_t *sigList = ME->getExportForEachSignatureList();
  119. const uint32_t *inputCountList = ME->getExportForEachInputCountList();
  120. for (size_t i = 0; i < ME->getExportForEachSignatureCount(); i++) {
  121. fprintf(info, "%u - %s - %u\n", sigList[i], nameList[i],
  122. inputCountList[i]);
  123. }
  124. fprintf(info, "exportReduceCount: %zu\n", ME->getExportReduceCount());
  125. const bcinfo::MetadataExtractor::Reduce *reduceList =
  126. ME->getExportReduceList();
  127. for (size_t i = 0; i < ME->getExportReduceCount(); i++) {
  128. const bcinfo::MetadataExtractor::Reduce &reduce = reduceList[i];
  129. fprintf(info, "%u - %s - %u - %u\n", reduce.mSignature, reduce.mReduceName,
  130. reduce.mInputCount, reduce.mAccumulatorDataSize);
  131. dumpReduceInfo(info, "initializer", reduce.mInitializerName);
  132. dumpReduceInfo(info, "accumulator", reduce.mAccumulatorName);
  133. dumpReduceInfo(info, "combiner", reduce.mCombinerName);
  134. dumpReduceInfo(info, "outconverter", reduce.mOutConverterName);
  135. dumpReduceInfo(info, "halter", reduce.mHalterName);
  136. }
  137. fprintf(info, "objectSlotCount: %zu\n", ME->getObjectSlotCount());
  138. const uint32_t *slotList = ME->getObjectSlotList();
  139. for (size_t i = 0; i < ME->getObjectSlotCount(); i++) {
  140. fprintf(info, "%u\n", slotList[i]);
  141. }
  142. fclose(info);
  143. return 0;
  144. }
  145. static void dumpMetadata(bcinfo::MetadataExtractor *ME) {
  146. if (!ME) {
  147. return;
  148. }
  149. printf("RSFloatPrecision: ");
  150. switch (ME->getRSFloatPrecision()) {
  151. case bcinfo::RS_FP_Full:
  152. printf("Full\n\n");
  153. break;
  154. case bcinfo::RS_FP_Relaxed:
  155. printf("Relaxed\n\n");
  156. break;
  157. default:
  158. printf("UNKNOWN\n\n");
  159. break;
  160. }
  161. printf("exportVarCount: %zu\n", ME->getExportVarCount());
  162. const char **varNameList = ME->getExportVarNameList();
  163. for (size_t i = 0; i < ME->getExportVarCount(); i++) {
  164. printf("var[%zu]: %s\n", i, varNameList[i]);
  165. }
  166. printf("\n");
  167. printf("exportFuncCount: %zu\n", ME->getExportFuncCount());
  168. const char **funcNameList = ME->getExportFuncNameList();
  169. for (size_t i = 0; i < ME->getExportFuncCount(); i++) {
  170. printf("func[%zu]: %s\n", i, funcNameList[i]);
  171. }
  172. printf("\n");
  173. printf("exportForEachSignatureCount: %zu\n",
  174. ME->getExportForEachSignatureCount());
  175. const char **nameList = ME->getExportForEachNameList();
  176. const uint32_t *sigList = ME->getExportForEachSignatureList();
  177. const uint32_t *inputCountList = ME->getExportForEachInputCountList();
  178. for (size_t i = 0; i < ME->getExportForEachSignatureCount(); i++) {
  179. printf("exportForEachSignatureList[%zu]: %s - 0x%08x - %u\n", i, nameList[i],
  180. sigList[i], inputCountList[i]);
  181. }
  182. printf("\n");
  183. printf("exportReduceCount: %zu\n", ME->getExportReduceCount());
  184. const bcinfo::MetadataExtractor::Reduce *reduceList = ME->getExportReduceList();
  185. for (size_t i = 0; i < ME->getExportReduceCount(); i++) {
  186. const bcinfo::MetadataExtractor::Reduce &reduce = reduceList[i];
  187. printf("exportReduceList[%zu]: %s - 0x%08x - %u - %u\n", i, reduce.mReduceName,
  188. reduce.mSignature, reduce.mInputCount, reduce.mAccumulatorDataSize);
  189. dumpReduceInfo(stdout, "initializer", reduce.mInitializerName);
  190. dumpReduceInfo(stdout, "accumulator", reduce.mAccumulatorName);
  191. dumpReduceInfo(stdout, "combiner", reduce.mCombinerName);
  192. dumpReduceInfo(stdout, "outconverter", reduce.mOutConverterName);
  193. dumpReduceInfo(stdout, "halter", reduce.mHalterName);
  194. }
  195. printf("\n");
  196. printf("pragmaCount: %zu\n", ME->getPragmaCount());
  197. const char **keyList = ME->getPragmaKeyList();
  198. const char **valueList = ME->getPragmaValueList();
  199. for (size_t i = 0; i < ME->getPragmaCount(); i++) {
  200. printf("pragma[%zu]: %s - %s\n", i, keyList[i], valueList[i]);
  201. }
  202. printf("\n");
  203. printf("objectSlotCount: %zu\n", ME->getObjectSlotCount());
  204. const uint32_t *slotList = ME->getObjectSlotList();
  205. for (size_t i = 0; i < ME->getObjectSlotCount(); i++) {
  206. printf("objectSlotList[%zu]: %u\n", i, slotList[i]);
  207. }
  208. printf("\n");
  209. return;
  210. }
  211. static size_t readBitcode(const char **bitcode) {
  212. if (!inFile.length()) {
  213. fprintf(stderr, "input file required\n");
  214. return 0;
  215. }
  216. struct stat statInFile;
  217. if (stat(inFile.c_str(), &statInFile) < 0) {
  218. fprintf(stderr, "Unable to stat input file: %s\n", strerror(errno));
  219. return 0;
  220. }
  221. if (!S_ISREG(statInFile.st_mode)) {
  222. fprintf(stderr, "Input file should be a regular file.\n");
  223. return 0;
  224. }
  225. FILE *in = fopen(inFile.c_str(), "r");
  226. if (!in) {
  227. fprintf(stderr, "Could not open input file %s\n", inFile.c_str());
  228. return 0;
  229. }
  230. size_t bitcodeSize = statInFile.st_size;
  231. *bitcode = (const char*) calloc(1, bitcodeSize + 1);
  232. size_t nread = fread((void*) *bitcode, 1, bitcodeSize, in);
  233. if (nread != bitcodeSize)
  234. fprintf(stderr, "Could not read all of file %s\n", inFile.c_str());
  235. fclose(in);
  236. return nread;
  237. }
  238. static void releaseBitcode(const char **bitcode) {
  239. if (bitcode && *bitcode) {
  240. free((void*) *bitcode);
  241. *bitcode = nullptr;
  242. }
  243. return;
  244. }
  245. int main(int argc, char** argv) {
  246. if(!parseOption(argc, argv)) {
  247. fprintf(stderr, "failed to parse option\n");
  248. return 1;
  249. }
  250. const char *bitcode = nullptr;
  251. size_t bitcodeSize = readBitcode(&bitcode);
  252. unsigned int version = 0;
  253. bcinfo::BitcodeWrapper bcWrapper((const char *)bitcode, bitcodeSize);
  254. if (bcWrapper.getBCFileType() == bcinfo::BC_WRAPPER) {
  255. version = bcWrapper.getTargetAPI();
  256. if (verbose) {
  257. printf("Found bitcodeWrapper\n");
  258. }
  259. } else if (translateFlag) {
  260. version = 12;
  261. }
  262. if (verbose) {
  263. printf("targetAPI: %u\n", version);
  264. printf("compilerVersion: %u\n", bcWrapper.getCompilerVersion());
  265. printf("optimizationLevel: %u\n\n", bcWrapper.getOptimizationLevel());
  266. }
  267. std::unique_ptr<bcinfo::BitcodeTranslator> BT;
  268. BT.reset(new bcinfo::BitcodeTranslator(bitcode, bitcodeSize, version));
  269. if (!BT->translate()) {
  270. fprintf(stderr, "failed to translate bitcode\n");
  271. return 3;
  272. }
  273. std::unique_ptr<bcinfo::MetadataExtractor> ME;
  274. ME.reset(new bcinfo::MetadataExtractor(BT->getTranslatedBitcode(),
  275. BT->getTranslatedBitcodeSize()));
  276. if (!ME->extract()) {
  277. fprintf(stderr, "failed to get metadata\n");
  278. return 4;
  279. }
  280. if (verbose) {
  281. dumpMetadata(ME.get());
  282. const char *translatedBitcode = BT->getTranslatedBitcode();
  283. size_t translatedBitcodeSize = BT->getTranslatedBitcodeSize();
  284. llvm::LLVMContext ctx;
  285. llvm::llvm_shutdown_obj called_on_exit;
  286. std::unique_ptr<llvm::MemoryBuffer> mem;
  287. mem = llvm::MemoryBuffer::getMemBuffer(
  288. llvm::StringRef(translatedBitcode, translatedBitcodeSize),
  289. inFile.c_str(), false);
  290. std::unique_ptr<llvm::Module> module;
  291. llvm::ErrorOr<std::unique_ptr<llvm::Module> > moduleOrError =
  292. llvm::parseBitcodeFile(mem.get()->getMemBufferRef(), ctx);
  293. std::error_code ec = moduleOrError.getError();
  294. if (!ec) {
  295. module = std::move(moduleOrError.get());
  296. ec = module->materializeAll();
  297. }
  298. std::string errmsg;
  299. if (ec) {
  300. errmsg = ec.message();
  301. module.reset();
  302. if (errmsg.size()) {
  303. fprintf(stderr, "error: %s\n", errmsg.c_str());
  304. } else {
  305. fprintf(stderr, "error: failed to parse bitcode file\n");
  306. }
  307. return 5;
  308. }
  309. std::unique_ptr<llvm::tool_output_file> tof(
  310. new llvm::tool_output_file(outFile.c_str(), ec,
  311. llvm::sys::fs::F_None));
  312. std::unique_ptr<llvm::AssemblyAnnotationWriter> ann;
  313. module->print(tof->os(), ann.get());
  314. tof->keep();
  315. }
  316. if (infoFlag) {
  317. if (dumpInfo(ME.get()) != 0) {
  318. fprintf(stderr, "Error dumping info file\n");
  319. return 6;
  320. }
  321. }
  322. releaseBitcode(&bitcode);
  323. return 0;
  324. }