diff options
Diffstat (limited to 'lib/Bitcode')
-rw-r--r-- | lib/Bitcode/Reader/BitcodeReader.cpp | 67 | ||||
-rw-r--r-- | lib/Bitcode/Reader/BitcodeReader.h | 10 | ||||
-rw-r--r-- | lib/Bitcode/Writer/BitcodeWriter.cpp | 29 | ||||
-rw-r--r-- | lib/Bitcode/Writer/ValueEnumerator.cpp | 45 | ||||
-rw-r--r-- | lib/Bitcode/Writer/ValueEnumerator.h | 9 |
5 files changed, 138 insertions, 22 deletions
diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp index 3a385cb..68527e3 100644 --- a/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/lib/Bitcode/Reader/BitcodeReader.cpp @@ -837,12 +837,14 @@ bool BitcodeReader::ParseMetadata() { SmallString<8> Name; Name.resize(RecordLength-1); unsigned Kind = Record[0]; + (void) Kind; for (unsigned i = 1; i != RecordLength; ++i) Name[i-1] = Record[i]; MetadataContext &TheMetadata = Context.getMetadata(); unsigned ExistingKind = TheMetadata.getMDKind(Name.str()); if (ExistingKind == 0) { unsigned NewKind = TheMetadata.registerMDKind(Name.str()); + (void) NewKind; assert (Kind == NewKind && "Unable to handle custom metadata mismatch!"); } else { @@ -1190,6 +1192,22 @@ bool BitcodeReader::ParseConstants() { AsmStr, ConstrStr, HasSideEffects, IsAlignStack); break; } + case bitc::CST_CODE_BLOCKADDRESS:{ + if (Record.size() < 3) return Error("Invalid CE_BLOCKADDRESS record"); + const Type *FnTy = getTypeByID(Record[0]); + if (FnTy == 0) return Error("Invalid CE_BLOCKADDRESS record"); + Function *Fn = + dyn_cast_or_null<Function>(ValueList.getConstantFwdRef(Record[1],FnTy)); + if (Fn == 0) return Error("Invalid CE_BLOCKADDRESS record"); + + GlobalVariable *FwdRef = new GlobalVariable(*Fn->getParent(), + Type::getInt8Ty(Context), + false, GlobalValue::InternalLinkage, + 0, ""); + BlockAddrFwdRefs[Fn].push_back(std::make_pair(Record[2], FwdRef)); + V = FwdRef; + break; + } } ValueList.AssignValue(V, NextCstNo); @@ -1949,7 +1967,7 @@ bool BitcodeReader::ParseFunctionBody(Function *F) { } break; } - case bitc::FUNC_CODE_INST_SWITCH: { // SWITCH: [opty, opval, n, n x ops] + case bitc::FUNC_CODE_INST_SWITCH: { // SWITCH: [opty, op0, op1, ...] if (Record.size() < 3 || (Record.size() & 1) == 0) return Error("Invalid SWITCH record"); const Type *OpTy = getTypeByID(Record[0]); @@ -1973,7 +1991,28 @@ bool BitcodeReader::ParseFunctionBody(Function *F) { I = SI; break; } - + case bitc::FUNC_CODE_INST_INDIRECTBR: { // INDIRECTBR: [opty, op0, op1, ...] + if (Record.size() < 2) + return Error("Invalid INDIRECTBR record"); + const Type *OpTy = getTypeByID(Record[0]); + Value *Address = getFnValueByID(Record[1], OpTy); + if (OpTy == 0 || Address == 0) + return Error("Invalid INDIRECTBR record"); + unsigned NumDests = Record.size()-2; + IndirectBrInst *IBI = IndirectBrInst::Create(Address, NumDests); + InstructionList.push_back(IBI); + for (unsigned i = 0, e = NumDests; i != e; ++i) { + if (BasicBlock *DestBB = getBasicBlock(Record[2+i])) { + IBI->addDestination(DestBB); + } else { + delete IBI; + return Error("Invalid INDIRECTBR record!"); + } + } + I = IBI; + break; + } + case bitc::FUNC_CODE_INST_INVOKE: { // INVOKE: [attrs, cc, normBB, unwindBB, fnty, op0,op1,op2, ...] if (Record.size() < 4) return Error("Invalid INVOKE record"); @@ -2073,7 +2112,8 @@ bool BitcodeReader::ParseFunctionBody(Function *F) { if (getValueTypePair(Record, OpNum, NextValueNo, Op) || OpNum != Record.size()) return Error("Invalid FREE record"); - I = new FreeInst(Op); + if (!CurBB) return Error("Invalid free instruction with no BB"); + I = CallInst::CreateFree(Op, CurBB); InstructionList.push_back(I); break; } @@ -2224,6 +2264,27 @@ bool BitcodeReader::ParseFunctionBody(Function *F) { } } + // See if anything took the address of blocks in this function. If so, + // resolve them now. + /// BlockAddrFwdRefs - These are blockaddr references to basic blocks. These + /// are resolved lazily when functions are loaded. + DenseMap<Function*, std::vector<BlockAddrRefTy> >::iterator BAFRI = + BlockAddrFwdRefs.find(F); + if (BAFRI != BlockAddrFwdRefs.end()) { + std::vector<BlockAddrRefTy> &RefList = BAFRI->second; + for (unsigned i = 0, e = RefList.size(); i != e; ++i) { + unsigned BlockIdx = RefList[i].first; + if (BlockIdx >= FunctionBBs.size()) + return Error("Invalid blockaddress block #"); + + GlobalVariable *FwdRef = RefList[i].second; + FwdRef->replaceAllUsesWith(BlockAddress::get(F, FunctionBBs[BlockIdx])); + FwdRef->eraseFromParent(); + } + + BlockAddrFwdRefs.erase(BAFRI); + } + // Trim the value list down to the size it was before we parsed this function. ValueList.shrinkTo(ModuleValueListSize); std::vector<BasicBlock*>().swap(FunctionBBs); diff --git a/lib/Bitcode/Reader/BitcodeReader.h b/lib/Bitcode/Reader/BitcodeReader.h index eefc7bd..7b3a1ae 100644 --- a/lib/Bitcode/Reader/BitcodeReader.h +++ b/lib/Bitcode/Reader/BitcodeReader.h @@ -94,7 +94,7 @@ public: class BitcodeReaderMDValueList { std::vector<WeakVH> MDValuePtrs; - LLVMContext& Context; + LLVMContext &Context; public: BitcodeReaderMDValueList(LLVMContext& C) : Context(C) {} @@ -122,7 +122,7 @@ public: }; class BitcodeReader : public ModuleProvider { - LLVMContext& Context; + LLVMContext &Context; MemoryBuffer *Buffer; BitstreamReader StreamFile; BitstreamCursor Stream; @@ -163,6 +163,12 @@ class BitcodeReader : public ModuleProvider { /// map contains info about where to find deferred function body (in the /// stream) and what linkage the original function had. DenseMap<Function*, std::pair<uint64_t, unsigned> > DeferredFunctionInfo; + + /// BlockAddrFwdRefs - These are blockaddr references to basic blocks. These + /// are resolved lazily when functions are loaded. + typedef std::pair<unsigned, GlobalVariable*> BlockAddrRefTy; + DenseMap<Function*, std::vector<BlockAddrRefTy> > BlockAddrFwdRefs; + public: explicit BitcodeReader(MemoryBuffer *buffer, LLVMContext& C) : Context(C), Buffer(buffer), ErrorString(0), ValueList(C), MDValueList(C) { diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp index 037854e..af0b8ac 100644 --- a/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -19,6 +19,7 @@ #include "llvm/DerivedTypes.h" #include "llvm/InlineAsm.h" #include "llvm/Instructions.h" +#include "llvm/LLVMContext.h" #include "llvm/Metadata.h" #include "llvm/Module.h" #include "llvm/Operator.h" @@ -750,10 +751,11 @@ static void WriteConstants(unsigned FirstVal, unsigned LastVal, assert (0 && "Unknown FP type!"); } } else if (isa<ConstantArray>(C) && cast<ConstantArray>(C)->isString()) { + const ConstantArray *CA = cast<ConstantArray>(C); // Emit constant strings specially. - unsigned NumOps = C->getNumOperands(); + unsigned NumOps = CA->getNumOperands(); // If this is a null-terminated string, use the denser CSTRING encoding. - if (C->getOperand(NumOps-1)->isNullValue()) { + if (CA->getOperand(NumOps-1)->isNullValue()) { Code = bitc::CST_CODE_CSTRING; --NumOps; // Don't encode the null, which isn't allowed by char6. } else { @@ -763,7 +765,7 @@ static void WriteConstants(unsigned FirstVal, unsigned LastVal, bool isCStr7 = Code == bitc::CST_CODE_CSTRING; bool isCStrChar6 = Code == bitc::CST_CODE_CSTRING; for (unsigned i = 0; i != NumOps; ++i) { - unsigned char V = cast<ConstantInt>(C->getOperand(i))->getZExtValue(); + unsigned char V = cast<ConstantInt>(CA->getOperand(i))->getZExtValue(); Record.push_back(V); isCStr7 &= (V & 128) == 0; if (isCStrChar6) @@ -851,6 +853,13 @@ static void WriteConstants(unsigned FirstVal, unsigned LastVal, Record.push_back(CE->getPredicate()); break; } + } else if (const BlockAddress *BA = dyn_cast<BlockAddress>(C)) { + assert(BA->getFunction() == BA->getBasicBlock()->getParent() && + "Malformed blockaddress"); + Code = bitc::CST_CODE_BLOCKADDRESS; + Record.push_back(VE.getTypeID(BA->getFunction()->getType())); + Record.push_back(VE.getValueID(BA->getFunction())); + Record.push_back(VE.getGlobalBasicBlockID(BA->getBasicBlock())); } else { llvm_unreachable("Unknown constant!"); } @@ -1000,7 +1009,7 @@ static void WriteInstruction(const Instruction &I, unsigned InstID, case Instruction::Br: { Code = bitc::FUNC_CODE_INST_BR; - BranchInst &II(cast<BranchInst>(I)); + BranchInst &II = cast<BranchInst>(I); Vals.push_back(VE.getValueID(II.getSuccessor(0))); if (II.isConditional()) { Vals.push_back(VE.getValueID(II.getSuccessor(1))); @@ -1014,6 +1023,13 @@ static void WriteInstruction(const Instruction &I, unsigned InstID, for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) Vals.push_back(VE.getValueID(I.getOperand(i))); break; + case Instruction::IndirectBr: + Code = bitc::FUNC_CODE_INST_INDIRECTBR; + Vals.push_back(VE.getTypeID(I.getOperand(0)->getType())); + for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) + Vals.push_back(VE.getValueID(I.getOperand(i))); + break; + case Instruction::Invoke: { const InvokeInst *II = cast<InvokeInst>(&I); const Value *Callee(II->getCalledValue()); @@ -1054,11 +1070,6 @@ static void WriteInstruction(const Instruction &I, unsigned InstID, Vals.push_back(VE.getValueID(I.getOperand(i))); break; - case Instruction::Free: - Code = bitc::FUNC_CODE_INST_FREE; - PushValueAndType(I.getOperand(0), InstID, Vals, VE); - break; - case Instruction::Alloca: Code = bitc::FUNC_CODE_INST_ALLOCA; Vals.push_back(VE.getTypeID(I.getType())); diff --git a/lib/Bitcode/Writer/ValueEnumerator.cpp b/lib/Bitcode/Writer/ValueEnumerator.cpp index 85aa5fa..d840d4a 100644 --- a/lib/Bitcode/Writer/ValueEnumerator.cpp +++ b/lib/Bitcode/Writer/ValueEnumerator.cpp @@ -14,6 +14,7 @@ #include "ValueEnumerator.h" #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" +#include "llvm/LLVMContext.h" #include "llvm/Metadata.h" #include "llvm/Module.h" #include "llvm/TypeSymbolTable.h" @@ -222,7 +223,9 @@ void ValueEnumerator::EnumerateMetadata(const MetadataBase *MD) { EnumerateType(Type::getVoidTy(MD->getContext())); } return; - } else if (const NamedMDNode *N = dyn_cast<NamedMDNode>(MD)) { + } + + if (const NamedMDNode *N = dyn_cast<NamedMDNode>(MD)) { for(NamedMDNode::const_elem_iterator I = N->elem_begin(), E = N->elem_end(); I != E; ++I) { MetadataBase *M = *I; @@ -273,7 +276,8 @@ void ValueEnumerator::EnumerateValue(const Value *V) { // graph that don't go through a global variable. for (User::const_op_iterator I = C->op_begin(), E = C->op_end(); I != E; ++I) - EnumerateValue(*I); + if (!isa<BasicBlock>(*I)) // Don't enumerate BB operand to BlockAddress. + EnumerateValue(*I); // Finally, add the value. Doing this could make the ValueID reference be // dangling, don't reuse it. @@ -319,15 +323,20 @@ void ValueEnumerator::EnumerateOperandType(const Value *V) { // This constant may have operands, make sure to enumerate the types in // them. - for (unsigned i = 0, e = C->getNumOperands(); i != e; ++i) - EnumerateOperandType(C->getOperand(i)); + for (unsigned i = 0, e = C->getNumOperands(); i != e; ++i) { + const User *Op = C->getOperand(i); + + // Don't enumerate basic blocks here, this happens as operands to + // blockaddress. + if (isa<BasicBlock>(Op)) continue; + + EnumerateOperandType(cast<Constant>(Op)); + } if (const MDNode *N = dyn_cast<MDNode>(V)) { - for (unsigned i = 0, e = N->getNumElements(); i != e; ++i) { - Value *Elem = N->getElement(i); - if (Elem) + for (unsigned i = 0, e = N->getNumElements(); i != e; ++i) + if (Value *Elem = N->getElement(i)) EnumerateOperandType(Elem); - } } } else if (isa<MDString>(V) || isa<MDNode>(V)) EnumerateValue(V); @@ -396,3 +405,23 @@ void ValueEnumerator::purgeFunction() { Values.resize(NumModuleValues); BasicBlocks.clear(); } + +static void IncorporateFunctionInfoGlobalBBIDs(const Function *F, + DenseMap<const BasicBlock*, unsigned> &IDMap) { + unsigned Counter = 0; + for (Function::const_iterator BB = F->begin(), E = F->end(); BB != E; ++BB) + IDMap[BB] = ++Counter; +} + +/// getGlobalBasicBlockID - This returns the function-specific ID for the +/// specified basic block. This is relatively expensive information, so it +/// should only be used by rare constructs such as address-of-label. +unsigned ValueEnumerator::getGlobalBasicBlockID(const BasicBlock *BB) const { + unsigned &Idx = GlobalBasicBlockIDs[BB]; + if (Idx != 0) + return Idx-1; + + IncorporateFunctionInfoGlobalBBIDs(BB->getParent(), GlobalBasicBlockIDs); + return getGlobalBasicBlockID(BB); +} + diff --git a/lib/Bitcode/Writer/ValueEnumerator.h b/lib/Bitcode/Writer/ValueEnumerator.h index da63dde..3c83e35 100644 --- a/lib/Bitcode/Writer/ValueEnumerator.h +++ b/lib/Bitcode/Writer/ValueEnumerator.h @@ -53,6 +53,10 @@ private: AttributeMapType AttributeMap; std::vector<AttrListPtr> Attributes; + /// GlobalBasicBlockIDs - This map memoizes the basic block ID's referenced by + /// the "getGlobalBasicBlockID" method. + mutable DenseMap<const BasicBlock*, unsigned> GlobalBasicBlockIDs; + typedef DenseMap<const Instruction*, unsigned> InstructionMapType; InstructionMapType InstructionMap; unsigned InstructionCount; @@ -106,6 +110,11 @@ public: const std::vector<AttrListPtr> &getAttributes() const { return Attributes; } + + /// getGlobalBasicBlockID - This returns the function-specific ID for the + /// specified basic block. This is relatively expensive information, so it + /// should only be used by rare constructs such as address-of-label. + unsigned getGlobalBasicBlockID(const BasicBlock *BB) const; /// incorporateFunction/purgeFunction - If you'd like to deal with a function, /// use these two methods to get its data into the ValueEnumerator! |