mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-14 14:24:05 +00:00
- 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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@3366 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -5,7 +5,7 @@
|
||||
// Note that this library should be as fast as possible, reentrant, and
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -13,7 +13,6 @@
|
||||
#include "ReaderInternals.h"
|
||||
#include "llvm/Bytecode/Reader.h"
|
||||
#include "llvm/Bytecode/Format.h"
|
||||
#include "llvm/GlobalVariable.h"
|
||||
#include "llvm/Module.h"
|
||||
#include "llvm/Constants.h"
|
||||
#include "llvm/iPHINode.h"
|
||||
@ -24,7 +23,6 @@
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
using std::cerr;
|
||||
using std::pair;
|
||||
using std::make_pair;
|
||||
@ -56,14 +54,14 @@ const Type *BytecodeParser::getType(unsigned ID) {
|
||||
//cerr << "Looking up Type ID: " << ID << "\n";
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
int BytecodeParser::insertValue(Value *Val, std::vector<ValueList> &ValueTab) {
|
||||
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!");
|
||||
|
||||
if (ValueTab.size() <= type)
|
||||
@ -80,7 +78,7 @@ Value *BytecodeParser::getValue(const Type *Ty, unsigned oNum, bool Create) {
|
||||
unsigned Num = oNum;
|
||||
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
|
||||
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)
|
||||
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;
|
||||
switch (Ty->getPrimitiveID()) {
|
||||
case Type::LabelTyID: d = new BBPHolder(Ty, oNum); break;
|
||||
case Type::FunctionTyID:
|
||||
cerr << "Creating method pholder! : " << type << ":" << oNum << " "
|
||||
<< Ty->getName() << "\n";
|
||||
d = new MethPHolder(Ty, oNum);
|
||||
if (insertValue(d, LateResolveModuleValues) ==-1) return failure<Value*>(0);
|
||||
d = new FunctionPHolder(Ty, oNum);
|
||||
if (insertValue(d, LateResolveModuleValues) == -1) return 0;
|
||||
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?");
|
||||
if (insertValue(d, LateResolveValues) == -1) return failure<Value*>(0);
|
||||
if (insertValue(d, LateResolveValues) == -1) return 0;
|
||||
return d;
|
||||
}
|
||||
|
||||
@ -168,11 +170,11 @@ bool BytecodeParser::ParseBasicBlock(const uchar *&Buf, const uchar *EndBuf,
|
||||
Instruction *Inst;
|
||||
if (ParseInstruction(Buf, EndBuf, Inst)) {
|
||||
delete BB;
|
||||
return failure(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Inst == 0) { delete BB; return failure(true); }
|
||||
if (insertValue(Inst, Values) == -1) { delete BB; return failure(true); }
|
||||
if (Inst == 0) { delete BB; return true; }
|
||||
if (insertValue(Inst, Values) == -1) { delete BB; return true; }
|
||||
|
||||
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]
|
||||
unsigned NumEntries, Typ;
|
||||
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);
|
||||
if (Ty == 0) return failure(true);
|
||||
if (Ty == 0) return true;
|
||||
|
||||
BCR_TRACE(3, "Plane Type: '" << Ty << "' with " << NumEntries <<
|
||||
" entries\n");
|
||||
@ -198,15 +200,15 @@ bool BytecodeParser::ParseSymbolTable(const uchar *&Buf, const uchar *EndBuf,
|
||||
for (unsigned i = 0; i < NumEntries; ++i) {
|
||||
// Symtab entry: [def slot #][name]
|
||||
unsigned slot;
|
||||
if (read_vbr(Buf, EndBuf, slot)) return failure(true);
|
||||
if (read_vbr(Buf, EndBuf, slot)) return true;
|
||||
std::string Name;
|
||||
if (read(Buf, EndBuf, Name, false)) // Not aligned...
|
||||
return failure(true);
|
||||
return true;
|
||||
|
||||
Value *D = getValue(Ty, slot, false); // Find mapping...
|
||||
if (D == 0) {
|
||||
BCR_TRACE(3, "FAILED LOOKUP: Slot #" << slot << "\n");
|
||||
return failure(true);
|
||||
return true;
|
||||
}
|
||||
BCR_TRACE(4, "Map: '" << Name << "' to #" << slot << ":" << D;
|
||||
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;
|
||||
}
|
||||
|
||||
Value*
|
||||
ConstantFwdRefs::find(const Type* Ty, unsigned Slot) {
|
||||
GlobalRefsType::iterator I = GlobalRefs.find(make_pair(Ty, Slot));
|
||||
if (I != GlobalRefs.end()) {
|
||||
return I->second;
|
||||
} else {
|
||||
return failure<Value*>(0);
|
||||
}
|
||||
}
|
||||
void BytecodeParser::ResolveReferencesToValue(Value *NewV, unsigned Slot) {
|
||||
GlobalRefsType::iterator I = GlobalRefs.find(make_pair(NewV->getType(),Slot));
|
||||
if (I == GlobalRefs.end()) return; // Never forward referenced?
|
||||
|
||||
void
|
||||
ConstantFwdRefs::insert(const Type* Ty, unsigned Slot, Value* V) {
|
||||
// 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?");
|
||||
}
|
||||
BCR_TRACE(3, "Mutating forward refs!\n");
|
||||
Value *VPH = I->second; // Get the placeholder...
|
||||
|
||||
void
|
||||
ConstantFwdRefs::erase(const Type* Ty, unsigned Slot) {
|
||||
GlobalRefsType::iterator I = GlobalRefs.find(make_pair(Ty, Slot));
|
||||
if (I != GlobalRefs.end())
|
||||
GlobalRefs.erase(I);
|
||||
}
|
||||
|
||||
// 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?");
|
||||
// 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));
|
||||
}
|
||||
if (GlobalValue* GVal = dyn_cast<GlobalValue>(NewV)) {
|
||||
// Remove the placeholder GlobalValue from the module...
|
||||
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
|
||||
// form of ConstantPointerRef.
|
||||
//
|
||||
void BytecodeParser::resolveRefsToGlobal(GlobalValue *GV, unsigned Slot) {
|
||||
fwdRefs.ResolveRefsToValue(GV, Slot);
|
||||
delete VPH; // Delete the old placeholder
|
||||
GlobalRefs.erase(I); // Remove the map entry for it
|
||||
}
|
||||
|
||||
// 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,
|
||||
Module *C) {
|
||||
// Clear out the local values table...
|
||||
Values.clear();
|
||||
if (MethodSignatureList.empty()) {
|
||||
if (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());
|
||||
if (MTy == 0) return failure(true); // Not ptr to method!
|
||||
if (MTy == 0) return true; // Not ptr to method!
|
||||
|
||||
unsigned isInternal;
|
||||
if (read_vbr(Buf, EndBuf, isInternal)) return failure(true);
|
||||
if (read_vbr(Buf, EndBuf, isInternal)) return true;
|
||||
|
||||
unsigned MethSlot = MethodSignatureList.front().second;
|
||||
MethodSignatureList.pop_front();
|
||||
unsigned MethSlot = FunctionSignatureList.back().second;
|
||||
FunctionSignatureList.pop_back();
|
||||
Function *M = new Function(MTy, isInternal != 0);
|
||||
|
||||
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);
|
||||
if (insertValue(FA, Values) == -1) {
|
||||
Error = "Error reading method arguments!\n";
|
||||
delete M; return failure(true);
|
||||
delete M; return true;
|
||||
}
|
||||
M->getArgumentList().push_back(FA);
|
||||
}
|
||||
@ -370,14 +284,14 @@ bool BytecodeParser::ParseMethod(const uchar *&Buf, const uchar *EndBuf,
|
||||
const uchar *OldBuf = Buf;
|
||||
if (readBlock(Buf, EndBuf, Type, Size)) {
|
||||
Error = "Error reading Function level block!";
|
||||
delete M; return failure(true);
|
||||
delete M; return true;
|
||||
}
|
||||
|
||||
switch (Type) {
|
||||
case BytecodeFormat::ConstantPool:
|
||||
BCR_TRACE(2, "BLOCK BytecodeFormat::ConstantPool: {\n");
|
||||
if (ParseConstantPool(Buf, Buf+Size, Values, MethodTypeValues)) {
|
||||
delete M; return failure(true);
|
||||
delete M; return true;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -386,7 +300,7 @@ bool BytecodeParser::ParseMethod(const uchar *&Buf, const uchar *EndBuf,
|
||||
BasicBlock *BB;
|
||||
if (ParseBasicBlock(Buf, Buf+Size, BB) ||
|
||||
insertValue(BB, Values) == -1) {
|
||||
delete M; return failure(true); // Parse error... :(
|
||||
delete M; return true; // Parse error... :(
|
||||
}
|
||||
|
||||
M->getBasicBlockList().push_back(BB);
|
||||
@ -396,14 +310,14 @@ bool BytecodeParser::ParseMethod(const uchar *&Buf, const uchar *EndBuf,
|
||||
case BytecodeFormat::SymbolTable:
|
||||
BCR_TRACE(2, "BLOCK BytecodeFormat::SymbolTable: {\n");
|
||||
if (ParseSymbolTable(Buf, Buf+Size, M->getSymbolTableSure())) {
|
||||
delete M; return failure(true);
|
||||
delete M; return true;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
BCR_TRACE(2, "BLOCK <unknown>:ignored! {\n");
|
||||
Buf += Size;
|
||||
if (OldBuf > Buf) return failure(true); // Wrap around!
|
||||
if (OldBuf > Buf) return true; // Wrap around!
|
||||
break;
|
||||
}
|
||||
BCR_TRACE(2, "} end block\n");
|
||||
@ -411,19 +325,19 @@ bool BytecodeParser::ParseMethod(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 failure(true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (postResolveValues(LateResolveValues) ||
|
||||
postResolveValues(LateResolveModuleValues)) {
|
||||
Error = "Error resolving method values!";
|
||||
delete M; return failure(true); // Unresolvable references!
|
||||
delete M; return true; // Unresolvable references!
|
||||
}
|
||||
|
||||
Value *MethPHolder = getValue(PMTy, MethSlot, false);
|
||||
assert(MethPHolder && "Something is broken no placeholder found!");
|
||||
assert(isa<Function>(MethPHolder) && "Not a function?");
|
||||
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?");
|
||||
@ -438,37 +352,37 @@ bool BytecodeParser::ParseMethod(const uchar *&Buf, const uchar *EndBuf,
|
||||
MethodTypeValues.clear();
|
||||
|
||||
// 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!
|
||||
delete MethPHolder;
|
||||
delete FunctionPHolder;
|
||||
|
||||
// If the method is empty, we don't need the method argument entries...
|
||||
if (M->isExternal())
|
||||
M->getArgumentList().clear();
|
||||
|
||||
resolveRefsToGlobal(M, MethSlot);
|
||||
ResolveReferencesToValue(M, MethSlot);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BytecodeParser::ParseModuleGlobalInfo(const uchar *&Buf, const uchar *End,
|
||||
Module *Mod) {
|
||||
if (!MethodSignatureList.empty()) {
|
||||
if (!FunctionSignatureList.empty()) {
|
||||
Error = "Two ModuleGlobalInfo packets found!";
|
||||
return failure(true); // Two ModuleGlobal blocks?
|
||||
return true; // Two ModuleGlobal blocks?
|
||||
}
|
||||
|
||||
// Read global variables...
|
||||
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
|
||||
// VarType Fields: bit0 = isConstant, bit1 = hasInitializer,
|
||||
// bit2 = isInternal, bit3+ = slot#
|
||||
const Type *Ty = getType(VarType >> 3);
|
||||
if (!Ty || !isa<PointerType>(Ty)) {
|
||||
Error = "Global not pointer type! Ty = " + Ty->getDescription();
|
||||
return failure(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
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.
|
||||
//
|
||||
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);
|
||||
if (V == 0) return failure(true);
|
||||
if (V == 0) return true;
|
||||
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,
|
||||
Initializer);
|
||||
int DestSlot = insertValue(GV, ModuleValues);
|
||||
if (DestSlot == -1) return failure(true);
|
||||
if (DestSlot == -1) return true;
|
||||
|
||||
Mod->getGlobalList().push_back(GV);
|
||||
|
||||
resolveRefsToGlobal(GV, unsigned(DestSlot));
|
||||
ResolveReferencesToValue(GV, (unsigned)DestSlot);
|
||||
|
||||
BCR_TRACE(2, "Global Variable of type: " << PTy->getDescription()
|
||||
<< " 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
|
||||
// create fillers in the Value tables.
|
||||
unsigned MethSignature;
|
||||
if (read_vbr(Buf, End, MethSignature)) return failure(true);
|
||||
while (MethSignature != Type::VoidTyID) { // List is terminated by Void
|
||||
const Type *Ty = getType(MethSignature);
|
||||
unsigned FnSignature;
|
||||
if (read_vbr(Buf, End, FnSignature)) return true;
|
||||
while (FnSignature != Type::VoidTyID) { // List is terminated by Void
|
||||
const Type *Ty = getType(FnSignature);
|
||||
if (!Ty || !isa<PointerType>(Ty) ||
|
||||
!isa<FunctionType>(cast<PointerType>(Ty)->getElementType())) {
|
||||
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...
|
||||
@ -524,25 +438,29 @@ bool BytecodeParser::ParseModuleGlobalInfo(const uchar *&Buf, const uchar *End,
|
||||
// placeholder is replaced.
|
||||
|
||||
// Insert the placeholder...
|
||||
Value *Val = new MethPHolder(Ty, 0);
|
||||
if (insertValue(Val, ModuleValues) == -1) return failure(true);
|
||||
Value *Val = new FunctionPHolder(Ty, 0);
|
||||
if (insertValue(Val, ModuleValues) == -1) return true;
|
||||
|
||||
// Figure out which entry of its typeslot it went into...
|
||||
unsigned TypeSlot;
|
||||
if (getTypeSlot(Val->getType(), TypeSlot)) return failure(true);
|
||||
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
|
||||
// methods are loaded...
|
||||
//
|
||||
MethodSignatureList.push_back(
|
||||
FunctionSignatureList.push_back(
|
||||
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");
|
||||
}
|
||||
|
||||
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
|
||||
// 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,
|
||||
Module *&C) {
|
||||
Module *&Mod) {
|
||||
|
||||
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) {
|
||||
Error = "Expected Module packet!";
|
||||
return failure(true); // Hrm, not a class?
|
||||
return true; // Hrm, not a class?
|
||||
}
|
||||
|
||||
BCR_TRACE(0, "BLOCK BytecodeFormat::Module: {\n");
|
||||
MethodSignatureList.clear(); // Just in case...
|
||||
FunctionSignatureList.clear(); // Just in case...
|
||||
|
||||
// Read into instance variables...
|
||||
if (read_vbr(Buf, EndBuf, FirstDerivedTyID)) return failure(true);
|
||||
if (align32(Buf, EndBuf)) return failure(true);
|
||||
if (read_vbr(Buf, EndBuf, FirstDerivedTyID)) return true;
|
||||
if (align32(Buf, EndBuf)) return true;
|
||||
BCR_TRACE(1, "FirstDerivedTyID = " << FirstDerivedTyID << "\n");
|
||||
|
||||
TheModule = C = new Module();
|
||||
fwdRefs.VisitingModule(TheModule);
|
||||
TheModule = Mod = new Module();
|
||||
|
||||
while (Buf < EndBuf) {
|
||||
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) {
|
||||
case BytecodeFormat::ConstantPool:
|
||||
BCR_TRACE(1, "BLOCK BytecodeFormat::ConstantPool: {\n");
|
||||
if (ParseConstantPool(Buf, Buf+Size, ModuleValues, ModuleTypeValues)) {
|
||||
delete C; return failure(true);
|
||||
delete Mod; return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case BytecodeFormat::ModuleGlobalInfo:
|
||||
BCR_TRACE(1, "BLOCK BytecodeFormat::ModuleGlobalInfo: {\n");
|
||||
|
||||
if (ParseModuleGlobalInfo(Buf, Buf+Size, C)) {
|
||||
delete C; return failure(true);
|
||||
if (ParseModuleGlobalInfo(Buf, Buf+Size, Mod)) {
|
||||
delete Mod; return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case BytecodeFormat::Function: {
|
||||
BCR_TRACE(1, "BLOCK BytecodeFormat::Function: {\n");
|
||||
if (ParseMethod(Buf, Buf+Size, C)) {
|
||||
delete C; return failure(true); // Error parsing method
|
||||
if (ParseMethod(Buf, Buf+Size, Mod)) {
|
||||
delete Mod; return true; // Error parsing function
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case BytecodeFormat::SymbolTable:
|
||||
BCR_TRACE(1, "BLOCK BytecodeFormat::SymbolTable: {\n");
|
||||
if (ParseSymbolTable(Buf, Buf+Size, C->getSymbolTableSure())) {
|
||||
delete C; return failure(true);
|
||||
if (ParseSymbolTable(Buf, Buf+Size, Mod->getSymbolTableSure())) {
|
||||
delete Mod; return true;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
Error = "Expected Module Block!";
|
||||
Buf += Size;
|
||||
if (OldBuf > Buf) return failure(true); // Wrap around!
|
||||
if (OldBuf > Buf) return true; // Wrap around!
|
||||
break;
|
||||
}
|
||||
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!";
|
||||
return failure(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
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) ||
|
||||
Sig != ('l' | ('l' << 8) | ('v' << 16) | 'm' << 24)) {
|
||||
Error = "Invalid bytecode signature!";
|
||||
return failure<Module*>(0); // Invalid signature!
|
||||
return 0; // Invalid signature!
|
||||
}
|
||||
|
||||
Module *Result;
|
||||
@ -656,21 +573,21 @@ Module *ParseBytecodeFile(const std::string &Filename, std::string *ErrorStr) {
|
||||
int FD = open(Filename.c_str(), O_RDONLY);
|
||||
if (FD == -1) {
|
||||
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;
|
||||
if (Length == 0) {
|
||||
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,
|
||||
MAP_PRIVATE, FD, 0);
|
||||
if (Buffer == (uchar*)-1) {
|
||||
if (ErrorStr) *ErrorStr = "Error mmapping file!";
|
||||
close(FD); return failure<Module*>(0);
|
||||
close(FD); return 0;
|
||||
}
|
||||
|
||||
BytecodeParser Parser;
|
||||
@ -684,7 +601,7 @@ Module *ParseBytecodeFile(const std::string &Filename, std::string *ErrorStr) {
|
||||
int BlockSize;
|
||||
uchar Buffer[4096], *FileData = 0;
|
||||
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);
|
||||
memcpy(FileData+FileSize, Buffer, BlockSize);
|
||||
@ -693,7 +610,7 @@ Module *ParseBytecodeFile(const std::string &Filename, std::string *ErrorStr) {
|
||||
|
||||
if (FileSize == 0) {
|
||||
if (ErrorStr) *ErrorStr = "Standard Input empty!";
|
||||
free(FileData); return failure<Module*>(0);
|
||||
free(FileData); return 0;
|
||||
}
|
||||
|
||||
#define ALIGN_PTRS 1
|
||||
|
Reference in New Issue
Block a user