mirror of
https://github.com/RPCS3/llvm.git
synced 2025-02-22 19:50:55 +00:00
* Bug fixes:
- Fix problems where the constant table would not get updated when resolving constants causes other constants to change. Changes to the V2 bytecode format - Null values are implicitly encoded instead of explicitly, this makes things more compact! - More compactly represent ConstantPointerRefs - Bytecode files are represented as: Header|GlobalTypes|GlobalVars/Function Protos|Constants|Functions|SymTab instead of Header|GlobalTypes|Constants|GlobalVars/Function Protos|Functions|SymTab which makes a lot of things simpler. Changes to the reader: - Function loading code is much simpler. We now no longer make function PlaceHolderHelper objects to be replaced with real functions. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@5748 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
1b079f9685
commit
52e20b0977
@ -316,7 +316,11 @@ bool BytecodeParser::parseConstantValue(const uchar *&Buf, const uchar *EndBuf,
|
||||
case Type::PointerTyID: {
|
||||
const PointerType *PT = cast<const PointerType>(Ty);
|
||||
unsigned SubClass;
|
||||
if (read_vbr(Buf, EndBuf, SubClass)) return true;
|
||||
if (HasImplicitZeroInitializer)
|
||||
SubClass = 1;
|
||||
else
|
||||
if (read_vbr(Buf, EndBuf, SubClass)) return true;
|
||||
|
||||
switch (SubClass) {
|
||||
case 0: // ConstantPointerNull value...
|
||||
V = ConstantPointerNull::get(PT);
|
||||
@ -333,6 +337,10 @@ bool BytecodeParser::parseConstantValue(const uchar *&Buf, const uchar *EndBuf,
|
||||
if (Val) {
|
||||
if (!(GV = dyn_cast<GlobalValue>(Val))) return true;
|
||||
BCR_TRACE(5, "Value Found in ValueTable!\n");
|
||||
} else if (RevisionNum > 0) {
|
||||
// Revision #0 could have forward references to globals that were wierd.
|
||||
// We got rid of this in subsequent revs.
|
||||
return true;
|
||||
} else { // Nope... find or create a forward ref. for it
|
||||
GlobalRefsType::iterator I = GlobalRefs.find(std::make_pair(PT, Slot));
|
||||
|
||||
@ -341,12 +349,12 @@ bool BytecodeParser::parseConstantValue(const uchar *&Buf, const uchar *EndBuf,
|
||||
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...
|
||||
|
||||
// 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
|
||||
// Keep track of the fact that we have a forward ref to recycle it
|
||||
GlobalRefs.insert(std::make_pair(std::make_pair(PT, Slot), GVar));
|
||||
|
||||
// Must temporarily push this value into the module table...
|
||||
@ -354,6 +362,7 @@ bool BytecodeParser::parseConstantValue(const uchar *&Buf, const uchar *EndBuf,
|
||||
GV = GVar;
|
||||
}
|
||||
}
|
||||
|
||||
V = ConstantPointerRef::get(GV);
|
||||
break;
|
||||
}
|
||||
@ -375,6 +384,11 @@ bool BytecodeParser::parseConstantValue(const uchar *&Buf, const uchar *EndBuf,
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BytecodeParser::ParseGlobalTypes(const uchar *&Buf, const uchar *EndBuf) {
|
||||
ValueTable T;
|
||||
return ParseConstantPool(Buf, EndBuf, T, ModuleTypeValues);
|
||||
}
|
||||
|
||||
bool BytecodeParser::ParseConstantPool(const uchar *&Buf, const uchar *EndBuf,
|
||||
ValueTable &Tab,
|
||||
TypeValuesListTy &TypeTab) {
|
||||
@ -391,20 +405,19 @@ bool BytecodeParser::ParseConstantPool(const uchar *&Buf, const uchar *EndBuf,
|
||||
if (parseTypeConstants(Buf, EndBuf, TypeTab, NumEntries)) return true;
|
||||
} else {
|
||||
for (unsigned i = 0; i < NumEntries; ++i) {
|
||||
Constant *I;
|
||||
Constant *C;
|
||||
int Slot;
|
||||
if (parseConstantValue(Buf, EndBuf, Ty, I)) return true;
|
||||
assert(I && "parseConstantValue returned NULL!");
|
||||
BCR_TRACE(4, "Read Constant: '" << I << "'\n");
|
||||
if ((Slot = insertValue(I, Tab)) < 0) return true;
|
||||
if (parseConstantValue(Buf, EndBuf, Ty, C)) return true;
|
||||
assert(C && "parseConstantValue returned NULL!");
|
||||
BCR_TRACE(4, "Read Constant: '" << *C << "'\n");
|
||||
if ((Slot = insertValue(C, Tab)) == -1) return true;
|
||||
|
||||
// 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 (&Tab != &ModuleValues && Typ < ModuleValues.size())
|
||||
Slot += ModuleValues[Typ]->size();
|
||||
ResolveReferencesToValue(C, (unsigned)Slot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -55,23 +55,44 @@ const Type *BytecodeParser::getType(unsigned ID) {
|
||||
return cast_or_null<Type>(V);
|
||||
}
|
||||
|
||||
int BytecodeParser::insertValue(Value *Val, std::vector<ValueList> &ValueTab) {
|
||||
int BytecodeParser::insertValue(Value *Val, ValueTable &ValueTab) {
|
||||
assert((!HasImplicitZeroInitializer || !isa<Constant>(Val) ||
|
||||
Val->getType()->isPrimitiveType() ||
|
||||
!cast<Constant>(Val)->isNullValue()) &&
|
||||
"Cannot read null values from bytecode!");
|
||||
unsigned type;
|
||||
if (getTypeSlot(Val->getType(), type)) return -1;
|
||||
assert(type != Type::TypeTyID && "Types should never be insertValue'd!");
|
||||
|
||||
while (ValueTab.size() <= type) {
|
||||
ValueTab.push_back(ValueList());
|
||||
if (HasImplicitZeroInitializer) // add a zero initializer if appropriate
|
||||
ValueTab.back().push_back(
|
||||
Constant::getNullValue(getType(ValueTab.size()-1)));
|
||||
if (ValueTab.size() <= type) {
|
||||
unsigned OldSize = ValueTab.size();
|
||||
ValueTab.resize(type+1);
|
||||
while (OldSize != type+1)
|
||||
ValueTab[OldSize++] = new ValueList();
|
||||
}
|
||||
|
||||
//cerr << "insertValue Values[" << type << "][" << ValueTab[type].size()
|
||||
// << "] = " << Val << "\n";
|
||||
ValueTab[type].push_back(Val);
|
||||
ValueTab[type]->push_back(Val);
|
||||
|
||||
return ValueTab[type].size()-1;
|
||||
bool HasOffset = HasImplicitZeroInitializer &&
|
||||
!Val->getType()->isPrimitiveType();
|
||||
|
||||
return ValueTab[type]->size()-1 + HasOffset;
|
||||
}
|
||||
|
||||
|
||||
void BytecodeParser::setValueTo(ValueTable &ValueTab, unsigned Slot,
|
||||
Value *Val) {
|
||||
assert(&ValueTab == &ModuleValues && "Can only setValueTo on Module values!");
|
||||
unsigned type;
|
||||
if (getTypeSlot(Val->getType(), type))
|
||||
assert(0 && "getTypeSlot failed!");
|
||||
|
||||
assert((!HasImplicitZeroInitializer || Slot != 0) &&
|
||||
"Cannot change zero init");
|
||||
assert(type < ValueTab.size() && Slot <= ValueTab[type]->size());
|
||||
ValueTab[type]->setOperand(Slot-HasImplicitZeroInitializer, Val);
|
||||
}
|
||||
|
||||
Value *BytecodeParser::getValue(const Type *Ty, unsigned oNum, bool Create) {
|
||||
@ -102,25 +123,25 @@ Value *BytecodeParser::getValue(const Type *Ty, unsigned oNum, bool Create) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (type < ModuleValues.size()) {
|
||||
if (Num < ModuleValues[type].size())
|
||||
return ModuleValues[type][Num];
|
||||
Num -= ModuleValues[type].size();
|
||||
if (HasImplicitZeroInitializer && type >= FirstDerivedTyID) {
|
||||
if (Num == 0)
|
||||
return Constant::getNullValue(Ty);
|
||||
--Num;
|
||||
}
|
||||
|
||||
if (Values.size() > type && Values[type].size() > Num)
|
||||
return Values[type][Num];
|
||||
if (type < ModuleValues.size()) {
|
||||
if (Num < ModuleValues[type]->size())
|
||||
return ModuleValues[type]->getOperand(Num);
|
||||
Num -= ModuleValues[type]->size();
|
||||
}
|
||||
|
||||
if (Values.size() > type && Values[type]->size() > Num)
|
||||
return Values[type]->getOperand(Num);
|
||||
|
||||
if (!Create) return 0; // Do not create a placeholder?
|
||||
|
||||
Value *d = 0;
|
||||
switch (Ty->getPrimitiveID()) {
|
||||
case Type::FunctionTyID:
|
||||
std::cerr << "Creating function pholder! : " << type << ":" << oNum << " "
|
||||
<< Ty->getName() << "\n";
|
||||
d = new FunctionPHolder(Ty, oNum);
|
||||
if (insertValue(d, LateResolveModuleValues) == -1) return 0;
|
||||
return d;
|
||||
case Type::LabelTyID:
|
||||
d = new BBPHolder(Ty, oNum);
|
||||
break;
|
||||
@ -144,8 +165,10 @@ Constant *BytecodeParser::getConstantValue(const Type *Ty, unsigned Slot) {
|
||||
if (Value *V = getValue(Ty, Slot, false))
|
||||
return dyn_cast<Constant>(V); // If we already have the value parsed...
|
||||
|
||||
GlobalRefsType::iterator I = GlobalRefs.find(std::make_pair(Ty, Slot));
|
||||
if (I != GlobalRefs.end()) {
|
||||
std::pair<const Type*, unsigned> Key(Ty, Slot);
|
||||
GlobalRefsType::iterator I = GlobalRefs.lower_bound(Key);
|
||||
|
||||
if (I != GlobalRefs.end() && I->first == Key) {
|
||||
BCR_TRACE(5, "Previous forward ref found!\n");
|
||||
return cast<Constant>(I->second);
|
||||
} else {
|
||||
@ -155,29 +178,28 @@ Constant *BytecodeParser::getConstantValue(const Type *Ty, unsigned Slot) {
|
||||
Constant *C = new ConstPHolder(Ty, Slot);
|
||||
|
||||
// Keep track of the fact that we have a forward ref to recycle it
|
||||
GlobalRefs.insert(std::make_pair(std::make_pair(Ty, Slot), C));
|
||||
GlobalRefs.insert(I, std::make_pair(Key, C));
|
||||
return C;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool BytecodeParser::postResolveValues(ValueTable &ValTab) {
|
||||
bool Error = false;
|
||||
for (unsigned ty = 0; ty < ValTab.size(); ++ty) {
|
||||
ValueList &DL = ValTab[ty];
|
||||
unsigned Size;
|
||||
while ((Size = DL.size())) {
|
||||
unsigned IDNumber = getValueIDNumberFromPlaceHolder(DL[Size-1]);
|
||||
while (!ValTab.empty()) {
|
||||
ValueList &DL = *ValTab.back();
|
||||
ValTab.pop_back();
|
||||
|
||||
Value *D = DL[Size-1];
|
||||
while (!DL.empty()) {
|
||||
Value *D = DL.back();
|
||||
unsigned IDNumber = getValueIDNumberFromPlaceHolder(D);
|
||||
DL.pop_back();
|
||||
|
||||
Value *NewDef = getValue(D->getType(), IDNumber, false);
|
||||
if (NewDef == 0) {
|
||||
Error = true; // Unresolved thinger
|
||||
std::cerr << "Unresolvable reference found: <"
|
||||
<< D->getType()->getDescription() << ">:" << IDNumber <<"!\n";
|
||||
<< *D->getType() << ">:" << IDNumber <<"!\n";
|
||||
} else {
|
||||
// Fixup all of the uses of this placeholder def...
|
||||
D->replaceAllUsesWith(NewDef);
|
||||
@ -187,6 +209,7 @@ bool BytecodeParser::postResolveValues(ValueTable &ValTab) {
|
||||
delete D; // memory, 'cause otherwise we can't remove all uses!
|
||||
}
|
||||
}
|
||||
delete &DL;
|
||||
}
|
||||
|
||||
return Error;
|
||||
@ -235,15 +258,15 @@ bool BytecodeParser::ParseSymbolTable(const uchar *&Buf, const uchar *EndBuf,
|
||||
if (read(Buf, EndBuf, Name, false)) // Not aligned...
|
||||
return true;
|
||||
|
||||
Value *D = getValue(Ty, slot, false); // Find mapping...
|
||||
if (D == 0) {
|
||||
Value *V = getValue(Ty, slot, false); // Find mapping...
|
||||
if (V == 0) {
|
||||
BCR_TRACE(3, "FAILED LOOKUP: Slot #" << slot << "\n");
|
||||
return true;
|
||||
}
|
||||
BCR_TRACE(4, "Map: '" << Name << "' to #" << slot << ":" << D;
|
||||
if (!isa<Instruction>(D)) std::cerr << "\n");
|
||||
BCR_TRACE(4, "Map: '" << Name << "' to #" << slot << ":" << *V;
|
||||
if (!isa<Instruction>(V)) std::cerr << "\n");
|
||||
|
||||
D->setName(Name, ST);
|
||||
V->setName(Name, ST);
|
||||
}
|
||||
}
|
||||
|
||||
@ -259,52 +282,40 @@ void BytecodeParser::ResolveReferencesToValue(Value *NewV, unsigned Slot) {
|
||||
BCR_TRACE(3, "Mutating forward refs!\n");
|
||||
Value *VPH = I->second; // Get the placeholder...
|
||||
|
||||
// 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)) {
|
||||
// Remove the placeholder GlobalValue from the module...
|
||||
GVal->getParent()->getGlobalList().remove(cast<GlobalVariable>(VPH));
|
||||
}
|
||||
}
|
||||
VPH->replaceAllUsesWith(NewV);
|
||||
|
||||
// If this is a global variable being resolved, remove the placeholder from
|
||||
// the module...
|
||||
if (GlobalValue* GVal = dyn_cast<GlobalValue>(NewV))
|
||||
GVal->getParent()->getGlobalList().remove(cast<GlobalVariable>(VPH));
|
||||
|
||||
delete VPH; // Delete the old placeholder
|
||||
GlobalRefs.erase(I); // Remove the map entry for it
|
||||
}
|
||||
|
||||
|
||||
bool BytecodeParser::ParseFunction(const uchar *&Buf, const uchar *EndBuf) {
|
||||
// Clear out the local values table...
|
||||
Values.clear();
|
||||
if (FunctionSignatureList.empty()) {
|
||||
Error = "Function found, but FunctionSignatureList empty!";
|
||||
return true; // Unexpected function!
|
||||
}
|
||||
|
||||
const PointerType *PMTy = FunctionSignatureList.back().first; // PtrMeth
|
||||
const FunctionType *MTy = dyn_cast<FunctionType>(PMTy->getElementType());
|
||||
if (MTy == 0) return true; // Not ptr to function!
|
||||
|
||||
unsigned isInternal;
|
||||
if (read_vbr(Buf, EndBuf, isInternal)) return true;
|
||||
|
||||
unsigned MethSlot = FunctionSignatureList.back().second;
|
||||
Function *F = FunctionSignatureList.back().first;
|
||||
unsigned FunctionSlot = FunctionSignatureList.back().second;
|
||||
FunctionSignatureList.pop_back();
|
||||
Function *M = new Function(MTy, isInternal != 0);
|
||||
F->setInternalLinkage(isInternal != 0);
|
||||
|
||||
BCR_TRACE(2, "FUNCTION TYPE: " << MTy << "\n");
|
||||
|
||||
const FunctionType::ParamTypes &Params = MTy->getParamTypes();
|
||||
Function::aiterator AI = M->abegin();
|
||||
const FunctionType::ParamTypes &Params =F->getFunctionType()->getParamTypes();
|
||||
Function::aiterator AI = F->abegin();
|
||||
for (FunctionType::ParamTypes::const_iterator It = Params.begin();
|
||||
It != Params.end(); ++It, ++AI) {
|
||||
if (insertValue(AI, Values) == -1) {
|
||||
Error = "Error reading function arguments!\n";
|
||||
delete M; return true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -313,34 +324,31 @@ bool BytecodeParser::ParseFunction(const uchar *&Buf, const uchar *EndBuf) {
|
||||
const unsigned char *OldBuf = Buf;
|
||||
if (readBlock(Buf, EndBuf, Type, Size)) {
|
||||
Error = "Error reading Function level block!";
|
||||
delete M; return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (Type) {
|
||||
case BytecodeFormat::ConstantPool:
|
||||
BCR_TRACE(2, "BLOCK BytecodeFormat::ConstantPool: {\n");
|
||||
if (ParseConstantPool(Buf, Buf+Size, Values, FunctionTypeValues)) {
|
||||
delete M; return true;
|
||||
}
|
||||
if (ParseConstantPool(Buf, Buf+Size, Values, FunctionTypeValues))
|
||||
return true;
|
||||
break;
|
||||
|
||||
case BytecodeFormat::BasicBlock: {
|
||||
BCR_TRACE(2, "BLOCK BytecodeFormat::BasicBlock: {\n");
|
||||
BasicBlock *BB;
|
||||
if (ParseBasicBlock(Buf, Buf+Size, BB) ||
|
||||
insertValue(BB, Values) == -1) {
|
||||
delete M; return true; // Parse error... :(
|
||||
}
|
||||
insertValue(BB, Values) == -1)
|
||||
return true; // Parse error... :(
|
||||
|
||||
M->getBasicBlockList().push_back(BB);
|
||||
F->getBasicBlockList().push_back(BB);
|
||||
break;
|
||||
}
|
||||
|
||||
case BytecodeFormat::SymbolTable:
|
||||
BCR_TRACE(2, "BLOCK BytecodeFormat::SymbolTable: {\n");
|
||||
if (ParseSymbolTable(Buf, Buf+Size, &M->getSymbolTable())) {
|
||||
delete M; return true;
|
||||
}
|
||||
if (ParseSymbolTable(Buf, Buf+Size, &F->getSymbolTable()))
|
||||
return true;
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -353,41 +361,21 @@ bool BytecodeParser::ParseFunction(const uchar *&Buf, const uchar *EndBuf) {
|
||||
|
||||
if (align32(Buf, EndBuf)) {
|
||||
Error = "Error aligning Function level block!";
|
||||
delete M; // Malformed bc file, read past end of block.
|
||||
return true;
|
||||
return true; // Malformed bc file, read past end of block.
|
||||
}
|
||||
}
|
||||
|
||||
if (postResolveValues(LateResolveValues) ||
|
||||
postResolveValues(LateResolveModuleValues)) {
|
||||
if (postResolveValues(LateResolveValues)) {
|
||||
Error = "Error resolving function values!";
|
||||
delete M; return true; // Unresolvable references!
|
||||
return true; // Unresolvable references!
|
||||
}
|
||||
|
||||
Value *FunctionPHolder = getValue(PMTy, MethSlot, false);
|
||||
assert(FunctionPHolder && "Something is broken, no placeholder found!");
|
||||
assert(isa<Function>(FunctionPHolder) && "Not a function?");
|
||||
|
||||
unsigned type; // Type slot
|
||||
assert(!getTypeSlot(MTy, type) && "How can meth type not exist?");
|
||||
getTypeSlot(PMTy, type);
|
||||
|
||||
TheModule->getFunctionList().push_back(M);
|
||||
|
||||
// Replace placeholder with the real function pointer...
|
||||
ModuleValues[type][MethSlot] = M;
|
||||
ResolveReferencesToValue(F, FunctionSlot);
|
||||
|
||||
// Clear out function level types...
|
||||
FunctionTypeValues.clear();
|
||||
|
||||
// If anyone is using the placeholder make them use the real function instead
|
||||
FunctionPHolder->replaceAllUsesWith(M);
|
||||
|
||||
// We don't need the placeholder anymore!
|
||||
delete FunctionPHolder;
|
||||
|
||||
ResolveReferencesToValue(M, MethSlot);
|
||||
|
||||
freeTable(Values);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -409,40 +397,25 @@ bool BytecodeParser::ParseModuleGlobalInfo(const uchar *&Buf, const uchar *End){
|
||||
return true;
|
||||
}
|
||||
|
||||
const PointerType *PTy = cast<const PointerType>(Ty);
|
||||
const Type *ElTy = PTy->getElementType();
|
||||
|
||||
Constant *Initializer = 0;
|
||||
if (VarType & 2) { // Does it have an initalizer?
|
||||
// Do not improvise... values must have been stored in the constant pool,
|
||||
// which should have been read before now.
|
||||
//
|
||||
unsigned InitSlot;
|
||||
if (read_vbr(Buf, End, InitSlot)) return true;
|
||||
|
||||
Value *V = getValue(ElTy, InitSlot, false);
|
||||
if (V == 0) return true;
|
||||
Initializer = cast<Constant>(V);
|
||||
}
|
||||
const Type *ElTy = cast<PointerType>(Ty)->getElementType();
|
||||
|
||||
// Create the global variable...
|
||||
GlobalVariable *GV = new GlobalVariable(ElTy, VarType & 1, VarType & 4,
|
||||
Initializer);
|
||||
0, "", TheModule);
|
||||
int DestSlot = insertValue(GV, ModuleValues);
|
||||
if (DestSlot == -1) return true;
|
||||
|
||||
TheModule->getGlobalList().push_back(GV);
|
||||
|
||||
BCR_TRACE(2, "Global Variable of type: " << *Ty << "\n");
|
||||
ResolveReferencesToValue(GV, (unsigned)DestSlot);
|
||||
|
||||
BCR_TRACE(2, "Global Variable of type: " << PTy->getDescription()
|
||||
<< " into slot #" << DestSlot << "\n");
|
||||
|
||||
if (VarType & 2) { // Does it have an initalizer?
|
||||
unsigned InitSlot;
|
||||
if (read_vbr(Buf, End, InitSlot)) return true;
|
||||
GlobalInits.push_back(std::make_pair(GV, InitSlot));
|
||||
}
|
||||
if (read_vbr(Buf, End, VarType)) return true;
|
||||
}
|
||||
|
||||
// Read the function signatures for all of the functions that are coming, and
|
||||
// create fillers in the Value tables.
|
||||
// Read the function objects for all of the functions that are coming
|
||||
unsigned FnSignature;
|
||||
if (read_vbr(Buf, End, FnSignature)) return true;
|
||||
while (FnSignature != Type::VoidTyID) { // List is terminated by Void
|
||||
@ -462,20 +435,16 @@ bool BytecodeParser::ParseModuleGlobalInfo(const uchar *&Buf, const uchar *End){
|
||||
// this placeholder is replaced.
|
||||
|
||||
// Insert the placeholder...
|
||||
Value *Val = new FunctionPHolder(Ty, 0);
|
||||
if (insertValue(Val, ModuleValues) == -1) return true;
|
||||
Function *Func = new Function(cast<FunctionType>(Ty), false, "", TheModule);
|
||||
int DestSlot = insertValue(Func, ModuleValues);
|
||||
if (DestSlot == -1) return true;
|
||||
ResolveReferencesToValue(Func, (unsigned)DestSlot);
|
||||
|
||||
// Figure out which entry of its typeslot it went into...
|
||||
unsigned TypeSlot;
|
||||
if (getTypeSlot(Val->getType(), TypeSlot)) return true;
|
||||
|
||||
unsigned SlotNo = ModuleValues[TypeSlot].size()-1;
|
||||
|
||||
// Keep track of this information in a linked list that is emptied as
|
||||
// functions are loaded...
|
||||
// Keep track of this information in a list that is emptied as functions are
|
||||
// loaded...
|
||||
//
|
||||
FunctionSignatureList.push_back(
|
||||
std::make_pair(cast<const PointerType>(Val->getType()), SlotNo));
|
||||
FunctionSignatureList.push_back(std::make_pair(Func, DestSlot));
|
||||
|
||||
if (read_vbr(Buf, End, FnSignature)) return true;
|
||||
BCR_TRACE(2, "Function of type: " << Ty << "\n");
|
||||
}
|
||||
@ -505,12 +474,17 @@ bool BytecodeParser::ParseVersionInfo(const uchar *&Buf, const uchar *EndBuf) {
|
||||
|
||||
switch (RevisionNum) {
|
||||
case 0: // Initial revision
|
||||
// Version #0 didn't have any of the flags stored correctly, and in fact as
|
||||
// only valid with a 14 in the flags values. Also, it does not support
|
||||
// encoding zero initializers for arrays compactly.
|
||||
//
|
||||
if (Version != 14) return true; // Unknown revision 0 flags?
|
||||
FirstDerivedTyID = 14;
|
||||
HasImplicitZeroInitializer = false;
|
||||
isBigEndian = hasLongPointers = true;
|
||||
break;
|
||||
case 1:
|
||||
// Version #1 has two bit fields: isBigEndian and hasLongPointers
|
||||
FirstDerivedTyID = 14;
|
||||
break;
|
||||
default:
|
||||
@ -544,20 +518,26 @@ bool BytecodeParser::ParseModule(const uchar *Buf, const uchar *EndBuf) {
|
||||
const unsigned char *OldBuf = Buf;
|
||||
if (readBlock(Buf, EndBuf, Type, Size)) return true;
|
||||
switch (Type) {
|
||||
case BytecodeFormat::GlobalTypePlane:
|
||||
BCR_TRACE(1, "BLOCK BytecodeFormat::GlobalTypePlane: {\n");
|
||||
if (ParseGlobalTypes(Buf, Buf+Size)) return true;
|
||||
break;
|
||||
|
||||
case BytecodeFormat::ModuleGlobalInfo:
|
||||
BCR_TRACE(1, "BLOCK BytecodeFormat::ModuleGlobalInfo: {\n");
|
||||
if (ParseModuleGlobalInfo(Buf, Buf+Size)) return true;
|
||||
break;
|
||||
|
||||
case BytecodeFormat::ConstantPool:
|
||||
BCR_TRACE(1, "BLOCK BytecodeFormat::ConstantPool: {\n");
|
||||
if (ParseConstantPool(Buf, Buf+Size, ModuleValues, ModuleTypeValues))
|
||||
return true;
|
||||
break;
|
||||
|
||||
case BytecodeFormat::ModuleGlobalInfo:
|
||||
BCR_TRACE(1, "BLOCK BytecodeFormat::ModuleGlobalInfo: {\n");
|
||||
if (ParseModuleGlobalInfo(Buf, Buf+Size)) return true;
|
||||
break;
|
||||
|
||||
case BytecodeFormat::Function: {
|
||||
BCR_TRACE(1, "BLOCK BytecodeFormat::Function: {\n");
|
||||
if (ParseFunction(Buf, Buf+Size)) return true; // Error parsing function
|
||||
if (ParseFunction(Buf, Buf+Size))
|
||||
return true; // Error parsing function
|
||||
break;
|
||||
}
|
||||
|
||||
@ -577,6 +557,21 @@ bool BytecodeParser::ParseModule(const uchar *Buf, const uchar *EndBuf) {
|
||||
if (align32(Buf, EndBuf)) return true;
|
||||
}
|
||||
|
||||
// After the module constant pool has been read, we can safely initialize
|
||||
// global variables...
|
||||
while (!GlobalInits.empty()) {
|
||||
GlobalVariable *GV = GlobalInits.back().first;
|
||||
unsigned Slot = GlobalInits.back().second;
|
||||
GlobalInits.pop_back();
|
||||
|
||||
// Look up the initializer value...
|
||||
if (Value *V = getValue(GV->getType()->getElementType(), Slot, false)) {
|
||||
if (GV->hasInitializer()) return true;
|
||||
GV->setInitializer(cast<Constant>(V));
|
||||
} else
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!FunctionSignatureList.empty()) { // Expected more functions!
|
||||
Error = "Function expected, but bytecode stream at end!";
|
||||
return true;
|
||||
@ -592,7 +587,6 @@ static inline Module *Error(std::string *ErrorStr, const char *Message) {
|
||||
}
|
||||
|
||||
Module *BytecodeParser::ParseBytecode(const uchar *Buf, const uchar *EndBuf) {
|
||||
LateResolveValues.clear();
|
||||
unsigned Sig;
|
||||
// Read and check signature...
|
||||
if (read(Buf, EndBuf, Sig) ||
|
||||
|
@ -18,7 +18,8 @@
|
||||
#define TRACE_LEVEL 0
|
||||
|
||||
#if TRACE_LEVEL // ByteCodeReading_TRACEer
|
||||
#define BCR_TRACE(n, X) if (n < TRACE_LEVEL) std::cerr << std::string(n*2, ' ') << X
|
||||
#define BCR_TRACE(n, X) \
|
||||
if (n < TRACE_LEVEL) std::cerr << std::string(n*2, ' ') << X
|
||||
#else
|
||||
#define BCR_TRACE(n, X)
|
||||
#endif
|
||||
@ -45,6 +46,11 @@ public:
|
||||
// Define this in case we don't see a ModuleGlobalInfo block.
|
||||
FirstDerivedTyID = Type::FirstDerivedTyID;
|
||||
}
|
||||
~BytecodeParser() {
|
||||
freeTable(Values);
|
||||
freeTable(LateResolveValues);
|
||||
freeTable(ModuleValues);
|
||||
}
|
||||
|
||||
Module *ParseBytecode(const uchar *Buf, const uchar *EndBuf);
|
||||
|
||||
@ -55,6 +61,23 @@ public:
|
||||
}
|
||||
|
||||
private: // All of this data is transient across calls to ParseBytecode
|
||||
struct ValueList : public User {
|
||||
ValueList() : User(Type::TypeTy, Value::TypeVal) {
|
||||
}
|
||||
~ValueList() {}
|
||||
|
||||
// vector compatibility methods
|
||||
unsigned size() const { return getNumOperands(); }
|
||||
void push_back(Value *V) { Operands.push_back(Use(V, this)); }
|
||||
Value *back() const { return Operands.back(); }
|
||||
void pop_back() { Operands.pop_back(); }
|
||||
bool empty() const { return Operands.empty(); }
|
||||
|
||||
virtual void print(std::ostream& OS) const {
|
||||
OS << "Bytecode Reader UseHandle!";
|
||||
}
|
||||
};
|
||||
|
||||
Module *TheModule; // Current Module being read into...
|
||||
|
||||
// Information about the module, extracted from the bytecode revision number.
|
||||
@ -63,18 +86,16 @@ private: // All of this data is transient across calls to ParseBytecode
|
||||
bool HasImplicitZeroInitializer; // Is entry 0 of every slot implicity zeros?
|
||||
bool isBigEndian, hasLongPointers;// Information about the target compiled for
|
||||
|
||||
typedef std::vector<Value *> ValueList;
|
||||
typedef std::vector<ValueList> ValueTable;
|
||||
typedef std::vector<ValueList*> ValueTable;
|
||||
ValueTable Values, LateResolveValues;
|
||||
ValueTable ModuleValues, LateResolveModuleValues;
|
||||
ValueTable ModuleValues;
|
||||
|
||||
// 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;
|
||||
typedef std::map<std::pair<const Type *, unsigned>, Value*> GlobalRefsType;
|
||||
GlobalRefsType GlobalRefs;
|
||||
|
||||
// TypesLoaded - This vector mirrors the Values[TypeTyID] plane. It is used
|
||||
@ -84,14 +105,27 @@ private: // All of this data is transient across calls to ParseBytecode
|
||||
TypeValuesListTy ModuleTypeValues;
|
||||
TypeValuesListTy FunctionTypeValues;
|
||||
|
||||
// When the ModuleGlobalInfo section is read, we load the type of each
|
||||
// function and the 'ModuleValues' slot that it lands in. We then load a
|
||||
// placeholder into its slot to reserve it. When the function is loaded, this
|
||||
// placeholder is replaced.
|
||||
// When the ModuleGlobalInfo section is read, we create a function object for
|
||||
// each function in the module. When the function is loaded, this function is
|
||||
// filled in.
|
||||
//
|
||||
std::vector<std::pair<const PointerType *, unsigned> > FunctionSignatureList;
|
||||
std::vector<std::pair<Function*, unsigned> > FunctionSignatureList;
|
||||
|
||||
// Constant values are read in after global variables. Because of this, we
|
||||
// must defer setting the initializers on global variables until after module
|
||||
// level constants have been read. In the mean time, this list keeps track of
|
||||
// what we must do.
|
||||
//
|
||||
std::vector<std::pair<GlobalVariable*, unsigned> > GlobalInits;
|
||||
|
||||
private:
|
||||
void freeTable(ValueTable &Tab) {
|
||||
while (!Tab.empty()) {
|
||||
delete Tab.back();
|
||||
Tab.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
bool ParseModule (const uchar * Buf, const uchar *End);
|
||||
bool ParseVersionInfo (const uchar *&Buf, const uchar *End);
|
||||
bool ParseModuleGlobalInfo(const uchar *&Buf, const uchar *End);
|
||||
@ -102,6 +136,7 @@ private:
|
||||
BasicBlock *BB /*HACK*/);
|
||||
bool ParseRawInst (const uchar *&Buf, const uchar *End, RawInst &);
|
||||
|
||||
bool ParseGlobalTypes(const uchar *&Buf, const uchar *EndBuf);
|
||||
bool ParseConstantPool(const uchar *&Buf, const uchar *EndBuf,
|
||||
ValueTable &Tab, TypeValuesListTy &TypeTab);
|
||||
bool parseConstantValue(const uchar *&Buf, const uchar *End,
|
||||
@ -114,7 +149,8 @@ private:
|
||||
const Type *getType(unsigned ID);
|
||||
Constant *getConstantValue(const Type *Ty, unsigned num);
|
||||
|
||||
int insertValue(Value *D, std::vector<ValueList> &D); // -1 = Failure
|
||||
int insertValue(Value *V, ValueTable &Table); // -1 = Failure
|
||||
void setValueTo(ValueTable &D, unsigned Slot, Value *V);
|
||||
bool postResolveValues(ValueTable &ValTab);
|
||||
|
||||
bool getTypeSlot(const Type *Ty, unsigned &Slot);
|
||||
@ -152,12 +188,6 @@ struct BBPlaceHolderHelper : public BasicBlock {
|
||||
}
|
||||
};
|
||||
|
||||
struct FunctionPlaceHolderHelper : public Function {
|
||||
FunctionPlaceHolderHelper(const Type *Ty)
|
||||
: Function(cast<const FunctionType>(Ty), true) {
|
||||
}
|
||||
};
|
||||
|
||||
struct ConstantPlaceHolderHelper : public Constant {
|
||||
ConstantPlaceHolderHelper(const Type *Ty)
|
||||
: Constant(Ty) {}
|
||||
@ -166,7 +196,6 @@ struct ConstantPlaceHolderHelper : public Constant {
|
||||
|
||||
typedef PlaceholderDef<InstPlaceHolderHelper> ValPHolder;
|
||||
typedef PlaceholderDef<BBPlaceHolderHelper> BBPHolder;
|
||||
typedef PlaceholderDef<FunctionPlaceHolderHelper> FunctionPHolder;
|
||||
typedef PlaceholderDef<ConstantPlaceHolderHelper> ConstPHolder;
|
||||
|
||||
|
||||
@ -177,7 +206,6 @@ static inline unsigned getValueIDNumberFromPlaceHolder(Value *Val) {
|
||||
// else discriminate by type
|
||||
switch (Val->getType()->getPrimitiveID()) {
|
||||
case Type::LabelTyID: return ((BBPHolder*)Val)->getID();
|
||||
case Type::FunctionTyID: return ((FunctionPHolder*)Val)->getID();
|
||||
default: return ((ValPHolder*)Val)->getID();
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user