mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-19 02:25:01 +00:00
handle function-level forward references, read binops.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@36620 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -15,6 +15,7 @@
|
|||||||
#include "BitcodeReader.h"
|
#include "BitcodeReader.h"
|
||||||
#include "llvm/Constants.h"
|
#include "llvm/Constants.h"
|
||||||
#include "llvm/DerivedTypes.h"
|
#include "llvm/DerivedTypes.h"
|
||||||
|
#include "llvm/Instructions.h"
|
||||||
#include "llvm/Module.h"
|
#include "llvm/Module.h"
|
||||||
#include "llvm/ADT/SmallString.h"
|
#include "llvm/ADT/SmallString.h"
|
||||||
#include "llvm/Support/MathExtras.h"
|
#include "llvm/Support/MathExtras.h"
|
||||||
@@ -125,10 +126,9 @@ Constant *BitcodeReaderValueList::getConstantFwdRef(unsigned Idx,
|
|||||||
NumOperands = Idx+1;
|
NumOperands = Idx+1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Uses[Idx]) {
|
if (Value *V = Uses[Idx]) {
|
||||||
assert(Ty == getOperand(Idx)->getType() &&
|
assert(Ty == V->getType() && "Type mismatch in constant table!");
|
||||||
"Type mismatch in constant table!");
|
return cast<Constant>(V);
|
||||||
return cast<Constant>(getOperand(Idx));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create and return a placeholder, which will later be RAUW'd.
|
// Create and return a placeholder, which will later be RAUW'd.
|
||||||
@@ -137,6 +137,25 @@ Constant *BitcodeReaderValueList::getConstantFwdRef(unsigned Idx,
|
|||||||
return C;
|
return C;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Value *BitcodeReaderValueList::getValueFwdRef(unsigned Idx, const Type *Ty) {
|
||||||
|
if (Idx >= size()) {
|
||||||
|
// Insert a bunch of null values.
|
||||||
|
Uses.resize(Idx+1);
|
||||||
|
OperandList = &Uses[0];
|
||||||
|
NumOperands = Idx+1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Value *V = Uses[Idx]) {
|
||||||
|
assert((Ty == 0 || Ty == V->getType()) && "Type mismatch in value table!");
|
||||||
|
return V;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create and return a placeholder, which will later be RAUW'd.
|
||||||
|
Value *V = new Argument(Ty);
|
||||||
|
Uses[Idx].init(V, this);
|
||||||
|
return V;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const Type *BitcodeReader::getTypeByID(unsigned ID, bool isTypeTable) {
|
const Type *BitcodeReader::getTypeByID(unsigned ID, bool isTypeTable) {
|
||||||
// If the TypeID is in range, return it.
|
// If the TypeID is in range, return it.
|
||||||
@@ -151,7 +170,6 @@ const Type *BitcodeReader::getTypeByID(unsigned ID, bool isTypeTable) {
|
|||||||
return TypeList.back().get();
|
return TypeList.back().get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool BitcodeReader::ParseTypeTable() {
|
bool BitcodeReader::ParseTypeTable() {
|
||||||
if (Stream.EnterSubBlock())
|
if (Stream.EnterSubBlock())
|
||||||
return Error("Malformed block record");
|
return Error("Malformed block record");
|
||||||
@@ -643,18 +661,7 @@ bool BitcodeReader::ParseConstants() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NextCstNo == ValueList.size())
|
ValueList.AssignValue(V, NextCstNo);
|
||||||
ValueList.push_back(V);
|
|
||||||
else if (ValueList[NextCstNo] == 0)
|
|
||||||
ValueList.initVal(NextCstNo, V);
|
|
||||||
else {
|
|
||||||
// If there was a forward reference to this constant,
|
|
||||||
Value *OldV = ValueList[NextCstNo];
|
|
||||||
ValueList.setOperand(NextCstNo, V);
|
|
||||||
OldV->replaceAllUsesWith(V);
|
|
||||||
delete OldV;
|
|
||||||
}
|
|
||||||
|
|
||||||
++NextCstNo;
|
++NextCstNo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -998,6 +1005,8 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
|
|||||||
for(Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I)
|
for(Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I)
|
||||||
ValueList.push_back(I);
|
ValueList.push_back(I);
|
||||||
|
|
||||||
|
unsigned NextValueNo = ValueList.size();
|
||||||
|
|
||||||
// Read all the records.
|
// Read all the records.
|
||||||
SmallVector<uint64_t, 64> Record;
|
SmallVector<uint64_t, 64> Record;
|
||||||
while (1) {
|
while (1) {
|
||||||
@@ -1016,6 +1025,7 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
|
|||||||
break;
|
break;
|
||||||
case bitc::CONSTANTS_BLOCK_ID:
|
case bitc::CONSTANTS_BLOCK_ID:
|
||||||
if (ParseConstants()) return true;
|
if (ParseConstants()) return true;
|
||||||
|
NextValueNo = ValueList.size();
|
||||||
break;
|
break;
|
||||||
case bitc::VALUE_SYMTAB_BLOCK_ID:
|
case bitc::VALUE_SYMTAB_BLOCK_ID:
|
||||||
if (ParseValueSymbolTable()) return true;
|
if (ParseValueSymbolTable()) return true;
|
||||||
@@ -1031,19 +1041,115 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
|
|||||||
|
|
||||||
// Read a record.
|
// Read a record.
|
||||||
Record.clear();
|
Record.clear();
|
||||||
|
Instruction *I = 0;
|
||||||
|
BasicBlock *CurBB = 0;
|
||||||
|
unsigned CurBBNo = 0;
|
||||||
switch (Stream.ReadRecord(Code, Record)) {
|
switch (Stream.ReadRecord(Code, Record)) {
|
||||||
default: // Default behavior: unknown constant
|
default: // Default behavior: reject
|
||||||
|
return Error("Unknown instruction");
|
||||||
case bitc::FUNC_CODE_DECLAREBLOCKS: // DECLAREBLOCKS: [nblocks]
|
case bitc::FUNC_CODE_DECLAREBLOCKS: // DECLAREBLOCKS: [nblocks]
|
||||||
if (Record.size() < 1)
|
if (Record.size() < 1 || Record[0] == 0)
|
||||||
return Error("Invalid FUNC_CODE_DECLAREBLOCKS record");
|
return Error("Invalid DECLAREBLOCKS record");
|
||||||
// Create all the basic blocks for the function.
|
// Create all the basic blocks for the function.
|
||||||
FunctionBBs.resize(Record.size());
|
FunctionBBs.resize(Record.size());
|
||||||
for (unsigned i = 0, e = FunctionBBs.size(); i != e; ++i)
|
for (unsigned i = 0, e = FunctionBBs.size(); i != e; ++i)
|
||||||
FunctionBBs[i] = new BasicBlock("", F);
|
FunctionBBs[i] = new BasicBlock("", F);
|
||||||
|
CurBB = FunctionBBs[0];
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case bitc::FUNC_CODE_INST_BINOP: {
|
||||||
|
// BINOP: [opcode, ty, opval, opval]
|
||||||
|
if (Record.size() < 4) return Error("Invalid BINOP record");
|
||||||
|
const Type *Ty = getTypeByID(Record[1]);
|
||||||
|
int Opc = GetDecodedBinaryOpcode(Record[0], Ty);
|
||||||
|
Value *LHS = getFnValueByID(Record[2], Ty);
|
||||||
|
Value *RHS = getFnValueByID(Record[3], Ty);
|
||||||
|
if (Opc == -1 || Ty == 0 || LHS == 0 || RHS == 0)
|
||||||
|
return Error("Invalid BINOP record");
|
||||||
|
I = BinaryOperator::create((Instruction::BinaryOps)Opc, LHS, RHS);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
|
case bitc::FUNC_CODE_INST_CAST:
|
||||||
|
// CAST: [opcode, ty, opty, opval]
|
||||||
|
case bitc::FUNC_CODE_INST_GEP:
|
||||||
|
// GEP: [n, n x operands]
|
||||||
|
case bitc::FUNC_CODE_INST_SELECT:
|
||||||
|
// SELECT: [ty, opval, opval, opval]
|
||||||
|
case bitc::FUNC_CODE_INST_EXTRACTELT:
|
||||||
|
// EXTRACTELT: [opty, opval, opval]
|
||||||
|
case bitc::FUNC_CODE_INST_INSERTELT:
|
||||||
|
// INSERTELT: [ty, opval, opval, opval]
|
||||||
|
case bitc::FUNC_CODE_INST_SHUFFLEVEC:
|
||||||
|
// SHUFFLEVEC: [ty, opval, opval, opval]
|
||||||
|
case bitc::FUNC_CODE_INST_CMP:
|
||||||
|
// CMP: [opty, opval, opval, pred]
|
||||||
|
|
||||||
|
case bitc::FUNC_CODE_INST_RET:
|
||||||
|
// RET: [opty,opval<optional>]
|
||||||
|
case bitc::FUNC_CODE_INST_BR:
|
||||||
|
// BR: [opval, bb#, bb#] or [bb#]
|
||||||
|
case bitc::FUNC_CODE_INST_SWITCH:
|
||||||
|
// SWITCH: [opty, opval, n, n x ops]
|
||||||
|
case bitc::FUNC_CODE_INST_INVOKE:
|
||||||
|
// INVOKE: [fnty, op0,op1,op2, ...]
|
||||||
|
case bitc::FUNC_CODE_INST_UNWIND:
|
||||||
|
// UNWIND
|
||||||
|
case bitc::FUNC_CODE_INST_UNREACHABLE:
|
||||||
|
// UNREACHABLE
|
||||||
|
|
||||||
|
case bitc::FUNC_CODE_INST_PHI:
|
||||||
|
// PHI: [ty, #ops, val0,bb0, ...]
|
||||||
|
case bitc::FUNC_CODE_INST_MALLOC:
|
||||||
|
// MALLOC: [instty, op, align]
|
||||||
|
case bitc::FUNC_CODE_INST_FREE:
|
||||||
|
// FREE: [opty, op]
|
||||||
|
case bitc::FUNC_CODE_INST_ALLOCA:
|
||||||
|
// ALLOCA: [instty, op, align]
|
||||||
|
case bitc::FUNC_CODE_INST_LOAD:
|
||||||
|
// LOAD: [opty, op, align, vol]
|
||||||
|
case bitc::FUNC_CODE_INST_STORE:
|
||||||
|
// STORE: [ptrty,val,ptr, align, vol]
|
||||||
|
case bitc::FUNC_CODE_INST_CALL:
|
||||||
|
// CALL: [fnty, fnid, arg0, arg1...]
|
||||||
|
case bitc::FUNC_CODE_INST_VAARG:
|
||||||
|
// VAARG: [valistty, valist, instty]
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add instruction to end of current BB. If there is no current BB, reject
|
||||||
|
// this file.
|
||||||
|
if (CurBB == 0) {
|
||||||
|
delete I;
|
||||||
|
return Error("Invalid instruction with no BB");
|
||||||
|
}
|
||||||
|
CurBB->getInstList().push_back(I);
|
||||||
|
|
||||||
|
// If this was a terminator instruction, move to the next block.
|
||||||
|
if (isa<TerminatorInst>(I)) {
|
||||||
|
++CurBBNo;
|
||||||
|
CurBB = CurBBNo < FunctionBBs.size() ? FunctionBBs[CurBBNo] : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Non-void values get registered in the value table for future use.
|
||||||
|
if (I && I->getType() != Type::VoidTy)
|
||||||
|
ValueList.AssignValue(I, NextValueNo++);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the function list for unresolved values.
|
||||||
|
if (Argument *A = dyn_cast<Argument>(ValueList.back())) {
|
||||||
|
if (A->getParent() == 0) {
|
||||||
|
// We found at least one unresolved value. Nuke them all to avoid leaks.
|
||||||
|
for (unsigned i = ModuleValueListSize, e = ValueList.size(); i != e; ++i){
|
||||||
|
if ((A = dyn_cast<Argument>(ValueList.back())) && A->getParent() == 0) {
|
||||||
|
A->replaceAllUsesWith(UndefValue::get(A->getType()));
|
||||||
|
delete A;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Error("Never resolved value found in function!");
|
||||||
|
}
|
||||||
|
|
||||||
// Trim the value list down to the size it was before we parsed this function.
|
// Trim the value list down to the size it was before we parsed this function.
|
||||||
ValueList.shrinkTo(ModuleValueListSize);
|
ValueList.shrinkTo(ModuleValueListSize);
|
||||||
|
@@ -51,6 +51,22 @@ public:
|
|||||||
virtual void print(std::ostream&) const {}
|
virtual void print(std::ostream&) const {}
|
||||||
|
|
||||||
Constant *getConstantFwdRef(unsigned Idx, const Type *Ty);
|
Constant *getConstantFwdRef(unsigned Idx, const Type *Ty);
|
||||||
|
Value *getValueFwdRef(unsigned Idx, const Type *Ty);
|
||||||
|
|
||||||
|
void AssignValue(Value *V, unsigned Idx) {
|
||||||
|
if (Idx == size()) {
|
||||||
|
push_back(V);
|
||||||
|
} else if (Value *OldV = getOperand(Idx)) {
|
||||||
|
// If there was a forward reference to this value, replace it.
|
||||||
|
setOperand(Idx, V);
|
||||||
|
OldV->replaceAllUsesWith(V);
|
||||||
|
delete OldV;
|
||||||
|
} else {
|
||||||
|
initVal(Idx, V);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
void initVal(unsigned Idx, Value *V) {
|
void initVal(unsigned Idx, Value *V) {
|
||||||
assert(Uses[Idx] == 0 && "Cannot init an already init'd Use!");
|
assert(Uses[Idx] == 0 && "Cannot init an already init'd Use!");
|
||||||
Uses[Idx].init(V, this);
|
Uses[Idx].init(V, this);
|
||||||
@@ -113,6 +129,9 @@ public:
|
|||||||
bool ParseBitcode();
|
bool ParseBitcode();
|
||||||
private:
|
private:
|
||||||
const Type *getTypeByID(unsigned ID, bool isTypeTable = false);
|
const Type *getTypeByID(unsigned ID, bool isTypeTable = false);
|
||||||
|
Value *getFnValueByID(unsigned ID, const Type *Ty) {
|
||||||
|
return ValueList.getValueFwdRef(ID, Ty);
|
||||||
|
}
|
||||||
|
|
||||||
bool ParseModule(const std::string &ModuleID);
|
bool ParseModule(const std::string &ModuleID);
|
||||||
bool ParseTypeTable();
|
bool ParseTypeTable();
|
||||||
|
Reference in New Issue
Block a user