delete PN;
return true;
case 2: PN->addIncoming(getValue(Raw->Ty, Raw->Arg1),
- cast<BasicBlock>(getValue(Type::LabelTyID,
- Raw->Arg2)));
+ getBasicBlock(Raw->Arg2));
break;
default:
- PN->addIncoming(getValue(Raw->Ty, Raw->Arg1),
- cast<BasicBlock>(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;
} else {
std::vector<unsigned> &args = *Raw->VarArgs;
for (unsigned i = 0; i < args.size(); i+=2)
- PN->addIncoming(getValue(Raw->Ty, args[i]),
- cast<BasicBlock>(getValue(Type::LabelTyID, args[i+1])));
+ PN->addIncoming(getValue(Raw->Ty, args[i]), getBasicBlock(args[i+1]));
}
delete Raw->VarArgs;
break;
case Instruction::Br:
if (Raw->NumOperands == 1) {
- Res = new BranchInst(cast<BasicBlock>(getValue(Type::LabelTyID,Raw->Arg1)));
+ Res = new BranchInst(getBasicBlock(Raw->Arg1));
return false;
} else if (Raw->NumOperands == 3) {
- Res = new BranchInst(cast<BasicBlock>(getValue(Type::LabelTyID, Raw->Arg1)),
- cast<BasicBlock>(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<BasicBlock>(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.
std::vector<unsigned> &args = *Raw->VarArgs;
for (unsigned i = 0; i < args.size(); i += 2)
I->addCase(cast<Constant>(getValue(Raw->Ty, args[i])),
- cast<BasicBlock>(getValue(Type::LabelTyID, args[i+1])));
+ getBasicBlock(args[i+1]));
delete Raw->VarArgs;
return false;
if (!FTy->isVarArg()) {
if (Raw->NumOperands < 3) return true;
- Normal = cast<BasicBlock>(getValue(Type::LabelTyID, Raw->Arg2));
+ Normal = getBasicBlock(Raw->Arg2);
if (Raw->NumOperands == 3)
- Except = cast<BasicBlock>(getValue(Type::LabelTyID, Raw->Arg3));
+ Except = getBasicBlock(Raw->Arg3);
else {
- Except = cast<BasicBlock>(getValue(Type::LabelTyID, args[0]));
+ Except = getBasicBlock(args[0]);
FunctionType::ParamTypes::const_iterator It = PL.begin();
for (unsigned i = 1; i < args.size(); i++) {
}
} else {
if (args.size() < 4) return true;
- if (getType(args[0]) != Type::LabelTy ||
- getType(args[2]) != Type::LabelTy) return true;
- Normal = cast<BasicBlock>(getValue(Type::LabelTyID, args[1]));
- Except = cast<BasicBlock>(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
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) {
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
}
-std::auto_ptr<BasicBlock>
-BytecodeParser::ParseBasicBlock(const unsigned char *&Buf,
- const unsigned char *EndBuf) {
- std::auto_ptr<BasicBlock> 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;
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;
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;
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!");
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;
case BytecodeFormat::BasicBlock: {
BCR_TRACE(2, "BLOCK BytecodeFormat::BasicBlock: {\n");
- std::auto_ptr<BasicBlock> 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;
}
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();
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:
ValueTable Values, LateResolveValues;
ValueTable ModuleValues;
+ std::vector<BasicBlock*> ParsedBasicBlocks;
+
// GlobalRefs - This maintains a mapping between <Type, Slot #>'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
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<BasicBlock>
- 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<RawInst> ParseRawInst(const unsigned char *&Buf,
const unsigned char *End);
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
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) {}
};
typedef PlaceholderDef<InstPlaceHolderHelper> ValPHolder;
-typedef PlaceholderDef<BBPlaceHolderHelper> BBPHolder;
typedef PlaceholderDef<ConstantPlaceHolderHelper> ConstPHolder;
// Some common errors we find
static inline unsigned getValueIDNumberFromPlaceHolder(Value *Val) {
if (isa<Constant>(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,