Stephen Hines | 932bc6e | 2011-07-27 16:26:26 -0700 | [diff] [blame] | 1 | /* |
Stephen Hines | cc366e5 | 2012-02-21 17:22:04 -0800 | [diff] [blame] | 2 | * Copyright 2011-2012, The Android Open Source Project |
Stephen Hines | 932bc6e | 2011-07-27 16:26:26 -0700 | [diff] [blame] | 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> |
Stephen Hines | 04261e0 | 2012-01-21 17:11:22 -0800 | [diff] [blame] | 18 | #include <bcinfo/BitcodeWrapper.h> |
Stephen Hines | 932bc6e | 2011-07-27 16:26:26 -0700 | [diff] [blame] | 19 | #include <bcinfo/MetadataExtractor.h> |
| 20 | |
Stephen Hines | e126b62 | 2012-05-31 18:41:40 -0700 | [diff] [blame] | 21 | #include <llvm/ADT/StringRef.h> |
Stephen Hines | e126b62 | 2012-05-31 18:41:40 -0700 | [diff] [blame] | 22 | #include <llvm/Bitcode/ReaderWriter.h> |
Tim Murray | c2074ca | 2014-04-08 15:39:08 -0700 | [diff] [blame] | 23 | #include <llvm/IR/AssemblyAnnotationWriter.h> |
Stephen Hines | b730e23 | 2013-01-09 15:31:36 -0800 | [diff] [blame] | 24 | #include <llvm/IR/LLVMContext.h> |
| 25 | #include <llvm/IR/Module.h> |
Stephen Hines | a630078 | 2014-05-28 15:17:19 -0700 | [diff] [blame] | 26 | #include <llvm/Support/FileSystem.h> |
Stephen Hines | e126b62 | 2012-05-31 18:41:40 -0700 | [diff] [blame] | 27 | #include <llvm/Support/ManagedStatic.h> |
| 28 | #include <llvm/Support/MemoryBuffer.h> |
| 29 | #include <llvm/Support/ToolOutputFile.h> |
| 30 | |
Stephen Hines | 932bc6e | 2011-07-27 16:26:26 -0700 | [diff] [blame] | 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 | |
Stephen Hines | e126b62 | 2012-05-31 18:41:40 -0700 | [diff] [blame] | 46 | #include <string> |
Stephen Hines | 932bc6e | 2011-07-27 16:26:26 -0700 | [diff] [blame] | 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 | |
Stephen Hines | e126b62 | 2012-05-31 18:41:40 -0700 | [diff] [blame] | 52 | std::string inFile; |
| 53 | std::string outFile; |
Stephen Hines | 3ffc833 | 2012-08-28 17:23:47 -0700 | [diff] [blame] | 54 | std::string infoFile; |
Stephen Hines | 932bc6e | 2011-07-27 16:26:26 -0700 | [diff] [blame] | 55 | |
| 56 | extern int opterr; |
| 57 | extern int optind; |
| 58 | |
Stephen Hines | 04261e0 | 2012-01-21 17:11:22 -0800 | [diff] [blame] | 59 | bool translateFlag = false; |
Stephen Hines | 3ffc833 | 2012-08-28 17:23:47 -0700 | [diff] [blame] | 60 | bool infoFlag = false; |
| 61 | bool verbose = true; |
Stephen Hines | 932bc6e | 2011-07-27 16:26:26 -0700 | [diff] [blame] | 62 | |
| 63 | static int parseOption(int argc, char** argv) { |
| 64 | int c; |
Stephen Hines | 3ffc833 | 2012-08-28 17:23:47 -0700 | [diff] [blame] | 65 | while ((c = getopt(argc, argv, "itv")) != -1) { |
Stephen Hines | 932bc6e | 2011-07-27 16:26:26 -0700 | [diff] [blame] | 66 | opterr = 0; |
| 67 | |
| 68 | switch(c) { |
| 69 | case '?': |
| 70 | // ignore any error |
| 71 | break; |
| 72 | |
| 73 | case 't': |
Stephen Hines | 04261e0 | 2012-01-21 17:11:22 -0800 | [diff] [blame] | 74 | translateFlag = true; |
Stephen Hines | 932bc6e | 2011-07-27 16:26:26 -0700 | [diff] [blame] | 75 | break; |
| 76 | |
Stephen Hines | 3ffc833 | 2012-08-28 17:23:47 -0700 | [diff] [blame] | 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 | |
Stephen Hines | 932bc6e | 2011-07-27 16:26:26 -0700 | [diff] [blame] | 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]; |
Stephen Hines | e126b62 | 2012-05-31 18:41:40 -0700 | [diff] [blame] | 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"; |
Stephen Hines | 3ffc833 | 2012-08-28 17:23:47 -0700 | [diff] [blame] | 104 | infoFile = std::string(inFile.begin(), inFile.end() - 3) + ".bcinfo"; |
Stephen Hines | e126b62 | 2012-05-31 18:41:40 -0700 | [diff] [blame] | 105 | } else { |
| 106 | outFile = inFile + ".ll"; |
Stephen Hines | 3ffc833 | 2012-08-28 17:23:47 -0700 | [diff] [blame] | 107 | infoFile = inFile + ".bcinfo"; |
Stephen Hines | e126b62 | 2012-05-31 18:41:40 -0700 | [diff] [blame] | 108 | } |
Stephen Hines | 932bc6e | 2011-07-27 16:26:26 -0700 | [diff] [blame] | 109 | return 1; |
| 110 | } |
| 111 | |
| 112 | |
David Gross | a48ea36 | 2016-06-02 14:46:55 -0700 | [diff] [blame] | 113 | static void dumpReduceInfo(FILE *info, const char *Kind, const char *Name) { |
David Gross | 79e1a05 | 2016-01-11 14:42:51 -0800 | [diff] [blame] | 114 | if (Name) |
| 115 | fprintf(info, " %s(%s)\n", Kind, Name); |
| 116 | } |
| 117 | |
Stephen Hines | 3ffc833 | 2012-08-28 17:23:47 -0700 | [diff] [blame] | 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 | |
Stephen Hines | 4cb4c55 | 2014-11-06 15:36:35 -0800 | [diff] [blame] | 129 | fprintf(info, "exportVarCount: %zu\n", ME->getExportVarCount()); |
Stephen Hines | 3ffc833 | 2012-08-28 17:23:47 -0700 | [diff] [blame] | 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 | |
Stephen Hines | 4cb4c55 | 2014-11-06 15:36:35 -0800 | [diff] [blame] | 135 | fprintf(info, "exportFuncCount: %zu\n", ME->getExportFuncCount()); |
Stephen Hines | 3ffc833 | 2012-08-28 17:23:47 -0700 | [diff] [blame] | 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 | |
Stephen Hines | 4cb4c55 | 2014-11-06 15:36:35 -0800 | [diff] [blame] | 141 | fprintf(info, "exportForEachCount: %zu\n", |
Stephen Hines | 3ffc833 | 2012-08-28 17:23:47 -0700 | [diff] [blame] | 142 | ME->getExportForEachSignatureCount()); |
| 143 | const char **nameList = ME->getExportForEachNameList(); |
| 144 | const uint32_t *sigList = ME->getExportForEachSignatureList(); |
Chris Wailes | a668182 | 2014-07-11 15:15:46 -0700 | [diff] [blame] | 145 | const uint32_t *inputCountList = ME->getExportForEachInputCountList(); |
Stephen Hines | 3ffc833 | 2012-08-28 17:23:47 -0700 | [diff] [blame] | 146 | for (size_t i = 0; i < ME->getExportForEachSignatureCount(); i++) { |
Chris Wailes | a668182 | 2014-07-11 15:15:46 -0700 | [diff] [blame] | 147 | fprintf(info, "%u - %s - %u\n", sigList[i], nameList[i], |
| 148 | inputCountList[i]); |
Stephen Hines | 3ffc833 | 2012-08-28 17:23:47 -0700 | [diff] [blame] | 149 | } |
| 150 | |
Matt Wala | 1895ac1 | 2015-07-16 15:34:29 -0700 | [diff] [blame] | 151 | fprintf(info, "exportReduceCount: %zu\n", ME->getExportReduceCount()); |
David Gross | a48ea36 | 2016-06-02 14:46:55 -0700 | [diff] [blame] | 152 | const bcinfo::MetadataExtractor::Reduce *reduceList = |
| 153 | ME->getExportReduceList(); |
Matt Wala | 1895ac1 | 2015-07-16 15:34:29 -0700 | [diff] [blame] | 154 | for (size_t i = 0; i < ME->getExportReduceCount(); i++) { |
David Gross | a48ea36 | 2016-06-02 14:46:55 -0700 | [diff] [blame] | 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); |
David Gross | 79e1a05 | 2016-01-11 14:42:51 -0800 | [diff] [blame] | 163 | } |
| 164 | |
Stephen Hines | 4cb4c55 | 2014-11-06 15:36:35 -0800 | [diff] [blame] | 165 | fprintf(info, "objectSlotCount: %zu\n", ME->getObjectSlotCount()); |
Stephen Hines | 3ffc833 | 2012-08-28 17:23:47 -0700 | [diff] [blame] | 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 | |
Stephen Hines | 932bc6e | 2011-07-27 16:26:26 -0700 | [diff] [blame] | 176 | static void dumpMetadata(bcinfo::MetadataExtractor *ME) { |
| 177 | if (!ME) { |
| 178 | return; |
| 179 | } |
| 180 | |
Stephen Hines | e1fd804 | 2012-03-27 11:03:46 -0700 | [diff] [blame] | 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; |
Stephen Hines | e1fd804 | 2012-03-27 11:03:46 -0700 | [diff] [blame] | 189 | default: |
| 190 | printf("UNKNOWN\n\n"); |
| 191 | break; |
| 192 | } |
| 193 | |
Stephen Hines | 4cb4c55 | 2014-11-06 15:36:35 -0800 | [diff] [blame] | 194 | printf("exportVarCount: %zu\n", ME->getExportVarCount()); |
Stephen Hines | 569986d | 2012-03-09 19:58:45 -0800 | [diff] [blame] | 195 | const char **varNameList = ME->getExportVarNameList(); |
| 196 | for (size_t i = 0; i < ME->getExportVarCount(); i++) { |
Stephen Hines | 4cb4c55 | 2014-11-06 15:36:35 -0800 | [diff] [blame] | 197 | printf("var[%zu]: %s\n", i, varNameList[i]); |
Stephen Hines | 569986d | 2012-03-09 19:58:45 -0800 | [diff] [blame] | 198 | } |
| 199 | printf("\n"); |
| 200 | |
Stephen Hines | 4cb4c55 | 2014-11-06 15:36:35 -0800 | [diff] [blame] | 201 | printf("exportFuncCount: %zu\n", ME->getExportFuncCount()); |
Stephen Hines | 569986d | 2012-03-09 19:58:45 -0800 | [diff] [blame] | 202 | const char **funcNameList = ME->getExportFuncNameList(); |
| 203 | for (size_t i = 0; i < ME->getExportFuncCount(); i++) { |
Stephen Hines | 4cb4c55 | 2014-11-06 15:36:35 -0800 | [diff] [blame] | 204 | printf("func[%zu]: %s\n", i, funcNameList[i]); |
Stephen Hines | 569986d | 2012-03-09 19:58:45 -0800 | [diff] [blame] | 205 | } |
| 206 | printf("\n"); |
Stephen Hines | 33f8fe2 | 2011-08-17 12:56:22 -0700 | [diff] [blame] | 207 | |
Stephen Hines | 4cb4c55 | 2014-11-06 15:36:35 -0800 | [diff] [blame] | 208 | printf("exportForEachSignatureCount: %zu\n", |
Stephen Hines | 33f8fe2 | 2011-08-17 12:56:22 -0700 | [diff] [blame] | 209 | ME->getExportForEachSignatureCount()); |
Stephen Hines | cc366e5 | 2012-02-21 17:22:04 -0800 | [diff] [blame] | 210 | const char **nameList = ME->getExportForEachNameList(); |
Stephen Hines | 33f8fe2 | 2011-08-17 12:56:22 -0700 | [diff] [blame] | 211 | const uint32_t *sigList = ME->getExportForEachSignatureList(); |
Chris Wailes | a668182 | 2014-07-11 15:15:46 -0700 | [diff] [blame] | 212 | const uint32_t *inputCountList = ME->getExportForEachInputCountList(); |
Stephen Hines | 33f8fe2 | 2011-08-17 12:56:22 -0700 | [diff] [blame] | 213 | for (size_t i = 0; i < ME->getExportForEachSignatureCount(); i++) { |
David Gross | 33cda5c | 2015-01-30 11:41:19 -0800 | [diff] [blame] | 214 | printf("exportForEachSignatureList[%zu]: %s - 0x%08x - %u\n", i, nameList[i], |
Chris Wailes | a668182 | 2014-07-11 15:15:46 -0700 | [diff] [blame] | 215 | sigList[i], inputCountList[i]); |
Stephen Hines | 33f8fe2 | 2011-08-17 12:56:22 -0700 | [diff] [blame] | 216 | } |
Stephen Hines | 569986d | 2012-03-09 19:58:45 -0800 | [diff] [blame] | 217 | printf("\n"); |
Stephen Hines | 33f8fe2 | 2011-08-17 12:56:22 -0700 | [diff] [blame] | 218 | |
Matt Wala | 1895ac1 | 2015-07-16 15:34:29 -0700 | [diff] [blame] | 219 | printf("exportReduceCount: %zu\n", ME->getExportReduceCount()); |
David Gross | a48ea36 | 2016-06-02 14:46:55 -0700 | [diff] [blame] | 220 | const bcinfo::MetadataExtractor::Reduce *reduceList = ME->getExportReduceList(); |
Matt Wala | 1895ac1 | 2015-07-16 15:34:29 -0700 | [diff] [blame] | 221 | for (size_t i = 0; i < ME->getExportReduceCount(); i++) { |
David Gross | a48ea36 | 2016-06-02 14:46:55 -0700 | [diff] [blame] | 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); |
David Gross | 79e1a05 | 2016-01-11 14:42:51 -0800 | [diff] [blame] | 230 | } |
| 231 | printf("\n"); |
| 232 | |
Stephen Hines | 4cb4c55 | 2014-11-06 15:36:35 -0800 | [diff] [blame] | 233 | printf("pragmaCount: %zu\n", ME->getPragmaCount()); |
Stephen Hines | 932bc6e | 2011-07-27 16:26:26 -0700 | [diff] [blame] | 234 | const char **keyList = ME->getPragmaKeyList(); |
| 235 | const char **valueList = ME->getPragmaValueList(); |
| 236 | for (size_t i = 0; i < ME->getPragmaCount(); i++) { |
Stephen Hines | 4cb4c55 | 2014-11-06 15:36:35 -0800 | [diff] [blame] | 237 | printf("pragma[%zu]: %s - %s\n", i, keyList[i], valueList[i]); |
Stephen Hines | 932bc6e | 2011-07-27 16:26:26 -0700 | [diff] [blame] | 238 | } |
Stephen Hines | 569986d | 2012-03-09 19:58:45 -0800 | [diff] [blame] | 239 | printf("\n"); |
Stephen Hines | 932bc6e | 2011-07-27 16:26:26 -0700 | [diff] [blame] | 240 | |
Stephen Hines | 4cb4c55 | 2014-11-06 15:36:35 -0800 | [diff] [blame] | 241 | printf("objectSlotCount: %zu\n", ME->getObjectSlotCount()); |
Stephen Hines | 932bc6e | 2011-07-27 16:26:26 -0700 | [diff] [blame] | 242 | const uint32_t *slotList = ME->getObjectSlotList(); |
| 243 | for (size_t i = 0; i < ME->getObjectSlotCount(); i++) { |
Stephen Hines | 4cb4c55 | 2014-11-06 15:36:35 -0800 | [diff] [blame] | 244 | printf("objectSlotList[%zu]: %u\n", i, slotList[i]); |
Stephen Hines | 932bc6e | 2011-07-27 16:26:26 -0700 | [diff] [blame] | 245 | } |
Stephen Hines | 569986d | 2012-03-09 19:58:45 -0800 | [diff] [blame] | 246 | printf("\n"); |
Stephen Hines | 932bc6e | 2011-07-27 16:26:26 -0700 | [diff] [blame] | 247 | |
| 248 | return; |
| 249 | } |
| 250 | |
| 251 | |
| 252 | static size_t readBitcode(const char **bitcode) { |
Stephen Hines | e126b62 | 2012-05-31 18:41:40 -0700 | [diff] [blame] | 253 | if (!inFile.length()) { |
Stephen Hines | 932bc6e | 2011-07-27 16:26:26 -0700 | [diff] [blame] | 254 | fprintf(stderr, "input file required\n"); |
Stephen Hines | e126b62 | 2012-05-31 18:41:40 -0700 | [diff] [blame] | 255 | return 0; |
Stephen Hines | 932bc6e | 2011-07-27 16:26:26 -0700 | [diff] [blame] | 256 | } |
| 257 | |
| 258 | struct stat statInFile; |
Stephen Hines | e126b62 | 2012-05-31 18:41:40 -0700 | [diff] [blame] | 259 | if (stat(inFile.c_str(), &statInFile) < 0) { |
Stephen Hines | 932bc6e | 2011-07-27 16:26:26 -0700 | [diff] [blame] | 260 | fprintf(stderr, "Unable to stat input file: %s\n", strerror(errno)); |
Stephen Hines | e126b62 | 2012-05-31 18:41:40 -0700 | [diff] [blame] | 261 | return 0; |
Stephen Hines | 932bc6e | 2011-07-27 16:26:26 -0700 | [diff] [blame] | 262 | } |
| 263 | |
| 264 | if (!S_ISREG(statInFile.st_mode)) { |
| 265 | fprintf(stderr, "Input file should be a regular file.\n"); |
Stephen Hines | e126b62 | 2012-05-31 18:41:40 -0700 | [diff] [blame] | 266 | return 0; |
Stephen Hines | 932bc6e | 2011-07-27 16:26:26 -0700 | [diff] [blame] | 267 | } |
| 268 | |
Stephen Hines | e126b62 | 2012-05-31 18:41:40 -0700 | [diff] [blame] | 269 | FILE *in = fopen(inFile.c_str(), "r"); |
Stephen Hines | 932bc6e | 2011-07-27 16:26:26 -0700 | [diff] [blame] | 270 | if (!in) { |
Stephen Hines | e126b62 | 2012-05-31 18:41:40 -0700 | [diff] [blame] | 271 | fprintf(stderr, "Could not open input file %s\n", inFile.c_str()); |
| 272 | return 0; |
Stephen Hines | 932bc6e | 2011-07-27 16:26:26 -0700 | [diff] [blame] | 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) |
Stephen Hines | e126b62 | 2012-05-31 18:41:40 -0700 | [diff] [blame] | 281 | fprintf(stderr, "Could not read all of file %s\n", inFile.c_str()); |
Stephen Hines | 932bc6e | 2011-07-27 16:26:26 -0700 | [diff] [blame] | 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); |
Chris Wailes | 900c6c1 | 2014-08-13 15:40:00 -0700 | [diff] [blame] | 291 | *bitcode = nullptr; |
Stephen Hines | 932bc6e | 2011-07-27 16:26:26 -0700 | [diff] [blame] | 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 | |
Chris Wailes | 900c6c1 | 2014-08-13 15:40:00 -0700 | [diff] [blame] | 303 | const char *bitcode = nullptr; |
Stephen Hines | 932bc6e | 2011-07-27 16:26:26 -0700 | [diff] [blame] | 304 | size_t bitcodeSize = readBitcode(&bitcode); |
| 305 | |
Stephen Hines | 04261e0 | 2012-01-21 17:11:22 -0800 | [diff] [blame] | 306 | unsigned int version = 0; |
Stephen Hines | 932bc6e | 2011-07-27 16:26:26 -0700 | [diff] [blame] | 307 | |
Stephen Hines | 04261e0 | 2012-01-21 17:11:22 -0800 | [diff] [blame] | 308 | bcinfo::BitcodeWrapper bcWrapper((const char *)bitcode, bitcodeSize); |
Stephen Hines | 04261e0 | 2012-01-21 17:11:22 -0800 | [diff] [blame] | 309 | if (bcWrapper.getBCFileType() == bcinfo::BC_WRAPPER) { |
| 310 | version = bcWrapper.getTargetAPI(); |
Stephen Hines | 3ffc833 | 2012-08-28 17:23:47 -0700 | [diff] [blame] | 311 | if (verbose) { |
| 312 | printf("Found bitcodeWrapper\n"); |
| 313 | } |
Stephen Hines | 04261e0 | 2012-01-21 17:11:22 -0800 | [diff] [blame] | 314 | } else if (translateFlag) { |
Stephen Hines | 932bc6e | 2011-07-27 16:26:26 -0700 | [diff] [blame] | 315 | version = 12; |
| 316 | } |
| 317 | |
Stephen Hines | 3ffc833 | 2012-08-28 17:23:47 -0700 | [diff] [blame] | 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 | } |
Stephen Hines | 04261e0 | 2012-01-21 17:11:22 -0800 | [diff] [blame] | 323 | |
Stephen Hines | d0993af | 2014-07-15 16:49:25 -0700 | [diff] [blame] | 324 | std::unique_ptr<bcinfo::BitcodeTranslator> BT; |
Stephen Hines | e126b62 | 2012-05-31 18:41:40 -0700 | [diff] [blame] | 325 | BT.reset(new bcinfo::BitcodeTranslator(bitcode, bitcodeSize, version)); |
Stephen Hines | 932bc6e | 2011-07-27 16:26:26 -0700 | [diff] [blame] | 326 | if (!BT->translate()) { |
| 327 | fprintf(stderr, "failed to translate bitcode\n"); |
Stephen Hines | 04261e0 | 2012-01-21 17:11:22 -0800 | [diff] [blame] | 328 | return 3; |
Stephen Hines | 932bc6e | 2011-07-27 16:26:26 -0700 | [diff] [blame] | 329 | } |
| 330 | |
Stephen Hines | d0993af | 2014-07-15 16:49:25 -0700 | [diff] [blame] | 331 | std::unique_ptr<bcinfo::MetadataExtractor> ME; |
Stephen Hines | e126b62 | 2012-05-31 18:41:40 -0700 | [diff] [blame] | 332 | ME.reset(new bcinfo::MetadataExtractor(BT->getTranslatedBitcode(), |
| 333 | BT->getTranslatedBitcodeSize())); |
Stephen Hines | 932bc6e | 2011-07-27 16:26:26 -0700 | [diff] [blame] | 334 | if (!ME->extract()) { |
| 335 | fprintf(stderr, "failed to get metadata\n"); |
Stephen Hines | 04261e0 | 2012-01-21 17:11:22 -0800 | [diff] [blame] | 336 | return 4; |
Stephen Hines | 932bc6e | 2011-07-27 16:26:26 -0700 | [diff] [blame] | 337 | } |
| 338 | |
Stephen Hines | 3ffc833 | 2012-08-28 17:23:47 -0700 | [diff] [blame] | 339 | if (verbose) { |
| 340 | dumpMetadata(ME.get()); |
Stephen Hines | 932bc6e | 2011-07-27 16:26:26 -0700 | [diff] [blame] | 341 | |
Stephen Hines | 3ffc833 | 2012-08-28 17:23:47 -0700 | [diff] [blame] | 342 | const char *translatedBitcode = BT->getTranslatedBitcode(); |
| 343 | size_t translatedBitcodeSize = BT->getTranslatedBitcodeSize(); |
Stephen Hines | e126b62 | 2012-05-31 18:41:40 -0700 | [diff] [blame] | 344 | |
Stephen Hines | 3ffc833 | 2012-08-28 17:23:47 -0700 | [diff] [blame] | 345 | llvm::LLVMContext &ctx = llvm::getGlobalContext(); |
| 346 | llvm::llvm_shutdown_obj called_on_exit; |
Stephen Hines | e126b62 | 2012-05-31 18:41:40 -0700 | [diff] [blame] | 347 | |
Stephen Hines | d0993af | 2014-07-15 16:49:25 -0700 | [diff] [blame] | 348 | std::unique_ptr<llvm::MemoryBuffer> mem; |
Stephen Hines | e126b62 | 2012-05-31 18:41:40 -0700 | [diff] [blame] | 349 | |
Stephen Hines | 5793613 | 2014-11-25 17:54:59 -0800 | [diff] [blame] | 350 | mem = llvm::MemoryBuffer::getMemBuffer( |
Stephen Hines | 3ffc833 | 2012-08-28 17:23:47 -0700 | [diff] [blame] | 351 | llvm::StringRef(translatedBitcode, translatedBitcodeSize), |
Stephen Hines | 5793613 | 2014-11-25 17:54:59 -0800 | [diff] [blame] | 352 | inFile.c_str(), false); |
Stephen Hines | e126b62 | 2012-05-31 18:41:40 -0700 | [diff] [blame] | 353 | |
Stephen Hines | d0993af | 2014-07-15 16:49:25 -0700 | [diff] [blame] | 354 | std::unique_ptr<llvm::Module> module; |
Pirama Arumuga Nainar | 8e90893 | 2016-03-06 23:05:45 -0800 | [diff] [blame] | 355 | llvm::ErrorOr<std::unique_ptr<llvm::Module> > moduleOrError = |
| 356 | llvm::parseBitcodeFile(mem.get()->getMemBufferRef(), ctx); |
Stephen Hines | d0993af | 2014-07-15 16:49:25 -0700 | [diff] [blame] | 357 | std::error_code ec = moduleOrError.getError(); |
Tim Murray | c2074ca | 2014-04-08 15:39:08 -0700 | [diff] [blame] | 358 | if (!ec) { |
Pirama Arumuga Nainar | 8e90893 | 2016-03-06 23:05:45 -0800 | [diff] [blame] | 359 | module = std::move(moduleOrError.get()); |
| 360 | ec = module->materializeAll(); |
Stephen Hines | e126b62 | 2012-05-31 18:41:40 -0700 | [diff] [blame] | 361 | } |
Tim Murray | c2074ca | 2014-04-08 15:39:08 -0700 | [diff] [blame] | 362 | std::string errmsg; |
| 363 | if (ec) { |
| 364 | errmsg = ec.message(); |
| 365 | module.reset(); |
Stephen Hines | 3ffc833 | 2012-08-28 17:23:47 -0700 | [diff] [blame] | 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 | |
Stephen Hines | d0993af | 2014-07-15 16:49:25 -0700 | [diff] [blame] | 374 | std::unique_ptr<llvm::tool_output_file> tof( |
Stephen Hines | 5793613 | 2014-11-25 17:54:59 -0800 | [diff] [blame] | 375 | new llvm::tool_output_file(outFile.c_str(), ec, |
Tim Murray | c2074ca | 2014-04-08 15:39:08 -0700 | [diff] [blame] | 376 | llvm::sys::fs::F_None)); |
Stephen Hines | d0993af | 2014-07-15 16:49:25 -0700 | [diff] [blame] | 377 | std::unique_ptr<llvm::AssemblyAnnotationWriter> ann; |
Stephen Hines | 3ffc833 | 2012-08-28 17:23:47 -0700 | [diff] [blame] | 378 | module->print(tof->os(), ann.get()); |
| 379 | |
| 380 | tof->keep(); |
Stephen Hines | e126b62 | 2012-05-31 18:41:40 -0700 | [diff] [blame] | 381 | } |
| 382 | |
Stephen Hines | 3ffc833 | 2012-08-28 17:23:47 -0700 | [diff] [blame] | 383 | if (infoFlag) { |
| 384 | if (dumpInfo(ME.get()) != 0) { |
| 385 | fprintf(stderr, "Error dumping info file\n"); |
| 386 | return 6; |
| 387 | } |
| 388 | } |
Stephen Hines | 932bc6e | 2011-07-27 16:26:26 -0700 | [diff] [blame] | 389 | |
| 390 | releaseBitcode(&bitcode); |
| 391 | |
| 392 | return 0; |
| 393 | } |