X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FBitcode%2FWriter%2FBitcodeWriter.cpp;h=9cb57585762cd938a51ef8c71f4ed77d318a5f50;hb=b515d75856f58a8b3b71d782eb00916d686329ad;hp=aaad22688a41831b23fbf8ab5ddae3e2de4de4b8;hpb=f8342b98663096186c3a367f7d0fd5ebb7064a52;p=oota-llvm.git diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp index aaad22688a4..9cb57585762 100644 --- a/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -19,11 +19,15 @@ #include "llvm/DerivedTypes.h" #include "llvm/InlineAsm.h" #include "llvm/Instructions.h" +#include "llvm/Metadata.h" #include "llvm/Module.h" -#include "llvm/ParamAttrsList.h" +#include "llvm/Operator.h" #include "llvm/TypeSymbolTable.h" #include "llvm/ValueSymbolTable.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/System/Program.h" using namespace llvm; /// These are manifest constants used by the bitcode writer. They do not need to @@ -46,6 +50,7 @@ enum { // FUNCTION_BLOCK abbrev id's. FUNCTION_INST_LOAD_ABBREV = bitc::FIRST_APPLICATION_ABBREV, FUNCTION_INST_BINOP_ABBREV, + FUNCTION_INST_BINOP_FLAGS_ABBREV, FUNCTION_INST_CAST_ABBREV, FUNCTION_INST_RET_VOID_ABBREV, FUNCTION_INST_RET_VAL_ABBREV, @@ -55,7 +60,7 @@ enum { static unsigned GetEncodedCastOpcode(unsigned Opcode) { switch (Opcode) { - default: assert(0 && "Unknown cast instruction!"); + default: llvm_unreachable("Unknown cast instruction!"); case Instruction::Trunc : return bitc::CAST_TRUNC; case Instruction::ZExt : return bitc::CAST_ZEXT; case Instruction::SExt : return bitc::CAST_SEXT; @@ -73,10 +78,13 @@ static unsigned GetEncodedCastOpcode(unsigned Opcode) { static unsigned GetEncodedBinaryOpcode(unsigned Opcode) { switch (Opcode) { - default: assert(0 && "Unknown binary instruction!"); - case Instruction::Add: return bitc::BINOP_ADD; - case Instruction::Sub: return bitc::BINOP_SUB; - case Instruction::Mul: return bitc::BINOP_MUL; + default: llvm_unreachable("Unknown binary instruction!"); + case Instruction::Add: + case Instruction::FAdd: return bitc::BINOP_ADD; + case Instruction::Sub: + case Instruction::FSub: return bitc::BINOP_SUB; + case Instruction::Mul: + case Instruction::FMul: return bitc::BINOP_MUL; case Instruction::UDiv: return bitc::BINOP_UDIV; case Instruction::FDiv: case Instruction::SDiv: return bitc::BINOP_SDIV; @@ -107,19 +115,30 @@ static void WriteStringRecord(unsigned Code, const std::string &Str, } // Emit information about parameter attributes. -static void WriteParamAttrTable(const ValueEnumerator &VE, +static void WriteAttributeTable(const ValueEnumerator &VE, BitstreamWriter &Stream) { - const std::vector &Attrs = VE.getParamAttrs(); + const std::vector &Attrs = VE.getAttributes(); if (Attrs.empty()) return; Stream.EnterSubblock(bitc::PARAMATTR_BLOCK_ID, 3); SmallVector Record; for (unsigned i = 0, e = Attrs.size(); i != e; ++i) { - const ParamAttrsList *A = Attrs[i]; - for (unsigned op = 0, e = A->size(); op != e; ++op) { - Record.push_back(A->getParamIndex(op)); - Record.push_back(A->getParamAttrsAtIndex(op)); + const AttrListPtr &A = Attrs[i]; + for (unsigned i = 0, e = A.getNumSlots(); i != e; ++i) { + const AttributeWithIndex &PAWI = A.getSlot(i); + Record.push_back(PAWI.Index); + + // FIXME: remove in LLVM 3.0 + // Store the alignment in the bitcode as a 16-bit raw value instead of a + // 5-bit log2 encoded value. Shift the bits above the alignment up by + // 11 bits. + uint64_t FauxAttr = PAWI.Attrs & 0xffff; + if (PAWI.Attrs & Attribute::Alignment) + FauxAttr |= (1ull<<16)<<(((PAWI.Attrs & Attribute::Alignment)-1) >> 16); + FauxAttr |= (PAWI.Attrs & (0x3FFull << 21)) << 11; + + Record.push_back(FauxAttr); } Stream.EmitRecord(bitc::PARAMATTR_CODE_ENTRY, Record); @@ -183,7 +202,7 @@ static void WriteTypeTable(const ValueEnumerator &VE, BitstreamWriter &Stream) { unsigned Code = 0; switch (T->getTypeID()) { - default: assert(0 && "Unknown type!"); + default: llvm_unreachable("Unknown type!"); case Type::VoidTyID: Code = bitc::TYPE_CODE_VOID; break; case Type::FloatTyID: Code = bitc::TYPE_CODE_FLOAT; break; case Type::DoubleTyID: Code = bitc::TYPE_CODE_DOUBLE; break; @@ -192,6 +211,7 @@ static void WriteTypeTable(const ValueEnumerator &VE, BitstreamWriter &Stream) { case Type::PPC_FP128TyID: Code = bitc::TYPE_CODE_PPC_FP128; break; case Type::LabelTyID: Code = bitc::TYPE_CODE_LABEL; break; case Type::OpaqueTyID: Code = bitc::TYPE_CODE_OPAQUE; break; + case Type::MetadataTyID: Code = bitc::TYPE_CODE_METADATA; break; case Type::IntegerTyID: // INTEGER: [width] Code = bitc::TYPE_CODE_INTEGER; @@ -260,22 +280,28 @@ static void WriteTypeTable(const ValueEnumerator &VE, BitstreamWriter &Stream) { static unsigned getEncodedLinkage(const GlobalValue *GV) { switch (GV->getLinkage()) { - default: assert(0 && "Invalid linkage!"); + default: llvm_unreachable("Invalid linkage!"); case GlobalValue::GhostLinkage: // Map ghost linkage onto external. - case GlobalValue::ExternalLinkage: return 0; - case GlobalValue::WeakLinkage: return 1; - case GlobalValue::AppendingLinkage: return 2; - case GlobalValue::InternalLinkage: return 3; - case GlobalValue::LinkOnceLinkage: return 4; - case GlobalValue::DLLImportLinkage: return 5; - case GlobalValue::DLLExportLinkage: return 6; - case GlobalValue::ExternalWeakLinkage: return 7; + case GlobalValue::ExternalLinkage: return 0; + case GlobalValue::WeakAnyLinkage: return 1; + case GlobalValue::AppendingLinkage: return 2; + case GlobalValue::InternalLinkage: return 3; + case GlobalValue::LinkOnceAnyLinkage: return 4; + case GlobalValue::DLLImportLinkage: return 5; + case GlobalValue::DLLExportLinkage: return 6; + case GlobalValue::ExternalWeakLinkage: return 7; + case GlobalValue::CommonLinkage: return 8; + case GlobalValue::PrivateLinkage: return 9; + case GlobalValue::WeakODRLinkage: return 10; + case GlobalValue::LinkOnceODRLinkage: return 11; + case GlobalValue::AvailableExternallyLinkage: return 12; + case GlobalValue::LinkerPrivateLinkage: return 13; } } static unsigned getEncodedVisibility(const GlobalValue *GV) { switch (GV->getVisibility()) { - default: assert(0 && "Invalid visibility!"); + default: llvm_unreachable("Invalid visibility!"); case GlobalValue::DefaultVisibility: return 0; case GlobalValue::HiddenVisibility: return 1; case GlobalValue::ProtectedVisibility: return 2; @@ -301,10 +327,10 @@ static void WriteModuleInfo(const Module *M, const ValueEnumerator &VE, WriteStringRecord(bitc::MODULE_CODE_ASM, M->getModuleInlineAsm(), 0/*TODO*/, Stream); - // Emit information about sections and collectors, computing how many there - // are. Also compute the maximum alignment value. + // Emit information about sections and GC, computing how many there are. Also + // compute the maximum alignment value. std::map SectionMap; - std::map CollectorMap; + std::map GCMap; unsigned MaxAlignment = 0; unsigned MaxGlobalType = 0; for (Module::const_global_iterator GV = M->global_begin(),E = M->global_end(); @@ -331,13 +357,13 @@ static void WriteModuleInfo(const Module *M, const ValueEnumerator &VE, Entry = SectionMap.size(); } } - if (F->hasCollector()) { - // Same for collector names. - unsigned &Entry = CollectorMap[F->getCollector()]; + if (F->hasGC()) { + // Same for GC names. + unsigned &Entry = GCMap[F->getGC()]; if (!Entry) { - WriteStringRecord(bitc::MODULE_CODE_COLLECTORNAME, F->getCollector(), + WriteStringRecord(bitc::MODULE_CODE_GCNAME, F->getGC(), 0/*TODO*/, Stream); - Entry = CollectorMap.size(); + Entry = GCMap.size(); } } } @@ -352,7 +378,7 @@ static void WriteModuleInfo(const Module *M, const ValueEnumerator &VE, Log2_32_Ceil(MaxGlobalType+1))); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Constant. Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Initializer. - Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Linkage. + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // Linkage. if (MaxAlignment == 0) // Alignment. Abbv->Add(BitCodeAbbrevOp(0)); else { @@ -399,16 +425,16 @@ static void WriteModuleInfo(const Module *M, const ValueEnumerator &VE, // Emit the function proto information. for (Module::const_iterator F = M->begin(), E = M->end(); F != E; ++F) { // FUNCTION: [type, callingconv, isproto, paramattr, - // linkage, alignment, section, visibility, collector] + // linkage, alignment, section, visibility, gc] Vals.push_back(VE.getTypeID(F->getType())); Vals.push_back(F->getCallingConv()); Vals.push_back(F->isDeclaration()); Vals.push_back(getEncodedLinkage(F)); - Vals.push_back(VE.getParamAttrID(F->getParamAttrs())); + Vals.push_back(VE.getAttributeID(F->getAttributes())); Vals.push_back(Log2_32(F->getAlignment())+1); Vals.push_back(F->hasSection() ? SectionMap[F->getSection()] : 0); Vals.push_back(getEncodedVisibility(F)); - Vals.push_back(F->hasCollector() ? CollectorMap[F->getCollector()] : 0); + Vals.push_back(F->hasGC() ? GCMap[F->getGC()] : 0); unsigned AbbrevToUse = 0; Stream.EmitRecord(bitc::MODULE_CODE_FUNCTION, Vals, AbbrevToUse); @@ -429,6 +455,104 @@ static void WriteModuleInfo(const Module *M, const ValueEnumerator &VE, } } +static uint64_t GetOptimizationFlags(const Value *V) { + uint64_t Flags = 0; + + if (const OverflowingBinaryOperator *OBO = + dyn_cast(V)) { + if (OBO->hasNoSignedWrap()) + Flags |= 1 << bitc::OBO_NO_SIGNED_WRAP; + if (OBO->hasNoUnsignedWrap()) + Flags |= 1 << bitc::OBO_NO_UNSIGNED_WRAP; + } else if (const SDivOperator *Div = dyn_cast(V)) { + if (Div->isExact()) + Flags |= 1 << bitc::SDIV_EXACT; + } + + return Flags; +} + +static void WriteMDNode(const MDNode *N, + const ValueEnumerator &VE, + BitstreamWriter &Stream, + SmallVector &Record) { + for (unsigned i = 0, e = N->getNumElements(); i != e; ++i) { + if (N->getElement(i)) { + Record.push_back(VE.getTypeID(N->getElement(i)->getType())); + Record.push_back(VE.getValueID(N->getElement(i))); + } else { + Record.push_back(VE.getTypeID(Type::getVoidTy(N->getContext()))); + Record.push_back(0); + } + } + Stream.EmitRecord(bitc::METADATA_NODE, Record, 0); + Record.clear(); +} + +static void WriteModuleMetadata(const ValueEnumerator &VE, + BitstreamWriter &Stream) { + const ValueEnumerator::ValueList &Vals = VE.getMDValues(); + bool StartedMetadataBlock = false; + unsigned MDSAbbrev = 0; + SmallVector Record; + for (unsigned i = 0, e = Vals.size(); i != e; ++i) { + + if (const MDNode *N = dyn_cast(Vals[i].first)) { + if (!StartedMetadataBlock) { + Stream.EnterSubblock(bitc::METADATA_BLOCK_ID, 3); + StartedMetadataBlock = true; + } + WriteMDNode(N, VE, Stream, Record); + } else if (const MDString *MDS = dyn_cast(Vals[i].first)) { + if (!StartedMetadataBlock) { + Stream.EnterSubblock(bitc::METADATA_BLOCK_ID, 3); + + // Abbrev for METADATA_STRING. + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::METADATA_STRING)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8)); + MDSAbbrev = Stream.EmitAbbrev(Abbv); + StartedMetadataBlock = true; + } + + // Code: [strchar x N] + const char *StrBegin = MDS->begin(); + for (unsigned i = 0, e = MDS->length(); i != e; ++i) + Record.push_back(StrBegin[i]); + + // Emit the finished record. + Stream.EmitRecord(bitc::METADATA_STRING, Record, MDSAbbrev); + Record.clear(); + } else if (const NamedMDNode *NMD = dyn_cast(Vals[i].first)) { + if (!StartedMetadataBlock) { + Stream.EnterSubblock(bitc::METADATA_BLOCK_ID, 3); + StartedMetadataBlock = true; + } + + // Write name. + std::string Str = NMD->getNameStr(); + const char *StrBegin = Str.c_str(); + for (unsigned i = 0, e = Str.length(); i != e; ++i) + Record.push_back(StrBegin[i]); + Stream.EmitRecord(bitc::METADATA_NAME, Record, 0/*TODO*/); + Record.clear(); + + // Write named metadata elements. + for (unsigned i = 0, e = NMD->getNumElements(); i != e; ++i) { + if (NMD->getElement(i)) + Record.push_back(VE.getValueID(NMD->getElement(i))); + else + Record.push_back(0); + } + Stream.EmitRecord(bitc::METADATA_NAMED_NODE, Record, 0); + Record.clear(); + } + } + + if (StartedMetadataBlock) + Stream.ExitBlock(); +} static void WriteConstants(unsigned FirstVal, unsigned LastVal, const ValueEnumerator &VE, @@ -538,16 +662,19 @@ static void WriteConstants(unsigned FirstVal, unsigned LastVal, } else if (const ConstantFP *CFP = dyn_cast(C)) { Code = bitc::CST_CODE_FLOAT; const Type *Ty = CFP->getType(); - if (Ty == Type::FloatTy || Ty == Type::DoubleTy) { - Record.push_back(CFP->getValueAPF().convertToAPInt().getZExtValue()); - } else if (Ty == Type::X86_FP80Ty) { + if (Ty == Type::getFloatTy(Ty->getContext()) || + Ty == Type::getDoubleTy(Ty->getContext())) { + Record.push_back(CFP->getValueAPF().bitcastToAPInt().getZExtValue()); + } else if (Ty == Type::getX86_FP80Ty(Ty->getContext())) { // api needed to prevent premature destruction - APInt api = CFP->getValueAPF().convertToAPInt(); + // bits are not in the same order as a normal i80 APInt, compensate. + APInt api = CFP->getValueAPF().bitcastToAPInt(); const uint64_t *p = api.getRawData(); - Record.push_back(p[0]); - Record.push_back((uint16_t)p[1]); - } else if (Ty == Type::FP128Ty || Ty == Type::PPC_FP128Ty) { - APInt api = CFP->getValueAPF().convertToAPInt(); + Record.push_back((p[1] << 48) | (p[0] >> 16)); + Record.push_back(p[0] & 0xffffLL); + } else if (Ty == Type::getFP128Ty(Ty->getContext()) || + Ty == Type::getPPC_FP128Ty(Ty->getContext())) { + APInt api = CFP->getValueAPF().bitcastToAPInt(); const uint64_t *p = api.getRawData(); Record.push_back(p[0]); Record.push_back(p[1]); @@ -600,10 +727,15 @@ static void WriteConstants(unsigned FirstVal, unsigned LastVal, Record.push_back(GetEncodedBinaryOpcode(CE->getOpcode())); Record.push_back(VE.getValueID(C->getOperand(0))); Record.push_back(VE.getValueID(C->getOperand(1))); + uint64_t Flags = GetOptimizationFlags(CE); + if (Flags != 0) + Record.push_back(Flags); } break; case Instruction::GetElementPtr: Code = bitc::CST_CODE_CE_GEP; + if (cast(C)->isInBounds()) + Code = bitc::CST_CODE_CE_INBOUNDS_GEP; for (unsigned i = 0, e = CE->getNumOperands(); i != e; ++i) { Record.push_back(VE.getTypeID(C->getOperand(i)->getType())); Record.push_back(VE.getValueID(C->getOperand(i))); @@ -628,7 +760,16 @@ static void WriteConstants(unsigned FirstVal, unsigned LastVal, Record.push_back(VE.getValueID(C->getOperand(2))); break; case Instruction::ShuffleVector: - Code = bitc::CST_CODE_CE_SHUFFLEVEC; + // If the return type and argument types are the same, this is a + // standard shufflevector instruction. If the types are different, + // then the shuffle is widening or truncating the input vectors, and + // the argument type must also be encoded. + if (C->getType() == C->getOperand(0)->getType()) { + Code = bitc::CST_CODE_CE_SHUFFLEVEC; + } else { + Code = bitc::CST_CODE_CE_SHUFVEC_EX; + Record.push_back(VE.getTypeID(C->getOperand(0)->getType())); + } Record.push_back(VE.getValueID(C->getOperand(0))); Record.push_back(VE.getValueID(C->getOperand(1))); Record.push_back(VE.getValueID(C->getOperand(2))); @@ -643,7 +784,7 @@ static void WriteConstants(unsigned FirstVal, unsigned LastVal, break; } } else { - assert(0 && "Unknown constant!"); + llvm_unreachable("Unknown constant!"); } Stream.EmitRecord(Code, Record, AbbrevToUse); Record.clear(); @@ -674,7 +815,7 @@ static void WriteModuleConstants(const ValueEnumerator &VE, /// This function adds V's value ID to Vals. If the value ID is higher than the /// instruction ID, then it is a forward reference, and it also includes the /// type ID. -static bool PushValueAndType(Value *V, unsigned InstID, +static bool PushValueAndType(const Value *V, unsigned InstID, SmallVector &Vals, ValueEnumerator &VE) { unsigned ValID = VE.getValueID(V); @@ -707,19 +848,44 @@ static void WriteInstruction(const Instruction &I, unsigned InstID, AbbrevToUse = FUNCTION_INST_BINOP_ABBREV; Vals.push_back(VE.getValueID(I.getOperand(1))); Vals.push_back(GetEncodedBinaryOpcode(I.getOpcode())); + uint64_t Flags = GetOptimizationFlags(&I); + if (Flags != 0) { + if (AbbrevToUse == FUNCTION_INST_BINOP_ABBREV) + AbbrevToUse = FUNCTION_INST_BINOP_FLAGS_ABBREV; + Vals.push_back(Flags); + } } break; case Instruction::GetElementPtr: Code = bitc::FUNC_CODE_INST_GEP; + if (cast(&I)->isInBounds()) + Code = bitc::FUNC_CODE_INST_INBOUNDS_GEP; for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) PushValueAndType(I.getOperand(i), InstID, Vals, VE); break; + case Instruction::ExtractValue: { + Code = bitc::FUNC_CODE_INST_EXTRACTVAL; + PushValueAndType(I.getOperand(0), InstID, Vals, VE); + const ExtractValueInst *EVI = cast(&I); + for (const unsigned *i = EVI->idx_begin(), *e = EVI->idx_end(); i != e; ++i) + Vals.push_back(*i); + break; + } + case Instruction::InsertValue: { + Code = bitc::FUNC_CODE_INST_INSERTVAL; + PushValueAndType(I.getOperand(0), InstID, Vals, VE); + PushValueAndType(I.getOperand(1), InstID, Vals, VE); + const InsertValueInst *IVI = cast(&I); + for (const unsigned *i = IVI->idx_begin(), *e = IVI->idx_end(); i != e; ++i) + Vals.push_back(*i); + break; + } case Instruction::Select: - Code = bitc::FUNC_CODE_INST_SELECT; + Code = bitc::FUNC_CODE_INST_VSELECT; PushValueAndType(I.getOperand(1), InstID, Vals, VE); Vals.push_back(VE.getValueID(I.getOperand(2))); - Vals.push_back(VE.getValueID(I.getOperand(0))); + PushValueAndType(I.getOperand(0), InstID, Vals, VE); break; case Instruction::ExtractElement: Code = bitc::FUNC_CODE_INST_EXTRACTELT; @@ -740,16 +906,12 @@ static void WriteInstruction(const Instruction &I, unsigned InstID, break; case Instruction::ICmp: case Instruction::FCmp: - Code = bitc::FUNC_CODE_INST_CMP; + // compare returning Int1Ty or vector of Int1Ty + Code = bitc::FUNC_CODE_INST_CMP2; PushValueAndType(I.getOperand(0), InstID, Vals, VE); Vals.push_back(VE.getValueID(I.getOperand(1))); Vals.push_back(cast(I).getPredicate()); break; - case Instruction::GetResult: - Code = bitc::FUNC_CODE_INST_GETRESULT; - PushValueAndType(I.getOperand(0), InstID, Vals, VE); - Vals.push_back(cast(I).getIndex()); - break; case Instruction::Ret: { @@ -767,11 +929,14 @@ static void WriteInstruction(const Instruction &I, unsigned InstID, } break; case Instruction::Br: - Code = bitc::FUNC_CODE_INST_BR; - Vals.push_back(VE.getValueID(I.getOperand(0))); - if (cast(I).isConditional()) { - Vals.push_back(VE.getValueID(I.getOperand(1))); - Vals.push_back(VE.getValueID(I.getOperand(2))); + { + Code = bitc::FUNC_CODE_INST_BR; + BranchInst &II(cast(I)); + Vals.push_back(VE.getValueID(II.getSuccessor(0))); + if (II.isConditional()) { + Vals.push_back(VE.getValueID(II.getSuccessor(1))); + Vals.push_back(VE.getValueID(II.getCondition())); + } } break; case Instruction::Switch: @@ -781,16 +946,17 @@ static void WriteInstruction(const Instruction &I, unsigned InstID, Vals.push_back(VE.getValueID(I.getOperand(i))); break; case Instruction::Invoke: { - const PointerType *PTy = cast(I.getOperand(0)->getType()); + const InvokeInst *II = cast(&I); + const Value *Callee(II->getCalledValue()); + const PointerType *PTy = cast(Callee->getType()); const FunctionType *FTy = cast(PTy->getElementType()); Code = bitc::FUNC_CODE_INST_INVOKE; - const InvokeInst *II = cast(&I); - Vals.push_back(VE.getParamAttrID(II->getParamAttrs())); + Vals.push_back(VE.getAttributeID(II->getAttributes())); Vals.push_back(II->getCallingConv()); - Vals.push_back(VE.getValueID(I.getOperand(1))); // normal dest - Vals.push_back(VE.getValueID(I.getOperand(2))); // unwind dest - PushValueAndType(I.getOperand(0), InstID, Vals, VE); // callee + Vals.push_back(VE.getValueID(II->getNormalDest())); + Vals.push_back(VE.getValueID(II->getUnwindDest())); + PushValueAndType(Callee, InstID, Vals, VE); // Emit value #'s for the fixed parameters. for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i) @@ -860,7 +1026,7 @@ static void WriteInstruction(const Instruction &I, unsigned InstID, Code = bitc::FUNC_CODE_INST_CALL; const CallInst *CI = cast(&I); - Vals.push_back(VE.getParamAttrID(CI->getParamAttrs())); + Vals.push_back(VE.getAttributeID(CI->getAttributes())); Vals.push_back((CI->getCallingConv() << 1) | unsigned(CI->isTailCall())); PushValueAndType(CI->getOperand(0), InstID, Vals, VE); // Callee @@ -970,20 +1136,13 @@ static void WriteFunction(const Function &F, ValueEnumerator &VE, unsigned InstID = CstEnd; // Finally, emit all the instructions, in order. - for (Function::const_iterator BB = F.begin(), E = F.end(); BB != E; ++BB) { - if (const BasicBlock *unwindDest = BB->getUnwindDest()) { - Vals.push_back(VE.getValueID(unwindDest)); - Stream.EmitRecord(bitc::FUNC_CODE_INST_BB_UNWINDDEST, Vals); - Vals.clear(); - } - + for (Function::const_iterator BB = F.begin(), E = F.end(); BB != E; ++BB) for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I != E; ++I) { WriteInstruction(*I, InstID, VE, Stream, Vals); - if (I->getType() != Type::VoidTy) + if (I->getType() != Type::getVoidTy(F.getContext())) ++InstID; } - } // Emit names for all the instructions etc. WriteValueSymbolTable(F.getValueSymbolTable(), VE, Stream); @@ -1047,7 +1206,7 @@ static void WriteBlockInfo(const ValueEnumerator &VE, BitstreamWriter &Stream) { Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8)); if (Stream.EmitBlockInfoAbbrev(bitc::VALUE_SYMTAB_BLOCK_ID, Abbv) != VST_ENTRY_8_ABBREV) - assert(0 && "Unexpected abbrev ordering!"); + llvm_unreachable("Unexpected abbrev ordering!"); } { // 7-bit fixed width VST_ENTRY strings. @@ -1058,7 +1217,7 @@ static void WriteBlockInfo(const ValueEnumerator &VE, BitstreamWriter &Stream) { Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 7)); if (Stream.EmitBlockInfoAbbrev(bitc::VALUE_SYMTAB_BLOCK_ID, Abbv) != VST_ENTRY_7_ABBREV) - assert(0 && "Unexpected abbrev ordering!"); + llvm_unreachable("Unexpected abbrev ordering!"); } { // 6-bit char6 VST_ENTRY strings. BitCodeAbbrev *Abbv = new BitCodeAbbrev(); @@ -1068,7 +1227,7 @@ static void WriteBlockInfo(const ValueEnumerator &VE, BitstreamWriter &Stream) { Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Char6)); if (Stream.EmitBlockInfoAbbrev(bitc::VALUE_SYMTAB_BLOCK_ID, Abbv) != VST_ENTRY_6_ABBREV) - assert(0 && "Unexpected abbrev ordering!"); + llvm_unreachable("Unexpected abbrev ordering!"); } { // 6-bit char6 VST_BBENTRY strings. BitCodeAbbrev *Abbv = new BitCodeAbbrev(); @@ -1078,7 +1237,7 @@ static void WriteBlockInfo(const ValueEnumerator &VE, BitstreamWriter &Stream) { Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Char6)); if (Stream.EmitBlockInfoAbbrev(bitc::VALUE_SYMTAB_BLOCK_ID, Abbv) != VST_BBENTRY_6_ABBREV) - assert(0 && "Unexpected abbrev ordering!"); + llvm_unreachable("Unexpected abbrev ordering!"); } @@ -1090,7 +1249,7 @@ static void WriteBlockInfo(const ValueEnumerator &VE, BitstreamWriter &Stream) { Log2_32_Ceil(VE.getTypes().size()+1))); if (Stream.EmitBlockInfoAbbrev(bitc::CONSTANTS_BLOCK_ID, Abbv) != CONSTANTS_SETTYPE_ABBREV) - assert(0 && "Unexpected abbrev ordering!"); + llvm_unreachable("Unexpected abbrev ordering!"); } { // INTEGER abbrev for CONSTANTS_BLOCK. @@ -1099,7 +1258,7 @@ static void WriteBlockInfo(const ValueEnumerator &VE, BitstreamWriter &Stream) { Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); if (Stream.EmitBlockInfoAbbrev(bitc::CONSTANTS_BLOCK_ID, Abbv) != CONSTANTS_INTEGER_ABBREV) - assert(0 && "Unexpected abbrev ordering!"); + llvm_unreachable("Unexpected abbrev ordering!"); } { // CE_CAST abbrev for CONSTANTS_BLOCK. @@ -1112,14 +1271,14 @@ static void WriteBlockInfo(const ValueEnumerator &VE, BitstreamWriter &Stream) { if (Stream.EmitBlockInfoAbbrev(bitc::CONSTANTS_BLOCK_ID, Abbv) != CONSTANTS_CE_CAST_Abbrev) - assert(0 && "Unexpected abbrev ordering!"); + llvm_unreachable("Unexpected abbrev ordering!"); } { // NULL abbrev for CONSTANTS_BLOCK. BitCodeAbbrev *Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_NULL)); if (Stream.EmitBlockInfoAbbrev(bitc::CONSTANTS_BLOCK_ID, Abbv) != CONSTANTS_NULL_Abbrev) - assert(0 && "Unexpected abbrev ordering!"); + llvm_unreachable("Unexpected abbrev ordering!"); } // FIXME: This should only use space for first class types! @@ -1132,7 +1291,7 @@ static void WriteBlockInfo(const ValueEnumerator &VE, BitstreamWriter &Stream) { Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // volatile if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, Abbv) != FUNCTION_INST_LOAD_ABBREV) - assert(0 && "Unexpected abbrev ordering!"); + llvm_unreachable("Unexpected abbrev ordering!"); } { // INST_BINOP abbrev for FUNCTION_BLOCK. BitCodeAbbrev *Abbv = new BitCodeAbbrev(); @@ -1142,7 +1301,18 @@ static void WriteBlockInfo(const ValueEnumerator &VE, BitstreamWriter &Stream) { Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // opc if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, Abbv) != FUNCTION_INST_BINOP_ABBREV) - assert(0 && "Unexpected abbrev ordering!"); + llvm_unreachable("Unexpected abbrev ordering!"); + } + { // INST_BINOP_FLAGS abbrev for FUNCTION_BLOCK. + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_BINOP)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LHS + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // RHS + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // opc + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 7)); // flags + if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, + Abbv) != FUNCTION_INST_BINOP_FLAGS_ABBREV) + llvm_unreachable("Unexpected abbrev ordering!"); } { // INST_CAST abbrev for FUNCTION_BLOCK. BitCodeAbbrev *Abbv = new BitCodeAbbrev(); @@ -1153,7 +1323,7 @@ static void WriteBlockInfo(const ValueEnumerator &VE, BitstreamWriter &Stream) { Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // opc if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, Abbv) != FUNCTION_INST_CAST_ABBREV) - assert(0 && "Unexpected abbrev ordering!"); + llvm_unreachable("Unexpected abbrev ordering!"); } { // INST_RET abbrev for FUNCTION_BLOCK. @@ -1161,7 +1331,7 @@ static void WriteBlockInfo(const ValueEnumerator &VE, BitstreamWriter &Stream) { Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_RET)); if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, Abbv) != FUNCTION_INST_RET_VOID_ABBREV) - assert(0 && "Unexpected abbrev ordering!"); + llvm_unreachable("Unexpected abbrev ordering!"); } { // INST_RET abbrev for FUNCTION_BLOCK. BitCodeAbbrev *Abbv = new BitCodeAbbrev(); @@ -1169,14 +1339,14 @@ static void WriteBlockInfo(const ValueEnumerator &VE, BitstreamWriter &Stream) { Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // ValID if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, Abbv) != FUNCTION_INST_RET_VAL_ABBREV) - assert(0 && "Unexpected abbrev ordering!"); + llvm_unreachable("Unexpected abbrev ordering!"); } { // INST_UNREACHABLE abbrev for FUNCTION_BLOCK. BitCodeAbbrev *Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_UNREACHABLE)); if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, Abbv) != FUNCTION_INST_UNREACHABLE_ABBREV) - assert(0 && "Unexpected abbrev ordering!"); + llvm_unreachable("Unexpected abbrev ordering!"); } Stream.ExitBlock(); @@ -1201,7 +1371,7 @@ static void WriteModule(const Module *M, BitstreamWriter &Stream) { WriteBlockInfo(VE, Stream); // Emit information about parameter attributes. - WriteParamAttrTable(VE, Stream); + WriteAttributeTable(VE, Stream); // Emit information describing all of the types in the module. WriteTypeTable(VE, Stream); @@ -1209,20 +1379,13 @@ static void WriteModule(const Module *M, BitstreamWriter &Stream) { // Emit top-level description of module, including target triple, inline asm, // descriptors for global variables, and function prototype info. WriteModuleInfo(M, VE, Stream); - + // Emit constants. WriteModuleConstants(VE, Stream); - - // If we have any aggregate values in the value table, purge them - these can - // only be used to initialize global variables. Doing so makes the value - // namespace smaller for code in functions. - int NumNonAggregates = VE.PurgeAggregateValues(); - if (NumNonAggregates != -1) { - SmallVector Vals; - Vals.push_back(NumNonAggregates); - Stream.EmitRecord(bitc::MODULE_CODE_PURGEVALS, Vals); - } - + + // Emit metadata. + WriteModuleMetadata(VE, Stream); + // Emit function bodies. for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I) if (!I->isDeclaration()) @@ -1237,14 +1400,99 @@ static void WriteModule(const Module *M, BitstreamWriter &Stream) { Stream.ExitBlock(); } +/// EmitDarwinBCHeader - If generating a bc file on darwin, we have to emit a +/// header and trailer to make it compatible with the system archiver. To do +/// this we emit the following header, and then emit a trailer that pads the +/// file out to be a multiple of 16 bytes. +/// +/// struct bc_header { +/// uint32_t Magic; // 0x0B17C0DE +/// uint32_t Version; // Version, currently always 0. +/// uint32_t BitcodeOffset; // Offset to traditional bitcode file. +/// uint32_t BitcodeSize; // Size of traditional bitcode file. +/// uint32_t CPUType; // CPU specifier. +/// ... potentially more later ... +/// }; +enum { + DarwinBCSizeFieldOffset = 3*4, // Offset to bitcode_size. + DarwinBCHeaderSize = 5*4 +}; + +static void EmitDarwinBCHeader(BitstreamWriter &Stream, + const std::string &TT) { + unsigned CPUType = ~0U; + + // Match x86_64-*, i[3-9]86-*, powerpc-*, powerpc64-*. The CPUType is a + // magic number from /usr/include/mach/machine.h. It is ok to reproduce the + // specific constants here because they are implicitly part of the Darwin ABI. + enum { + DARWIN_CPU_ARCH_ABI64 = 0x01000000, + DARWIN_CPU_TYPE_X86 = 7, + DARWIN_CPU_TYPE_POWERPC = 18 + }; + + if (TT.find("x86_64-") == 0) + CPUType = DARWIN_CPU_TYPE_X86 | DARWIN_CPU_ARCH_ABI64; + else if (TT.size() >= 5 && TT[0] == 'i' && TT[2] == '8' && TT[3] == '6' && + TT[4] == '-' && TT[1] - '3' < 6) + CPUType = DARWIN_CPU_TYPE_X86; + else if (TT.find("powerpc-") == 0) + CPUType = DARWIN_CPU_TYPE_POWERPC; + else if (TT.find("powerpc64-") == 0) + CPUType = DARWIN_CPU_TYPE_POWERPC | DARWIN_CPU_ARCH_ABI64; + + // Traditional Bitcode starts after header. + unsigned BCOffset = DarwinBCHeaderSize; + + Stream.Emit(0x0B17C0DE, 32); + Stream.Emit(0 , 32); // Version. + Stream.Emit(BCOffset , 32); + Stream.Emit(0 , 32); // Filled in later. + Stream.Emit(CPUType , 32); +} + +/// EmitDarwinBCTrailer - Emit the darwin epilog after the bitcode file and +/// finalize the header. +static void EmitDarwinBCTrailer(BitstreamWriter &Stream, unsigned BufferSize) { + // Update the size field in the header. + Stream.BackpatchWord(DarwinBCSizeFieldOffset, BufferSize-DarwinBCHeaderSize); + + // If the file is not a multiple of 16 bytes, insert dummy padding. + while (BufferSize & 15) { + Stream.Emit(0, 8); + ++BufferSize; + } +} + /// WriteBitcodeToFile - Write the specified module to the specified output /// stream. -void llvm::WriteBitcodeToFile(const Module *M, std::ostream &Out) { +void llvm::WriteBitcodeToFile(const Module *M, raw_ostream &Out) { std::vector Buffer; BitstreamWriter Stream(Buffer); Buffer.reserve(256*1024); + + WriteBitcodeToStream( M, Stream ); + + // If writing to stdout, set binary mode. + if (&llvm::outs() == &Out) + sys::Program::ChangeStdoutToBinary(); + + // Write the generated bitstream to "Out". + Out.write((char*)&Buffer.front(), Buffer.size()); + + // Make sure it hits disk now. + Out.flush(); +} + +/// WriteBitcodeToStream - Write the specified module to the specified output +/// stream. +void llvm::WriteBitcodeToStream(const Module *M, BitstreamWriter &Stream) { + // If this is darwin, emit a file header and trailer if needed. + bool isDarwin = M->getTargetTriple().find("-darwin") != std::string::npos; + if (isDarwin) + EmitDarwinBCHeader(Stream, M->getTargetTriple()); // Emit the file header. Stream.Emit((unsigned)'B', 8); @@ -1256,10 +1504,7 @@ void llvm::WriteBitcodeToFile(const Module *M, std::ostream &Out) { // Emit the module. WriteModule(M, Stream); - - // Write the generated bitstream to "Out". - Out.write((char*)&Buffer.front(), Buffer.size()); - - // Make sure it hits disk now. - Out.flush(); + + if (isDarwin) + EmitDarwinBCTrailer(Stream, Stream.getBuffer().size()); }