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