#include "llvm/DerivedTypes.h"
#include "llvm/iTerminators.h"
#include "llvm/iMemory.h"
-#include "llvm/Support/STLExtras.h"
-#include "llvm/Support/DepthFirstIterator.h"
+#include "Support/STLExtras.h"
+#include "Support/DepthFirstIterator.h"
#include <list>
#include <utility> // Get definition of pair class
#include <algorithm>
#include <stdio.h> // This embarasment is due to our flex lexer...
-int yyerror(const char *ErrorMsg); // Forward declarations to prevent "implicit
+int yyerror(const char *ErrorMsg); // Forward declarations to prevent "implicit
int yylex(); // declaration" of xxx warnings.
int yyparse();
// when the method is completed.
//
typedef vector<Value *> ValueList; // Numbered defs
-static void ResolveDefinitions(vector<ValueList> &LateResolvers);
+static void ResolveDefinitions(vector<ValueList> &LateResolvers,
+ vector<ValueList> *FutureLateResolvers = 0);
static void ResolveTypes (vector<PATypeHolder<Type> > &LateResolveTypes);
static struct PerModuleInfo {
Module *CurrentModule;
vector<ValueList> Values; // Module level numbered definitions
vector<ValueList> LateResolveValues;
- vector<PATypeHolder<Type> > Types, LateResolveTypes;
+ vector<PATypeHolder<Type> > Types;
+ map<ValID, PATypeHolder<Type> > LateResolveTypes;
+
+ // GlobalRefs - This maintains a mapping between <Type, ValID>'s and forward
+ // references to global values. Global values may be referenced before they
+ // are defined, and if so, the temporary object that they represent is held
+ // here. This is used for forward references of ConstPoolPointerRefs.
+ //
+ typedef map<pair<const PointerType *, ValID>, GlobalVariable*> GlobalRefsType;
+ GlobalRefsType GlobalRefs;
void ModuleDone() {
// If we could not resolve some methods at method compilation time (calls to
//
ResolveDefinitions(LateResolveValues);
+ // Check to make sure that all global value forward references have been
+ // resolved!
+ //
+ if (!GlobalRefs.empty()) {
+ // TODO: Make this more detailed! Loop over each undef value and print
+ // info
+ ThrowException("TODO: Make better error - Unresolved forward constant "
+ "references exist!");
+ }
+
Values.clear(); // Clear out method local definitions
Types.clear();
CurrentModule = 0;
}
+
+
+ // DeclareNewGlobalValue - Called every type a new GV has been defined. This
+ // is used to remove things from the forward declaration map, resolving them
+ // to the correct thing as needed.
+ //
+ void DeclareNewGlobalValue(GlobalValue *GV, ValID D) {
+ // Check to see if there is a forward reference to this global variable...
+ // if there is, eliminate it and patch the reference to use the new def'n.
+ GlobalRefsType::iterator I = GlobalRefs.find(make_pair(GV->getType(), D));
+
+ if (I != GlobalRefs.end()) {
+ GlobalVariable *OldGV = I->second; // Get the placeholder...
+ I->first.second.destroy(); // Free string memory if neccesary
+
+ // Loop over all of the uses of the GlobalValue. The only thing they are
+ // allowed to be at this point is ConstPoolPointerRef's.
+ assert(OldGV->use_size() == 1 && "Only one reference should exist!");
+ while (!OldGV->use_empty()) {
+ User *U = OldGV->use_back(); // Must be a ConstPoolPointerRef...
+ ConstPoolPointerRef *CPPR = cast<ConstPoolPointerRef>(U);
+ assert(CPPR->getValue() == OldGV && "Something isn't happy");
+
+ // Change the const pool reference to point to the real global variable
+ // now. This should drop a use from the OldGV.
+ CPPR->mutateReference(GV);
+ }
+
+ // Remove GV from the module...
+ CurrentModule->getGlobalList().remove(OldGV);
+ delete OldGV; // Delete the old placeholder
+
+ // Remove the map entry for the global now that it has been created...
+ GlobalRefs.erase(I);
+ }
+ }
+
} CurModule;
static struct PerMethodInfo {
vector<ValueList> Values; // Keep track of numbered definitions
vector<ValueList> LateResolveValues;
- vector<PATypeHolder<Type> > Types, LateResolveTypes;
+ vector<PATypeHolder<Type> > Types;
+ map<ValID, PATypeHolder<Type> > LateResolveTypes;
bool isDeclare; // Is this method a forward declararation?
inline PerMethodInfo() {
void MethodDone() {
// If we could not resolve some blocks at parsing time (forward branches)
// resolve the branches now...
- ResolveDefinitions(LateResolveValues);
+ ResolveDefinitions(LateResolveValues, &CurModule.LateResolveValues);
Values.clear(); // Clear out method local definitions
Types.clear();
} CurMeth; // Info for the current method...
static bool inMethodScope() { return CurMeth.CurrentMethod != 0; }
-static bool inModuleScope() { return CurMeth.CurrentMethod == 0; }
//===----------------------------------------------------------------------===//
// Code to handle definitions of all the types
//===----------------------------------------------------------------------===//
-static void InsertValue(Value *D, vector<ValueList> &ValueTab = CurMeth.Values){
- if (!D->hasName()) { // Is this a numbered definition?
- unsigned type = D->getType()->getUniqueID();
- if (ValueTab.size() <= type)
- ValueTab.resize(type+1, ValueList());
- //printf("Values[%d][%d] = %d\n", type, ValueTab[type].size(), D);
- ValueTab[type].push_back(D);
- }
+static int InsertValue(Value *D, vector<ValueList> &ValueTab = CurMeth.Values) {
+ if (D->hasName()) return -1; // Is this a numbered definition?
+
+ // Yes, insert the value into the value table...
+ unsigned type = D->getType()->getUniqueID();
+ if (ValueTab.size() <= type)
+ ValueTab.resize(type+1, ValueList());
+ //printf("Values[%d][%d] = %d\n", type, ValueTab[type].size(), D);
+ ValueTab[type].push_back(D);
+ return ValueTab[type].size()-1;
}
// TODO: FIXME when Type are not const
// Check that the number is within bounds...
if (Num <= CurMeth.Types.size())
return CurMeth.Types[Num];
+ break;
}
case 1: { // Is it a named definition?
string Name(D.Name);
//
if (DoNotImprovise) return 0; // Do we just want a null to be returned?
- vector<PATypeHolder<Type> > *LateResolver = inMethodScope() ?
- &CurMeth.LateResolveTypes : &CurModule.LateResolveTypes;
+ map<ValID, PATypeHolder<Type> > &LateResolver = inMethodScope() ?
+ CurMeth.LateResolveTypes : CurModule.LateResolveTypes;
+
+ map<ValID, PATypeHolder<Type> >::iterator I = LateResolver.find(D);
+ if (I != LateResolver.end()) {
+ return I->second;
+ }
- Type *Typ = new TypePlaceHolder(Type::TypeTy, D);
- InsertType(Typ, *LateResolver);
+ Type *Typ = OpaqueType::get();
+ LateResolver.insert(make_pair(D, Typ));
return Typ;
}
return N;
}
-static Value *getVal(const Type *Ty, const ValID &D,
- bool DoNotImprovise = false) {
- assert(Ty != Type::TypeTy && "Should use getTypeVal for types!");
+// getValNonImprovising - Look up the value specified by the provided type and
+// the provided ValID. If the value exists and has already been defined, return
+// it. Otherwise return null.
+//
+static Value *getValNonImprovising(const Type *Ty, const ValID &D) {
+ if (isa<MethodType>(Ty))
+ ThrowException("Methods are not values and must be referenced as pointers");
switch (D.Type) {
case ValID::NumberVal: { // Is it a numbered definition?
}
// Make sure that our type is within bounds
- if (CurMeth.Values.size() <= type)
- break;
+ if (CurMeth.Values.size() <= type) return 0;
// Check that the number is within bounds...
- if (CurMeth.Values[type].size() <= Num)
- break;
+ if (CurMeth.Values[type].size() <= Num) return 0;
return CurMeth.Values[type][Num];
}
+
case ValID::NameVal: { // Is it a named definition?
- string Name(D.Name);
- Value *N = lookupInSymbolTable(Ty, Name);
- if (N == 0) break;
+ Value *N = lookupInSymbolTable(Ty, string(D.Name));
+ if (N == 0) return 0;
D.destroy(); // Free old strdup'd memory...
return N;
}
- case ValID::ConstSIntVal: // Is it a constant pool reference??
+ // Check to make sure that "Ty" is an integral type, and that our
+ // value will fit into the specified type...
+ case ValID::ConstSIntVal: // Is it a constant pool reference??
+ if (Ty == Type::BoolTy) { // Special handling for boolean data
+ return ConstPoolBool::get(D.ConstPool64 != 0);
+ } else {
+ if (!ConstPoolSInt::isValueValidForType(Ty, D.ConstPool64))
+ ThrowException("Symbolic constant pool value '" +
+ itostr(D.ConstPool64) + "' is invalid for type '" +
+ Ty->getName() + "'!");
+ return ConstPoolSInt::get(Ty, D.ConstPool64);
+ }
+
case ValID::ConstUIntVal: // Is it an unsigned const pool reference?
- case ValID::ConstStringVal: // Is it a string const pool reference?
- case ValID::ConstFPVal: // Is it a floating point const pool reference?
- case ValID::ConstNullVal: { // Is it a null value?
- ConstPoolVal *CPV = 0;
-
- // Check to make sure that "Ty" is an integral type, and that our
- // value will fit into the specified type...
- switch (D.Type) {
- case ValID::ConstSIntVal:
- if (Ty == Type::BoolTy) { // Special handling for boolean data
- CPV = ConstPoolBool::get(D.ConstPool64 != 0);
- } else {
- if (!ConstPoolSInt::isValueValidForType(Ty, D.ConstPool64))
- ThrowException("Symbolic constant pool value '" +
- itostr(D.ConstPool64) + "' is invalid for type '" +
- Ty->getName() + "'!");
- CPV = ConstPoolSInt::get(Ty, D.ConstPool64);
+ if (!ConstPoolUInt::isValueValidForType(Ty, D.UConstPool64)) {
+ if (!ConstPoolSInt::isValueValidForType(Ty, D.ConstPool64)) {
+ ThrowException("Integral constant pool reference is invalid!");
+ } else { // This is really a signed reference. Transmogrify.
+ return ConstPoolSInt::get(Ty, D.ConstPool64);
}
- break;
- case ValID::ConstUIntVal:
- if (!ConstPoolUInt::isValueValidForType(Ty, D.UConstPool64)) {
- if (!ConstPoolSInt::isValueValidForType(Ty, D.ConstPool64)) {
- ThrowException("Integral constant pool reference is invalid!");
- } else { // This is really a signed reference. Transmogrify.
- CPV = ConstPoolSInt::get(Ty, D.ConstPool64);
- }
- } else {
- CPV = ConstPoolUInt::get(Ty, D.UConstPool64);
- }
- break;
- case ValID::ConstStringVal:
- cerr << "FIXME: TODO: String constants [sbyte] not implemented yet!\n";
- abort();
- break;
- case ValID::ConstFPVal:
- if (!ConstPoolFP::isValueValidForType(Ty, D.ConstPoolFP))
- ThrowException("FP constant invalid for type!!");
- CPV = ConstPoolFP::get(Ty, D.ConstPoolFP);
- break;
- case ValID::ConstNullVal:
- if (!Ty->isPointerType())
- ThrowException("Cannot create a a non pointer null!");
- CPV = ConstPoolPointer::getNull(cast<PointerType>(Ty));
- break;
- default:
- assert(0 && "Unhandled case!");
+ } else {
+ return ConstPoolUInt::get(Ty, D.UConstPool64);
}
- assert(CPV && "How did we escape creating a constant??");
- return CPV;
- } // End of case 2,3,4
+
+ case ValID::ConstStringVal: // Is it a string const pool reference?
+ cerr << "FIXME: TODO: String constants [sbyte] not implemented yet!\n";
+ abort();
+ return 0;
+
+ case ValID::ConstFPVal: // Is it a floating point const pool reference?
+ if (!ConstPoolFP::isValueValidForType(Ty, D.ConstPoolFP))
+ ThrowException("FP constant invalid for type!!");
+ return ConstPoolFP::get(Ty, D.ConstPoolFP);
+
+ case ValID::ConstNullVal: // Is it a null value?
+ if (!Ty->isPointerType())
+ ThrowException("Cannot create a a non pointer null!");
+ return ConstPoolPointerNull::get(cast<PointerType>(Ty));
+
default:
assert(0 && "Unhandled case!");
+ return 0;
} // End of switch
+ assert(0 && "Unhandled case!");
+ return 0;
+}
+
+
+// getVal - This function is identical to getValNonImprovising, except that if a
+// value is not already defined, it "improvises" by creating a placeholder var
+// that looks and acts just like the requested variable. When the value is
+// defined later, all uses of the placeholder variable are replaced with the
+// real thing.
+//
+static Value *getVal(const Type *Ty, const ValID &D) {
+ assert(Ty != Type::TypeTy && "Should use getTypeVal for types!");
+
+ // See if the value has already been defined...
+ Value *V = getValNonImprovising(Ty, D);
+ if (V) return V;
// If we reached here, we referenced either a symbol that we don't know about
// or an id number that hasn't been read yet. We may be referencing something
// forward, so just create an entry to be resolved later and get to it...
//
- if (DoNotImprovise) return 0; // Do we just want a null to be returned?
-
Value *d = 0;
- vector<ValueList> *LateResolver = inMethodScope() ?
- &CurMeth.LateResolveValues : &CurModule.LateResolveValues;
-
- if (isa<MethodType>(Ty))
- ThrowException("Methods are not values and must be referenced as pointers");
-
- if (const PointerType *PTy = dyn_cast<PointerType>(Ty))
- if (const MethodType *MTy = dyn_cast<MethodType>(PTy->getValueType()))
- Ty = MTy; // Convert pointer to method to method type
-
switch (Ty->getPrimitiveID()) {
case Type::LabelTyID: d = new BBPlaceHolder(Ty, D); break;
- case Type::MethodTyID: d = new MethPlaceHolder(Ty, D);
- LateResolver = &CurModule.LateResolveValues; break;
default: d = new ValuePlaceHolder(Ty, D); break;
}
assert(d != 0 && "How did we not make something?");
- InsertValue(d, *LateResolver);
+ if (inMethodScope())
+ InsertValue(d, CurMeth.LateResolveValues);
+ else
+ InsertValue(d, CurModule.LateResolveValues);
return d;
}
// time (forward branches, phi functions for loops, etc...) resolve the
// defs now...
//
-static void ResolveDefinitions(vector<ValueList> &LateResolvers) {
+static void ResolveDefinitions(vector<ValueList> &LateResolvers,
+ vector<ValueList> *FutureLateResolvers = 0) {
// Loop over LateResolveDefs fixing up stuff that couldn't be resolved
for (unsigned ty = 0; ty < LateResolvers.size(); ty++) {
while (!LateResolvers[ty].empty()) {
Value *V = LateResolvers[ty].back();
+ assert(!isa<Type>(V) && "Types should be in LateResolveTypes!");
+
LateResolvers[ty].pop_back();
ValID &DID = getValIDFromPlaceHolder(V);
- Value *TheRealValue = getVal(Type::getUniqueIDType(ty), DID, true);
-
- if (TheRealValue == 0) {
+ Value *TheRealValue = getValNonImprovising(Type::getUniqueIDType(ty),DID);
+ if (TheRealValue) {
+ V->replaceAllUsesWith(TheRealValue);
+ delete V;
+ } else if (FutureLateResolvers) {
+ // Methods have their unresolved items forwarded to the module late
+ // resolver table
+ InsertValue(V, *FutureLateResolvers);
+ } else {
if (DID.Type == 1)
ThrowException("Reference to an invalid definition: '" +DID.getName()+
"' of type '" + V->getType()->getDescription() + "'",
V->getType()->getDescription() + "'",
getLineNumFromPlaceHolder(V));
}
-
- assert(!isa<Type>(V) && "Types should be in LateResolveTypes!");
-
- V->replaceAllUsesWith(TheRealValue);
- delete V;
}
}
ValID &DID = getValIDFromPlaceHolder(Ty);
const Type *TheRealType = getTypeVal(DID, true);
- if (TheRealType == 0) return true;
+ if (TheRealType == 0 || TheRealType == Ty) return true;
// Refine the opaque type we had to the new type we are getting.
cast<DerivedType>(Ty)->refineAbstractTypeTo(TheRealType);
return false;
}
-
-// ResolveTypes - This goes through the forward referenced type table and makes
-// sure that all type references are complete. This code is executed after the
-// constant pool of a method or module is completely parsed.
+// ResolveTypeTo - A brand new type was just declared. This means that (if
+// name is not null) things referencing Name can be resolved. Otherwise, things
+// refering to the number can be resolved. Do this now.
//
-static void ResolveTypes(vector<PATypeHolder<Type> > &LateResolveTypes) {
- while (!LateResolveTypes.empty()) {
- if (ResolveType(LateResolveTypes.back())) {
- const Type *Ty = LateResolveTypes.back();
- ValID &DID = getValIDFromPlaceHolder(Ty);
-
- if (DID.Type == ValID::NameVal)
- ThrowException("Reference to an invalid type: '" +DID.getName(),
- getLineNumFromPlaceHolder(Ty));
- else
- ThrowException("Reference to an invalid type: #" + itostr(DID.Num),
- getLineNumFromPlaceHolder(Ty));
- }
+static void ResolveTypeTo(char *Name, const Type *ToTy) {
+ vector<PATypeHolder<Type> > &Types = inMethodScope() ?
+ CurMeth.Types : CurModule.Types;
- // No need to delete type, refine does that for us.
- LateResolveTypes.pop_back();
- }
-}
+ ValID D;
+ if (Name) D = ValID::create(Name);
+ else D = ValID::create((int)Types.size());
+ map<ValID, PATypeHolder<Type> > &LateResolver = inMethodScope() ?
+ CurMeth.LateResolveTypes : CurModule.LateResolveTypes;
+
+ map<ValID, PATypeHolder<Type> >::iterator I = LateResolver.find(D);
+ if (I != LateResolver.end()) {
+ cast<DerivedType>(I->second.get())->refineAbstractTypeTo(ToTy);
+ LateResolver.erase(I);
+ }
+}
-// ResolveSomeTypes - This goes through the forward referenced type table and
-// completes references that are now done. This is so that types are
-// immediately resolved to be as concrete as possible. This does not cause
-// thrown exceptions if not everything is resolved.
+// ResolveTypes - At this point, all types should be resolved. Any that aren't
+// are errors.
//
-static void ResolveSomeTypes(vector<PATypeHolder<Type> > &LateResolveTypes) {
- for (unsigned i = 0; i < LateResolveTypes.size(); ) {
- if (ResolveType(LateResolveTypes[i]))
- ++i; // Type didn't resolve
+static void ResolveTypes(map<ValID, PATypeHolder<Type> > &LateResolveTypes) {
+ if (!LateResolveTypes.empty()) {
+ const ValID &DID = LateResolveTypes.begin()->first;
+
+ if (DID.Type == ValID::NameVal)
+ ThrowException("Reference to an invalid type: '" +DID.getName() + "'");
else
- LateResolveTypes.erase(LateResolveTypes.begin()+i); // Type resolved!
+ ThrowException("Reference to an invalid type: #" + itostr(DID.Num));
}
}
//
static bool setValueName(Value *V, char *NameStr) {
if (NameStr == 0) return false;
+
string Name(NameStr); // Copy string
free(NameStr); // Free old string
+ if (V->getType() == Type::VoidTy)
+ ThrowException("Can't assign name '" + Name +
+ "' to a null valued instruction!");
+
SymbolTable *ST = inMethodScope() ?
CurMeth.CurrentMethod->getSymbolTableSure() :
CurModule.CurrentModule->getSymbolTableSure();
// cerr << "Type: " << Ty->getDescription() << " != "
// << cast<const Type>(V)->getDescription() << "!\n";
} else if (GlobalVariable *EGV = dyn_cast<GlobalVariable>(Existing)) {
- GlobalVariable *GV = cast<GlobalVariable>(V);
-
// We are allowed to redefine a global variable in two circumstances:
// 1. If at least one of the globals is uninitialized or
// 2. If both initializers have the same value.
//
// This can only be done if the const'ness of the vars is the same.
//
- if (EGV->isConstant() == GV->isConstant() &&
- (!EGV->hasInitializer() || !GV->hasInitializer() ||
- EGV->getInitializer() == GV->getInitializer())) {
-
- // Make sure the existing global version gets the initializer!
- if (GV->hasInitializer() && !EGV->hasInitializer())
- EGV->setInitializer(GV->getInitializer());
-
- return true; // They are equivalent!
+ if (GlobalVariable *GV = dyn_cast<GlobalVariable>(V)) {
+ if (EGV->isConstant() == GV->isConstant() &&
+ (!EGV->hasInitializer() || !GV->hasInitializer() ||
+ EGV->getInitializer() == GV->getInitializer())) {
+
+ // Make sure the existing global version gets the initializer!
+ if (GV->hasInitializer() && !EGV->hasInitializer())
+ EGV->setInitializer(GV->getInitializer());
+
+ delete GV; // Destroy the duplicate!
+ return true; // They are equivalent!
+ }
}
-
}
- ThrowException("Redefinition of value name '" + Name + "' in the '" +
+ ThrowException("Redefinition of value named '" + Name + "' in the '" +
V->getType()->getDescription() + "' type plane!");
}
static PATypeHolder<Type> HandleUpRefs(const Type *ty) {
PATypeHolder<Type> Ty(ty);
- UR_OUT(UpRefs.size() << " upreferences active!\n");
+ UR_OUT("Type '" << ty->getDescription() <<
+ "' newly formed. Resolving upreferences.\n" <<
+ UpRefs.size() << " upreferences active!\n");
for (unsigned i = 0; i < UpRefs.size(); ) {
- UR_OUT("TypeContains(" << Ty->getDescription() << ", "
+ UR_OUT(" UR#" << i << " - TypeContains(" << Ty->getDescription() << ", "
<< UpRefs[i].second->getDescription() << ") = "
- << TypeContains(Ty, UpRefs[i].second) << endl);
+ << (TypeContains(Ty, UpRefs[i].second) ? "true" : "false") << endl);
if (TypeContains(Ty, UpRefs[i].second)) {
unsigned Level = --UpRefs[i].first; // Decrement level of upreference
- UR_OUT("Uplevel Ref Level = " << Level << endl);
+ UR_OUT(" Uplevel Ref Level = " << Level << endl);
if (Level == 0) { // Upreference should be resolved!
- UR_OUT("About to resolve upreference!\n";
+ UR_OUT(" * Resolving upreference for "
+ << UpRefs[i].second->getDescription() << endl;
string OldName = UpRefs[i].second->getDescription());
UpRefs[i].second->refineAbstractTypeTo(Ty);
UpRefs.erase(UpRefs.begin()+i); // Remove from upreference list...
- UR_OUT("Type '" << OldName << "' refined upreference to: "
+ UR_OUT(" * Type '" << OldName << "' refined upreference to: "
<< (const void*)Ty << ", " << Ty->getDescription() << endl);
continue;
}
Value *ValueVal;
list<MethodArgument*> *MethodArgList;
- list<Value*> *ValueList;
+ vector<Value*> *ValueList;
list<PATypeHolder<Type> > *TypeList;
list<pair<Value*, BasicBlock*> > *PHIList; // Represent the RHS of PHI node
list<pair<ConstPoolVal*, BasicBlock*> > *JumpTable;
%type <TermInstVal> BBTerminatorInst
%type <InstVal> Inst InstVal MemoryInst
%type <ConstVal> ConstVal
-%type <ConstVector> ConstVector UByteList
+%type <ConstVector> ConstVector
%type <MethodArgList> ArgList ArgListH
%type <MethArgVal> ArgVal
%type <PHIList> PHIList
%type <ValueList> ValueRefList ValueRefListE // For call param lists
+%type <ValueList> IndexList // For GEP derived indices
%type <TypeList> TypeListI ArgTypeListI
%type <JumpTable> JumpTable
-%type <BoolVal> GlobalType // GLOBAL or CONSTANT?
+%type <BoolVal> GlobalType OptInternal // GLOBAL or CONSTANT? Intern?
-%type <ValIDVal> ValueRef ConstValueRef // Reference to a definition or BB
+// ValueRef - Unresolved reference to a definition or BB
+%type <ValIDVal> ValueRef ConstValueRef SymbolicValueRef
%type <ValueVal> ResolvedVal // <type> <valref> pair
// Tokens and types for handling constant integer values
//
%token IMPLEMENTATION TRUE FALSE BEGINTOK END DECLARE GLOBAL CONSTANT UNINIT
-%token TO DOTDOTDOT STRING NULL_TOK CONST
+%token TO EXCEPT DOTDOTDOT STRING NULL_TOK CONST INTERNAL
// Basic Block Terminating Operators
%token <TermOpVal> RET BR SWITCH
// Binary Operators
%type <BinaryOpVal> BinaryOps // all the binary operators
-%token <BinaryOpVal> ADD SUB MUL DIV REM
+%token <BinaryOpVal> ADD SUB MUL DIV REM AND OR XOR
%token <BinaryOpVal> SETLE SETGE SETLT SETGT SETEQ SETNE // Binary Comarators
// Memory Instructions
// Other Operators
%type <OtherOpVal> ShiftOps
-%token <OtherOpVal> PHI CALL CAST SHL SHR
+%token <OtherOpVal> PHI CALL INVOKE CAST SHL SHR
%start Module
%%
// RET, BR, & SWITCH because they end basic blocks and are treated specially.
//
UnaryOps : NOT
-BinaryOps : ADD | SUB | MUL | DIV | REM
+BinaryOps : ADD | SUB | MUL | DIV | REM | AND | OR | XOR
BinaryOps : SETLE | SETGE | SETLT | SETGT | SETEQ | SETNE
ShiftOps : SHL | SHR
$$ = 0;
}
+OptInternal : INTERNAL { $$ = true; } | /*empty*/ { $$ = false; }
//===----------------------------------------------------------------------===//
// Types includes all predefined types... except void, because it can only be
vector<const Type*> Params;
mapto($3->begin(), $3->end(), back_inserter(Params),
mem_fun_ref(&PATypeHandle<Type>::get));
- $$ = newTH(HandleUpRefs(MethodType::get(*$1, Params)));
+ bool isVarArg = Params.size() && Params.back() == Type::VoidTy;
+ if (isVarArg) Params.pop_back();
+
+ $$ = newTH(HandleUpRefs(MethodType::get(*$1, Params, isVarArg)));
delete $3; // Delete the argument list
delete $1; // Delete the old type handle
}
ThrowException("Cannot make null pointer constant with type: '" +
(*$1)->getDescription() + "'!");
- $$ = ConstPoolPointer::getNull(PTy);
+ $$ = ConstPoolPointerNull::get(PTy);
delete $1;
}
- | Types VAR_ID {
- string Name($2); free($2); // Change to a responsible mem manager
+ | Types SymbolicValueRef {
const PointerType *Ty = dyn_cast<const PointerType>($1->get());
if (Ty == 0)
ThrowException("Global const reference must be a pointer type!");
- Value *N = lookupInSymbolTable(Ty, Name);
- if (N == 0)
- ThrowException("Global pointer reference '%" + Name +
- "' must be defined before use!");
+ Value *V = getValNonImprovising(Ty, $2);
- // TODO FIXME: This should also allow methods... when common baseclass
- // exists
- if (GlobalVariable *GV = dyn_cast<GlobalVariable>(N)) {
- $$ = ConstPoolPointerReference::get(GV);
- } else {
- ThrowException("'%" + Name + "' is not a global value reference!");
+ // If this is an initializer for a constant pointer, which is referencing a
+ // (currently) undefined variable, create a stub now that shall be replaced
+ // in the future with the right type of variable.
+ //
+ if (V == 0) {
+ assert(isa<PointerType>(Ty) && "Globals may only be used as pointers!");
+ const PointerType *PT = cast<PointerType>(Ty);
+
+ // First check to see if the forward references value is already created!
+ PerModuleInfo::GlobalRefsType::iterator I =
+ CurModule.GlobalRefs.find(make_pair(PT, $2));
+
+ if (I != CurModule.GlobalRefs.end()) {
+ V = I->second; // Placeholder already exists, use it...
+ } else {
+ // TODO: Include line number info by creating a subclass of
+ // TODO: GlobalVariable here that includes the said information!
+
+ // Create a placeholder for the global variable reference...
+ GlobalVariable *GV = new GlobalVariable(PT->getValueType(), false,true);
+ // Keep track of the fact that we have a forward ref to recycle it
+ CurModule.GlobalRefs.insert(make_pair(make_pair(PT, $2), GV));
+
+ // Must temporarily push this value into the module table...
+ CurModule.CurrentModule->getGlobalList().push_back(GV);
+ V = GV;
+ }
}
- delete $1;
+ GlobalValue *GV = cast<GlobalValue>(V);
+ $$ = ConstPoolPointerRef::get(GV);
+ delete $1; // Free the type handle
}
InsertValue($4);
}
| ConstPool OptAssign TYPE TypesV { // Types can be defined in the const pool
+ // Eagerly resolve types. This is not an optimization, this is a
+ // requirement that is due to the fact that we could have this:
+ //
+ // %list = type { %list * }
+ // %list = type { %list * } ; repeated type decl
+ //
+ // If types are not resolved eagerly, then the two types will not be
+ // determined to be the same type!
+ //
+ ResolveTypeTo($2, $4->get());
+
// TODO: FIXME when Type are not const
if (!setValueName(const_cast<Type*>($4->get()), $2)) {
// If this is not a redefinition of a type...
InsertType($4->get(),
inMethodScope() ? CurMeth.Types : CurModule.Types);
}
- delete $4;
-
- ResolveSomeTypes(inMethodScope() ? CurMeth.LateResolveTypes :
- CurModule.LateResolveTypes);
}
+
+ delete $4;
}
| ConstPool MethodProto { // Method prototypes can be in const pool
}
- | ConstPool OptAssign GlobalType ConstVal {
- const Type *Ty = $4->getType();
+ | ConstPool OptAssign OptInternal GlobalType ConstVal {
+ const Type *Ty = $5->getType();
// Global declarations appear in Constant Pool
- ConstPoolVal *Initializer = $4;
+ ConstPoolVal *Initializer = $5;
if (Initializer == 0)
ThrowException("Global value initializer is not a constant!");
- GlobalVariable *GV = new GlobalVariable(Ty, $3, Initializer);
+ GlobalVariable *GV = new GlobalVariable(Ty, $4, $3, Initializer);
if (!setValueName(GV, $2)) { // If not redefining...
CurModule.CurrentModule->getGlobalList().push_back(GV);
- InsertValue(GV, CurModule.Values);
+ int Slot = InsertValue(GV, CurModule.Values);
+
+ if (Slot != -1) {
+ CurModule.DeclareNewGlobalValue(GV, ValID::create(Slot));
+ } else {
+ CurModule.DeclareNewGlobalValue(GV, ValID::create(
+ (char*)GV->getName().c_str()));
+ }
}
}
- | ConstPool OptAssign UNINIT GlobalType Types {
- const Type *Ty = *$5;
+ | ConstPool OptAssign OptInternal UNINIT GlobalType Types {
+ const Type *Ty = *$6;
// Global declarations appear in Constant Pool
- if (isa<ArrayType>(Ty) && cast<ArrayType>(Ty)->isUnsized()) {
- ThrowException("Type '" + Ty->getDescription() +
- "' is not a sized type!");
- }
-
- GlobalVariable *GV = new GlobalVariable(Ty, $4);
+ GlobalVariable *GV = new GlobalVariable(Ty, $5, $3);
if (!setValueName(GV, $2)) { // If not redefining...
CurModule.CurrentModule->getGlobalList().push_back(GV);
- InsertValue(GV, CurModule.Values);
+ int Slot = InsertValue(GV, CurModule.Values);
+
+ if (Slot != -1) {
+ CurModule.DeclareNewGlobalValue(GV, ValID::create(Slot));
+ } else {
+ assert(GV->hasName() && "Not named and not numbered!?");
+ CurModule.DeclareNewGlobalValue(GV, ValID::create(
+ (char*)GV->getName().c_str()));
+ }
}
}
| /* empty: end of list */ {
}
| DOTDOTDOT {
$$ = new list<MethodArgument*>();
- $$->push_back(new MethodArgument(Type::VoidTy));
+ $$->push_front(new MethodArgument(Type::VoidTy));
}
ArgList : ArgListH {
$$ = 0;
}
-MethodHeaderH : TypesV STRINGCONSTANT '(' ArgList ')' {
- UnEscapeLexed($2);
+MethodHeaderH : OptInternal TypesV STRINGCONSTANT '(' ArgList ')' {
+ UnEscapeLexed($3);
+ string MethodName($3);
+
vector<const Type*> ParamTypeList;
- if ($4)
- for (list<MethodArgument*>::iterator I = $4->begin(); I != $4->end(); ++I)
+ if ($5)
+ for (list<MethodArgument*>::iterator I = $5->begin(); I != $5->end(); ++I)
ParamTypeList.push_back((*I)->getType());
- const MethodType *MT = MethodType::get(*$1, ParamTypeList);
+ bool isVarArg = ParamTypeList.size() && ParamTypeList.back() == Type::VoidTy;
+ if (isVarArg) ParamTypeList.pop_back();
+
+ const MethodType *MT = MethodType::get(*$2, ParamTypeList, isVarArg);
const PointerType *PMT = PointerType::get(MT);
- delete $1;
+ delete $2;
Method *M = 0;
if (SymbolTable *ST = CurModule.CurrentModule->getSymbolTable()) {
- if (Value *V = ST->lookup(PMT, $2)) { // Method already in symtab?
+ if (Value *V = ST->lookup(PMT, MethodName)) { // Method already in symtab?
M = cast<Method>(V);
// Yes it is. If this is the case, either we need to be a forward decl,
// or it needs to be.
if (!CurMeth.isDeclare && !M->isExternal())
- ThrowException("Redefinition of method '" + string($2) + "'!");
+ ThrowException("Redefinition of method '" + MethodName + "'!");
}
}
if (M == 0) { // Not already defined?
- M = new Method(MT, $2);
+ M = new Method(MT, $1, MethodName);
InsertValue(M, CurModule.Values);
+ CurModule.DeclareNewGlobalValue(M, ValID::create($3));
}
-
- free($2); // Free strdup'd memory!
+ free($3); // Free strdup'd memory!
CurMeth.MethodStart(M);
// Add all of the arguments we parsed to the method...
- if ($4 && !CurMeth.isDeclare) { // Is null if empty...
+ if ($5 && !CurMeth.isDeclare) { // Is null if empty...
Method::ArgumentListType &ArgList = M->getArgumentList();
- for (list<MethodArgument*>::iterator I = $4->begin(); I != $4->end(); ++I) {
+ for (list<MethodArgument*>::iterator I = $5->begin(); I != $5->end(); ++I) {
InsertValue(*I);
ArgList.push_back(*I);
}
- delete $4; // We're now done with the argument list
+ delete $5; // We're now done with the argument list
}
}
}
*/
-// ValueRef - A reference to a definition...
-ValueRef : INTVAL { // Is it an integer reference...?
+// SymbolicValueRef - Reference to one of two ways of symbolically refering to
+// another value.
+//
+SymbolicValueRef : INTVAL { // Is it an integer reference...?
$$ = ValID::create($1);
}
| VAR_ID { // Is it a named reference...?
$$ = ValID::create($1);
}
- | ConstValueRef {
- $$ = $1;
- }
+
+// ValueRef - A reference to a definition... either constant or symbolic
+ValueRef : SymbolicValueRef | ConstValueRef
+
// ResolvedVal - a <type> <value> pair. This is used only in cases where the
// type immediately preceeds the value reference, and allows complex constant
BasicBlockList : BasicBlockList BasicBlock {
- $1->getBasicBlocks().push_back($2);
- $$ = $1;
+ ($$ = $1)->getBasicBlocks().push_back($2);
}
| MethodHeader BasicBlock { // Do not allow methods with 0 basic blocks
- $$ = $1; // in them...
- $1->getBasicBlocks().push_back($2);
+ ($$ = $1)->getBasicBlocks().push_back($2);
}
// Basic blocks are terminated by branching instructions:
// br, br/cc, switch, ret
//
-BasicBlock : InstructionList BBTerminatorInst {
- $1->getInstList().push_back($2);
+BasicBlock : InstructionList OptAssign BBTerminatorInst {
+ if (setValueName($3, $2)) { assert(0 && "No redefn allowed!"); }
+ InsertValue($3);
+
+ $1->getInstList().push_back($3);
InsertValue($1);
$$ = $1;
}
- | LABELSTR InstructionList BBTerminatorInst {
- $2->getInstList().push_back($3);
+ | LABELSTR InstructionList OptAssign BBTerminatorInst {
+ if (setValueName($4, $3)) { assert(0 && "No redefn allowed!"); }
+ InsertValue($4);
+
+ $2->getInstList().push_back($4);
if (setValueName($2, $1)) { assert(0 && "No label redef allowed!"); }
InsertValue($2);
for (; I != end; ++I)
S->dest_push_back(I->first, I->second);
}
+ | INVOKE TypesV ValueRef '(' ValueRefListE ')' TO ResolvedVal
+ EXCEPT ResolvedVal {
+ const PointerType *PMTy;
+ const MethodType *Ty;
+
+ if (!(PMTy = dyn_cast<PointerType>($2->get())) ||
+ !(Ty = dyn_cast<MethodType>(PMTy->getValueType()))) {
+ // Pull out the types of all of the arguments...
+ vector<const Type*> ParamTypes;
+ if ($5) {
+ for (vector<Value*>::iterator I = $5->begin(), E = $5->end(); I!=E; ++I)
+ ParamTypes.push_back((*I)->getType());
+ }
+
+ bool isVarArg = ParamTypes.size() && ParamTypes.back() == Type::VoidTy;
+ if (isVarArg) ParamTypes.pop_back();
+
+ Ty = MethodType::get($2->get(), ParamTypes, isVarArg);
+ PMTy = PointerType::get(Ty);
+ }
+ delete $2;
+
+ Value *V = getVal(PMTy, $3); // Get the method we're calling...
+
+ BasicBlock *Normal = dyn_cast<BasicBlock>($8);
+ BasicBlock *Except = dyn_cast<BasicBlock>($10);
+
+ if (Normal == 0 || Except == 0)
+ ThrowException("Invoke instruction without label destinations!");
+
+ // Create the call node...
+ if (!$5) { // Has no arguments?
+ $$ = new InvokeInst(V, Normal, Except, vector<Value*>());
+ } else { // Has arguments?
+ // Loop through MethodType's arguments and ensure they are specified
+ // correctly!
+ //
+ MethodType::ParamTypes::const_iterator I = Ty->getParamTypes().begin();
+ MethodType::ParamTypes::const_iterator E = Ty->getParamTypes().end();
+ vector<Value*>::iterator ArgI = $5->begin(), ArgE = $5->end();
+
+ for (; ArgI != ArgE && I != E; ++ArgI, ++I)
+ if ((*ArgI)->getType() != *I)
+ ThrowException("Parameter " +(*ArgI)->getName()+ " is not of type '" +
+ (*I)->getName() + "'!");
+
+ if (I != E || (ArgI != ArgE && !Ty->isVarArg()))
+ ThrowException("Invalid number of parameters detected!");
+
+ $$ = new InvokeInst(V, Normal, Except, *$5);
+ }
+ delete $5;
+ }
+
+
JumpTable : JumpTable IntType ConstValueRef ',' LABEL ValueRef {
$$ = $1;
- ConstPoolVal *V = cast<ConstPoolVal>(getVal($2, $3, true));
+ ConstPoolVal *V = cast<ConstPoolVal>(getValNonImprovising($2, $3));
if (V == 0)
ThrowException("May only switch on a constant pool value!");
}
| IntType ConstValueRef ',' LABEL ValueRef {
$$ = new list<pair<ConstPoolVal*, BasicBlock*> >();
- ConstPoolVal *V = cast<ConstPoolVal>(getVal($1, $2, true));
+ ConstPoolVal *V = cast<ConstPoolVal>(getValNonImprovising($1, $2));
if (V == 0)
ThrowException("May only switch on a constant pool value!");
ValueRefList : ResolvedVal { // Used for call statements, and memory insts...
- $$ = new list<Value*>();
+ $$ = new vector<Value*>();
$$->push_back($1);
}
| ValueRefList ',' ResolvedVal {
// Pull out the types of all of the arguments...
vector<const Type*> ParamTypes;
if ($5) {
- for (list<Value*>::iterator I = $5->begin(), E = $5->end(); I != E; ++I)
+ for (vector<Value*>::iterator I = $5->begin(), E = $5->end(); I!=E; ++I)
ParamTypes.push_back((*I)->getType());
}
- Ty = MethodType::get($2->get(), ParamTypes);
+
+ bool isVarArg = ParamTypes.size() && ParamTypes.back() == Type::VoidTy;
+ if (isVarArg) ParamTypes.pop_back();
+
+ Ty = MethodType::get($2->get(), ParamTypes, isVarArg);
PMTy = PointerType::get(Ty);
}
delete $2;
// Create the call node...
if (!$5) { // Has no arguments?
- $$ = new CallInst(cast<Method>(V), vector<Value*>());
+ $$ = new CallInst(V, vector<Value*>());
} else { // Has arguments?
// Loop through MethodType's arguments and ensure they are specified
// correctly!
//
MethodType::ParamTypes::const_iterator I = Ty->getParamTypes().begin();
MethodType::ParamTypes::const_iterator E = Ty->getParamTypes().end();
- list<Value*>::iterator ArgI = $5->begin(), ArgE = $5->end();
+ vector<Value*>::iterator ArgI = $5->begin(), ArgE = $5->end();
for (; ArgI != ArgE && I != E; ++ArgI, ++I)
if ((*ArgI)->getType() != *I)
if (I != E || (ArgI != ArgE && !Ty->isVarArg()))
ThrowException("Invalid number of parameters detected!");
- $$ = new CallInst(cast<Method>(V),
- vector<Value*>($5->begin(), $5->end()));
+ $$ = new CallInst(V, *$5);
}
delete $5;
}
$$ = $1;
}
-// UByteList - List of ubyte values for load and store instructions
-UByteList : ',' ConstVector {
+
+// IndexList - List of indices for GEP based instructions...
+IndexList : ',' ValueRefList {
$$ = $2;
} | /* empty */ {
- $$ = new vector<ConstPoolVal*>();
+ $$ = new vector<Value*>();
}
MemoryInst : MALLOC Types {
$$ = new FreeInst($2);
}
- | LOAD Types ValueRef UByteList {
+ | LOAD Types ValueRef IndexList {
if (!(*$2)->isPointerType())
- ThrowException("Can't load from nonpointer type: " + (*$2)->getName());
+ ThrowException("Can't load from nonpointer type: " +
+ (*$2)->getDescription());
if (LoadInst::getIndexedType(*$2, *$4) == 0)
ThrowException("Invalid indices for load instruction!");
delete $4; // Free the vector...
delete $2;
}
- | STORE ResolvedVal ',' Types ValueRef UByteList {
+ | STORE ResolvedVal ',' Types ValueRef IndexList {
if (!(*$4)->isPointerType())
ThrowException("Can't store to a nonpointer type: " + (*$4)->getName());
const Type *ElTy = StoreInst::getIndexedType(*$4, *$6);
$$ = new StoreInst($2, getVal(*$4, $5), *$6);
delete $4; delete $6;
}
- | GETELEMENTPTR Types ValueRef UByteList {
+ | GETELEMENTPTR Types ValueRef IndexList {
if (!(*$2)->isPointerType())
ThrowException("getelementptr insn requires pointer operand!");
if (!GetElementPtrInst::getIndexedType(*$2, *$4, true))