- Finally nailed: test/Regression/Assembler/2002-08-16-ConstExprInlined.llx

- ParseConstantPool was resolving reference to value using the function
      slot # instead of the global slot #.
  - Bytecode reader changes:
    - Remove the failure<> template from Bytecode Reader
    - Remove extraneous #includes
    - s/method/function/ a bit
    - Eliminate the fwdRefs class that just added abstraction where it was not
      needed, making things more complex.
    - Use a vector instead of a list for function signatures.

llvm-svn: 3366
This commit is contained in:
Chris Lattner 2002-08-17 22:01:27 +00:00
parent 56b56d90f0
commit 51fa0ef925
4 changed files with 292 additions and 378 deletions

View File

@ -10,17 +10,14 @@
#include "ReaderInternals.h" #include "ReaderInternals.h"
#include "llvm/Module.h" #include "llvm/Module.h"
#include "llvm/Constants.h"
#include "llvm/GlobalVariable.h"
#include <algorithm> #include <algorithm>
#include <iostream>
using std::make_pair; using std::make_pair;
const Type *BytecodeParser::parseTypeConstant(const uchar *&Buf, const Type *BytecodeParser::parseTypeConstant(const uchar *&Buf,
const uchar *EndBuf) { const uchar *EndBuf) {
unsigned PrimType; unsigned PrimType;
if (read_vbr(Buf, EndBuf, PrimType)) return failure<const Type*>(0); if (read_vbr(Buf, EndBuf, PrimType)) return 0;
const Type *Val = 0; const Type *Val = 0;
if ((Val = Type::getPrimitiveType((Type::PrimitiveID)PrimType))) if ((Val = Type::getPrimitiveType((Type::PrimitiveID)PrimType)))
@ -29,18 +26,18 @@ const Type *BytecodeParser::parseTypeConstant(const uchar *&Buf,
switch (PrimType) { switch (PrimType) {
case Type::FunctionTyID: { case Type::FunctionTyID: {
unsigned Typ; unsigned Typ;
if (read_vbr(Buf, EndBuf, Typ)) return failure(Val); if (read_vbr(Buf, EndBuf, Typ)) return Val;
const Type *RetType = getType(Typ); const Type *RetType = getType(Typ);
if (RetType == 0) return failure(Val); if (RetType == 0) return Val;
unsigned NumParams; unsigned NumParams;
if (read_vbr(Buf, EndBuf, NumParams)) return failure(Val); if (read_vbr(Buf, EndBuf, NumParams)) return Val;
std::vector<const Type*> Params; std::vector<const Type*> Params;
while (NumParams--) { while (NumParams--) {
if (read_vbr(Buf, EndBuf, Typ)) return failure(Val); if (read_vbr(Buf, EndBuf, Typ)) return Val;
const Type *Ty = getType(Typ); const Type *Ty = getType(Typ);
if (Ty == 0) return failure(Val); if (Ty == 0) return Val;
Params.push_back(Ty); Params.push_back(Ty);
} }
@ -51,12 +48,12 @@ const Type *BytecodeParser::parseTypeConstant(const uchar *&Buf,
} }
case Type::ArrayTyID: { case Type::ArrayTyID: {
unsigned ElTyp; unsigned ElTyp;
if (read_vbr(Buf, EndBuf, ElTyp)) return failure(Val); if (read_vbr(Buf, EndBuf, ElTyp)) return Val;
const Type *ElementType = getType(ElTyp); const Type *ElementType = getType(ElTyp);
if (ElementType == 0) return failure(Val); if (ElementType == 0) return Val;
unsigned NumElements; unsigned NumElements;
if (read_vbr(Buf, EndBuf, NumElements)) return failure(Val); if (read_vbr(Buf, EndBuf, NumElements)) return Val;
BCR_TRACE(5, "Array Type Constant #" << ElTyp << " size=" BCR_TRACE(5, "Array Type Constant #" << ElTyp << " size="
<< NumElements << "\n"); << NumElements << "\n");
@ -66,23 +63,23 @@ const Type *BytecodeParser::parseTypeConstant(const uchar *&Buf,
unsigned Typ; unsigned Typ;
std::vector<const Type*> Elements; std::vector<const Type*> Elements;
if (read_vbr(Buf, EndBuf, Typ)) return failure(Val); if (read_vbr(Buf, EndBuf, Typ)) return Val;
while (Typ) { // List is terminated by void/0 typeid while (Typ) { // List is terminated by void/0 typeid
const Type *Ty = getType(Typ); const Type *Ty = getType(Typ);
if (Ty == 0) return failure(Val); if (Ty == 0) return Val;
Elements.push_back(Ty); Elements.push_back(Ty);
if (read_vbr(Buf, EndBuf, Typ)) return failure(Val); if (read_vbr(Buf, EndBuf, Typ)) return Val;
} }
return StructType::get(Elements); return StructType::get(Elements);
} }
case Type::PointerTyID: { case Type::PointerTyID: {
unsigned ElTyp; unsigned ElTyp;
if (read_vbr(Buf, EndBuf, ElTyp)) return failure(Val); if (read_vbr(Buf, EndBuf, ElTyp)) return Val;
BCR_TRACE(5, "Pointer Type Constant #" << (ElTyp-14) << "\n"); BCR_TRACE(5, "Pointer Type Constant #" << (ElTyp-14) << "\n");
const Type *ElementType = getType(ElTyp); const Type *ElementType = getType(ElTyp);
if (ElementType == 0) return failure(Val); if (ElementType == 0) return Val;
return PointerType::get(ElementType); return PointerType::get(ElementType);
} }
@ -94,7 +91,7 @@ const Type *BytecodeParser::parseTypeConstant(const uchar *&Buf,
std::cerr << __FILE__ << ":" << __LINE__ std::cerr << __FILE__ << ":" << __LINE__
<< ": Don't know how to deserialize" << ": Don't know how to deserialize"
<< " primitive Type " << PrimType << "\n"; << " primitive Type " << PrimType << "\n";
return failure(Val); return Val;
} }
} }
@ -149,7 +146,7 @@ bool BytecodeParser::parseTypeConstants(const uchar *&Buf, const uchar *EndBuf,
// //
for (unsigned i = 0; i < NumEntries; ++i) { for (unsigned i = 0; i < NumEntries; ++i) {
const Type *NewTy = parseTypeConstant(Buf, EndBuf), *OldTy = Tab[i].get(); const Type *NewTy = parseTypeConstant(Buf, EndBuf), *OldTy = Tab[i].get();
if (NewTy == 0) return failure(true); if (NewTy == 0) return true;
BCR_TRACE(4, "#" << i << ": Read Type Constant: '" << NewTy << BCR_TRACE(4, "#" << i << ": Read Type Constant: '" << NewTy <<
"' Replacing: " << OldTy << "\n"); "' Replacing: " << OldTy << "\n");
@ -184,21 +181,21 @@ bool BytecodeParser::parseConstantValue(const uchar *&Buf, const uchar *EndBuf,
// a ConstantExpr can be of any type, and has no explicit value. // a ConstantExpr can be of any type, and has no explicit value.
// //
unsigned isExprNumArgs; // 0 if not expr; numArgs if is expr unsigned isExprNumArgs; // 0 if not expr; numArgs if is expr
if (read_vbr(Buf, EndBuf, isExprNumArgs)) return failure(true); if (read_vbr(Buf, EndBuf, isExprNumArgs)) return true;
if (isExprNumArgs) { if (isExprNumArgs) {
// FIXME: Encoding of constant exprs could be much more compact! // FIXME: Encoding of constant exprs could be much more compact!
unsigned Opcode; unsigned Opcode;
std::vector<Constant*> ArgVec; std::vector<Constant*> ArgVec;
ArgVec.reserve(isExprNumArgs); ArgVec.reserve(isExprNumArgs);
if (read_vbr(Buf, EndBuf, Opcode)) return failure(true); if (read_vbr(Buf, EndBuf, Opcode)) return true;
// Read the slot number and types of each of the arguments // Read the slot number and types of each of the arguments
for (unsigned i = 0; i != isExprNumArgs; ++i) { for (unsigned i = 0; i != isExprNumArgs; ++i) {
unsigned ArgValSlot, ArgTypeSlot; unsigned ArgValSlot, ArgTypeSlot;
if (read_vbr(Buf, EndBuf, ArgValSlot)) return failure(true); if (read_vbr(Buf, EndBuf, ArgValSlot)) return true;
if (read_vbr(Buf, EndBuf, ArgTypeSlot)) return failure(true); if (read_vbr(Buf, EndBuf, ArgTypeSlot)) return true;
const Type *ArgTy = getType(ArgTypeSlot); const Type *ArgTy = getType(ArgTypeSlot);
if (ArgTy == 0) return failure(true); if (ArgTy == 0) return true;
BCR_TRACE(4, "CE Arg " << i << ": Type: '" << ArgTy << "' slot: " BCR_TRACE(4, "CE Arg " << i << ": Type: '" << ArgTy << "' slot: "
<< ArgValSlot << "\n"); << ArgValSlot << "\n");
@ -207,10 +204,23 @@ bool BytecodeParser::parseConstantValue(const uchar *&Buf, const uchar *EndBuf,
Value *Val = getValue(ArgTy, ArgValSlot, false); Value *Val = getValue(ArgTy, ArgValSlot, false);
Constant *C; Constant *C;
if (Val) { if (Val) {
if (!(C = dyn_cast<Constant>(Val))) return failure(true); if (!(C = dyn_cast<Constant>(Val))) return true;
BCR_TRACE(5, "Constant Found in ValueTable!\n"); BCR_TRACE(5, "Constant Found in ValueTable!\n");
} else { // Nope... find or create a forward ref. for it } else { // Nope... find or create a forward ref. for it
C = fwdRefs.GetFwdRefToConstant(ArgTy, ArgValSlot); GlobalRefsType::iterator I = GlobalRefs.find(make_pair(Ty, ArgValSlot));
if (I != GlobalRefs.end()) {
BCR_TRACE(5, "Previous forward ref found!\n");
C = cast<Constant>(I->second);
} else {
// Create a placeholder for the constant reference and
// keep track of the fact that we have a forward ref to recycle it
BCR_TRACE(5, "Creating new forward ref to a constant!\n");
C = new ConstPHolder(ArgTy, ArgValSlot);
// Keep track of the fact that we have a forward ref to recycle it
GlobalRefs.insert(make_pair(make_pair(ArgTy, ArgValSlot), C));
}
} }
ArgVec.push_back(C); ArgVec.push_back(C);
} }
@ -232,8 +242,8 @@ bool BytecodeParser::parseConstantValue(const uchar *&Buf, const uchar *EndBuf,
switch (Ty->getPrimitiveID()) { switch (Ty->getPrimitiveID()) {
case Type::BoolTyID: { case Type::BoolTyID: {
unsigned Val; unsigned Val;
if (read_vbr(Buf, EndBuf, Val)) return failure(true); if (read_vbr(Buf, EndBuf, Val)) return true;
if (Val != 0 && Val != 1) return failure(true); if (Val != 0 && Val != 1) return true;
V = ConstantBool::get(Val == 1); V = ConstantBool::get(Val == 1);
break; break;
} }
@ -242,15 +252,15 @@ bool BytecodeParser::parseConstantValue(const uchar *&Buf, const uchar *EndBuf,
case Type::UShortTyID: case Type::UShortTyID:
case Type::UIntTyID: { case Type::UIntTyID: {
unsigned Val; unsigned Val;
if (read_vbr(Buf, EndBuf, Val)) return failure(true); if (read_vbr(Buf, EndBuf, Val)) return true;
if (!ConstantUInt::isValueValidForType(Ty, Val)) return failure(true); if (!ConstantUInt::isValueValidForType(Ty, Val)) return true;
V = ConstantUInt::get(Ty, Val); V = ConstantUInt::get(Ty, Val);
break; break;
} }
case Type::ULongTyID: { case Type::ULongTyID: {
uint64_t Val; uint64_t Val;
if (read_vbr(Buf, EndBuf, Val)) return failure(true); if (read_vbr(Buf, EndBuf, Val)) return true;
V = ConstantUInt::get(Ty, Val); V = ConstantUInt::get(Ty, Val);
break; break;
} }
@ -259,29 +269,29 @@ bool BytecodeParser::parseConstantValue(const uchar *&Buf, const uchar *EndBuf,
case Type::ShortTyID: case Type::ShortTyID:
case Type::IntTyID: { case Type::IntTyID: {
int Val; int Val;
if (read_vbr(Buf, EndBuf, Val)) return failure(true); if (read_vbr(Buf, EndBuf, Val)) return true;
if (!ConstantSInt::isValueValidForType(Ty, Val)) return failure(true); if (!ConstantSInt::isValueValidForType(Ty, Val)) return true;
V = ConstantSInt::get(Ty, Val); V = ConstantSInt::get(Ty, Val);
break; break;
} }
case Type::LongTyID: { case Type::LongTyID: {
int64_t Val; int64_t Val;
if (read_vbr(Buf, EndBuf, Val)) return failure(true); if (read_vbr(Buf, EndBuf, Val)) return true;
V = ConstantSInt::get(Ty, Val); V = ConstantSInt::get(Ty, Val);
break; break;
} }
case Type::FloatTyID: { case Type::FloatTyID: {
float F; float F;
if (input_data(Buf, EndBuf, &F, &F+1)) return failure(true); if (input_data(Buf, EndBuf, &F, &F+1)) return true;
V = ConstantFP::get(Ty, F); V = ConstantFP::get(Ty, F);
break; break;
} }
case Type::DoubleTyID: { case Type::DoubleTyID: {
double Val; double Val;
if (input_data(Buf, EndBuf, &Val, &Val+1)) return failure(true); if (input_data(Buf, EndBuf, &Val, &Val+1)) return true;
V = ConstantFP::get(Ty, Val); V = ConstantFP::get(Ty, Val);
break; break;
} }
@ -297,9 +307,9 @@ bool BytecodeParser::parseConstantValue(const uchar *&Buf, const uchar *EndBuf,
std::vector<Constant*> Elements; std::vector<Constant*> Elements;
while (NumElements--) { // Read all of the elements of the constant. while (NumElements--) { // Read all of the elements of the constant.
unsigned Slot; unsigned Slot;
if (read_vbr(Buf, EndBuf, Slot)) return failure(true); if (read_vbr(Buf, EndBuf, Slot)) return true;
Value *V = getValue(AT->getElementType(), Slot, false); Value *V = getValue(AT->getElementType(), Slot, false);
if (!V || !isa<Constant>(V)) return failure(true); if (!V || !isa<Constant>(V)) return true;
Elements.push_back(cast<Constant>(V)); Elements.push_back(cast<Constant>(V));
} }
V = ConstantArray::get(AT, Elements); V = ConstantArray::get(AT, Elements);
@ -313,10 +323,10 @@ bool BytecodeParser::parseConstantValue(const uchar *&Buf, const uchar *EndBuf,
std::vector<Constant *> Elements; std::vector<Constant *> Elements;
for (unsigned i = 0; i < ET.size(); ++i) { for (unsigned i = 0; i < ET.size(); ++i) {
unsigned Slot; unsigned Slot;
if (read_vbr(Buf, EndBuf, Slot)) return failure(true); if (read_vbr(Buf, EndBuf, Slot)) return true;
Value *V = getValue(ET[i], Slot, false); Value *V = getValue(ET[i], Slot, false);
if (!V || !isa<Constant>(V)) if (!V || !isa<Constant>(V))
return failure(true); return true;
Elements.push_back(cast<Constant>(V)); Elements.push_back(cast<Constant>(V));
} }
@ -327,7 +337,7 @@ bool BytecodeParser::parseConstantValue(const uchar *&Buf, const uchar *EndBuf,
case Type::PointerTyID: { case Type::PointerTyID: {
const PointerType *PT = cast<const PointerType>(Ty); const PointerType *PT = cast<const PointerType>(Ty);
unsigned SubClass; unsigned SubClass;
if (read_vbr(Buf, EndBuf, SubClass)) return failure(true); if (read_vbr(Buf, EndBuf, SubClass)) return true;
switch (SubClass) { switch (SubClass) {
case 0: // ConstantPointerNull value... case 0: // ConstantPointerNull value...
V = ConstantPointerNull::get(PT); V = ConstantPointerNull::get(PT);
@ -335,17 +345,35 @@ bool BytecodeParser::parseConstantValue(const uchar *&Buf, const uchar *EndBuf,
case 1: { // ConstantPointerRef value... case 1: { // ConstantPointerRef value...
unsigned Slot; unsigned Slot;
if (read_vbr(Buf, EndBuf, Slot)) return failure(true); if (read_vbr(Buf, EndBuf, Slot)) return true;
BCR_TRACE(4, "CPR: Type: '" << Ty << "' slot: " << Slot << "\n"); BCR_TRACE(4, "CPR: Type: '" << Ty << "' slot: " << Slot << "\n");
// Check to see if we have already read this global variable yet... // Check to see if we have already read this global variable...
Value *Val = getValue(PT, Slot, false); Value *Val = getValue(PT, Slot, false);
GlobalValue* GV; GlobalValue *GV;
if (Val) { if (Val) {
if (!(GV = dyn_cast<GlobalValue>(Val))) return failure(true); if (!(GV = dyn_cast<GlobalValue>(Val))) return true;
BCR_TRACE(5, "Value Found in ValueTable!\n"); BCR_TRACE(5, "Value Found in ValueTable!\n");
} else { // Nope... find or create a forward ref. for it } else { // Nope... find or create a forward ref. for it
GV = fwdRefs.GetFwdRefToGlobal(PT, Slot); GlobalRefsType::iterator I = GlobalRefs.find(make_pair(PT, Slot));
if (I != GlobalRefs.end()) {
BCR_TRACE(5, "Previous forward ref found!\n");
GV = cast<GlobalValue>(I->second);
} else {
BCR_TRACE(5, "Creating new forward ref to a global variable!\n");
// Create a placeholder for the global variable reference...
GlobalVariable *GVar =
new GlobalVariable(PT->getElementType(), false, true);
// Keep track of the fact that we have a forward ref to recycle it
GlobalRefs.insert(make_pair(make_pair(PT, Slot), GVar));
// Must temporarily push this value into the module table...
TheModule->getGlobalList().push_back(GVar);
GV = GVar;
}
} }
V = ConstantPointerRef::get(GV); V = ConstantPointerRef::get(GV);
break; break;
@ -353,7 +381,7 @@ bool BytecodeParser::parseConstantValue(const uchar *&Buf, const uchar *EndBuf,
default: default:
BCR_TRACE(5, "UNKNOWN Pointer Constant Type!\n"); BCR_TRACE(5, "UNKNOWN Pointer Constant Type!\n");
return failure(true); return true;
} }
break; break;
} }
@ -362,7 +390,7 @@ bool BytecodeParser::parseConstantValue(const uchar *&Buf, const uchar *EndBuf,
std::cerr << __FILE__ << ":" << __LINE__ std::cerr << __FILE__ << ":" << __LINE__
<< ": Don't know how to deserialize constant value of type '" << ": Don't know how to deserialize constant value of type '"
<< Ty->getName() << "'\n"; << Ty->getName() << "'\n";
return failure(true); return true;
} }
return false; return false;
@ -375,9 +403,9 @@ bool BytecodeParser::ParseConstantPool(const uchar *&Buf, const uchar *EndBuf,
unsigned NumEntries, Typ; unsigned NumEntries, Typ;
if (read_vbr(Buf, EndBuf, NumEntries) || if (read_vbr(Buf, EndBuf, NumEntries) ||
read_vbr(Buf, EndBuf, Typ)) return failure(true); read_vbr(Buf, EndBuf, Typ)) return true;
const Type *Ty = getType(Typ); const Type *Ty = getType(Typ);
if (Ty == 0) return failure(true); if (Ty == 0) return true;
BCR_TRACE(3, "Type: '" << Ty << "' NumEntries: " << NumEntries << "\n"); BCR_TRACE(3, "Type: '" << Ty << "' NumEntries: " << NumEntries << "\n");
if (Typ == Type::TypeTyID) { if (Typ == Type::TypeTyID) {
@ -386,15 +414,22 @@ bool BytecodeParser::ParseConstantPool(const uchar *&Buf, const uchar *EndBuf,
for (unsigned i = 0; i < NumEntries; ++i) { for (unsigned i = 0; i < NumEntries; ++i) {
Constant *I; Constant *I;
int Slot; int Slot;
if (parseConstantValue(Buf, EndBuf, Ty, I)) return failure(true); if (parseConstantValue(Buf, EndBuf, Ty, I)) return true;
assert(I && "parseConstantValue returned `!failure' and NULL result"); assert(I && "parseConstantValue returned NULL!");
BCR_TRACE(4, "Read Constant: '" << I << "'\n"); BCR_TRACE(4, "Read Constant: '" << I << "'\n");
if ((Slot = insertValue(I, Tab)) < 0) return failure(true); if ((Slot = insertValue(I, Tab)) < 0) return true;
resolveRefsToConstant(I, (unsigned) Slot);
// If we are reading a function constant table, make sure that we adjust
// the slot number to be the real global constant number.
//
if (&Tab != &ModuleValues)
Slot += ModuleValues[Typ].size();
ResolveReferencesToValue(I, (unsigned)Slot);
} }
} }
} }
if (Buf > EndBuf) return failure(true); if (Buf > EndBuf) return true;
return false; return false;
} }

View File

@ -16,14 +16,13 @@
#include "llvm/iMemory.h" #include "llvm/iMemory.h"
#include "llvm/iPHINode.h" #include "llvm/iPHINode.h"
#include "llvm/iOther.h" #include "llvm/iOther.h"
#include <iostream>
using std::vector; using std::vector;
using std::cerr; using std::cerr;
bool BytecodeParser::ParseRawInst(const uchar *&Buf, const uchar *EndBuf, bool BytecodeParser::ParseRawInst(const uchar *&Buf, const uchar *EndBuf,
RawInst &Result) { RawInst &Result) {
unsigned Op, Typ; unsigned Op, Typ;
if (read(Buf, EndBuf, Op)) return failure(true); if (read(Buf, EndBuf, Op)) return true;
// bits Instruction format: Common to all formats // bits Instruction format: Common to all formats
// -------------------------- // --------------------------
@ -70,40 +69,40 @@ bool BytecodeParser::ParseRawInst(const uchar *&Buf, const uchar *EndBuf,
break; break;
case 0: case 0:
Buf -= 4; // Hrm, try this again... Buf -= 4; // Hrm, try this again...
if (read_vbr(Buf, EndBuf, Result.Opcode)) return failure(true); if (read_vbr(Buf, EndBuf, Result.Opcode)) return true;
Result.Opcode >>= 2; Result.Opcode >>= 2;
if (read_vbr(Buf, EndBuf, Typ)) return failure(true); if (read_vbr(Buf, EndBuf, Typ)) return true;
Result.Ty = getType(Typ); Result.Ty = getType(Typ);
if (Result.Ty == 0) return failure(true); if (Result.Ty == 0) return true;
if (read_vbr(Buf, EndBuf, Result.NumOperands)) return failure(true); if (read_vbr(Buf, EndBuf, Result.NumOperands)) return true;
switch (Result.NumOperands) { switch (Result.NumOperands) {
case 0: case 0:
cerr << "Zero Arg instr found!\n"; cerr << "Zero Arg instr found!\n";
return failure(true); // This encoding is invalid! return true; // This encoding is invalid!
case 1: case 1:
if (read_vbr(Buf, EndBuf, Result.Arg1)) return failure(true); if (read_vbr(Buf, EndBuf, Result.Arg1)) return true;
break; break;
case 2: case 2:
if (read_vbr(Buf, EndBuf, Result.Arg1) || if (read_vbr(Buf, EndBuf, Result.Arg1) ||
read_vbr(Buf, EndBuf, Result.Arg2)) return failure(true); read_vbr(Buf, EndBuf, Result.Arg2)) return true;
break; break;
case 3: case 3:
if (read_vbr(Buf, EndBuf, Result.Arg1) || if (read_vbr(Buf, EndBuf, Result.Arg1) ||
read_vbr(Buf, EndBuf, Result.Arg2) || read_vbr(Buf, EndBuf, Result.Arg2) ||
read_vbr(Buf, EndBuf, Result.Arg3)) return failure(true); read_vbr(Buf, EndBuf, Result.Arg3)) return true;
break; break;
default: default:
if (read_vbr(Buf, EndBuf, Result.Arg1) || if (read_vbr(Buf, EndBuf, Result.Arg1) ||
read_vbr(Buf, EndBuf, Result.Arg2)) return failure(true); read_vbr(Buf, EndBuf, Result.Arg2)) return true;
// Allocate a vector to hold arguments 3, 4, 5, 6 ... // Allocate a vector to hold arguments 3, 4, 5, 6 ...
Result.VarArgs = new vector<unsigned>(Result.NumOperands-2); Result.VarArgs = new vector<unsigned>(Result.NumOperands-2);
for (unsigned a = 0; a < Result.NumOperands-2; a++) for (unsigned a = 0; a < Result.NumOperands-2; a++)
if (read_vbr(Buf, EndBuf, (*Result.VarArgs)[a])) return failure(true); if (read_vbr(Buf, EndBuf, (*Result.VarArgs)[a])) return true;
break; break;
} }
if (align32(Buf, EndBuf)) return failure(true); if (align32(Buf, EndBuf)) return true;
break; break;
} }
@ -120,7 +119,7 @@ bool BytecodeParser::ParseInstruction(const uchar *&Buf, const uchar *EndBuf,
Instruction *&Res) { Instruction *&Res) {
RawInst Raw; RawInst Raw;
if (ParseRawInst(Buf, EndBuf, Raw)) if (ParseRawInst(Buf, EndBuf, Raw))
return failure(true); return true;
if (Raw.Opcode >= Instruction::FirstBinaryOp && if (Raw.Opcode >= Instruction::FirstBinaryOp &&
Raw.Opcode < Instruction::NumBinaryOps && Raw.NumOperands == 2) { Raw.Opcode < Instruction::NumBinaryOps && Raw.NumOperands == 2) {
@ -146,7 +145,7 @@ bool BytecodeParser::ParseInstruction(const uchar *&Buf, const uchar *EndBuf,
case 1: case 1:
case 3: cerr << "Invalid phi node encountered!\n"; case 3: cerr << "Invalid phi node encountered!\n";
delete PN; delete PN;
return failure(true); return true;
case 2: PN->addIncoming(getValue(Raw.Ty, Raw.Arg1), case 2: PN->addIncoming(getValue(Raw.Ty, Raw.Arg1),
cast<BasicBlock>(getValue(Type::LabelTy,Raw.Arg2))); cast<BasicBlock>(getValue(Type::LabelTy,Raw.Arg2)));
break; break;
@ -156,7 +155,7 @@ bool BytecodeParser::ParseInstruction(const uchar *&Buf, const uchar *EndBuf,
if (Raw.VarArgs->size() & 1) { if (Raw.VarArgs->size() & 1) {
cerr << "PHI Node with ODD number of arguments!\n"; cerr << "PHI Node with ODD number of arguments!\n";
delete PN; delete PN;
return failure(true); return true;
} else { } else {
vector<unsigned> &args = *Raw.VarArgs; vector<unsigned> &args = *Raw.VarArgs;
for (unsigned i = 0; i < args.size(); i+=2) for (unsigned i = 0; i < args.size(); i+=2)
@ -206,7 +205,7 @@ bool BytecodeParser::ParseInstruction(const uchar *&Buf, const uchar *EndBuf,
if (Raw.NumOperands == 3 || Raw.VarArgs->size() & 1) { if (Raw.NumOperands == 3 || Raw.VarArgs->size() & 1) {
cerr << "Switch statement with odd number of arguments!\n"; cerr << "Switch statement with odd number of arguments!\n";
delete I; delete I;
return failure(true); return true;
} }
vector<unsigned> &args = *Raw.VarArgs; vector<unsigned> &args = *Raw.VarArgs;
@ -220,13 +219,13 @@ bool BytecodeParser::ParseInstruction(const uchar *&Buf, const uchar *EndBuf,
case Instruction::Call: { case Instruction::Call: {
Value *M = getValue(Raw.Ty, Raw.Arg1); Value *M = getValue(Raw.Ty, Raw.Arg1);
if (M == 0) return failure(true); if (M == 0) return true;
// Check to make sure we have a pointer to method type // Check to make sure we have a pointer to method type
const PointerType *PTy = dyn_cast<PointerType>(M->getType()); const PointerType *PTy = dyn_cast<PointerType>(M->getType());
if (PTy == 0) return failure(true); if (PTy == 0) return true;
const FunctionType *MTy = dyn_cast<FunctionType>(PTy->getElementType()); const FunctionType *MTy = dyn_cast<FunctionType>(PTy->getElementType());
if (MTy == 0) return failure(true); if (MTy == 0) return true;
vector<Value *> Params; vector<Value *> Params;
const FunctionType::ParamTypes &PL = MTy->getParamTypes(); const FunctionType::ParamTypes &PL = MTy->getParamTypes();
@ -236,39 +235,39 @@ bool BytecodeParser::ParseInstruction(const uchar *&Buf, const uchar *EndBuf,
switch (Raw.NumOperands) { switch (Raw.NumOperands) {
case 0: cerr << "Invalid call instruction encountered!\n"; case 0: cerr << "Invalid call instruction encountered!\n";
return failure(true); return true;
case 1: break; case 1: break;
case 2: Params.push_back(getValue(*It++, Raw.Arg2)); break; case 2: Params.push_back(getValue(*It++, Raw.Arg2)); break;
case 3: Params.push_back(getValue(*It++, Raw.Arg2)); case 3: Params.push_back(getValue(*It++, Raw.Arg2));
if (It == PL.end()) return failure(true); if (It == PL.end()) return true;
Params.push_back(getValue(*It++, Raw.Arg3)); break; Params.push_back(getValue(*It++, Raw.Arg3)); break;
default: default:
Params.push_back(getValue(*It++, Raw.Arg2)); Params.push_back(getValue(*It++, Raw.Arg2));
{ {
vector<unsigned> &args = *Raw.VarArgs; vector<unsigned> &args = *Raw.VarArgs;
for (unsigned i = 0; i < args.size(); i++) { for (unsigned i = 0; i < args.size(); i++) {
if (It == PL.end()) return failure(true); if (It == PL.end()) return true;
// TODO: Check getValue for null! // TODO: Check getValue for null!
Params.push_back(getValue(*It++, args[i])); Params.push_back(getValue(*It++, args[i]));
} }
} }
delete Raw.VarArgs; delete Raw.VarArgs;
} }
if (It != PL.end()) return failure(true); if (It != PL.end()) return true;
} else { } else {
if (Raw.NumOperands > 2) { if (Raw.NumOperands > 2) {
vector<unsigned> &args = *Raw.VarArgs; vector<unsigned> &args = *Raw.VarArgs;
if (args.size() < 1) return failure(true); if (args.size() < 1) return true;
if ((args.size() & 1) != 0) if ((args.size() & 1) != 0)
return failure(true); // Must be pairs of type/value return true; // Must be pairs of type/value
for (unsigned i = 0; i < args.size(); i+=2) { for (unsigned i = 0; i < args.size(); i+=2) {
const Type *Ty = getType(args[i]); const Type *Ty = getType(args[i]);
if (Ty == 0) if (Ty == 0)
return failure(true); return true;
Value *V = getValue(Ty, args[i+1]); Value *V = getValue(Ty, args[i+1]);
if (V == 0) return failure(true); if (V == 0) return true;
Params.push_back(V); Params.push_back(V);
} }
delete Raw.VarArgs; delete Raw.VarArgs;
@ -280,13 +279,13 @@ bool BytecodeParser::ParseInstruction(const uchar *&Buf, const uchar *EndBuf,
} }
case Instruction::Invoke: { case Instruction::Invoke: {
Value *M = getValue(Raw.Ty, Raw.Arg1); Value *M = getValue(Raw.Ty, Raw.Arg1);
if (M == 0) return failure(true); if (M == 0) return true;
// Check to make sure we have a pointer to method type // Check to make sure we have a pointer to method type
const PointerType *PTy = dyn_cast<PointerType>(M->getType()); const PointerType *PTy = dyn_cast<PointerType>(M->getType());
if (PTy == 0) return failure(true); if (PTy == 0) return true;
const FunctionType *MTy = dyn_cast<FunctionType>(PTy->getElementType()); const FunctionType *MTy = dyn_cast<FunctionType>(PTy->getElementType());
if (MTy == 0) return failure(true); if (MTy == 0) return true;
vector<Value *> Params; vector<Value *> Params;
const FunctionType::ParamTypes &PL = MTy->getParamTypes(); const FunctionType::ParamTypes &PL = MTy->getParamTypes();
@ -295,27 +294,27 @@ bool BytecodeParser::ParseInstruction(const uchar *&Buf, const uchar *EndBuf,
BasicBlock *Normal, *Except; BasicBlock *Normal, *Except;
if (!MTy->isVarArg()) { if (!MTy->isVarArg()) {
if (Raw.NumOperands < 3) return failure(true); if (Raw.NumOperands < 3) return true;
Normal = cast<BasicBlock>(getValue(Type::LabelTy, Raw.Arg2)); Normal = cast<BasicBlock>(getValue(Type::LabelTy, Raw.Arg2));
Except = cast<BasicBlock>(getValue(Type::LabelTy, args[0])); Except = cast<BasicBlock>(getValue(Type::LabelTy, args[0]));
FunctionType::ParamTypes::const_iterator It = PL.begin(); FunctionType::ParamTypes::const_iterator It = PL.begin();
for (unsigned i = 1; i < args.size(); i++) { for (unsigned i = 1; i < args.size(); i++) {
if (It == PL.end()) return failure(true); if (It == PL.end()) return true;
// TODO: Check getValue for null! // TODO: Check getValue for null!
Params.push_back(getValue(*It++, args[i])); Params.push_back(getValue(*It++, args[i]));
} }
if (It != PL.end()) return failure(true); if (It != PL.end()) return true;
} else { } else {
if (args.size() < 4) return failure(true); if (args.size() < 4) return true;
Normal = cast<BasicBlock>(getValue(Type::LabelTy, args[0])); Normal = cast<BasicBlock>(getValue(Type::LabelTy, args[0]));
Except = cast<BasicBlock>(getValue(Type::LabelTy, args[2])); Except = cast<BasicBlock>(getValue(Type::LabelTy, args[2]));
if ((args.size() & 1) != 0) if ((args.size() & 1) != 0)
return failure(true); // Must be pairs of type/value return true; // Must be pairs of type/value
for (unsigned i = 4; i < args.size(); i+=2) { for (unsigned i = 4; i < args.size(); i+=2) {
// TODO: Check getValue for null! // TODO: Check getValue for null!
Params.push_back(getValue(getType(args[i]), args[i+1])); Params.push_back(getValue(getType(args[i]), args[i+1]));
@ -327,62 +326,62 @@ bool BytecodeParser::ParseInstruction(const uchar *&Buf, const uchar *EndBuf,
return false; return false;
} }
case Instruction::Malloc: case Instruction::Malloc:
if (Raw.NumOperands > 2) return failure(true); if (Raw.NumOperands > 2) return true;
V = Raw.NumOperands ? getValue(Type::UIntTy, Raw.Arg1) : 0; V = Raw.NumOperands ? getValue(Type::UIntTy, Raw.Arg1) : 0;
Res = new MallocInst(Raw.Ty, V); Res = new MallocInst(Raw.Ty, V);
return false; return false;
case Instruction::Alloca: case Instruction::Alloca:
if (Raw.NumOperands > 2) return failure(true); if (Raw.NumOperands > 2) return true;
V = Raw.NumOperands ? getValue(Type::UIntTy, Raw.Arg1) : 0; V = Raw.NumOperands ? getValue(Type::UIntTy, Raw.Arg1) : 0;
Res = new AllocaInst(Raw.Ty, V); Res = new AllocaInst(Raw.Ty, V);
return false; return false;
case Instruction::Free: case Instruction::Free:
V = getValue(Raw.Ty, Raw.Arg1); V = getValue(Raw.Ty, Raw.Arg1);
if (!isa<PointerType>(V->getType())) return failure(true); if (!isa<PointerType>(V->getType())) return true;
Res = new FreeInst(V); Res = new FreeInst(V);
return false; return false;
case Instruction::Load: case Instruction::Load:
case Instruction::GetElementPtr: { case Instruction::GetElementPtr: {
vector<Value*> Idx; vector<Value*> Idx;
if (!isa<PointerType>(Raw.Ty)) return failure(true); if (!isa<PointerType>(Raw.Ty)) return true;
const CompositeType *TopTy = dyn_cast<CompositeType>(Raw.Ty); const CompositeType *TopTy = dyn_cast<CompositeType>(Raw.Ty);
switch (Raw.NumOperands) { switch (Raw.NumOperands) {
case 0: cerr << "Invalid load encountered!\n"; return failure(true); case 0: cerr << "Invalid load encountered!\n"; return true;
case 1: break; case 1: break;
case 2: case 2:
if (!TopTy) return failure(true); if (!TopTy) return true;
Idx.push_back(V = getValue(TopTy->getIndexType(), Raw.Arg2)); Idx.push_back(V = getValue(TopTy->getIndexType(), Raw.Arg2));
if (!V) return failure(true); if (!V) return true;
break; break;
case 3: { case 3: {
if (!TopTy) return failure(true); if (!TopTy) return true;
Idx.push_back(V = getValue(TopTy->getIndexType(), Raw.Arg2)); Idx.push_back(V = getValue(TopTy->getIndexType(), Raw.Arg2));
if (!V) return failure(true); if (!V) return true;
const Type *ETy = MemAccessInst::getIndexedType(TopTy, Idx, true); const Type *ETy = MemAccessInst::getIndexedType(TopTy, Idx, true);
const CompositeType *ElTy = dyn_cast_or_null<CompositeType>(ETy); const CompositeType *ElTy = dyn_cast_or_null<CompositeType>(ETy);
if (!ElTy) return failure(true); if (!ElTy) return true;
Idx.push_back(V = getValue(ElTy->getIndexType(), Raw.Arg3)); Idx.push_back(V = getValue(ElTy->getIndexType(), Raw.Arg3));
if (!V) return failure(true); if (!V) return true;
break; break;
} }
default: default:
if (!TopTy) return failure(true); if (!TopTy) return true;
Idx.push_back(V = getValue(TopTy->getIndexType(), Raw.Arg2)); Idx.push_back(V = getValue(TopTy->getIndexType(), Raw.Arg2));
if (!V) return failure(true); if (!V) return true;
vector<unsigned> &args = *Raw.VarArgs; vector<unsigned> &args = *Raw.VarArgs;
for (unsigned i = 0, E = args.size(); i != E; ++i) { for (unsigned i = 0, E = args.size(); i != E; ++i) {
const Type *ETy = MemAccessInst::getIndexedType(Raw.Ty, Idx, true); const Type *ETy = MemAccessInst::getIndexedType(Raw.Ty, Idx, true);
const CompositeType *ElTy = dyn_cast_or_null<CompositeType>(ETy); const CompositeType *ElTy = dyn_cast_or_null<CompositeType>(ETy);
if (!ElTy) return failure(true); if (!ElTy) return true;
Idx.push_back(V = getValue(ElTy->getIndexType(), args[i])); Idx.push_back(V = getValue(ElTy->getIndexType(), args[i]));
if (!V) return failure(true); if (!V) return true;
} }
delete Raw.VarArgs; delete Raw.VarArgs;
break; break;
@ -400,17 +399,17 @@ bool BytecodeParser::ParseInstruction(const uchar *&Buf, const uchar *EndBuf,
} }
case Instruction::Store: { case Instruction::Store: {
vector<Value*> Idx; vector<Value*> Idx;
if (!isa<PointerType>(Raw.Ty)) return failure(true); if (!isa<PointerType>(Raw.Ty)) return true;
const CompositeType *TopTy = dyn_cast<CompositeType>(Raw.Ty); const CompositeType *TopTy = dyn_cast<CompositeType>(Raw.Ty);
switch (Raw.NumOperands) { switch (Raw.NumOperands) {
case 0: case 0:
case 1: cerr << "Invalid store encountered!\n"; return failure(true); case 1: cerr << "Invalid store encountered!\n"; return true;
case 2: break; case 2: break;
case 3: case 3:
if (!TopTy) return failure(true); if (!TopTy) return true;
Idx.push_back(V = getValue(TopTy->getIndexType(), Raw.Arg3)); Idx.push_back(V = getValue(TopTy->getIndexType(), Raw.Arg3));
if (!V) return failure(true); if (!V) return true;
break; break;
default: default:
vector<unsigned> &args = *Raw.VarArgs; vector<unsigned> &args = *Raw.VarArgs;
@ -418,20 +417,20 @@ bool BytecodeParser::ParseInstruction(const uchar *&Buf, const uchar *EndBuf,
unsigned i, E; unsigned i, E;
for (i = 0, E = args.size(); ElTy && i != E; ++i) { for (i = 0, E = args.size(); ElTy && i != E; ++i) {
Idx.push_back(V = getValue(ElTy->getIndexType(), args[i])); Idx.push_back(V = getValue(ElTy->getIndexType(), args[i]));
if (!V) return failure(true); if (!V) return true;
const Type *ETy = MemAccessInst::getIndexedType(Raw.Ty, Idx, true); const Type *ETy = MemAccessInst::getIndexedType(Raw.Ty, Idx, true);
ElTy = dyn_cast_or_null<CompositeType>(ETy); ElTy = dyn_cast_or_null<CompositeType>(ETy);
} }
if (i != E) if (i != E)
return failure(true); // didn't use up all of the indices! return true; // didn't use up all of the indices!
delete Raw.VarArgs; delete Raw.VarArgs;
break; break;
} }
const Type *ElType = StoreInst::getIndexedType(Raw.Ty, Idx); const Type *ElType = StoreInst::getIndexedType(Raw.Ty, Idx);
if (ElType == 0) return failure(true); if (ElType == 0) return true;
Res = new StoreInst(getValue(ElType, Raw.Arg1), getValue(Raw.Ty, Raw.Arg2), Res = new StoreInst(getValue(ElType, Raw.Arg1), getValue(Raw.Ty, Raw.Arg2),
Idx); Idx);
return false; return false;
@ -440,5 +439,5 @@ bool BytecodeParser::ParseInstruction(const uchar *&Buf, const uchar *EndBuf,
cerr << "Unrecognized instruction! " << Raw.Opcode cerr << "Unrecognized instruction! " << Raw.Opcode
<< " ADDR = 0x" << (void*)Buf << "\n"; << " ADDR = 0x" << (void*)Buf << "\n";
return failure(true); return true;
} }

View File

@ -5,7 +5,7 @@
// Note that this library should be as fast as possible, reentrant, and // Note that this library should be as fast as possible, reentrant, and
// threadsafe!! // threadsafe!!
// //
// TODO: Make error message outputs be configurable depending on an option? // TODO: Return error messages to caller instead of printing them out directly.
// TODO: Allow passing in an option to ignore the symbol table // TODO: Allow passing in an option to ignore the symbol table
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@ -13,7 +13,6 @@
#include "ReaderInternals.h" #include "ReaderInternals.h"
#include "llvm/Bytecode/Reader.h" #include "llvm/Bytecode/Reader.h"
#include "llvm/Bytecode/Format.h" #include "llvm/Bytecode/Format.h"
#include "llvm/GlobalVariable.h"
#include "llvm/Module.h" #include "llvm/Module.h"
#include "llvm/Constants.h" #include "llvm/Constants.h"
#include "llvm/iPHINode.h" #include "llvm/iPHINode.h"
@ -24,7 +23,6 @@
#include <fcntl.h> #include <fcntl.h>
#include <unistd.h> #include <unistd.h>
#include <algorithm> #include <algorithm>
#include <iostream>
using std::cerr; using std::cerr;
using std::pair; using std::pair;
using std::make_pair; using std::make_pair;
@ -56,14 +54,14 @@ const Type *BytecodeParser::getType(unsigned ID) {
//cerr << "Looking up Type ID: " << ID << "\n"; //cerr << "Looking up Type ID: " << ID << "\n";
const Value *D = getValue(Type::TypeTy, ID, false); const Value *D = getValue(Type::TypeTy, ID, false);
if (D == 0) return failure<const Type*>(0); if (D == 0) return 0;
return cast<Type>(D); return cast<Type>(D);
} }
int BytecodeParser::insertValue(Value *Val, std::vector<ValueList> &ValueTab) { int BytecodeParser::insertValue(Value *Val, std::vector<ValueList> &ValueTab) {
unsigned type; unsigned type;
if (getTypeSlot(Val->getType(), type)) return failure<int>(-1); if (getTypeSlot(Val->getType(), type)) return -1;
assert(type != Type::TypeTyID && "Types should never be insertValue'd!"); assert(type != Type::TypeTyID && "Types should never be insertValue'd!");
if (ValueTab.size() <= type) if (ValueTab.size() <= type)
@ -80,7 +78,7 @@ Value *BytecodeParser::getValue(const Type *Ty, unsigned oNum, bool Create) {
unsigned Num = oNum; unsigned Num = oNum;
unsigned type; // The type plane it lives in... unsigned type; // The type plane it lives in...
if (getTypeSlot(Ty, type)) return failure<Value*>(0); // TODO: true if (getTypeSlot(Ty, type)) return 0;
if (type == Type::TypeTyID) { // The 'type' plane has implicit values if (type == Type::TypeTyID) { // The 'type' plane has implicit values
assert(Create == false); assert(Create == false);
@ -111,22 +109,26 @@ Value *BytecodeParser::getValue(const Type *Ty, unsigned oNum, bool Create) {
if (Values.size() > type && Values[type].size() > Num) if (Values.size() > type && Values[type].size() > Num)
return Values[type][Num]; return Values[type][Num];
if (!Create) return failure<Value*>(0); // Do not create a placeholder? if (!Create) return 0; // Do not create a placeholder?
Value *d = 0; Value *d = 0;
switch (Ty->getPrimitiveID()) { switch (Ty->getPrimitiveID()) {
case Type::LabelTyID: d = new BBPHolder(Ty, oNum); break;
case Type::FunctionTyID: case Type::FunctionTyID:
cerr << "Creating method pholder! : " << type << ":" << oNum << " " cerr << "Creating method pholder! : " << type << ":" << oNum << " "
<< Ty->getName() << "\n"; << Ty->getName() << "\n";
d = new MethPHolder(Ty, oNum); d = new FunctionPHolder(Ty, oNum);
if (insertValue(d, LateResolveModuleValues) ==-1) return failure<Value*>(0); if (insertValue(d, LateResolveModuleValues) == -1) return 0;
return d; return d;
default: d = new DefPHolder(Ty, oNum); break; case Type::LabelTyID:
d = new BBPHolder(Ty, oNum);
break;
default:
d = new ValPHolder(Ty, oNum);
break;
} }
assert(d != 0 && "How did we not make something?"); assert(d != 0 && "How did we not make something?");
if (insertValue(d, LateResolveValues) == -1) return failure<Value*>(0); if (insertValue(d, LateResolveValues) == -1) return 0;
return d; return d;
} }
@ -168,11 +170,11 @@ bool BytecodeParser::ParseBasicBlock(const uchar *&Buf, const uchar *EndBuf,
Instruction *Inst; Instruction *Inst;
if (ParseInstruction(Buf, EndBuf, Inst)) { if (ParseInstruction(Buf, EndBuf, Inst)) {
delete BB; delete BB;
return failure(true); return true;
} }
if (Inst == 0) { delete BB; return failure(true); } if (Inst == 0) { delete BB; return true; }
if (insertValue(Inst, Values) == -1) { delete BB; return failure(true); } if (insertValue(Inst, Values) == -1) { delete BB; return true; }
BB->getInstList().push_back(Inst); BB->getInstList().push_back(Inst);
@ -188,9 +190,9 @@ bool BytecodeParser::ParseSymbolTable(const uchar *&Buf, const uchar *EndBuf,
// Symtab block header: [num entries][type id number] // Symtab block header: [num entries][type id number]
unsigned NumEntries, Typ; unsigned NumEntries, Typ;
if (read_vbr(Buf, EndBuf, NumEntries) || if (read_vbr(Buf, EndBuf, NumEntries) ||
read_vbr(Buf, EndBuf, Typ)) return failure(true); read_vbr(Buf, EndBuf, Typ)) return true;
const Type *Ty = getType(Typ); const Type *Ty = getType(Typ);
if (Ty == 0) return failure(true); if (Ty == 0) return true;
BCR_TRACE(3, "Plane Type: '" << Ty << "' with " << NumEntries << BCR_TRACE(3, "Plane Type: '" << Ty << "' with " << NumEntries <<
" entries\n"); " entries\n");
@ -198,15 +200,15 @@ bool BytecodeParser::ParseSymbolTable(const uchar *&Buf, const uchar *EndBuf,
for (unsigned i = 0; i < NumEntries; ++i) { for (unsigned i = 0; i < NumEntries; ++i) {
// Symtab entry: [def slot #][name] // Symtab entry: [def slot #][name]
unsigned slot; unsigned slot;
if (read_vbr(Buf, EndBuf, slot)) return failure(true); if (read_vbr(Buf, EndBuf, slot)) return true;
std::string Name; std::string Name;
if (read(Buf, EndBuf, Name, false)) // Not aligned... if (read(Buf, EndBuf, Name, false)) // Not aligned...
return failure(true); return true;
Value *D = getValue(Ty, slot, false); // Find mapping... Value *D = getValue(Ty, slot, false); // Find mapping...
if (D == 0) { if (D == 0) {
BCR_TRACE(3, "FAILED LOOKUP: Slot #" << slot << "\n"); BCR_TRACE(3, "FAILED LOOKUP: Slot #" << slot << "\n");
return failure(true); return true;
} }
BCR_TRACE(4, "Map: '" << Name << "' to #" << slot << ":" << D; BCR_TRACE(4, "Map: '" << Name << "' to #" << slot << ":" << D;
if (!isa<Instruction>(D)) cerr << "\n"); if (!isa<Instruction>(D)) cerr << "\n");
@ -215,141 +217,53 @@ bool BytecodeParser::ParseSymbolTable(const uchar *&Buf, const uchar *EndBuf,
} }
} }
if (Buf > EndBuf) return failure(true); if (Buf > EndBuf) return true;
return false; return false;
} }
Value* void BytecodeParser::ResolveReferencesToValue(Value *NewV, unsigned Slot) {
ConstantFwdRefs::find(const Type* Ty, unsigned Slot) { GlobalRefsType::iterator I = GlobalRefs.find(make_pair(NewV->getType(),Slot));
GlobalRefsType::iterator I = GlobalRefs.find(make_pair(Ty, Slot)); if (I == GlobalRefs.end()) return; // Never forward referenced?
if (I != GlobalRefs.end()) {
return I->second;
} else {
return failure<Value*>(0);
}
}
void BCR_TRACE(3, "Mutating forward refs!\n");
ConstantFwdRefs::insert(const Type* Ty, unsigned Slot, Value* V) { Value *VPH = I->second; // Get the placeholder...
// Keep track of the fact that we have a forward ref to recycle it
const pair<GlobalRefsType::iterator, bool>& result =
GlobalRefs.insert(make_pair(make_pair(Ty, Slot), V));
assert(result.second == true && "Entry already exists for this slot?");
}
void // Loop over all of the uses of the Value. What they are depends
ConstantFwdRefs::erase(const Type* Ty, unsigned Slot) { // on what NewV is. Replacing a use of the old reference takes the
GlobalRefsType::iterator I = GlobalRefs.find(make_pair(Ty, Slot)); // use off the use list, so loop with !use_empty(), not the use_iterator.
if (I != GlobalRefs.end()) while (!VPH->use_empty()) {
GlobalRefs.erase(I); Constant *C = cast<Constant>(VPH->use_back());
} unsigned numReplaced = C->mutateReferences(VPH, NewV);
assert(numReplaced > 0 && "Supposed user wasn't really a user?");
// GetFwdRefToConstant - Get a forward reference to a constant value.
// Create a unique one if it does not exist already.
//
Constant*
ConstantFwdRefs::GetFwdRefToConstant(const Type* Ty, unsigned Slot) {
Constant* C = cast_or_null<Constant>(find(Ty, Slot));
if (C) {
BCR_TRACE(5, "Previous forward ref found!\n");
} else {
// Create a placeholder for the constant reference and
// keep track of the fact that we have a forward ref to recycle it
BCR_TRACE(5, "Creating new forward ref to a constant!\n");
C = new ConstPHolder(Ty, Slot);
insert(Ty, Slot, C);
}
return C;
}
// GetFwdRefToGlobal - Get a forward reference to a global value.
// Create a unique one if it does not exist already.
//
GlobalValue*
ConstantFwdRefs::GetFwdRefToGlobal(const PointerType* PT, unsigned Slot) {
GlobalValue* GV = cast_or_null<GlobalValue>(find(PT, Slot));
if (GV) {
BCR_TRACE(5, "Previous forward ref found!\n");
} else {
BCR_TRACE(5, "Creating new forward ref to a global variable!\n");
// Create a placeholder for the global variable reference...
GlobalVariable *GVar =
new GlobalVariable(PT->getElementType(), false, true);
// Keep track of the fact that we have a forward ref to recycle it
insert(PT, Slot, GVar);
// Must temporarily push this value into the module table...
TheModule->getGlobalList().push_back(GVar);
GV = GVar;
}
return GV;
}
void
ConstantFwdRefs::ResolveRefsToValue(Value* NewV, unsigned Slot) {
if (Value* vph = find(NewV->getType(), Slot)) {
BCR_TRACE(3, "Mutating forward refs!\n");
// Loop over all of the uses of the Value. What they are depends
// on what NewV is. Replacing a use of the old reference takes the
// use off the use list, so loop with !use_empty(), not the use_iterator.
while (!vph->use_empty()) {
Constant *C = cast<Constant>(vph->use_back());
unsigned numReplaced = C->mutateReferences(vph, NewV);
assert(numReplaced > 0 && "Supposed user wasn't really a user?");
if (GlobalValue* GVal = dyn_cast<GlobalValue>(NewV)) { if (GlobalValue* GVal = dyn_cast<GlobalValue>(NewV)) {
// Remove the placeholder GlobalValue from the module... // Remove the placeholder GlobalValue from the module...
GVal->getParent()->getGlobalList().remove(cast<GlobalVariable>(vph)); GVal->getParent()->getGlobalList().remove(cast<GlobalVariable>(VPH));
}
} }
delete vph; // Delete the old placeholder
erase(NewV->getType(), Slot); // Remove the map entry for it
} }
}
// resolveRefsToGlobal - Patch up forward references to global values in the delete VPH; // Delete the old placeholder
// form of ConstantPointerRef. GlobalRefs.erase(I); // Remove the map entry for it
//
void BytecodeParser::resolveRefsToGlobal(GlobalValue *GV, unsigned Slot) {
fwdRefs.ResolveRefsToValue(GV, Slot);
} }
// resolveRefsToConstant - Patch up forward references to constants
//
void BytecodeParser::resolveRefsToConstant(Constant *C, unsigned Slot) {
fwdRefs.ResolveRefsToValue(C, Slot);
}
bool BytecodeParser::ParseMethod(const uchar *&Buf, const uchar *EndBuf, bool BytecodeParser::ParseMethod(const uchar *&Buf, const uchar *EndBuf,
Module *C) { Module *C) {
// Clear out the local values table... // Clear out the local values table...
Values.clear(); Values.clear();
if (MethodSignatureList.empty()) { if (FunctionSignatureList.empty()) {
Error = "Function found, but FunctionSignatureList empty!"; Error = "Function found, but FunctionSignatureList empty!";
return failure(true); // Unexpected method! return true; // Unexpected method!
} }
const PointerType *PMTy = MethodSignatureList.front().first; // PtrMeth const PointerType *PMTy = FunctionSignatureList.back().first; // PtrMeth
const FunctionType *MTy = dyn_cast<FunctionType>(PMTy->getElementType()); const FunctionType *MTy = dyn_cast<FunctionType>(PMTy->getElementType());
if (MTy == 0) return failure(true); // Not ptr to method! if (MTy == 0) return true; // Not ptr to method!
unsigned isInternal; unsigned isInternal;
if (read_vbr(Buf, EndBuf, isInternal)) return failure(true); if (read_vbr(Buf, EndBuf, isInternal)) return true;
unsigned MethSlot = MethodSignatureList.front().second; unsigned MethSlot = FunctionSignatureList.back().second;
MethodSignatureList.pop_front(); FunctionSignatureList.pop_back();
Function *M = new Function(MTy, isInternal != 0); Function *M = new Function(MTy, isInternal != 0);
BCR_TRACE(2, "METHOD TYPE: " << MTy << "\n"); BCR_TRACE(2, "METHOD TYPE: " << MTy << "\n");
@ -360,7 +274,7 @@ bool BytecodeParser::ParseMethod(const uchar *&Buf, const uchar *EndBuf,
Argument *FA = new Argument(*It); Argument *FA = new Argument(*It);
if (insertValue(FA, Values) == -1) { if (insertValue(FA, Values) == -1) {
Error = "Error reading method arguments!\n"; Error = "Error reading method arguments!\n";
delete M; return failure(true); delete M; return true;
} }
M->getArgumentList().push_back(FA); M->getArgumentList().push_back(FA);
} }
@ -370,14 +284,14 @@ bool BytecodeParser::ParseMethod(const uchar *&Buf, const uchar *EndBuf,
const uchar *OldBuf = Buf; const uchar *OldBuf = Buf;
if (readBlock(Buf, EndBuf, Type, Size)) { if (readBlock(Buf, EndBuf, Type, Size)) {
Error = "Error reading Function level block!"; Error = "Error reading Function level block!";
delete M; return failure(true); delete M; return true;
} }
switch (Type) { switch (Type) {
case BytecodeFormat::ConstantPool: case BytecodeFormat::ConstantPool:
BCR_TRACE(2, "BLOCK BytecodeFormat::ConstantPool: {\n"); BCR_TRACE(2, "BLOCK BytecodeFormat::ConstantPool: {\n");
if (ParseConstantPool(Buf, Buf+Size, Values, MethodTypeValues)) { if (ParseConstantPool(Buf, Buf+Size, Values, MethodTypeValues)) {
delete M; return failure(true); delete M; return true;
} }
break; break;
@ -386,7 +300,7 @@ bool BytecodeParser::ParseMethod(const uchar *&Buf, const uchar *EndBuf,
BasicBlock *BB; BasicBlock *BB;
if (ParseBasicBlock(Buf, Buf+Size, BB) || if (ParseBasicBlock(Buf, Buf+Size, BB) ||
insertValue(BB, Values) == -1) { insertValue(BB, Values) == -1) {
delete M; return failure(true); // Parse error... :( delete M; return true; // Parse error... :(
} }
M->getBasicBlockList().push_back(BB); M->getBasicBlockList().push_back(BB);
@ -396,14 +310,14 @@ bool BytecodeParser::ParseMethod(const uchar *&Buf, const uchar *EndBuf,
case BytecodeFormat::SymbolTable: case BytecodeFormat::SymbolTable:
BCR_TRACE(2, "BLOCK BytecodeFormat::SymbolTable: {\n"); BCR_TRACE(2, "BLOCK BytecodeFormat::SymbolTable: {\n");
if (ParseSymbolTable(Buf, Buf+Size, M->getSymbolTableSure())) { if (ParseSymbolTable(Buf, Buf+Size, M->getSymbolTableSure())) {
delete M; return failure(true); delete M; return true;
} }
break; break;
default: default:
BCR_TRACE(2, "BLOCK <unknown>:ignored! {\n"); BCR_TRACE(2, "BLOCK <unknown>:ignored! {\n");
Buf += Size; Buf += Size;
if (OldBuf > Buf) return failure(true); // Wrap around! if (OldBuf > Buf) return true; // Wrap around!
break; break;
} }
BCR_TRACE(2, "} end block\n"); BCR_TRACE(2, "} end block\n");
@ -411,19 +325,19 @@ bool BytecodeParser::ParseMethod(const uchar *&Buf, const uchar *EndBuf,
if (align32(Buf, EndBuf)) { if (align32(Buf, EndBuf)) {
Error = "Error aligning Function level block!"; Error = "Error aligning Function level block!";
delete M; // Malformed bc file, read past end of block. delete M; // Malformed bc file, read past end of block.
return failure(true); return true;
} }
} }
if (postResolveValues(LateResolveValues) || if (postResolveValues(LateResolveValues) ||
postResolveValues(LateResolveModuleValues)) { postResolveValues(LateResolveModuleValues)) {
Error = "Error resolving method values!"; Error = "Error resolving method values!";
delete M; return failure(true); // Unresolvable references! delete M; return true; // Unresolvable references!
} }
Value *MethPHolder = getValue(PMTy, MethSlot, false); Value *FunctionPHolder = getValue(PMTy, MethSlot, false);
assert(MethPHolder && "Something is broken no placeholder found!"); assert(FunctionPHolder && "Something is broken no placeholder found!");
assert(isa<Function>(MethPHolder) && "Not a function?"); assert(isa<Function>(FunctionPHolder) && "Not a function?");
unsigned type; // Type slot unsigned type; // Type slot
assert(!getTypeSlot(MTy, type) && "How can meth type not exist?"); assert(!getTypeSlot(MTy, type) && "How can meth type not exist?");
@ -438,37 +352,37 @@ bool BytecodeParser::ParseMethod(const uchar *&Buf, const uchar *EndBuf,
MethodTypeValues.clear(); MethodTypeValues.clear();
// If anyone is using the placeholder make them use the real method instead // If anyone is using the placeholder make them use the real method instead
MethPHolder->replaceAllUsesWith(M); FunctionPHolder->replaceAllUsesWith(M);
// We don't need the placeholder anymore! // We don't need the placeholder anymore!
delete MethPHolder; delete FunctionPHolder;
// If the method is empty, we don't need the method argument entries... // If the method is empty, we don't need the method argument entries...
if (M->isExternal()) if (M->isExternal())
M->getArgumentList().clear(); M->getArgumentList().clear();
resolveRefsToGlobal(M, MethSlot); ResolveReferencesToValue(M, MethSlot);
return false; return false;
} }
bool BytecodeParser::ParseModuleGlobalInfo(const uchar *&Buf, const uchar *End, bool BytecodeParser::ParseModuleGlobalInfo(const uchar *&Buf, const uchar *End,
Module *Mod) { Module *Mod) {
if (!MethodSignatureList.empty()) { if (!FunctionSignatureList.empty()) {
Error = "Two ModuleGlobalInfo packets found!"; Error = "Two ModuleGlobalInfo packets found!";
return failure(true); // Two ModuleGlobal blocks? return true; // Two ModuleGlobal blocks?
} }
// Read global variables... // Read global variables...
unsigned VarType; unsigned VarType;
if (read_vbr(Buf, End, VarType)) return failure(true); if (read_vbr(Buf, End, VarType)) return true;
while (VarType != Type::VoidTyID) { // List is terminated by Void while (VarType != Type::VoidTyID) { // List is terminated by Void
// VarType Fields: bit0 = isConstant, bit1 = hasInitializer, // VarType Fields: bit0 = isConstant, bit1 = hasInitializer,
// bit2 = isInternal, bit3+ = slot# // bit2 = isInternal, bit3+ = slot#
const Type *Ty = getType(VarType >> 3); const Type *Ty = getType(VarType >> 3);
if (!Ty || !isa<PointerType>(Ty)) { if (!Ty || !isa<PointerType>(Ty)) {
Error = "Global not pointer type! Ty = " + Ty->getDescription(); Error = "Global not pointer type! Ty = " + Ty->getDescription();
return failure(true); return true;
} }
const PointerType *PTy = cast<const PointerType>(Ty); const PointerType *PTy = cast<const PointerType>(Ty);
@ -480,10 +394,10 @@ bool BytecodeParser::ParseModuleGlobalInfo(const uchar *&Buf, const uchar *End,
// which should have been read before now. // which should have been read before now.
// //
unsigned InitSlot; unsigned InitSlot;
if (read_vbr(Buf, End, InitSlot)) return failure(true); if (read_vbr(Buf, End, InitSlot)) return true;
Value *V = getValue(ElTy, InitSlot, false); Value *V = getValue(ElTy, InitSlot, false);
if (V == 0) return failure(true); if (V == 0) return true;
Initializer = cast<Constant>(V); Initializer = cast<Constant>(V);
} }
@ -491,28 +405,28 @@ bool BytecodeParser::ParseModuleGlobalInfo(const uchar *&Buf, const uchar *End,
GlobalVariable *GV = new GlobalVariable(ElTy, VarType & 1, VarType & 4, GlobalVariable *GV = new GlobalVariable(ElTy, VarType & 1, VarType & 4,
Initializer); Initializer);
int DestSlot = insertValue(GV, ModuleValues); int DestSlot = insertValue(GV, ModuleValues);
if (DestSlot == -1) return failure(true); if (DestSlot == -1) return true;
Mod->getGlobalList().push_back(GV); Mod->getGlobalList().push_back(GV);
resolveRefsToGlobal(GV, unsigned(DestSlot)); ResolveReferencesToValue(GV, (unsigned)DestSlot);
BCR_TRACE(2, "Global Variable of type: " << PTy->getDescription() BCR_TRACE(2, "Global Variable of type: " << PTy->getDescription()
<< " into slot #" << DestSlot << "\n"); << " into slot #" << DestSlot << "\n");
if (read_vbr(Buf, End, VarType)) return failure(true); if (read_vbr(Buf, End, VarType)) return true;
} }
// Read the method signatures for all of the methods that are coming, and // Read the method signatures for all of the methods that are coming, and
// create fillers in the Value tables. // create fillers in the Value tables.
unsigned MethSignature; unsigned FnSignature;
if (read_vbr(Buf, End, MethSignature)) return failure(true); if (read_vbr(Buf, End, FnSignature)) return true;
while (MethSignature != Type::VoidTyID) { // List is terminated by Void while (FnSignature != Type::VoidTyID) { // List is terminated by Void
const Type *Ty = getType(MethSignature); const Type *Ty = getType(FnSignature);
if (!Ty || !isa<PointerType>(Ty) || if (!Ty || !isa<PointerType>(Ty) ||
!isa<FunctionType>(cast<PointerType>(Ty)->getElementType())) { !isa<FunctionType>(cast<PointerType>(Ty)->getElementType())) {
Error = "Function not ptr to func type! Ty = " + Ty->getDescription(); Error = "Function not ptr to func type! Ty = " + Ty->getDescription();
return failure(true); return true;
} }
// We create methods by passing the underlying FunctionType to create... // We create methods by passing the underlying FunctionType to create...
@ -524,25 +438,29 @@ bool BytecodeParser::ParseModuleGlobalInfo(const uchar *&Buf, const uchar *End,
// placeholder is replaced. // placeholder is replaced.
// Insert the placeholder... // Insert the placeholder...
Value *Val = new MethPHolder(Ty, 0); Value *Val = new FunctionPHolder(Ty, 0);
if (insertValue(Val, ModuleValues) == -1) return failure(true); if (insertValue(Val, ModuleValues) == -1) return true;
// Figure out which entry of its typeslot it went into... // Figure out which entry of its typeslot it went into...
unsigned TypeSlot; unsigned TypeSlot;
if (getTypeSlot(Val->getType(), TypeSlot)) return failure(true); if (getTypeSlot(Val->getType(), TypeSlot)) return true;
unsigned SlotNo = ModuleValues[TypeSlot].size()-1; unsigned SlotNo = ModuleValues[TypeSlot].size()-1;
// Keep track of this information in a linked list that is emptied as // Keep track of this information in a linked list that is emptied as
// methods are loaded... // methods are loaded...
// //
MethodSignatureList.push_back( FunctionSignatureList.push_back(
make_pair(cast<const PointerType>(Val->getType()), SlotNo)); make_pair(cast<const PointerType>(Val->getType()), SlotNo));
if (read_vbr(Buf, End, MethSignature)) return failure(true); if (read_vbr(Buf, End, FnSignature)) return true;
BCR_TRACE(2, "Function of type: " << Ty << "\n"); BCR_TRACE(2, "Function of type: " << Ty << "\n");
} }
if (align32(Buf, End)) return failure(true); if (align32(Buf, End)) return true;
// Now that the function signature list is set up, reverse it so that we can
// remove elements efficiently from the back of the vector.
std::reverse(FunctionSignatureList.begin(), FunctionSignatureList.end());
// This is for future proofing... in the future extra fields may be added that // This is for future proofing... in the future extra fields may be added that
// we don't understand, so we transparently ignore them. // we don't understand, so we transparently ignore them.
@ -552,73 +470,72 @@ bool BytecodeParser::ParseModuleGlobalInfo(const uchar *&Buf, const uchar *End,
} }
bool BytecodeParser::ParseModule(const uchar *Buf, const uchar *EndBuf, bool BytecodeParser::ParseModule(const uchar *Buf, const uchar *EndBuf,
Module *&C) { Module *&Mod) {
unsigned Type, Size; unsigned Type, Size;
if (readBlock(Buf, EndBuf, Type, Size)) return failure(true); if (readBlock(Buf, EndBuf, Type, Size)) return true;
if (Type != BytecodeFormat::Module || Buf+Size != EndBuf) { if (Type != BytecodeFormat::Module || Buf+Size != EndBuf) {
Error = "Expected Module packet!"; Error = "Expected Module packet!";
return failure(true); // Hrm, not a class? return true; // Hrm, not a class?
} }
BCR_TRACE(0, "BLOCK BytecodeFormat::Module: {\n"); BCR_TRACE(0, "BLOCK BytecodeFormat::Module: {\n");
MethodSignatureList.clear(); // Just in case... FunctionSignatureList.clear(); // Just in case...
// Read into instance variables... // Read into instance variables...
if (read_vbr(Buf, EndBuf, FirstDerivedTyID)) return failure(true); if (read_vbr(Buf, EndBuf, FirstDerivedTyID)) return true;
if (align32(Buf, EndBuf)) return failure(true); if (align32(Buf, EndBuf)) return true;
BCR_TRACE(1, "FirstDerivedTyID = " << FirstDerivedTyID << "\n"); BCR_TRACE(1, "FirstDerivedTyID = " << FirstDerivedTyID << "\n");
TheModule = C = new Module(); TheModule = Mod = new Module();
fwdRefs.VisitingModule(TheModule);
while (Buf < EndBuf) { while (Buf < EndBuf) {
const uchar *OldBuf = Buf; const uchar *OldBuf = Buf;
if (readBlock(Buf, EndBuf, Type, Size)) { delete C; return failure(true); } if (readBlock(Buf, EndBuf, Type, Size)) { delete Mod; return true;}
switch (Type) { switch (Type) {
case BytecodeFormat::ConstantPool: case BytecodeFormat::ConstantPool:
BCR_TRACE(1, "BLOCK BytecodeFormat::ConstantPool: {\n"); BCR_TRACE(1, "BLOCK BytecodeFormat::ConstantPool: {\n");
if (ParseConstantPool(Buf, Buf+Size, ModuleValues, ModuleTypeValues)) { if (ParseConstantPool(Buf, Buf+Size, ModuleValues, ModuleTypeValues)) {
delete C; return failure(true); delete Mod; return true;
} }
break; break;
case BytecodeFormat::ModuleGlobalInfo: case BytecodeFormat::ModuleGlobalInfo:
BCR_TRACE(1, "BLOCK BytecodeFormat::ModuleGlobalInfo: {\n"); BCR_TRACE(1, "BLOCK BytecodeFormat::ModuleGlobalInfo: {\n");
if (ParseModuleGlobalInfo(Buf, Buf+Size, C)) { if (ParseModuleGlobalInfo(Buf, Buf+Size, Mod)) {
delete C; return failure(true); delete Mod; return true;
} }
break; break;
case BytecodeFormat::Function: { case BytecodeFormat::Function: {
BCR_TRACE(1, "BLOCK BytecodeFormat::Function: {\n"); BCR_TRACE(1, "BLOCK BytecodeFormat::Function: {\n");
if (ParseMethod(Buf, Buf+Size, C)) { if (ParseMethod(Buf, Buf+Size, Mod)) {
delete C; return failure(true); // Error parsing method delete Mod; return true; // Error parsing function
} }
break; break;
} }
case BytecodeFormat::SymbolTable: case BytecodeFormat::SymbolTable:
BCR_TRACE(1, "BLOCK BytecodeFormat::SymbolTable: {\n"); BCR_TRACE(1, "BLOCK BytecodeFormat::SymbolTable: {\n");
if (ParseSymbolTable(Buf, Buf+Size, C->getSymbolTableSure())) { if (ParseSymbolTable(Buf, Buf+Size, Mod->getSymbolTableSure())) {
delete C; return failure(true); delete Mod; return true;
} }
break; break;
default: default:
Error = "Expected Module Block!"; Error = "Expected Module Block!";
Buf += Size; Buf += Size;
if (OldBuf > Buf) return failure(true); // Wrap around! if (OldBuf > Buf) return true; // Wrap around!
break; break;
} }
BCR_TRACE(1, "} end block\n"); BCR_TRACE(1, "} end block\n");
if (align32(Buf, EndBuf)) { delete C; return failure(true); } if (align32(Buf, EndBuf)) { delete Mod; return true; }
} }
if (!MethodSignatureList.empty()) { // Expected more methods! if (!FunctionSignatureList.empty()) { // Expected more methods!
Error = "Function expected, but bytecode stream at end!"; Error = "Function expected, but bytecode stream at end!";
return failure(true); return true;
} }
BCR_TRACE(0, "} end block\n\n"); BCR_TRACE(0, "} end block\n\n");
@ -632,7 +549,7 @@ Module *BytecodeParser::ParseBytecode(const uchar *Buf, const uchar *EndBuf) {
if (read(Buf, EndBuf, Sig) || if (read(Buf, EndBuf, Sig) ||
Sig != ('l' | ('l' << 8) | ('v' << 16) | 'm' << 24)) { Sig != ('l' | ('l' << 8) | ('v' << 16) | 'm' << 24)) {
Error = "Invalid bytecode signature!"; Error = "Invalid bytecode signature!";
return failure<Module*>(0); // Invalid signature! return 0; // Invalid signature!
} }
Module *Result; Module *Result;
@ -656,21 +573,21 @@ Module *ParseBytecodeFile(const std::string &Filename, std::string *ErrorStr) {
int FD = open(Filename.c_str(), O_RDONLY); int FD = open(Filename.c_str(), O_RDONLY);
if (FD == -1) { if (FD == -1) {
if (ErrorStr) *ErrorStr = "Error opening file!"; if (ErrorStr) *ErrorStr = "Error opening file!";
return failure<Module*>(0); return 0;
} }
if (fstat(FD, &StatBuf) == -1) { close(FD); return failure<Module*>(0); } if (fstat(FD, &StatBuf) == -1) { close(FD); return 0; }
int Length = StatBuf.st_size; int Length = StatBuf.st_size;
if (Length == 0) { if (Length == 0) {
if (ErrorStr) *ErrorStr = "Error stat'ing file!"; if (ErrorStr) *ErrorStr = "Error stat'ing file!";
close(FD); return failure<Module*>(0); close(FD); return 0;
} }
uchar *Buffer = (uchar*)mmap(0, Length, PROT_READ, uchar *Buffer = (uchar*)mmap(0, Length, PROT_READ,
MAP_PRIVATE, FD, 0); MAP_PRIVATE, FD, 0);
if (Buffer == (uchar*)-1) { if (Buffer == (uchar*)-1) {
if (ErrorStr) *ErrorStr = "Error mmapping file!"; if (ErrorStr) *ErrorStr = "Error mmapping file!";
close(FD); return failure<Module*>(0); close(FD); return 0;
} }
BytecodeParser Parser; BytecodeParser Parser;
@ -684,7 +601,7 @@ Module *ParseBytecodeFile(const std::string &Filename, std::string *ErrorStr) {
int BlockSize; int BlockSize;
uchar Buffer[4096], *FileData = 0; uchar Buffer[4096], *FileData = 0;
while ((BlockSize = read(0, Buffer, 4))) { while ((BlockSize = read(0, Buffer, 4))) {
if (BlockSize == -1) { free(FileData); return failure<Module*>(0); } if (BlockSize == -1) { free(FileData); return 0; }
FileData = (uchar*)realloc(FileData, FileSize+BlockSize); FileData = (uchar*)realloc(FileData, FileSize+BlockSize);
memcpy(FileData+FileSize, Buffer, BlockSize); memcpy(FileData+FileSize, Buffer, BlockSize);
@ -693,7 +610,7 @@ Module *ParseBytecodeFile(const std::string &Filename, std::string *ErrorStr) {
if (FileSize == 0) { if (FileSize == 0) {
if (ErrorStr) *ErrorStr = "Standard Input empty!"; if (ErrorStr) *ErrorStr = "Standard Input empty!";
free(FileData); return failure<Module*>(0); free(FileData); return 0;
} }
#define ALIGN_PTRS 1 #define ALIGN_PTRS 1

View File

@ -8,16 +8,11 @@
#define READER_INTERNALS_H #define READER_INTERNALS_H
#include "llvm/Bytecode/Primitives.h" #include "llvm/Bytecode/Primitives.h"
#include "llvm/Function.h"
#include "llvm/BasicBlock.h"
#include "llvm/Instruction.h"
#include "llvm/DerivedTypes.h" #include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
#include "llvm/Constant.h" #include "llvm/Constant.h"
#include "Support/NonCopyable.h"
#include <map>
#include <utility> #include <utility>
#include <list> #include <map>
#include <iostream>
// Enable to trace to figure out what the heck is going on when parsing fails // Enable to trace to figure out what the heck is going on when parsing fails
#define TRACE_LEVEL 0 #define TRACE_LEVEL 0
@ -41,38 +36,10 @@ struct RawInst { // The raw fields out of the bytecode stream...
}; };
}; };
class ConstantFwdRefs: public NonCopyable {
Module* TheModule;
// 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
// represent is held here.
//
typedef std::map<std::pair<const Type *, unsigned>,
Value*> GlobalRefsType;
GlobalRefsType GlobalRefs;
Value* find (const Type* Ty, unsigned Slot);
void insert (const Type* Ty, unsigned Slot, Value* V);
void erase (const Type* Ty, unsigned Slot);
public:
// sets the current module pointer: needed to insert placeholder globals
void VisitingModule (Module* M) { TheModule = M; }
// get a forward reference to a global or a constant
GlobalValue* GetFwdRefToGlobal (const PointerType* PT, unsigned Slot);
Constant* GetFwdRefToConstant (const Type* Ty, unsigned Slot);
// resolve all references to the placeholder (if any) for the given value
void ResolveRefsToValue (Value* val, unsigned Slot);
};
class BytecodeParser : public AbstractTypeUser { class BytecodeParser : public AbstractTypeUser {
std::string Error; // Error message string goes here... std::string Error; // Error message string goes here...
BytecodeParser(const BytecodeParser &); // DO NOT IMPLEMENT
void operator=(const BytecodeParser &); // DO NOT IMPLEMENT
public: public:
BytecodeParser() { BytecodeParser() {
// Define this in case we don't see a ModuleGlobalInfo block. // Define this in case we don't see a ModuleGlobalInfo block.
@ -95,8 +62,14 @@ private: // All of this data is transient across calls to ParseBytecode
ValueTable Values, LateResolveValues; ValueTable Values, LateResolveValues;
ValueTable ModuleValues, LateResolveModuleValues; ValueTable ModuleValues, LateResolveModuleValues;
// fwdRefs - This manages forward references to global values. // GlobalRefs - This maintains a mapping between <Type, Slot #>'s and forward
ConstantFwdRefs fwdRefs; // references to global values or constants. Such values may be referenced
// before they are defined, and if so, the temporary object that they
// represent is held here.
//
typedef std::map<std::pair<const Type *, unsigned>,
Value*> GlobalRefsType;
GlobalRefsType GlobalRefs;
// TypesLoaded - This vector mirrors the Values[TypeTyID] plane. It is used // TypesLoaded - This vector mirrors the Values[TypeTyID] plane. It is used
// to deal with forward references to types. // to deal with forward references to types.
@ -108,12 +81,12 @@ private: // All of this data is transient across calls to ParseBytecode
// Information read from the ModuleGlobalInfo section of the file... // Information read from the ModuleGlobalInfo section of the file...
unsigned FirstDerivedTyID; unsigned FirstDerivedTyID;
// When the ModuleGlobalInfo section is read, we load the type of each method // When the ModuleGlobalInfo section is read, we load the type of each
// and the 'ModuleValues' slot that it lands in. We then load a placeholder // function and the 'ModuleValues' slot that it lands in. We then load a
// into its slot to reserve it. When the method is loaded, this placeholder // placeholder into its slot to reserve it. When the function is loaded, this
// is replaced. // placeholder is replaced.
// //
std::list<std::pair<const PointerType *, unsigned> > MethodSignatureList; std::vector<std::pair<const PointerType *, unsigned> > FunctionSignatureList;
private: private:
bool ParseModule (const uchar * Buf, const uchar *End, Module *&); bool ParseModule (const uchar * Buf, const uchar *End, Module *&);
@ -140,11 +113,9 @@ private:
bool getTypeSlot(const Type *Ty, unsigned &Slot); bool getTypeSlot(const Type *Ty, unsigned &Slot);
// resolveRefsToGlobal -- resolve forward references to a global // resolve all references to the placeholder (if any) for the given value
// resolveRefsToConstant -- resolve forward references to a constant void ResolveReferencesToValue(Value *Val, unsigned Slot);
//
void resolveRefsToGlobal(GlobalValue* GV, unsigned Slot);
void resolveRefsToConstant(Constant* C, unsigned Slot);
// refineAbstractType - The callback method is invoked when one of the // refineAbstractType - The callback method is invoked when one of the
// elements of TypeValues becomes more concrete... // elements of TypeValues becomes more concrete...
@ -155,7 +126,8 @@ private:
template<class SuperType> template<class SuperType>
class PlaceholderDef : public SuperType { class PlaceholderDef : public SuperType {
unsigned ID; unsigned ID;
PlaceholderDef(); // do not implement PlaceholderDef(); // DO NOT IMPLEMENT
void operator=(const PlaceholderDef &); // DO NOT IMPLEMENT
public: public:
PlaceholderDef(const Type *Ty, unsigned id) : SuperType(Ty), ID(id) {} PlaceholderDef(const Type *Ty, unsigned id) : SuperType(Ty), ID(id) {}
unsigned getID() { return ID; } unsigned getID() { return ID; }
@ -174,8 +146,8 @@ struct BBPlaceHolderHelper : public BasicBlock {
} }
}; };
struct MethPlaceHolderHelper : public Function { struct FunctionPlaceHolderHelper : public Function {
MethPlaceHolderHelper(const Type *Ty) FunctionPlaceHolderHelper(const Type *Ty)
: Function(cast<const FunctionType>(Ty), true) { : Function(cast<const FunctionType>(Ty), true) {
} }
}; };
@ -186,21 +158,21 @@ struct ConstantPlaceHolderHelper : public Constant {
virtual bool isNullValue() const { return false; } virtual bool isNullValue() const { return false; }
}; };
typedef PlaceholderDef<InstPlaceHolderHelper> DefPHolder; typedef PlaceholderDef<InstPlaceHolderHelper> ValPHolder;
typedef PlaceholderDef<BBPlaceHolderHelper> BBPHolder; typedef PlaceholderDef<BBPlaceHolderHelper> BBPHolder;
typedef PlaceholderDef<MethPlaceHolderHelper> MethPHolder; typedef PlaceholderDef<FunctionPlaceHolderHelper> FunctionPHolder;
typedef PlaceholderDef<ConstantPlaceHolderHelper> ConstPHolder; typedef PlaceholderDef<ConstantPlaceHolderHelper> ConstPHolder;
static inline unsigned getValueIDNumberFromPlaceHolder(Value *Def) { static inline unsigned getValueIDNumberFromPlaceHolder(Value *Val) {
if (isa<Constant>(Def)) if (isa<Constant>(Val))
return ((ConstPHolder*)Def)->getID(); return ((ConstPHolder*)Val)->getID();
// else discriminate by type // else discriminate by type
switch (Def->getType()->getPrimitiveID()) { switch (Val->getType()->getPrimitiveID()) {
case Type::LabelTyID: return ((BBPHolder*)Def)->getID(); case Type::LabelTyID: return ((BBPHolder*)Val)->getID();
case Type::FunctionTyID: return ((MethPHolder*)Def)->getID(); case Type::FunctionTyID: return ((FunctionPHolder*)Val)->getID();
default: return ((DefPHolder*)Def)->getID(); default: return ((ValPHolder*)Val)->getID();
} }
} }
@ -216,13 +188,4 @@ static inline bool readBlock(const uchar *&Buf, const uchar *EndBuf,
#endif #endif
} }
// failure Template - This template function is used as a place to put
// breakpoints in to debug failures of the bytecode parser.
//
template <typename X>
static X failure(X Value) {
return Value;
}
#endif #endif