diff --git a/lib/Bytecode/Reader/InstructionReader.cpp b/lib/Bytecode/Reader/InstructionReader.cpp index d8a6af0179c..2f2e7960d60 100644 --- a/lib/Bytecode/Reader/InstructionReader.cpp +++ b/lib/Bytecode/Reader/InstructionReader.cpp @@ -161,12 +161,11 @@ bool BytecodeParser::ParseInstruction(const unsigned char *&Buf, delete PN; return true; case 2: PN->addIncoming(getValue(Raw->Ty, Raw->Arg1), - cast(getValue(Type::LabelTyID, - Raw->Arg2))); + getBasicBlock(Raw->Arg2)); break; default: - PN->addIncoming(getValue(Raw->Ty, Raw->Arg1), - cast(getValue(Type::LabelTyID, Raw->Arg2))); + PN->addIncoming(getValue(Raw->Ty, Raw->Arg1), + getBasicBlock(Raw->Arg2)); if (Raw->VarArgs->size() & 1) { std::cerr << "PHI Node with ODD number of arguments!\n"; delete PN; @@ -174,8 +173,7 @@ bool BytecodeParser::ParseInstruction(const unsigned char *&Buf, } else { std::vector &args = *Raw->VarArgs; for (unsigned i = 0; i < args.size(); i+=2) - PN->addIncoming(getValue(Raw->Ty, args[i]), - cast(getValue(Type::LabelTyID, args[i+1]))); + PN->addIncoming(getValue(Raw->Ty, args[i]), getBasicBlock(args[i+1])); } delete Raw->VarArgs; break; @@ -200,20 +198,18 @@ bool BytecodeParser::ParseInstruction(const unsigned char *&Buf, case Instruction::Br: if (Raw->NumOperands == 1) { - Res = new BranchInst(cast(getValue(Type::LabelTyID,Raw->Arg1))); + Res = new BranchInst(getBasicBlock(Raw->Arg1)); return false; } else if (Raw->NumOperands == 3) { - Res = new BranchInst(cast(getValue(Type::LabelTyID, Raw->Arg1)), - cast(getValue(Type::LabelTyID, Raw->Arg2)), - getValue(Type::BoolTyID , Raw->Arg3)); + Res = new BranchInst(getBasicBlock(Raw->Arg1), getBasicBlock(Raw->Arg2), + getValue(Type::BoolTyID , Raw->Arg3)); return false; } break; case Instruction::Switch: { SwitchInst *I = - new SwitchInst(getValue(Raw->Ty, Raw->Arg1), - cast(getValue(Type::LabelTyID, Raw->Arg2))); + new SwitchInst(getValue(Raw->Ty, Raw->Arg1), getBasicBlock(Raw->Arg2)); Res = I; if (Raw->NumOperands < 3) return false; // No destinations? Weird. @@ -226,7 +222,7 @@ bool BytecodeParser::ParseInstruction(const unsigned char *&Buf, std::vector &args = *Raw->VarArgs; for (unsigned i = 0; i < args.size(); i += 2) I->addCase(cast(getValue(Raw->Ty, args[i])), - cast(getValue(Type::LabelTyID, args[i+1]))); + getBasicBlock(args[i+1])); delete Raw->VarArgs; return false; @@ -311,11 +307,11 @@ bool BytecodeParser::ParseInstruction(const unsigned char *&Buf, if (!FTy->isVarArg()) { if (Raw->NumOperands < 3) return true; - Normal = cast(getValue(Type::LabelTyID, Raw->Arg2)); + Normal = getBasicBlock(Raw->Arg2); if (Raw->NumOperands == 3) - Except = cast(getValue(Type::LabelTyID, Raw->Arg3)); + Except = getBasicBlock(Raw->Arg3); else { - Except = cast(getValue(Type::LabelTyID, args[0])); + Except = getBasicBlock(args[0]); FunctionType::ParamTypes::const_iterator It = PL.begin(); for (unsigned i = 1; i < args.size(); i++) { @@ -327,10 +323,11 @@ bool BytecodeParser::ParseInstruction(const unsigned char *&Buf, } } else { if (args.size() < 4) return true; - if (getType(args[0]) != Type::LabelTy || - getType(args[2]) != Type::LabelTy) return true; - Normal = cast(getValue(Type::LabelTyID, args[1])); - Except = cast(getValue(Type::LabelTyID, args[3])); + if (args[0] != Type::LabelTyID || args[2] != Type::LabelTyID) + return true; + + Normal = getBasicBlock(args[1]); + Except = getBasicBlock(args[3]); if ((args.size() & 1) != 0) return true; // Must be pairs of type/value diff --git a/lib/Bytecode/Reader/Reader.cpp b/lib/Bytecode/Reader/Reader.cpp index 29812da561e..af775d282a4 100644 --- a/lib/Bytecode/Reader/Reader.cpp +++ b/lib/Bytecode/Reader/Reader.cpp @@ -119,6 +119,7 @@ Value *BytecodeParser::getValue(const Type *Ty, unsigned oNum, bool Create) { Value *BytecodeParser::getValue(unsigned type, unsigned oNum, bool Create) { assert(type != Type::TypeTyID && "getValue() cannot get types!"); + assert(type != Type::LabelTyID && "getValue() cannot get blocks!"); unsigned Num = oNum; if (HasImplicitZeroInitializer && type >= FirstDerivedTyID) { @@ -138,15 +139,30 @@ Value *BytecodeParser::getValue(unsigned type, unsigned oNum, bool Create) { if (!Create) return 0; // Do not create a placeholder? - const Type *Ty = getType(type); - Value *Val = type == Type::LabelTyID ? (Value*)new BBPHolder(Ty, oNum) : - (Value*)new ValPHolder(Ty, oNum); - - assert(Val != 0 && "How did we not make something?"); + Value *Val = new ValPHolder(getType(type), oNum); if (insertValue(Val, LateResolveValues) == -1) return 0; return Val; } +/// getBasicBlock - Get a particular numbered basic block, which might be a +/// forward reference. This works together with ParseBasicBlock to handle these +/// forward references in a clean manner. +/// +BasicBlock *BytecodeParser::getBasicBlock(unsigned ID) { + // Make sure there is room in the table... + if (ParsedBasicBlocks.size() <= ID) ParsedBasicBlocks.resize(ID+1); + + // First check to see if this is a backwards reference, i.e., ParseBasicBlock + // has already created this block, or if the forward reference has already + // been created. + if (ParsedBasicBlocks[ID]) + return ParsedBasicBlocks[ID]; + + // Otherwise, the basic block has not yet been created. Do so and add it to + // the ParsedBasicBlocks list. + return ParsedBasicBlocks[ID] = new BasicBlock(); +} + /// getConstantValue - Just like getValue, except that it returns a null pointer /// only on error. It always returns a constant (meaning that if the value is /// defined, but is not a constant, that is an error). If the specified @@ -176,10 +192,16 @@ Constant *BytecodeParser::getConstantValue(const Type *Ty, unsigned Slot) { } -std::auto_ptr -BytecodeParser::ParseBasicBlock(const unsigned char *&Buf, - const unsigned char *EndBuf) { - std::auto_ptr BB(new BasicBlock()); +BasicBlock *BytecodeParser::ParseBasicBlock(const unsigned char *&Buf, + const unsigned char *EndBuf, + unsigned BlockNo) { + BasicBlock *BB; + if (ParsedBasicBlocks.size() == BlockNo) + ParsedBasicBlocks.push_back(BB = new BasicBlock()); + else if (ParsedBasicBlocks[BlockNo] == 0) + BB = ParsedBasicBlocks[BlockNo] = new BasicBlock(); + else + BB = ParsedBasicBlocks[BlockNo]; while (Buf < EndBuf) { Instruction *Inst; @@ -199,7 +221,8 @@ BytecodeParser::ParseBasicBlock(const unsigned char *&Buf, void BytecodeParser::ParseSymbolTable(const unsigned char *&Buf, const unsigned char *EndBuf, - SymbolTable *ST) { + SymbolTable *ST, + Function *CurrentFunction) { while (Buf < EndBuf) { // Symtab block header: [num entries][type id number] unsigned NumEntries, Typ; @@ -219,10 +242,17 @@ void BytecodeParser::ParseSymbolTable(const unsigned char *&Buf, if (read(Buf, EndBuf, Name, false)) // Not aligned... throw std::string("Buffer not aligned."); - Value *V; + Value *V = 0; if (Typ == Type::TypeTyID) V = (Value*)getType(slot); - else + else if (Typ == Type::LabelTyID) { + if (CurrentFunction) { + // FIXME: THIS IS N^2!!! + Function::iterator BlockIterator = CurrentFunction->begin(); + std::advance(BlockIterator, slot); + V = BlockIterator; + } + } else V = getValue(Typ, slot, false); // Find mapping... if (V == 0) throw std::string("Failed value look-up."); BCR_TRACE(4, "Map: '" << Name << "' to #" << slot << ":" << *V; @@ -254,9 +284,8 @@ void BytecodeParser::ResolveReferencesToValue(Value *NewV, unsigned Slot) { GlobalRefs.erase(I); // Remove the map entry for it } -void -BytecodeParser::ParseFunction(const unsigned char *&Buf, - const unsigned char *EndBuf) { +void BytecodeParser::ParseFunction(const unsigned char *&Buf, + const unsigned char *EndBuf) { if (FunctionSignatureList.empty()) throw std::string("FunctionSignatureList empty!"); @@ -312,6 +341,9 @@ void BytecodeParser::materializeFunction(Function* F) { throw std::string("Error reading function arguments!"); } + // Keep track of how many basic blocks we have read in... + unsigned BlockNum = 0; + while (Buf < EndBuf) { unsigned Type, Size; const unsigned char *OldBuf = Buf; @@ -326,17 +358,14 @@ void BytecodeParser::materializeFunction(Function* F) { case BytecodeFormat::BasicBlock: { BCR_TRACE(2, "BLOCK BytecodeFormat::BasicBlock: {\n"); - std::auto_ptr BB = ParseBasicBlock(Buf, Buf+Size); - if (!BB.get() || insertValue(BB.get(), Values) == -1) - throw std::string("Parse error: BasicBlock"); - - F->getBasicBlockList().push_back(BB.release()); + BasicBlock *BB = ParseBasicBlock(Buf, Buf+Size, BlockNum++); + F->getBasicBlockList().push_back(BB); break; } case BytecodeFormat::SymbolTable: { BCR_TRACE(2, "BLOCK BytecodeFormat::SymbolTable: {\n"); - ParseSymbolTable(Buf, Buf+Size, &F->getSymbolTable()); + ParseSymbolTable(Buf, Buf+Size, &F->getSymbolTable(), F); break; } @@ -353,6 +382,12 @@ void BytecodeParser::materializeFunction(Function* F) { ALIGN32(Buf, EndBuf); } + // Make sure there were no references to non-existant basic blocks. + if (BlockNum != ParsedBasicBlocks.size()) + throw std::string("Illegal basic block operand reference"); + ParsedBasicBlocks.clear(); + + // Check for unresolvable references while (!LateResolveValues.empty()) { ValueList &VL = *LateResolveValues.back(); @@ -582,7 +617,7 @@ void BytecodeParser::ParseModule(const unsigned char *Buf, case BytecodeFormat::SymbolTable: BCR_TRACE(1, "BLOCK BytecodeFormat::SymbolTable: {\n"); - ParseSymbolTable(Buf, Buf+Size, &TheModule->getSymbolTable()); + ParseSymbolTable(Buf, Buf+Size, &TheModule->getSymbolTable(), 0); break; default: diff --git a/lib/Bytecode/Reader/ReaderInternals.h b/lib/Bytecode/Reader/ReaderInternals.h index 8825df7fbe0..b0c7abfff67 100644 --- a/lib/Bytecode/Reader/ReaderInternals.h +++ b/lib/Bytecode/Reader/ReaderInternals.h @@ -103,6 +103,8 @@ private: ValueTable Values, LateResolveValues; ValueTable ModuleValues; + std::vector ParsedBasicBlocks; + // GlobalRefs - This maintains a mapping between 's and forward // references to global values or constants. Such values may be referenced // before they are defined, and if so, the temporary object that they @@ -153,15 +155,16 @@ private: void ParseVersionInfo (const unsigned char *&Buf, const unsigned char *End); void ParseModuleGlobalInfo(const unsigned char *&Buf, const unsigned char *E); void ParseSymbolTable(const unsigned char *&Buf, const unsigned char *End, - SymbolTable *); + SymbolTable *, Function *CurrentFunction); void ParseFunction(const unsigned char *&Buf, const unsigned char *End); void ParseGlobalTypes(const unsigned char *&Buf, const unsigned char *EndBuf); - std::auto_ptr - ParseBasicBlock(const unsigned char *&Buf, const unsigned char *End); + BasicBlock *ParseBasicBlock(const unsigned char *&Buf, + const unsigned char *End, + unsigned BlockNo); - bool ParseInstruction (const unsigned char *&Buf, const unsigned char *End, - Instruction *&); + bool ParseInstruction(const unsigned char *&Buf, const unsigned char *End, + Instruction *&); std::auto_ptr ParseRawInst(const unsigned char *&Buf, const unsigned char *End); @@ -179,6 +182,7 @@ private: Value *getValue(const Type *Ty, unsigned num, bool Create = true); Value *getValue(unsigned TypeID, unsigned num, bool Create = true); const Type *getType(unsigned ID); + BasicBlock *getBasicBlock(unsigned ID); Constant *getConstantValue(const Type *Ty, unsigned num); int insertValue(Value *V, ValueTable &Table); // -1 = Failure @@ -207,12 +211,6 @@ struct InstPlaceHolderHelper : public Instruction { virtual Instruction *clone() const { abort(); return 0; } }; -struct BBPlaceHolderHelper : public BasicBlock { - BBPlaceHolderHelper(const Type *Ty) : BasicBlock() { - assert(Ty == Type::LabelTy); - } -}; - struct ConstantPlaceHolderHelper : public Constant { ConstantPlaceHolderHelper(const Type *Ty) : Constant(Ty) {} @@ -220,7 +218,6 @@ struct ConstantPlaceHolderHelper : public Constant { }; typedef PlaceholderDef ValPHolder; -typedef PlaceholderDef BBPHolder; typedef PlaceholderDef ConstPHolder; // Some common errors we find @@ -232,12 +229,7 @@ static const std::string Error_DestSlot = "No destination slot found."; static inline unsigned getValueIDNumberFromPlaceHolder(Value *Val) { if (isa(Val)) return ((ConstPHolder*)Val)->getID(); - - // else discriminate by type - switch (Val->getType()->getPrimitiveID()) { - case Type::LabelTyID: return ((BBPHolder*)Val)->getID(); - default: return ((ValPHolder*)Val)->getID(); - } + return ((ValPHolder*)Val)->getID(); } static inline void readBlock(const unsigned char *&Buf,