OLD | NEW |
(Empty) | |
| 1 //===--- Bitcode/NaCl/Writer/NaClBitcodeWriter.cpp - Bitcode Writer -------===// |
| 2 // |
| 3 // The LLVM Compiler Infrastructure |
| 4 // |
| 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. |
| 7 // |
| 8 //===----------------------------------------------------------------------===// |
| 9 // |
| 10 // Bitcode writer implementation. |
| 11 // |
| 12 //===----------------------------------------------------------------------===// |
| 13 |
| 14 #define DEBUG_TYPE "NaClBitcodeWriter" |
| 15 |
| 16 #include "llvm/Bitcode/NaCl/NaClBitcodeHeader.h" |
| 17 #include "llvm/Bitcode/NaCl/NaClReaderWriter.h" |
| 18 #include "NaClValueEnumerator.h" |
| 19 #include "llvm/Bitcode/NaCl/NaClBitstreamWriter.h" |
| 20 #include "llvm/Bitcode/NaCl/NaClLLVMBitCodes.h" |
| 21 #include "llvm/IR/Constants.h" |
| 22 #include "llvm/IR/DerivedTypes.h" |
| 23 #include "llvm/IR/InlineAsm.h" |
| 24 #include "llvm/IR/Instructions.h" |
| 25 #include "llvm/IR/Module.h" |
| 26 #include "llvm/IR/Operator.h" |
| 27 #include "llvm/IR/ValueSymbolTable.h" |
| 28 #include "llvm/Support/Debug.h" |
| 29 #include "llvm/Support/CommandLine.h" |
| 30 #include "llvm/Support/ErrorHandling.h" |
| 31 #include "llvm/Support/MathExtras.h" |
| 32 #include "llvm/Support/Program.h" |
| 33 #include "llvm/Support/raw_ostream.h" |
| 34 #include <cctype> |
| 35 #include <map> |
| 36 using namespace llvm; |
| 37 |
| 38 static cl::opt<unsigned> |
| 39 PNaClVersion("pnacl-version", |
| 40 cl::desc("Specify PNaCl bitcode version to write"), |
| 41 cl::init(2)); |
| 42 |
| 43 /// These are manifest constants used by the bitcode writer. They do |
| 44 /// not need to be kept in sync with the reader, but need to be |
| 45 /// consistent within this file. |
| 46 /// |
| 47 /// Note that for each block type GROUP, the last entry should be of |
| 48 /// the form: |
| 49 /// |
| 50 /// GROUP_MAX_ABBREV = GROUP_LAST_ABBREV, |
| 51 /// |
| 52 /// where GROUP_LAST_ABBREV is the last defined abbreviation. See |
| 53 /// include file "llvm/Bitcode/NaCl/NaClBitCodes.h" for more |
| 54 /// information on how groups should be defined. |
| 55 enum { |
| 56 // VALUE_SYMTAB_BLOCK abbrev id's. |
| 57 VST_ENTRY_8_ABBREV = naclbitc::FIRST_APPLICATION_ABBREV, |
| 58 VST_ENTRY_7_ABBREV, |
| 59 VST_ENTRY_6_ABBREV, |
| 60 VST_BBENTRY_6_ABBREV, |
| 61 VST_MAX_ABBREV = VST_BBENTRY_6_ABBREV, |
| 62 |
| 63 // CONSTANTS_BLOCK abbrev id's. |
| 64 CONSTANTS_SETTYPE_ABBREV = naclbitc::FIRST_APPLICATION_ABBREV, |
| 65 CONSTANTS_INTEGER_ABBREV, |
| 66 CONSTANTS_INTEGER_ZERO_ABBREV, |
| 67 CONSTANTS_FLOAT_ABBREV, |
| 68 CONSTANTS_MAX_ABBREV = CONSTANTS_FLOAT_ABBREV, |
| 69 |
| 70 // GLOBALVAR BLOCK abbrev id's. |
| 71 GLOBALVAR_VAR_ABBREV = naclbitc::FIRST_APPLICATION_ABBREV, |
| 72 GLOBALVAR_COMPOUND_ABBREV, |
| 73 GLOBALVAR_ZEROFILL_ABBREV, |
| 74 GLOBALVAR_DATA_ABBREV, |
| 75 GLOBALVAR_RELOC_ABBREV, |
| 76 GLOBALVAR_RELOC_WITH_ADDEND_ABBREV, |
| 77 GLOBALVAR_MAX_ABBREV = GLOBALVAR_RELOC_WITH_ADDEND_ABBREV, |
| 78 |
| 79 // FUNCTION_BLOCK abbrev id's. |
| 80 FUNCTION_INST_LOAD_ABBREV = naclbitc::FIRST_APPLICATION_ABBREV, |
| 81 FUNCTION_INST_BINOP_ABBREV, |
| 82 FUNCTION_INST_CAST_ABBREV, |
| 83 FUNCTION_INST_RET_VOID_ABBREV, |
| 84 FUNCTION_INST_RET_VAL_ABBREV, |
| 85 FUNCTION_INST_UNREACHABLE_ABBREV, |
| 86 FUNCTION_INST_FORWARDTYPEREF_ABBREV, |
| 87 FUNCTION_INST_STORE_ABBREV, |
| 88 FUNCTION_INST_MAX_ABBREV = FUNCTION_INST_STORE_ABBREV, |
| 89 |
| 90 // TYPE_BLOCK_ID_NEW abbrev id's. |
| 91 TYPE_FUNCTION_ABBREV = naclbitc::FIRST_APPLICATION_ABBREV, |
| 92 TYPE_MAX_ABBREV = TYPE_FUNCTION_ABBREV |
| 93 }; |
| 94 |
| 95 LLVM_ATTRIBUTE_NORETURN |
| 96 static void ReportIllegalValue(const char *ValueMessage, |
| 97 const Value &Value) { |
| 98 std::string Message; |
| 99 raw_string_ostream StrM(Message); |
| 100 StrM << "NaCl Illegal "; |
| 101 if (ValueMessage != 0) |
| 102 StrM << ValueMessage << " "; |
| 103 StrM << ": " << Value; |
| 104 report_fatal_error(StrM.str()); |
| 105 } |
| 106 |
| 107 static unsigned GetEncodedCastOpcode(unsigned Opcode, const Value &V) { |
| 108 switch (Opcode) { |
| 109 default: ReportIllegalValue("cast", V); |
| 110 case Instruction::Trunc : return naclbitc::CAST_TRUNC; |
| 111 case Instruction::ZExt : return naclbitc::CAST_ZEXT; |
| 112 case Instruction::SExt : return naclbitc::CAST_SEXT; |
| 113 case Instruction::FPToUI : return naclbitc::CAST_FPTOUI; |
| 114 case Instruction::FPToSI : return naclbitc::CAST_FPTOSI; |
| 115 case Instruction::UIToFP : return naclbitc::CAST_UITOFP; |
| 116 case Instruction::SIToFP : return naclbitc::CAST_SITOFP; |
| 117 case Instruction::FPTrunc : return naclbitc::CAST_FPTRUNC; |
| 118 case Instruction::FPExt : return naclbitc::CAST_FPEXT; |
| 119 case Instruction::BitCast : return naclbitc::CAST_BITCAST; |
| 120 } |
| 121 } |
| 122 |
| 123 static unsigned GetEncodedBinaryOpcode(unsigned Opcode, const Value &V) { |
| 124 switch (Opcode) { |
| 125 default: ReportIllegalValue("binary opcode", V); |
| 126 case Instruction::Add: |
| 127 case Instruction::FAdd: return naclbitc::BINOP_ADD; |
| 128 case Instruction::Sub: |
| 129 case Instruction::FSub: return naclbitc::BINOP_SUB; |
| 130 case Instruction::Mul: |
| 131 case Instruction::FMul: return naclbitc::BINOP_MUL; |
| 132 case Instruction::UDiv: return naclbitc::BINOP_UDIV; |
| 133 case Instruction::FDiv: |
| 134 case Instruction::SDiv: return naclbitc::BINOP_SDIV; |
| 135 case Instruction::URem: return naclbitc::BINOP_UREM; |
| 136 case Instruction::FRem: |
| 137 case Instruction::SRem: return naclbitc::BINOP_SREM; |
| 138 case Instruction::Shl: return naclbitc::BINOP_SHL; |
| 139 case Instruction::LShr: return naclbitc::BINOP_LSHR; |
| 140 case Instruction::AShr: return naclbitc::BINOP_ASHR; |
| 141 case Instruction::And: return naclbitc::BINOP_AND; |
| 142 case Instruction::Or: return naclbitc::BINOP_OR; |
| 143 case Instruction::Xor: return naclbitc::BINOP_XOR; |
| 144 } |
| 145 } |
| 146 |
| 147 static unsigned GetEncodedCallingConv(CallingConv::ID conv) { |
| 148 switch (conv) { |
| 149 default: report_fatal_error( |
| 150 "Calling convention not supported by PNaCL bitcode"); |
| 151 case CallingConv::C: return naclbitc::C_CallingConv; |
| 152 } |
| 153 } |
| 154 |
| 155 // Converts LLVM encoding of comparison predicates to the |
| 156 // corresponding bitcode versions. |
| 157 static unsigned GetEncodedCmpPredicate(const CmpInst &Cmp) { |
| 158 switch (Cmp.getPredicate()) { |
| 159 default: report_fatal_error( |
| 160 "Comparison predicate not supported by PNaCl bitcode"); |
| 161 case CmpInst::FCMP_FALSE: |
| 162 return naclbitc::FCMP_FALSE; |
| 163 case CmpInst::FCMP_OEQ: |
| 164 return naclbitc::FCMP_OEQ; |
| 165 case CmpInst::FCMP_OGT: |
| 166 return naclbitc::FCMP_OGT; |
| 167 case CmpInst::FCMP_OGE: |
| 168 return naclbitc::FCMP_OGE; |
| 169 case CmpInst::FCMP_OLT: |
| 170 return naclbitc::FCMP_OLT; |
| 171 case CmpInst::FCMP_OLE: |
| 172 return naclbitc::FCMP_OLE; |
| 173 case CmpInst::FCMP_ONE: |
| 174 return naclbitc::FCMP_ONE; |
| 175 case CmpInst::FCMP_ORD: |
| 176 return naclbitc::FCMP_ORD; |
| 177 case CmpInst::FCMP_UNO: |
| 178 return naclbitc::FCMP_UNO; |
| 179 case CmpInst::FCMP_UEQ: |
| 180 return naclbitc::FCMP_UEQ; |
| 181 case CmpInst::FCMP_UGT: |
| 182 return naclbitc::FCMP_UGT; |
| 183 case CmpInst::FCMP_UGE: |
| 184 return naclbitc::FCMP_UGE; |
| 185 case CmpInst::FCMP_ULT: |
| 186 return naclbitc::FCMP_ULT; |
| 187 case CmpInst::FCMP_ULE: |
| 188 return naclbitc::FCMP_ULE; |
| 189 case CmpInst::FCMP_UNE: |
| 190 return naclbitc::FCMP_UNE; |
| 191 case CmpInst::FCMP_TRUE: |
| 192 return naclbitc::FCMP_TRUE; |
| 193 case CmpInst::ICMP_EQ: |
| 194 return naclbitc::ICMP_EQ; |
| 195 case CmpInst::ICMP_NE: |
| 196 return naclbitc::ICMP_NE; |
| 197 case CmpInst::ICMP_UGT: |
| 198 return naclbitc::ICMP_UGT; |
| 199 case CmpInst::ICMP_UGE: |
| 200 return naclbitc::ICMP_UGE; |
| 201 case CmpInst::ICMP_ULT: |
| 202 return naclbitc::ICMP_ULT; |
| 203 case CmpInst::ICMP_ULE: |
| 204 return naclbitc::ICMP_ULE; |
| 205 case CmpInst::ICMP_SGT: |
| 206 return naclbitc::ICMP_SGT; |
| 207 case CmpInst::ICMP_SGE: |
| 208 return naclbitc::ICMP_SGE; |
| 209 case CmpInst::ICMP_SLT: |
| 210 return naclbitc::ICMP_SLT; |
| 211 case CmpInst::ICMP_SLE: |
| 212 return naclbitc::ICMP_SLE; |
| 213 } |
| 214 } |
| 215 |
| 216 // The type of encoding to use for type ids. |
| 217 static NaClBitCodeAbbrevOp::Encoding TypeIdEncoding = NaClBitCodeAbbrevOp::VBR; |
| 218 |
| 219 // The cutoff (in number of bits) from Fixed to VBR. |
| 220 static const unsigned TypeIdVBRCutoff = 6; |
| 221 |
| 222 // The number of bits to use in the encoding of type ids. |
| 223 static unsigned TypeIdNumBits = TypeIdVBRCutoff; |
| 224 |
| 225 // Optimizes the value for TypeIdEncoding and TypeIdNumBits based |
| 226 // the actual number of types. |
| 227 static inline void OptimizeTypeIdEncoding(const NaClValueEnumerator &VE) { |
| 228 // Note: modify to use maximum number of bits if under cutoff. Otherwise, |
| 229 // use VBR to take advantage that frequently referenced types have |
| 230 // small IDs. |
| 231 unsigned NumBits = NaClBitsNeededForValue(VE.getTypes().size()); |
| 232 TypeIdNumBits = (NumBits < TypeIdVBRCutoff ? NumBits : TypeIdVBRCutoff); |
| 233 TypeIdEncoding = NaClBitCodeAbbrevOp::Encoding( |
| 234 NumBits <= TypeIdVBRCutoff |
| 235 ? NaClBitCodeAbbrevOp::Fixed : NaClBitCodeAbbrevOp::VBR); |
| 236 } |
| 237 |
| 238 /// WriteTypeTable - Write out the type table for a module. |
| 239 static void WriteTypeTable(const NaClValueEnumerator &VE, |
| 240 NaClBitstreamWriter &Stream) { |
| 241 DEBUG(dbgs() << "-> WriteTypeTable\n"); |
| 242 const NaClValueEnumerator::TypeList &TypeList = VE.getTypes(); |
| 243 |
| 244 Stream.EnterSubblock(naclbitc::TYPE_BLOCK_ID_NEW, TYPE_MAX_ABBREV); |
| 245 |
| 246 SmallVector<uint64_t, 64> TypeVals; |
| 247 |
| 248 // Abbrev for TYPE_CODE_FUNCTION. |
| 249 NaClBitCodeAbbrev *Abbv = new NaClBitCodeAbbrev(); |
| 250 Abbv->Add(NaClBitCodeAbbrevOp(naclbitc::TYPE_CODE_FUNCTION)); |
| 251 Abbv->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::Fixed, 1)); // isvararg |
| 252 Abbv->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::Array)); |
| 253 Abbv->Add(NaClBitCodeAbbrevOp(TypeIdEncoding, TypeIdNumBits)); |
| 254 if (TYPE_FUNCTION_ABBREV != Stream.EmitAbbrev(Abbv)) |
| 255 llvm_unreachable("Unexpected abbrev ordering!"); |
| 256 |
| 257 // Emit an entry count so the reader can reserve space. |
| 258 TypeVals.push_back(TypeList.size()); |
| 259 Stream.EmitRecord(naclbitc::TYPE_CODE_NUMENTRY, TypeVals); |
| 260 TypeVals.clear(); |
| 261 |
| 262 // Loop over all of the types, emitting each in turn. |
| 263 for (unsigned i = 0, e = TypeList.size(); i != e; ++i) { |
| 264 Type *T = TypeList[i]; |
| 265 int AbbrevToUse = 0; |
| 266 unsigned Code = 0; |
| 267 |
| 268 switch (T->getTypeID()) { |
| 269 default: llvm_unreachable("Unknown type!"); |
| 270 case Type::VoidTyID: Code = naclbitc::TYPE_CODE_VOID; break; |
| 271 case Type::FloatTyID: Code = naclbitc::TYPE_CODE_FLOAT; break; |
| 272 case Type::DoubleTyID: Code = naclbitc::TYPE_CODE_DOUBLE; break; |
| 273 case Type::IntegerTyID: |
| 274 // INTEGER: [width] |
| 275 Code = naclbitc::TYPE_CODE_INTEGER; |
| 276 TypeVals.push_back(cast<IntegerType>(T)->getBitWidth()); |
| 277 break; |
| 278 case Type::VectorTyID: { |
| 279 VectorType *VT = cast<VectorType>(T); |
| 280 // VECTOR [numelts, eltty] |
| 281 Code = naclbitc::TYPE_CODE_VECTOR; |
| 282 TypeVals.push_back(VT->getNumElements()); |
| 283 TypeVals.push_back(VE.getTypeID(VT->getElementType())); |
| 284 break; |
| 285 } |
| 286 case Type::FunctionTyID: { |
| 287 FunctionType *FT = cast<FunctionType>(T); |
| 288 // FUNCTION: [isvararg, retty, paramty x N] |
| 289 Code = naclbitc::TYPE_CODE_FUNCTION; |
| 290 TypeVals.push_back(FT->isVarArg()); |
| 291 TypeVals.push_back(VE.getTypeID(FT->getReturnType())); |
| 292 for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) |
| 293 TypeVals.push_back(VE.getTypeID(FT->getParamType(i))); |
| 294 AbbrevToUse = TYPE_FUNCTION_ABBREV; |
| 295 break; |
| 296 } |
| 297 case Type::StructTyID: |
| 298 report_fatal_error("Struct types are not supported in PNaCl bitcode"); |
| 299 case Type::ArrayTyID: |
| 300 report_fatal_error("Array types are not supported in PNaCl bitcode"); |
| 301 } |
| 302 |
| 303 // Emit the finished record. |
| 304 Stream.EmitRecord(Code, TypeVals, AbbrevToUse); |
| 305 TypeVals.clear(); |
| 306 } |
| 307 |
| 308 Stream.ExitBlock(); |
| 309 DEBUG(dbgs() << "<- WriteTypeTable\n"); |
| 310 } |
| 311 |
| 312 static unsigned getEncodedLinkage(const GlobalValue *GV) { |
| 313 switch (GV->getLinkage()) { |
| 314 case GlobalValue::ExternalLinkage: return 0; |
| 315 case GlobalValue::InternalLinkage: return 3; |
| 316 default: |
| 317 report_fatal_error("Invalid linkage"); |
| 318 } |
| 319 } |
| 320 |
| 321 /// \brief Function to convert constant initializers for global |
| 322 /// variables into corresponding bitcode. Takes advantage that these |
| 323 /// global variable initializations are normalized (see |
| 324 /// lib/Transforms/NaCl/FlattenGlobals.cpp). |
| 325 void WriteGlobalInit(const Constant *C, unsigned GlobalVarID, |
| 326 SmallVectorImpl<uint32_t> &Vals, |
| 327 const NaClValueEnumerator &VE, |
| 328 NaClBitstreamWriter &Stream) { |
| 329 if (ArrayType *Ty = dyn_cast<ArrayType>(C->getType())) { |
| 330 if (!Ty->getElementType()->isIntegerTy(8)) |
| 331 report_fatal_error("Global array initializer not i8"); |
| 332 uint32_t Size = Ty->getNumElements(); |
| 333 if (isa<ConstantAggregateZero>(C)) { |
| 334 Vals.push_back(Size); |
| 335 Stream.EmitRecord(naclbitc::GLOBALVAR_ZEROFILL, Vals, |
| 336 GLOBALVAR_ZEROFILL_ABBREV); |
| 337 Vals.clear(); |
| 338 } else { |
| 339 const ConstantDataSequential *CD = cast<ConstantDataSequential>(C); |
| 340 StringRef Data = CD->getRawDataValues(); |
| 341 for (size_t i = 0; i < Size; ++i) { |
| 342 Vals.push_back(Data[i] & 0xFF); |
| 343 } |
| 344 Stream.EmitRecord(naclbitc::GLOBALVAR_DATA, Vals, |
| 345 GLOBALVAR_DATA_ABBREV); |
| 346 Vals.clear(); |
| 347 } |
| 348 return; |
| 349 } |
| 350 if (VE.IsIntPtrType(C->getType())) { |
| 351 // This constant defines a relocation. Start by verifying the |
| 352 // relocation is of the right form. |
| 353 const ConstantExpr *CE = dyn_cast<ConstantExpr>(C); |
| 354 if (CE == 0) |
| 355 report_fatal_error("Global i32 initializer not constant"); |
| 356 assert(CE); |
| 357 int32_t Addend = 0; |
| 358 if (CE->getOpcode() == Instruction::Add) { |
| 359 const ConstantInt *AddendConst = dyn_cast<ConstantInt>(CE->getOperand(1)); |
| 360 if (AddendConst == 0) |
| 361 report_fatal_error("Malformed addend in global relocation initializer"); |
| 362 Addend = AddendConst->getSExtValue(); |
| 363 CE = dyn_cast<ConstantExpr>(CE->getOperand(0)); |
| 364 if (CE == 0) |
| 365 report_fatal_error( |
| 366 "Base of global relocation initializer not constant"); |
| 367 } |
| 368 if (CE->getOpcode() != Instruction::PtrToInt) |
| 369 report_fatal_error("Global relocation base doesn't contain ptrtoint"); |
| 370 GlobalValue *GV = dyn_cast<GlobalValue>(CE->getOperand(0)); |
| 371 if (GV == 0) |
| 372 report_fatal_error( |
| 373 "Argument of ptrtoint in global relocation no global value"); |
| 374 |
| 375 // Now generate the corresponding relocation record. |
| 376 unsigned RelocID = VE.getValueID(GV); |
| 377 // This is a value index. |
| 378 unsigned AbbrevToUse = GLOBALVAR_RELOC_ABBREV; |
| 379 Vals.push_back(RelocID); |
| 380 if (Addend) { |
| 381 Vals.push_back(Addend); |
| 382 AbbrevToUse = GLOBALVAR_RELOC_WITH_ADDEND_ABBREV; |
| 383 } |
| 384 Stream.EmitRecord(naclbitc::GLOBALVAR_RELOC, Vals, AbbrevToUse); |
| 385 Vals.clear(); |
| 386 return; |
| 387 } |
| 388 report_fatal_error("Global initializer is not a SimpleElement"); |
| 389 } |
| 390 |
| 391 // Emit global variables. |
| 392 static void WriteGlobalVars(const Module *M, |
| 393 const NaClValueEnumerator &VE, |
| 394 NaClBitstreamWriter &Stream) { |
| 395 Stream.EnterSubblock(naclbitc::GLOBALVAR_BLOCK_ID); |
| 396 SmallVector<uint32_t, 32> Vals; |
| 397 unsigned GlobalVarID = VE.getFirstGlobalVarID(); |
| 398 |
| 399 // Emit the number of global variables. |
| 400 |
| 401 Vals.push_back(M->getGlobalList().size()); |
| 402 Stream.EmitRecord(naclbitc::GLOBALVAR_COUNT, Vals); |
| 403 Vals.clear(); |
| 404 |
| 405 // Now emit each global variable. |
| 406 for (Module::const_global_iterator |
| 407 GV = M->global_begin(), E = M->global_end(); |
| 408 GV != E; ++GV, ++GlobalVarID) { |
| 409 // Define the global variable. |
| 410 Vals.push_back(Log2_32(GV->getAlignment()) + 1); |
| 411 Vals.push_back(GV->isConstant()); |
| 412 Stream.EmitRecord(naclbitc::GLOBALVAR_VAR, Vals, GLOBALVAR_VAR_ABBREV); |
| 413 Vals.clear(); |
| 414 |
| 415 // Add the field(s). |
| 416 const Constant *C = GV->getInitializer(); |
| 417 if (C == 0) |
| 418 report_fatal_error("Global variable initializer not a constant"); |
| 419 if (const ConstantStruct *CS = dyn_cast<ConstantStruct>(C)) { |
| 420 if (!CS->getType()->isPacked()) |
| 421 report_fatal_error("Global variable type not packed"); |
| 422 if (CS->getType()->hasName()) |
| 423 report_fatal_error("Global variable type is named"); |
| 424 Vals.push_back(CS->getNumOperands()); |
| 425 Stream.EmitRecord(naclbitc::GLOBALVAR_COMPOUND, Vals, |
| 426 GLOBALVAR_COMPOUND_ABBREV); |
| 427 Vals.clear(); |
| 428 for (unsigned I = 0; I < CS->getNumOperands(); ++I) { |
| 429 WriteGlobalInit(dyn_cast<Constant>(CS->getOperand(I)), GlobalVarID, |
| 430 Vals, VE, Stream); |
| 431 } |
| 432 } else { |
| 433 WriteGlobalInit(C, GlobalVarID, Vals, VE, Stream); |
| 434 } |
| 435 } |
| 436 |
| 437 assert(GlobalVarID == VE.getFirstGlobalVarID() + VE.getNumGlobalVarIDs()); |
| 438 Stream.ExitBlock(); |
| 439 } |
| 440 |
| 441 // Emit top-level description of module, including inline asm, |
| 442 // descriptors for global variables, and function prototype info. |
| 443 static void WriteModuleInfo(const Module *M, const NaClValueEnumerator &VE, |
| 444 NaClBitstreamWriter &Stream) { |
| 445 DEBUG(dbgs() << "-> WriteModuleInfo\n"); |
| 446 |
| 447 // Emit the function proto information. Note: We do this before |
| 448 // global variables, so that global variable initializations can |
| 449 // refer to the functions without a forward reference. |
| 450 SmallVector<unsigned, 64> Vals; |
| 451 for (Module::const_iterator F = M->begin(), E = M->end(); F != E; ++F) { |
| 452 // FUNCTION: [type, callingconv, isproto, linkage] |
| 453 Type *Ty = F->getType()->getPointerElementType(); |
| 454 Vals.push_back(VE.getTypeID(Ty)); |
| 455 Vals.push_back(GetEncodedCallingConv(F->getCallingConv())); |
| 456 Vals.push_back(F->isDeclaration()); |
| 457 Vals.push_back(getEncodedLinkage(F)); |
| 458 |
| 459 unsigned AbbrevToUse = 0; |
| 460 Stream.EmitRecord(naclbitc::MODULE_CODE_FUNCTION, Vals, AbbrevToUse); |
| 461 Vals.clear(); |
| 462 } |
| 463 |
| 464 // Emit the global variable information. |
| 465 WriteGlobalVars(M, VE, Stream); |
| 466 DEBUG(dbgs() << "<- WriteModuleInfo\n"); |
| 467 } |
| 468 |
| 469 static void emitSignedInt64(SmallVectorImpl<uint64_t> &Vals, uint64_t V) { |
| 470 Vals.push_back(NaClEncodeSignRotatedValue((int64_t)V)); |
| 471 } |
| 472 |
| 473 static void EmitAPInt(SmallVectorImpl<uint64_t> &Vals, |
| 474 unsigned &Code, unsigned &AbbrevToUse, const APInt &Val) { |
| 475 if (Val.getBitWidth() <= 64) { |
| 476 uint64_t V = Val.getSExtValue(); |
| 477 emitSignedInt64(Vals, V); |
| 478 Code = naclbitc::CST_CODE_INTEGER; |
| 479 AbbrevToUse = |
| 480 Val == 0 ? CONSTANTS_INTEGER_ZERO_ABBREV : CONSTANTS_INTEGER_ABBREV; |
| 481 } else { |
| 482 report_fatal_error("Wide integers are not supported"); |
| 483 } |
| 484 } |
| 485 |
| 486 static void WriteConstants(unsigned FirstVal, unsigned LastVal, |
| 487 const NaClValueEnumerator &VE, |
| 488 NaClBitstreamWriter &Stream) { |
| 489 if (FirstVal == LastVal) return; |
| 490 |
| 491 Stream.EnterSubblock(naclbitc::CONSTANTS_BLOCK_ID, CONSTANTS_MAX_ABBREV); |
| 492 |
| 493 SmallVector<uint64_t, 64> Record; |
| 494 |
| 495 const NaClValueEnumerator::ValueList &Vals = VE.getValues(); |
| 496 Type *LastTy = 0; |
| 497 for (unsigned i = FirstVal; i != LastVal; ++i) { |
| 498 const Value *V = Vals[i].first; |
| 499 // If we need to switch types, do so now. |
| 500 if (V->getType() != LastTy) { |
| 501 LastTy = V->getType(); |
| 502 Record.push_back(VE.getTypeID(LastTy)); |
| 503 Stream.EmitRecord(naclbitc::CST_CODE_SETTYPE, Record, |
| 504 CONSTANTS_SETTYPE_ABBREV); |
| 505 Record.clear(); |
| 506 } |
| 507 |
| 508 if (isa<InlineAsm>(V)) { |
| 509 ReportIllegalValue("inline assembly", *V); |
| 510 } |
| 511 const Constant *C = cast<Constant>(V); |
| 512 unsigned Code = -1U; |
| 513 unsigned AbbrevToUse = 0; |
| 514 if (isa<UndefValue>(C)) { |
| 515 Code = naclbitc::CST_CODE_UNDEF; |
| 516 } else if (const ConstantInt *IV = dyn_cast<ConstantInt>(C)) { |
| 517 EmitAPInt(Record, Code, AbbrevToUse, IV->getValue()); |
| 518 } else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(C)) { |
| 519 Code = naclbitc::CST_CODE_FLOAT; |
| 520 AbbrevToUse = CONSTANTS_FLOAT_ABBREV; |
| 521 Type *Ty = CFP->getType(); |
| 522 if (Ty->isFloatTy() || Ty->isDoubleTy()) { |
| 523 Record.push_back(CFP->getValueAPF().bitcastToAPInt().getZExtValue()); |
| 524 } else { |
| 525 report_fatal_error("Unknown FP type"); |
| 526 } |
| 527 } else { |
| 528 #ifndef NDEBUG |
| 529 C->dump(); |
| 530 #endif |
| 531 ReportIllegalValue("constant", *C); |
| 532 } |
| 533 Stream.EmitRecord(Code, Record, AbbrevToUse); |
| 534 Record.clear(); |
| 535 } |
| 536 |
| 537 Stream.ExitBlock(); |
| 538 DEBUG(dbgs() << "<- WriteConstants\n"); |
| 539 } |
| 540 |
| 541 /// \brief Emits a type for the forward value reference. That is, if |
| 542 /// the ID for the given value is larger than or equal to the BaseID, |
| 543 /// the corresponding forward reference is generated. |
| 544 static void EmitFnForwardTypeRef(const Value *V, |
| 545 unsigned BaseID, |
| 546 NaClValueEnumerator &VE, |
| 547 NaClBitstreamWriter &Stream) { |
| 548 unsigned ValID = VE.getValueID(V); |
| 549 if (ValID >= BaseID && |
| 550 VE.InsertFnForwardTypeRef(ValID)) { |
| 551 SmallVector<unsigned, 2> Vals; |
| 552 Vals.push_back(ValID); |
| 553 Vals.push_back(VE.getTypeID(VE.NormalizeType(V->getType()))); |
| 554 Stream.EmitRecord(naclbitc::FUNC_CODE_INST_FORWARDTYPEREF, Vals, |
| 555 FUNCTION_INST_FORWARDTYPEREF_ABBREV); |
| 556 } |
| 557 } |
| 558 |
| 559 /// pushValue - The file has to encode both the value and type id for |
| 560 /// many values, because we need to know what type to create for forward |
| 561 /// references. However, most operands are not forward references, so this type |
| 562 /// field is not needed. |
| 563 /// |
| 564 /// This function adds V's value ID to Vals. If the value ID is higher than the |
| 565 /// instruction ID, then it is a forward reference, and it also includes the |
| 566 /// type ID. The value ID that is written is encoded relative to the InstID. |
| 567 static void pushValue(const Value *V, unsigned InstID, |
| 568 SmallVector<unsigned, 64> &Vals, |
| 569 NaClValueEnumerator &VE, |
| 570 NaClBitstreamWriter &Stream) { |
| 571 const Value *VElided = VE.ElideCasts(V); |
| 572 EmitFnForwardTypeRef(VElided, InstID, VE, Stream); |
| 573 unsigned ValID = VE.getValueID(VElided); |
| 574 // Make encoding relative to the InstID. |
| 575 Vals.push_back(InstID - ValID); |
| 576 } |
| 577 |
| 578 static void pushValue64(const Value *V, unsigned InstID, |
| 579 SmallVector<uint64_t, 128> &Vals, |
| 580 NaClValueEnumerator &VE, |
| 581 NaClBitstreamWriter &Stream) { |
| 582 const Value *VElided = VE.ElideCasts(V); |
| 583 EmitFnForwardTypeRef(VElided, InstID, VE, Stream); |
| 584 uint64_t ValID = VE.getValueID(VElided); |
| 585 Vals.push_back(InstID - ValID); |
| 586 } |
| 587 |
| 588 static void pushValueSigned(const Value *V, unsigned InstID, |
| 589 SmallVector<uint64_t, 128> &Vals, |
| 590 NaClValueEnumerator &VE, |
| 591 NaClBitstreamWriter &Stream) { |
| 592 const Value *VElided = VE.ElideCasts(V); |
| 593 EmitFnForwardTypeRef(VElided, InstID, VE, Stream); |
| 594 unsigned ValID = VE.getValueID(VElided); |
| 595 int64_t diff = ((int32_t)InstID - (int32_t)ValID); |
| 596 emitSignedInt64(Vals, diff); |
| 597 } |
| 598 |
| 599 /// WriteInstruction - Emit an instruction to the specified stream. |
| 600 /// Returns true if instruction actually emitted. |
| 601 static bool WriteInstruction(const Instruction &I, unsigned InstID, |
| 602 NaClValueEnumerator &VE, |
| 603 NaClBitstreamWriter &Stream, |
| 604 SmallVector<unsigned, 64> &Vals) { |
| 605 unsigned Code = 0; |
| 606 unsigned AbbrevToUse = 0; |
| 607 VE.setInstructionID(&I); |
| 608 switch (I.getOpcode()) { |
| 609 default: |
| 610 if (Instruction::isCast(I.getOpcode())) { |
| 611 // CAST: [opval, destty, castopc] |
| 612 if (VE.IsElidedCast(&I)) |
| 613 return false; |
| 614 Code = naclbitc::FUNC_CODE_INST_CAST; |
| 615 AbbrevToUse = FUNCTION_INST_CAST_ABBREV; |
| 616 pushValue(I.getOperand(0), InstID, Vals, VE, Stream); |
| 617 Vals.push_back(VE.getTypeID(I.getType())); |
| 618 unsigned Opcode = I.getOpcode(); |
| 619 Vals.push_back(GetEncodedCastOpcode(Opcode, I)); |
| 620 if (Opcode == Instruction::PtrToInt || |
| 621 Opcode == Instruction::IntToPtr || |
| 622 (Opcode == Instruction::BitCast && |
| 623 (I.getOperand(0)->getType()->isPointerTy() || |
| 624 I.getType()->isPointerTy()))) { |
| 625 ReportIllegalValue("(PNaCl ABI) pointer cast", I); |
| 626 } |
| 627 } else if (isa<BinaryOperator>(I)) { |
| 628 // BINOP: [opval, opval, opcode] |
| 629 Code = naclbitc::FUNC_CODE_INST_BINOP; |
| 630 AbbrevToUse = FUNCTION_INST_BINOP_ABBREV; |
| 631 pushValue(I.getOperand(0), InstID, Vals, VE, Stream); |
| 632 pushValue(I.getOperand(1), InstID, Vals, VE, Stream); |
| 633 Vals.push_back(GetEncodedBinaryOpcode(I.getOpcode(), I)); |
| 634 } else { |
| 635 ReportIllegalValue("instruction", I); |
| 636 } |
| 637 break; |
| 638 case Instruction::Select: |
| 639 Code = naclbitc::FUNC_CODE_INST_VSELECT; |
| 640 pushValue(I.getOperand(1), InstID, Vals, VE, Stream); |
| 641 pushValue(I.getOperand(2), InstID, Vals, VE, Stream); |
| 642 pushValue(I.getOperand(0), InstID, Vals, VE, Stream); |
| 643 break; |
| 644 case Instruction::ExtractElement: |
| 645 Code = naclbitc::FUNC_CODE_INST_EXTRACTELT; |
| 646 pushValue(I.getOperand(0), InstID, Vals, VE, Stream); |
| 647 pushValue(I.getOperand(1), InstID, Vals, VE, Stream); |
| 648 break; |
| 649 case Instruction::InsertElement: |
| 650 Code = naclbitc::FUNC_CODE_INST_INSERTELT; |
| 651 pushValue(I.getOperand(0), InstID, Vals, VE, Stream); |
| 652 pushValue(I.getOperand(1), InstID, Vals, VE, Stream); |
| 653 pushValue(I.getOperand(2), InstID, Vals, VE, Stream); |
| 654 break; |
| 655 case Instruction::ICmp: |
| 656 case Instruction::FCmp: |
| 657 // compare returning Int1Ty or vector of Int1Ty |
| 658 Code = naclbitc::FUNC_CODE_INST_CMP2; |
| 659 pushValue(I.getOperand(0), InstID, Vals, VE, Stream); |
| 660 pushValue(I.getOperand(1), InstID, Vals, VE, Stream); |
| 661 Vals.push_back(GetEncodedCmpPredicate(cast<CmpInst>(I))); |
| 662 break; |
| 663 |
| 664 case Instruction::Ret: |
| 665 { |
| 666 Code = naclbitc::FUNC_CODE_INST_RET; |
| 667 unsigned NumOperands = I.getNumOperands(); |
| 668 if (NumOperands == 0) |
| 669 AbbrevToUse = FUNCTION_INST_RET_VOID_ABBREV; |
| 670 else if (NumOperands == 1) { |
| 671 pushValue(I.getOperand(0), InstID, Vals, VE, Stream); |
| 672 AbbrevToUse = FUNCTION_INST_RET_VAL_ABBREV; |
| 673 } else { |
| 674 for (unsigned i = 0, e = NumOperands; i != e; ++i) |
| 675 pushValue(I.getOperand(i), InstID, Vals, VE, Stream); |
| 676 } |
| 677 } |
| 678 break; |
| 679 case Instruction::Br: |
| 680 { |
| 681 Code = naclbitc::FUNC_CODE_INST_BR; |
| 682 const BranchInst &II = cast<BranchInst>(I); |
| 683 Vals.push_back(VE.getValueID(II.getSuccessor(0))); |
| 684 if (II.isConditional()) { |
| 685 Vals.push_back(VE.getValueID(II.getSuccessor(1))); |
| 686 pushValue(II.getCondition(), InstID, Vals, VE, Stream); |
| 687 } |
| 688 } |
| 689 break; |
| 690 case Instruction::Switch: |
| 691 { |
| 692 // Redefine Vals, since here we need to use 64 bit values |
| 693 // explicitly to store large APInt numbers. |
| 694 SmallVector<uint64_t, 128> Vals64; |
| 695 |
| 696 Code = naclbitc::FUNC_CODE_INST_SWITCH; |
| 697 const SwitchInst &SI = cast<SwitchInst>(I); |
| 698 |
| 699 Vals64.push_back(VE.getTypeID(SI.getCondition()->getType())); |
| 700 pushValue64(SI.getCondition(), InstID, Vals64, VE, Stream); |
| 701 Vals64.push_back(VE.getValueID(SI.getDefaultDest())); |
| 702 Vals64.push_back(SI.getNumCases()); |
| 703 for (SwitchInst::ConstCaseIt i = SI.case_begin(), e = SI.case_end(); |
| 704 i != e; ++i) { |
| 705 // The PNaCl bitcode format has vestigial support for case |
| 706 // ranges, but we no longer support reading or writing them, |
| 707 // so the next two fields always have the same values. |
| 708 // See https://code.google.com/p/nativeclient/issues/detail?id=3758 |
| 709 Vals64.push_back(1/*NumItems = 1*/); |
| 710 Vals64.push_back(true/*IsSingleNumber = true*/); |
| 711 |
| 712 emitSignedInt64(Vals64, i.getCaseValue()->getSExtValue()); |
| 713 Vals64.push_back(VE.getValueID(i.getCaseSuccessor())); |
| 714 } |
| 715 |
| 716 Stream.EmitRecord(Code, Vals64, AbbrevToUse); |
| 717 |
| 718 // Also do expected action - clear external Vals collection: |
| 719 Vals.clear(); |
| 720 return true; |
| 721 } |
| 722 break; |
| 723 case Instruction::Unreachable: |
| 724 Code = naclbitc::FUNC_CODE_INST_UNREACHABLE; |
| 725 AbbrevToUse = FUNCTION_INST_UNREACHABLE_ABBREV; |
| 726 break; |
| 727 |
| 728 case Instruction::PHI: { |
| 729 const PHINode &PN = cast<PHINode>(I); |
| 730 Code = naclbitc::FUNC_CODE_INST_PHI; |
| 731 // With the newer instruction encoding, forward references could give |
| 732 // negative valued IDs. This is most common for PHIs, so we use |
| 733 // signed VBRs. |
| 734 SmallVector<uint64_t, 128> Vals64; |
| 735 Vals64.push_back(VE.getTypeID(PN.getType())); |
| 736 for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) { |
| 737 pushValueSigned(PN.getIncomingValue(i), InstID, Vals64, VE, Stream); |
| 738 Vals64.push_back(VE.getValueID(PN.getIncomingBlock(i))); |
| 739 } |
| 740 // Emit a Vals64 vector and exit. |
| 741 Stream.EmitRecord(Code, Vals64, AbbrevToUse); |
| 742 Vals64.clear(); |
| 743 return true; |
| 744 } |
| 745 |
| 746 case Instruction::Alloca: |
| 747 if (!cast<AllocaInst>(&I)->getAllocatedType()->isIntegerTy(8)) |
| 748 report_fatal_error("Type of alloca instruction is not i8"); |
| 749 Code = naclbitc::FUNC_CODE_INST_ALLOCA; |
| 750 pushValue(I.getOperand(0), InstID, Vals, VE, Stream); // size. |
| 751 Vals.push_back(Log2_32(cast<AllocaInst>(I).getAlignment())+1); |
| 752 break; |
| 753 case Instruction::Load: |
| 754 // LOAD: [op, align, ty] |
| 755 Code = naclbitc::FUNC_CODE_INST_LOAD; |
| 756 pushValue(I.getOperand(0), InstID, Vals, VE, Stream); |
| 757 AbbrevToUse = FUNCTION_INST_LOAD_ABBREV; |
| 758 Vals.push_back(Log2_32(cast<LoadInst>(I).getAlignment())+1); |
| 759 Vals.push_back(VE.getTypeID(I.getType())); |
| 760 break; |
| 761 case Instruction::Store: |
| 762 // STORE: [ptr, val, align] |
| 763 Code = naclbitc::FUNC_CODE_INST_STORE; |
| 764 AbbrevToUse = FUNCTION_INST_STORE_ABBREV; |
| 765 pushValue(I.getOperand(1), InstID, Vals, VE, Stream); |
| 766 pushValue(I.getOperand(0), InstID, Vals, VE, Stream); |
| 767 Vals.push_back(Log2_32(cast<StoreInst>(I).getAlignment())+1); |
| 768 break; |
| 769 case Instruction::Call: { |
| 770 // CALL: [cc, fnid, args...] |
| 771 // CALL_INDIRECT: [cc, fnid, fnty, args...] |
| 772 |
| 773 const CallInst &Call = cast<CallInst>(I); |
| 774 const Value* Callee = Call.getCalledValue(); |
| 775 Vals.push_back((GetEncodedCallingConv(Call.getCallingConv()) << 1) |
| 776 | unsigned(Call.isTailCall())); |
| 777 |
| 778 pushValue(Callee, InstID, Vals, VE, Stream); |
| 779 |
| 780 if (Callee == VE.ElideCasts(Callee)) { |
| 781 // Since the call pointer has not been elided, we know that |
| 782 // the call pointer has the type signature of the called |
| 783 // function. This implies that the reader can use the type |
| 784 // signature of the callee to figure out how to add casts to |
| 785 // the arguments. |
| 786 Code = naclbitc::FUNC_CODE_INST_CALL; |
| 787 } else { |
| 788 // If the cast was elided, a pointer conversion to a pointer |
| 789 // was applied, meaning that this is an indirect call. For the |
| 790 // reader, this implies that we can't use the type signature |
| 791 // of the callee to resolve elided call arguments, since it is |
| 792 // not known. Hence, we must send the type signature to the |
| 793 // reader. |
| 794 Code = naclbitc::FUNC_CODE_INST_CALL_INDIRECT; |
| 795 Vals.push_back(VE.getTypeID(I.getType())); |
| 796 } |
| 797 |
| 798 for (unsigned I = 0, E = Call.getNumArgOperands(); I < E; ++I) { |
| 799 pushValue(Call.getArgOperand(I), InstID, Vals, VE, Stream); |
| 800 } |
| 801 break; |
| 802 } |
| 803 } |
| 804 |
| 805 Stream.EmitRecord(Code, Vals, AbbrevToUse); |
| 806 Vals.clear(); |
| 807 return true; |
| 808 } |
| 809 |
| 810 // Emit names for globals/functions etc. |
| 811 static void WriteValueSymbolTable(const ValueSymbolTable &VST, |
| 812 const NaClValueEnumerator &VE, |
| 813 NaClBitstreamWriter &Stream) { |
| 814 if (VST.empty()) return; |
| 815 Stream.EnterSubblock(naclbitc::VALUE_SYMTAB_BLOCK_ID); |
| 816 |
| 817 // FIXME: Set up the abbrev, we know how many values there are! |
| 818 // FIXME: We know if the type names can use 7-bit ascii. |
| 819 SmallVector<unsigned, 64> NameVals; |
| 820 |
| 821 for (ValueSymbolTable::const_iterator SI = VST.begin(), SE = VST.end(); |
| 822 SI != SE; ++SI) { |
| 823 if (VE.IsElidedCast(SI->getValue())) continue; |
| 824 |
| 825 const ValueName &Name = *SI; |
| 826 |
| 827 // Figure out the encoding to use for the name. |
| 828 bool is7Bit = true; |
| 829 bool isChar6 = true; |
| 830 for (const char *C = Name.getKeyData(), *E = C+Name.getKeyLength(); |
| 831 C != E; ++C) { |
| 832 if (isChar6) |
| 833 isChar6 = NaClBitCodeAbbrevOp::isChar6(*C); |
| 834 if ((unsigned char)*C & 128) { |
| 835 is7Bit = false; |
| 836 break; // don't bother scanning the rest. |
| 837 } |
| 838 } |
| 839 |
| 840 unsigned AbbrevToUse = VST_ENTRY_8_ABBREV; |
| 841 |
| 842 // VST_ENTRY: [valueid, namechar x N] |
| 843 // VST_BBENTRY: [bbid, namechar x N] |
| 844 unsigned Code; |
| 845 if (isa<BasicBlock>(SI->getValue())) { |
| 846 Code = naclbitc::VST_CODE_BBENTRY; |
| 847 if (isChar6) |
| 848 AbbrevToUse = VST_BBENTRY_6_ABBREV; |
| 849 } else { |
| 850 Code = naclbitc::VST_CODE_ENTRY; |
| 851 if (isChar6) |
| 852 AbbrevToUse = VST_ENTRY_6_ABBREV; |
| 853 else if (is7Bit) |
| 854 AbbrevToUse = VST_ENTRY_7_ABBREV; |
| 855 } |
| 856 |
| 857 NameVals.push_back(VE.getValueID(SI->getValue())); |
| 858 for (const char *P = Name.getKeyData(), |
| 859 *E = Name.getKeyData()+Name.getKeyLength(); P != E; ++P) |
| 860 NameVals.push_back((unsigned char)*P); |
| 861 |
| 862 // Emit the finished record. |
| 863 Stream.EmitRecord(Code, NameVals, AbbrevToUse); |
| 864 NameVals.clear(); |
| 865 } |
| 866 Stream.ExitBlock(); |
| 867 } |
| 868 |
| 869 /// WriteFunction - Emit a function body to the module stream. |
| 870 static void WriteFunction(const Function &F, NaClValueEnumerator &VE, |
| 871 NaClBitstreamWriter &Stream) { |
| 872 Stream.EnterSubblock(naclbitc::FUNCTION_BLOCK_ID); |
| 873 VE.incorporateFunction(F); |
| 874 |
| 875 SmallVector<unsigned, 64> Vals; |
| 876 |
| 877 // Emit the number of basic blocks, so the reader can create them ahead of |
| 878 // time. |
| 879 Vals.push_back(VE.getBasicBlocks().size()); |
| 880 Stream.EmitRecord(naclbitc::FUNC_CODE_DECLAREBLOCKS, Vals); |
| 881 Vals.clear(); |
| 882 |
| 883 // If there are function-local constants, emit them now. |
| 884 unsigned CstStart, CstEnd; |
| 885 VE.getFunctionConstantRange(CstStart, CstEnd); |
| 886 WriteConstants(CstStart, CstEnd, VE, Stream); |
| 887 |
| 888 // Keep a running idea of what the instruction ID is. |
| 889 unsigned InstID = CstEnd; |
| 890 |
| 891 // Finally, emit all the instructions, in order. |
| 892 for (Function::const_iterator BB = F.begin(), E = F.end(); BB != E; ++BB) |
| 893 for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); |
| 894 I != E; ++I) { |
| 895 if (WriteInstruction(*I, InstID, VE, Stream, Vals) && |
| 896 !I->getType()->isVoidTy()) |
| 897 ++InstID; |
| 898 } |
| 899 |
| 900 // Emit names for instructions etc. |
| 901 if (PNaClAllowLocalSymbolTables) |
| 902 WriteValueSymbolTable(F.getValueSymbolTable(), VE, Stream); |
| 903 |
| 904 VE.purgeFunction(); |
| 905 Stream.ExitBlock(); |
| 906 } |
| 907 |
| 908 // Emit blockinfo, which defines the standard abbreviations etc. |
| 909 static void WriteBlockInfo(const NaClValueEnumerator &VE, |
| 910 NaClBitstreamWriter &Stream) { |
| 911 // We only want to emit block info records for blocks that have multiple |
| 912 // instances: CONSTANTS_BLOCK, FUNCTION_BLOCK and VALUE_SYMTAB_BLOCK. |
| 913 // Other blocks can define their abbrevs inline. |
| 914 Stream.EnterBlockInfoBlock(); |
| 915 |
| 916 { // 8-bit fixed-width VST_ENTRY/VST_BBENTRY strings. |
| 917 NaClBitCodeAbbrev *Abbv = new NaClBitCodeAbbrev(); |
| 918 Abbv->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::Fixed, 3)); |
| 919 Abbv->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::VBR, 8)); |
| 920 Abbv->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::Array)); |
| 921 Abbv->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::Fixed, 8)); |
| 922 if (Stream.EmitBlockInfoAbbrev(naclbitc::VALUE_SYMTAB_BLOCK_ID, |
| 923 Abbv) != VST_ENTRY_8_ABBREV) |
| 924 llvm_unreachable("Unexpected abbrev ordering!"); |
| 925 } |
| 926 |
| 927 { // 7-bit fixed width VST_ENTRY strings. |
| 928 NaClBitCodeAbbrev *Abbv = new NaClBitCodeAbbrev(); |
| 929 Abbv->Add(NaClBitCodeAbbrevOp(naclbitc::VST_CODE_ENTRY)); |
| 930 Abbv->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::VBR, 8)); |
| 931 Abbv->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::Array)); |
| 932 Abbv->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::Fixed, 7)); |
| 933 if (Stream.EmitBlockInfoAbbrev(naclbitc::VALUE_SYMTAB_BLOCK_ID, |
| 934 Abbv) != VST_ENTRY_7_ABBREV) |
| 935 llvm_unreachable("Unexpected abbrev ordering!"); |
| 936 } |
| 937 { // 6-bit char6 VST_ENTRY strings. |
| 938 NaClBitCodeAbbrev *Abbv = new NaClBitCodeAbbrev(); |
| 939 Abbv->Add(NaClBitCodeAbbrevOp(naclbitc::VST_CODE_ENTRY)); |
| 940 Abbv->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::VBR, 8)); |
| 941 Abbv->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::Array)); |
| 942 Abbv->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::Char6)); |
| 943 if (Stream.EmitBlockInfoAbbrev(naclbitc::VALUE_SYMTAB_BLOCK_ID, |
| 944 Abbv) != VST_ENTRY_6_ABBREV) |
| 945 llvm_unreachable("Unexpected abbrev ordering!"); |
| 946 } |
| 947 { // 6-bit char6 VST_BBENTRY strings. |
| 948 NaClBitCodeAbbrev *Abbv = new NaClBitCodeAbbrev(); |
| 949 Abbv->Add(NaClBitCodeAbbrevOp(naclbitc::VST_CODE_BBENTRY)); |
| 950 Abbv->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::VBR, 8)); |
| 951 Abbv->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::Array)); |
| 952 Abbv->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::Char6)); |
| 953 if (Stream.EmitBlockInfoAbbrev(naclbitc::VALUE_SYMTAB_BLOCK_ID, |
| 954 Abbv) != VST_BBENTRY_6_ABBREV) |
| 955 llvm_unreachable("Unexpected abbrev ordering!"); |
| 956 } |
| 957 |
| 958 |
| 959 |
| 960 { // SETTYPE abbrev for CONSTANTS_BLOCK. |
| 961 NaClBitCodeAbbrev *Abbv = new NaClBitCodeAbbrev(); |
| 962 Abbv->Add(NaClBitCodeAbbrevOp(naclbitc::CST_CODE_SETTYPE)); |
| 963 Abbv->Add(NaClBitCodeAbbrevOp(TypeIdEncoding, TypeIdNumBits)); |
| 964 if (Stream.EmitBlockInfoAbbrev(naclbitc::CONSTANTS_BLOCK_ID, |
| 965 Abbv) != CONSTANTS_SETTYPE_ABBREV) |
| 966 llvm_unreachable("Unexpected abbrev ordering!"); |
| 967 } |
| 968 |
| 969 { // INTEGER abbrev for CONSTANTS_BLOCK. |
| 970 NaClBitCodeAbbrev *Abbv = new NaClBitCodeAbbrev(); |
| 971 Abbv->Add(NaClBitCodeAbbrevOp(naclbitc::CST_CODE_INTEGER)); |
| 972 Abbv->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::VBR, 8)); |
| 973 if (Stream.EmitBlockInfoAbbrev(naclbitc::CONSTANTS_BLOCK_ID, |
| 974 Abbv) != CONSTANTS_INTEGER_ABBREV) |
| 975 llvm_unreachable("Unexpected abbrev ordering!"); |
| 976 } |
| 977 { // INTEGER_ZERO abbrev for CONSTANTS_BLOCK. |
| 978 NaClBitCodeAbbrev *Abbv = new NaClBitCodeAbbrev(); |
| 979 Abbv->Add(NaClBitCodeAbbrevOp(naclbitc::CST_CODE_INTEGER)); |
| 980 Abbv->Add(NaClBitCodeAbbrevOp(0)); |
| 981 if (Stream.EmitBlockInfoAbbrev(naclbitc::CONSTANTS_BLOCK_ID, |
| 982 Abbv) != CONSTANTS_INTEGER_ZERO_ABBREV) |
| 983 llvm_unreachable("Unexpected abbrev ordering!"); |
| 984 } |
| 985 { // FLOAT abbrev for CONSTANTS_BLOCK. |
| 986 NaClBitCodeAbbrev *Abbv = new NaClBitCodeAbbrev(); |
| 987 Abbv->Add(NaClBitCodeAbbrevOp(naclbitc::CST_CODE_FLOAT)); |
| 988 Abbv->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::VBR, 8)); |
| 989 if (Stream.EmitBlockInfoAbbrev(naclbitc::CONSTANTS_BLOCK_ID, |
| 990 Abbv) != CONSTANTS_FLOAT_ABBREV) |
| 991 llvm_unreachable("Unexpected abbrev ordering!"); |
| 992 } |
| 993 |
| 994 // FIXME: This should only use space for first class types! |
| 995 |
| 996 { // INST_LOAD abbrev for FUNCTION_BLOCK. |
| 997 NaClBitCodeAbbrev *Abbv = new NaClBitCodeAbbrev(); |
| 998 Abbv->Add(NaClBitCodeAbbrevOp(naclbitc::FUNC_CODE_INST_LOAD)); |
| 999 Abbv->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::VBR, 6)); // Ptr |
| 1000 Abbv->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::VBR, 4)); // Align |
| 1001 // Note: The vast majority of load operations are only on integers |
| 1002 // and floats. In addition, no function types are allowed. In |
| 1003 // addition, the type IDs have been sorted based on usage, moving |
| 1004 // type IDs associated integers and floats to very low |
| 1005 // indices. Hence, we assume that we can use a smaller width for |
| 1006 // the typecast. |
| 1007 Abbv->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::VBR, 4)); // TypeCast |
| 1008 if (Stream.EmitBlockInfoAbbrev(naclbitc::FUNCTION_BLOCK_ID, |
| 1009 Abbv) != FUNCTION_INST_LOAD_ABBREV) |
| 1010 llvm_unreachable("Unexpected abbrev ordering!"); |
| 1011 } |
| 1012 { // INST_BINOP abbrev for FUNCTION_BLOCK. |
| 1013 NaClBitCodeAbbrev *Abbv = new NaClBitCodeAbbrev(); |
| 1014 Abbv->Add(NaClBitCodeAbbrevOp(naclbitc::FUNC_CODE_INST_BINOP)); |
| 1015 Abbv->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::VBR, 6)); // LHS |
| 1016 Abbv->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::VBR, 6)); // RHS |
| 1017 Abbv->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::Fixed, 4)); // opc |
| 1018 if (Stream.EmitBlockInfoAbbrev(naclbitc::FUNCTION_BLOCK_ID, |
| 1019 Abbv) != FUNCTION_INST_BINOP_ABBREV) |
| 1020 llvm_unreachable("Unexpected abbrev ordering!"); |
| 1021 } |
| 1022 { // INST_CAST abbrev for FUNCTION_BLOCK. |
| 1023 NaClBitCodeAbbrev *Abbv = new NaClBitCodeAbbrev(); |
| 1024 Abbv->Add(NaClBitCodeAbbrevOp(naclbitc::FUNC_CODE_INST_CAST)); |
| 1025 Abbv->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::VBR, 6)); // OpVal |
| 1026 Abbv->Add(NaClBitCodeAbbrevOp(TypeIdEncoding, TypeIdNumBits)); // dest ty |
| 1027 Abbv->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::Fixed, 4)); // opc |
| 1028 if (Stream.EmitBlockInfoAbbrev(naclbitc::FUNCTION_BLOCK_ID, |
| 1029 Abbv) != FUNCTION_INST_CAST_ABBREV) |
| 1030 llvm_unreachable("Unexpected abbrev ordering!"); |
| 1031 } |
| 1032 |
| 1033 { // INST_RET abbrev for FUNCTION_BLOCK. |
| 1034 NaClBitCodeAbbrev *Abbv = new NaClBitCodeAbbrev(); |
| 1035 Abbv->Add(NaClBitCodeAbbrevOp(naclbitc::FUNC_CODE_INST_RET)); |
| 1036 if (Stream.EmitBlockInfoAbbrev(naclbitc::FUNCTION_BLOCK_ID, |
| 1037 Abbv) != FUNCTION_INST_RET_VOID_ABBREV) |
| 1038 llvm_unreachable("Unexpected abbrev ordering!"); |
| 1039 } |
| 1040 { // INST_RET abbrev for FUNCTION_BLOCK. |
| 1041 NaClBitCodeAbbrev *Abbv = new NaClBitCodeAbbrev(); |
| 1042 Abbv->Add(NaClBitCodeAbbrevOp(naclbitc::FUNC_CODE_INST_RET)); |
| 1043 Abbv->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::VBR, 6)); // ValID |
| 1044 if (Stream.EmitBlockInfoAbbrev(naclbitc::FUNCTION_BLOCK_ID, |
| 1045 Abbv) != FUNCTION_INST_RET_VAL_ABBREV) |
| 1046 llvm_unreachable("Unexpected abbrev ordering!"); |
| 1047 } |
| 1048 { // INST_UNREACHABLE abbrev for FUNCTION_BLOCK. |
| 1049 NaClBitCodeAbbrev *Abbv = new NaClBitCodeAbbrev(); |
| 1050 Abbv->Add(NaClBitCodeAbbrevOp(naclbitc::FUNC_CODE_INST_UNREACHABLE)); |
| 1051 if (Stream.EmitBlockInfoAbbrev(naclbitc::FUNCTION_BLOCK_ID, |
| 1052 Abbv) != FUNCTION_INST_UNREACHABLE_ABBREV) |
| 1053 llvm_unreachable("Unexpected abbrev ordering!"); |
| 1054 } |
| 1055 { // INST_FORWARDTYPEREF abbrev for FUNCTION_BLOCK. |
| 1056 NaClBitCodeAbbrev *Abbv = new NaClBitCodeAbbrev(); |
| 1057 Abbv->Add(NaClBitCodeAbbrevOp(naclbitc::FUNC_CODE_INST_FORWARDTYPEREF)); |
| 1058 Abbv->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::VBR, 6)); |
| 1059 Abbv->Add(NaClBitCodeAbbrevOp(TypeIdEncoding, TypeIdNumBits)); |
| 1060 if (Stream.EmitBlockInfoAbbrev(naclbitc::FUNCTION_BLOCK_ID, |
| 1061 Abbv) != FUNCTION_INST_FORWARDTYPEREF_ABBREV) |
| 1062 llvm_unreachable("Unexpected abbrev ordering!"); |
| 1063 } |
| 1064 { // INST_STORE abbrev for FUNCTION_BLOCK. |
| 1065 NaClBitCodeAbbrev *Abbv = new NaClBitCodeAbbrev(); |
| 1066 Abbv->Add(NaClBitCodeAbbrevOp(naclbitc::FUNC_CODE_INST_STORE)); |
| 1067 Abbv->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::VBR, 6)); // Ptr |
| 1068 Abbv->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::VBR, 6)); // Value |
| 1069 Abbv->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::VBR, 4)); // Align |
| 1070 if (Stream.EmitBlockInfoAbbrev(naclbitc::FUNCTION_BLOCK_ID, |
| 1071 Abbv) != FUNCTION_INST_STORE_ABBREV) |
| 1072 llvm_unreachable("Unexpected abbrev ordering!"); |
| 1073 } |
| 1074 |
| 1075 { // VAR abbrev for GLOBALVAR_BLOCK. |
| 1076 NaClBitCodeAbbrev *Abbv = new NaClBitCodeAbbrev(); |
| 1077 Abbv->Add(NaClBitCodeAbbrevOp(naclbitc::GLOBALVAR_VAR)); |
| 1078 Abbv->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::VBR, 6)); |
| 1079 Abbv->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::Fixed, 1)); |
| 1080 if (Stream.EmitBlockInfoAbbrev(naclbitc::GLOBALVAR_BLOCK_ID, |
| 1081 Abbv) != GLOBALVAR_VAR_ABBREV) |
| 1082 llvm_unreachable("Unexpected abbrev ordering!"); |
| 1083 } |
| 1084 { // COMPOUND abbrev for GLOBALVAR_BLOCK. |
| 1085 NaClBitCodeAbbrev *Abbv = new NaClBitCodeAbbrev(); |
| 1086 Abbv->Add(NaClBitCodeAbbrevOp(naclbitc::GLOBALVAR_COMPOUND)); |
| 1087 Abbv->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::VBR, 8)); |
| 1088 if (Stream.EmitBlockInfoAbbrev(naclbitc::GLOBALVAR_BLOCK_ID, |
| 1089 Abbv) != GLOBALVAR_COMPOUND_ABBREV) |
| 1090 llvm_unreachable("Unexpected abbrev ordering!"); |
| 1091 } |
| 1092 { // ZEROFILL abbrev for GLOBALVAR_BLOCK. |
| 1093 NaClBitCodeAbbrev *Abbv = new NaClBitCodeAbbrev(); |
| 1094 Abbv->Add(NaClBitCodeAbbrevOp(naclbitc::GLOBALVAR_ZEROFILL)); |
| 1095 Abbv->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::VBR, 8)); |
| 1096 if (Stream.EmitBlockInfoAbbrev(naclbitc::GLOBALVAR_BLOCK_ID, |
| 1097 Abbv) != GLOBALVAR_ZEROFILL_ABBREV) |
| 1098 llvm_unreachable("Unexpected abbrev ordering!"); |
| 1099 } |
| 1100 { // DATA abbrev for GLOBALVAR_BLOCK. |
| 1101 NaClBitCodeAbbrev *Abbv = new NaClBitCodeAbbrev(); |
| 1102 Abbv->Add(NaClBitCodeAbbrevOp(naclbitc::GLOBALVAR_DATA)); |
| 1103 Abbv->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::Array)); |
| 1104 Abbv->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::Fixed, 8)); |
| 1105 if (Stream.EmitBlockInfoAbbrev(naclbitc::GLOBALVAR_BLOCK_ID, |
| 1106 Abbv) != GLOBALVAR_DATA_ABBREV) |
| 1107 llvm_unreachable("Unexpected abbrev ordering!"); |
| 1108 } |
| 1109 { // RELOC abbrev for GLOBALVAR_BLOCK. |
| 1110 NaClBitCodeAbbrev *Abbv = new NaClBitCodeAbbrev(); |
| 1111 Abbv->Add(NaClBitCodeAbbrevOp(naclbitc::GLOBALVAR_RELOC)); |
| 1112 Abbv->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::VBR, 6)); |
| 1113 if (Stream.EmitBlockInfoAbbrev(naclbitc::GLOBALVAR_BLOCK_ID, |
| 1114 Abbv) != GLOBALVAR_RELOC_ABBREV) |
| 1115 llvm_unreachable("Unexpected abbrev ordering!"); |
| 1116 } |
| 1117 { // RELOC_WITH_ADDEND_ABBREV abbrev for GLOBALVAR_BLOCK. |
| 1118 NaClBitCodeAbbrev *Abbv = new NaClBitCodeAbbrev(); |
| 1119 Abbv->Add(NaClBitCodeAbbrevOp(naclbitc::GLOBALVAR_RELOC)); |
| 1120 Abbv->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::VBR, 6)); |
| 1121 Abbv->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::VBR, 6)); |
| 1122 if (Stream.EmitBlockInfoAbbrev( |
| 1123 naclbitc::GLOBALVAR_BLOCK_ID, |
| 1124 Abbv) != GLOBALVAR_RELOC_WITH_ADDEND_ABBREV) |
| 1125 llvm_unreachable("Unexpected abbrev ordering!"); |
| 1126 } |
| 1127 |
| 1128 Stream.ExitBlock(); |
| 1129 } |
| 1130 |
| 1131 /// WriteModule - Emit the specified module to the bitstream. |
| 1132 static void WriteModule(const Module *M, NaClBitstreamWriter &Stream) { |
| 1133 DEBUG(dbgs() << "-> WriteModule\n"); |
| 1134 Stream.EnterSubblock(naclbitc::MODULE_BLOCK_ID); |
| 1135 |
| 1136 SmallVector<unsigned, 1> Vals; |
| 1137 unsigned CurVersion = 1; |
| 1138 Vals.push_back(CurVersion); |
| 1139 Stream.EmitRecord(naclbitc::MODULE_CODE_VERSION, Vals); |
| 1140 |
| 1141 // Analyze the module, enumerating globals, functions, etc. |
| 1142 NaClValueEnumerator VE(M); |
| 1143 OptimizeTypeIdEncoding(VE); |
| 1144 |
| 1145 // Emit blockinfo, which defines the standard abbreviations etc. |
| 1146 WriteBlockInfo(VE, Stream); |
| 1147 |
| 1148 // Emit information describing all of the types in the module. |
| 1149 WriteTypeTable(VE, Stream); |
| 1150 |
| 1151 // Emit top-level description of module, including inline asm, |
| 1152 // descriptors for global variables, and function prototype info. |
| 1153 WriteModuleInfo(M, VE, Stream); |
| 1154 |
| 1155 // Emit names for globals/functions etc. |
| 1156 WriteValueSymbolTable(M->getValueSymbolTable(), VE, Stream); |
| 1157 |
| 1158 // Emit function bodies. |
| 1159 for (Module::const_iterator F = M->begin(), E = M->end(); F != E; ++F) |
| 1160 if (!F->isDeclaration()) |
| 1161 WriteFunction(*F, VE, Stream); |
| 1162 |
| 1163 Stream.ExitBlock(); |
| 1164 DEBUG(dbgs() << "<- WriteModule\n"); |
| 1165 } |
| 1166 |
| 1167 // Max size for variable fields. Currently only used for writing them |
| 1168 // out to files (the parsing works for arbitrary sizes). |
| 1169 static const size_t kMaxVariableFieldSize = 256; |
| 1170 |
| 1171 void llvm::NaClWriteHeader(NaClBitstreamWriter &Stream, |
| 1172 bool AcceptSupportedOnly) { |
| 1173 NaClBitcodeHeader Header; |
| 1174 Header.push_back( |
| 1175 new NaClBitcodeHeaderField(NaClBitcodeHeaderField::kPNaClVersion, |
| 1176 PNaClVersion)); |
| 1177 Header.InstallFields(); |
| 1178 if (!(Header.IsSupported() || |
| 1179 (!AcceptSupportedOnly && Header.IsReadable()))) { |
| 1180 report_fatal_error(Header.Unsupported()); |
| 1181 } |
| 1182 NaClWriteHeader(Header, Stream); |
| 1183 } |
| 1184 |
| 1185 // Write out the given Header to the bitstream. |
| 1186 void llvm::NaClWriteHeader(const NaClBitcodeHeader &Header, |
| 1187 NaClBitstreamWriter &Stream) { |
| 1188 // Emit the file magic number; |
| 1189 Stream.Emit((unsigned)'P', 8); |
| 1190 Stream.Emit((unsigned)'E', 8); |
| 1191 Stream.Emit((unsigned)'X', 8); |
| 1192 Stream.Emit((unsigned)'E', 8); |
| 1193 |
| 1194 // Emit placeholder for number of bytes used to hold header fields. |
| 1195 // This value is necessary so that the streamable reader can preallocate |
| 1196 // a buffer to read the fields. |
| 1197 Stream.Emit(0, naclbitc::BlockSizeWidth); |
| 1198 unsigned BytesForHeader = 0; |
| 1199 |
| 1200 unsigned NumberFields = Header.NumberFields(); |
| 1201 if (NumberFields > 0xFFFF) |
| 1202 report_fatal_error("Too many header fields"); |
| 1203 |
| 1204 uint8_t Buffer[kMaxVariableFieldSize]; |
| 1205 for (unsigned F = 0; F < NumberFields; ++F) { |
| 1206 NaClBitcodeHeaderField *Field = Header.GetField(F); |
| 1207 if (!Field->Write(Buffer, kMaxVariableFieldSize)) |
| 1208 report_fatal_error("Header field too big to generate"); |
| 1209 size_t limit = Field->GetTotalSize(); |
| 1210 for (size_t i = 0; i < limit; i++) { |
| 1211 Stream.Emit(Buffer[i], 8); |
| 1212 } |
| 1213 BytesForHeader += limit; |
| 1214 } |
| 1215 |
| 1216 if (BytesForHeader > 0xFFFF) |
| 1217 report_fatal_error("Header fields to big to save"); |
| 1218 |
| 1219 // Encode #fields in top two bytes, and #bytes to hold fields in |
| 1220 // bottom two bytes. Then backpatch into second word. |
| 1221 unsigned Value = NumberFields | (BytesForHeader << 16); |
| 1222 Stream.BackpatchWord(NaClBitcodeHeader::WordSize, Value); |
| 1223 } |
| 1224 |
| 1225 /// WriteBitcodeToFile - Write the specified module to the specified output |
| 1226 /// stream. |
| 1227 void llvm::NaClWriteBitcodeToFile(const Module *M, raw_ostream &Out, |
| 1228 bool AcceptSupportedOnly) { |
| 1229 SmallVector<char, 0> Buffer; |
| 1230 Buffer.reserve(256*1024); |
| 1231 |
| 1232 // Emit the module into the buffer. |
| 1233 { |
| 1234 NaClBitstreamWriter Stream(Buffer); |
| 1235 NaClWriteHeader(Stream, AcceptSupportedOnly); |
| 1236 WriteModule(M, Stream); |
| 1237 } |
| 1238 |
| 1239 // Write the generated bitstream to "Out". |
| 1240 Out.write((char*)&Buffer.front(), Buffer.size()); |
| 1241 } |
OLD | NEW |