From 25f4cd093b5e7f2dc39d21891c211ed3e65c17af Mon Sep 17 00:00:00 2001 From: Reid Spencer Date: Tue, 2 Jan 2007 05:44:33 +0000 Subject: [PATCH] For PR1070: Revise the upgrade parser to keep track of types more faithfully and use this information to resolve name conflicts resulting from collapsed type planes. The type planes have collapsed because the integer types are now signless so that uint and int became i32. Where two planes existed for uint and int, only i32 exists. Any variable names depending on the type planes to pmake the identifier unique would cause a conflict. This patch resolves that conflict for many but not all cases. Situations involving the integer types and pointers to them are handled by this patch. However, there are corner cases that are not handled well, such as: %t1 = type { uint, int } %t2 = type { int, uint } void %myfunc(%t1* one, %t2* two) { %var = load %t1* one %var = load %t2* two } In the scenario above, %t1 and %t2 are really the same type: { i32, i32 } Consequently attempting to name %var twice will yield a redefinition error when assembled. While this patch is sufficien to allow the llvm/test suite to pass, More work needs to be to complete the handling of these corner cases. llvm-svn: 32810 --- llvm/tools/llvm-upgrade/ParserInternals.h | 177 +++++- llvm/tools/llvm-upgrade/UpgradeLexer.l | 4 +- llvm/tools/llvm-upgrade/UpgradeParser.y | 699 +++++++++++++--------- 3 files changed, 565 insertions(+), 315 deletions(-) diff --git a/llvm/tools/llvm-upgrade/ParserInternals.h b/llvm/tools/llvm-upgrade/ParserInternals.h index 85182c5dc192..9de3588f8c8f 100644 --- a/llvm/tools/llvm-upgrade/ParserInternals.h +++ b/llvm/tools/llvm-upgrade/ParserInternals.h @@ -15,9 +15,11 @@ #ifndef PARSER_INTERNALS_H #define PARSER_INTERNALS_H +#include #include #include #include +#include // Global variables exported from the lexer... @@ -26,11 +28,15 @@ extern std::string Textin; extern int Upgradelineno; extern std::istream* LexInput; +struct TypeInfo; +typedef std::vector TypeList; void UpgradeAssembly( const std::string & infile, std::istream& in, std::ostream &out, bool debug, bool addAttrs); +TypeInfo* ResolveType(TypeInfo*& Ty); + // Globals exported by the parser... extern char* Upgradetext; extern int Upgradeleng; @@ -47,6 +53,17 @@ enum Types { OpaqueTy, VoidTy, LabelTy, FunctionTy, UnresolvedTy, NumericTy }; +/// This type is used to keep track of the signedness of values. Instead +/// of creating llvm::Value directly, the parser will create ValueInfo which +/// associates a Value* with a Signedness indication. +struct ValueInfo { + std::string* val; + TypeInfo* type; + bool constant; + bool isConstant() const { return constant; } + inline void destroy(); +}; + /// This type is used to keep track of the signedness of the obsolete /// integer types. Instead of creating an llvm::Type directly, the Lexer will /// create instances of TypeInfo which retains the signedness indication so @@ -55,20 +72,89 @@ enum Types { /// to "int32" and the "second" field will be set to "isUnsigned". If the /// type is not obsolete then "second" will be set to "isSignless". struct TypeInfo { - std::string* newTy; - Types oldTy; - Types elemTy; - - void destroy() const { delete newTy; } - - TypeInfo clone() const { - TypeInfo result = *this; - result.newTy = new std::string(*newTy); - return result; + TypeInfo() + : newTy(0), oldTy(UnresolvedTy), elemTy(0), resultTy(0), elements(0), + nelems(0) { } - Types getElementType() const { return elemTy; } + TypeInfo(const char * newType, Types oldType) + : newTy(0), oldTy(oldType), elemTy(0), resultTy(0), elements(0), nelems(0) { + newTy = new std::string(newType); + } + TypeInfo(std::string *newType, Types oldType, TypeInfo* eTy = 0, + TypeInfo *rTy = 0) + : newTy(newType), oldTy(oldType), elemTy(eTy), resultTy(rTy), elements(0), + nelems(0) { + } + + TypeInfo(std::string *newType, Types oldType, TypeInfo *eTy, uint64_t elems) + : newTy(newType), oldTy(oldType), elemTy(eTy), resultTy(0), elements(0), + nelems(elems) { + } + + TypeInfo(std::string *newType, Types oldType, TypeList* TL) + : newTy(newType), oldTy(oldType), elemTy(0), resultTy(0), elements(TL), + nelems(0) { + } + + TypeInfo(std::string *newType, TypeInfo* resTy, TypeList* TL) + : newTy(newType), oldTy(FunctionTy), elemTy(0), resultTy(resTy), + elements(TL), nelems(0) { + } + + TypeInfo(const TypeInfo& that) + : newTy(0), oldTy(that.oldTy), elemTy(0), resultTy(0), elements(0), + nelems(0) { + *this = that; + } + + TypeInfo& operator=(const TypeInfo& that) { + oldTy = that.oldTy; + nelems = that.nelems; + if (that.newTy) + newTy = new std::string(*that.newTy); + if (that.elemTy) + elemTy = that.elemTy->clone(); + if (that.resultTy) + resultTy = that.resultTy->clone(); + if (that.elements) { + elements = new std::vector(that.elements->size()); + *elements = *that.elements; + } + return *this; + } + + ~TypeInfo() { + delete newTy; delete elemTy; delete resultTy; delete elements; + } + + TypeInfo* clone() const { + return new TypeInfo(*this); + } + + Types getElementTy() const { + if (elemTy) { + return elemTy->oldTy; + } + return UnresolvedTy; + } + + const std::string& getNewTy() const { return *newTy; } + void setOldTy(Types Ty) { oldTy = Ty; } + + TypeInfo* getResultType() const { return resultTy; } + TypeInfo* getElementType() const { return elemTy; } + + TypeInfo* getPointerType() const { + std::string* ty = new std::string(*newTy + "*"); + return new TypeInfo(ty, PointerTy, this->clone(), (TypeInfo*)0); + } + + bool isUnresolved() const { return oldTy == UnresolvedTy; } + bool isNumeric() const { return oldTy == NumericTy; } + bool isVoid() const { return oldTy == VoidTy; } + bool isBool() const { return oldTy == BoolTy; } bool isSigned() const { return oldTy == SByteTy || oldTy == ShortTy || oldTy == IntTy || oldTy == LongTy; @@ -79,9 +165,6 @@ struct TypeInfo { oldTy == UIntTy || oldTy == ULongTy; } - bool isBool() const { - return oldTy == BoolTy; - } bool isSignless() const { return !isSigned() && !isUnsigned(); } bool isInteger() const { return isSigned() || isUnsigned(); } @@ -89,8 +172,14 @@ struct TypeInfo { bool isFloatingPoint() const { return oldTy == DoubleTy || oldTy == FloatTy; } bool isPacked() const { return oldTy == PackedTy; } bool isPointer() const { return oldTy == PointerTy; } + bool isStruct() const { return oldTy == StructTy || oldTy == PackedStructTy; } + bool isArray() const { return oldTy == ArrayTy; } bool isOther() const { return !isPacked() && !isPointer() && !isFloatingPoint() && !isIntegral(); } + bool isFunction() const { return oldTy == FunctionTy; } + bool isComposite() const { + return isStruct() || isPointer() || isArray() || isPacked(); + } bool isAttributeCandidate() const { return isIntegral() && getBitWidth() < 32; @@ -98,6 +187,7 @@ struct TypeInfo { unsigned getBitWidth() const { switch (oldTy) { + default: case LabelTy: case VoidTy : return 0; case BoolTy : return 1; @@ -106,32 +196,61 @@ struct TypeInfo { case IntTy: case UIntTy: case FloatTy: return 32; case LongTy: case ULongTy: case DoubleTy : return 64; case PointerTy: return SizeOfPointer; // global var - default: - return 128; /// Struct/Packed/Array --> doesn't matter - + case PackedTy: + case ArrayTy: + return nelems * elemTy->getBitWidth(); + case StructTy: + case PackedStructTy: { + uint64_t size = 0; + for (unsigned i = 0; i < elements->size(); i++) { + ResolveType((*elements)[i]); + size += (*elements)[i]->getBitWidth(); + } + return size; + } } } -}; -/// This type is used to keep track of the signedness of values. Instead -/// of creating llvm::Value directly, the parser will create ValueInfo which -/// associates a Value* with a Signedness indication. -struct ValueInfo { - std::string* val; - TypeInfo type; - bool constant; - bool isConstant() const { return constant; } - void destroy() { delete val; type.destroy(); } + TypeInfo* getIndexedType(const ValueInfo& VI) { + if (isStruct()) { + if (VI.isConstant() && VI.type->isInteger()) { + size_t pos = VI.val->find(' ') + 1; + if (pos < VI.val->size()) { + uint64_t idx = atoi(VI.val->substr(pos).c_str()); + return (*elements)[idx]; + } else { + yyerror("Invalid value for constant integer"); + return 0; + } + } else { + yyerror("Structure requires constant index"); + return 0; + } + } + if (isArray() || isPacked() || isPointer()) + return elemTy; + yyerror("Invalid type for getIndexedType"); + return 0; + } + +private: + std::string* newTy; + Types oldTy; + TypeInfo *elemTy; + TypeInfo *resultTy; + TypeList *elements; + uint64_t nelems; }; /// This type is used to keep track of the signedness of constants. struct ConstInfo { std::string *cnst; - TypeInfo type; - void destroy() { delete cnst; type.destroy(); } + TypeInfo *type; + void destroy() { delete cnst; delete type; } }; typedef std::vector ValueList; +inline void ValueInfo::destroy() { delete val; delete type; } #endif diff --git a/llvm/tools/llvm-upgrade/UpgradeLexer.l b/llvm/tools/llvm-upgrade/UpgradeLexer.l index 8ffca760fde2..d9e5d0ebe395 100644 --- a/llvm/tools/llvm-upgrade/UpgradeLexer.l +++ b/llvm/tools/llvm-upgrade/UpgradeLexer.l @@ -48,9 +48,7 @@ return sym #define RET_TY(sym,OldTY,NewTY,sign) \ - Upgradelval.Type.newTy = new std::string(NewTY); \ - Upgradelval.Type.oldTy = OldTY; \ - Upgradelval.Type.elemTy = VoidTy; \ + Upgradelval.Type = new TypeInfo(NewTY, OldTY); \ return sym #define YY_NEVER_INTERACTIVE 1 diff --git a/llvm/tools/llvm-upgrade/UpgradeParser.y b/llvm/tools/llvm-upgrade/UpgradeParser.y index 761bda1cdfc8..12ad18223be3 100644 --- a/llvm/tools/llvm-upgrade/UpgradeParser.y +++ b/llvm/tools/llvm-upgrade/UpgradeParser.y @@ -13,12 +13,10 @@ %{ #include "ParserInternals.h" -#include #include #include #include #include -#include #define YYERROR_VERBOSE 1 #define YYINCLUDED_STDLIB_H @@ -78,71 +76,72 @@ void UpgradeAssembly(const std::string &infile, std::istream& in, } } -static void ResolveType(TypeInfo& Ty) { - if (Ty.oldTy == UnresolvedTy) { - TypeMap::iterator I = NamedTypes.find(*Ty.newTy); +TypeInfo* ResolveType(TypeInfo*& Ty) { + if (Ty->isUnresolved()) { + TypeMap::iterator I = NamedTypes.find(Ty->getNewTy()); if (I != NamedTypes.end()) { - Ty.oldTy = I->second.oldTy; - Ty.elemTy = I->second.elemTy; + Ty = I->second.clone(); + return Ty; } else { - std::string msg("Can't resolve type: "); - msg += *Ty.newTy; + std::string msg("Cannot resolve type: "); + msg += Ty->getNewTy(); yyerror(msg.c_str()); } - } else if (Ty.oldTy == NumericTy) { - unsigned ref = atoi(&((Ty.newTy->c_str())[1])); // Skip the '\\' + } else if (Ty->isNumeric()) { + unsigned ref = atoi(&((Ty->getNewTy().c_str())[1])); // Skip the '\\' if (ref < EnumeratedTypes.size()) { - Ty.oldTy = EnumeratedTypes[ref].oldTy; - Ty.elemTy = EnumeratedTypes[ref].elemTy; + Ty = EnumeratedTypes[ref].clone(); + return Ty; } else { std::string msg("Can't resolve type: "); - msg += *Ty.newTy; + msg += Ty->getNewTy(); yyerror(msg.c_str()); } } // otherwise its already resolved. + return Ty; } static const char* getCastOpcode( - std::string& Source, const TypeInfo& SrcTy, const TypeInfo& DstTy) + std::string& Source, const TypeInfo* SrcTy, const TypeInfo* DstTy) { - unsigned SrcBits = SrcTy.getBitWidth(); - unsigned DstBits = DstTy.getBitWidth(); + unsigned SrcBits = SrcTy->getBitWidth(); + unsigned DstBits = DstTy->getBitWidth(); const char* opcode = "bitcast"; // Run through the possibilities ... - if (DstTy.isIntegral()) { // Casting to integral - if (SrcTy.isIntegral()) { // Casting from integral + if (DstTy->isIntegral()) { // Casting to integral + if (SrcTy->isIntegral()) { // Casting from integral if (DstBits < SrcBits) opcode = "trunc"; else if (DstBits > SrcBits) { // its an extension - if (SrcTy.isSigned()) + if (SrcTy->isSigned()) opcode ="sext"; // signed -> SEXT else opcode = "zext"; // unsigned -> ZEXT } else { opcode = "bitcast"; // Same size, No-op cast } - } else if (SrcTy.isFloatingPoint()) { // Casting from floating pt - if (DstTy.isSigned()) + } else if (SrcTy->isFloatingPoint()) { // Casting from floating pt + if (DstTy->isSigned()) opcode = "fptosi"; // FP -> sint else opcode = "fptoui"; // FP -> uint - } else if (SrcTy.isPacked()) { - assert(DstBits == SrcTy.getBitWidth() && + } else if (SrcTy->isPacked()) { + assert(DstBits == SrcTy->getBitWidth() && "Casting packed to integer of different width"); opcode = "bitcast"; // same size, no-op cast } else { - assert(SrcTy.isPointer() && + assert(SrcTy->isPointer() && "Casting from a value that is not first-class type"); opcode = "ptrtoint"; // ptr -> int } - } else if (DstTy.isFloatingPoint()) { // Casting to floating pt - if (SrcTy.isIntegral()) { // Casting from integral - if (SrcTy.isSigned()) + } else if (DstTy->isFloatingPoint()) { // Casting to floating pt + if (SrcTy->isIntegral()) { // Casting from integral + if (SrcTy->isSigned()) opcode = "sitofp"; // sint -> FP else opcode = "uitofp"; // uint -> FP - } else if (SrcTy.isFloatingPoint()) { // Casting from floating pt + } else if (SrcTy->isFloatingPoint()) { // Casting from floating pt if (DstBits < SrcBits) { opcode = "fptrunc"; // FP -> smaller FP } else if (DstBits > SrcBits) { @@ -150,27 +149,27 @@ static const char* getCastOpcode( } else { opcode ="bitcast"; // same size, no-op cast } - } else if (SrcTy.isPacked()) { - assert(DstBits == SrcTy.getBitWidth() && + } else if (SrcTy->isPacked()) { + assert(DstBits == SrcTy->getBitWidth() && "Casting packed to floating point of different width"); opcode = "bitcast"; // same size, no-op cast } else { assert(0 && "Casting pointer or non-first class to float"); } - } else if (DstTy.isPacked()) { - if (SrcTy.isPacked()) { - assert(DstTy.getBitWidth() == SrcTy.getBitWidth() && + } else if (DstTy->isPacked()) { + if (SrcTy->isPacked()) { + assert(DstTy->getBitWidth() == SrcTy->getBitWidth() && "Casting packed to packed of different widths"); opcode = "bitcast"; // packed -> packed - } else if (DstTy.getBitWidth() == SrcBits) { + } else if (DstTy->getBitWidth() == SrcBits) { opcode = "bitcast"; // float/int -> packed } else { assert(!"Illegal cast to packed (wrong type or size)"); } - } else if (DstTy.isPointer()) { - if (SrcTy.isPointer()) { + } else if (DstTy->isPointer()) { + if (SrcTy->isPointer()) { opcode = "bitcast"; // ptr -> ptr - } else if (SrcTy.isIntegral()) { + } else if (SrcTy->isIntegral()) { opcode = "inttoptr"; // int -> ptr } else { assert(!"Casting invalid type to pointer"); @@ -181,12 +180,12 @@ static const char* getCastOpcode( return opcode; } -static std::string getCastUpgrade( - const std::string& Src, TypeInfo& SrcTy, TypeInfo& DstTy, bool isConst) +static std::string getCastUpgrade(const std::string& Src, TypeInfo* SrcTy, + TypeInfo* DstTy, bool isConst) { std::string Result; std::string Source = Src; - if (SrcTy.isFloatingPoint() && DstTy.isPointer()) { + if (SrcTy->isFloatingPoint() && DstTy->isPointer()) { // fp -> ptr cast is no longer supported but we must upgrade this // by doing a double cast: fp -> int -> ptr if (isConst) @@ -197,16 +196,16 @@ static std::string getCastUpgrade( Source = "i64 %cast_upgrade" + llvm::utostr(unique); } // Update the SrcTy for the getCastOpcode call below - SrcTy.destroy(); - SrcTy.newTy = new std::string("i64"); - SrcTy.oldTy = ULongTy; - } else if (DstTy.oldTy == BoolTy && SrcTy.oldTy != BoolTy) { - // cast ptr %x to bool was previously defined as setne ptr %x, null - // The ptrtoint semantic is to truncate, not compare so we must retain - // the original intent by replace the cast with a setne - const char* comparator = SrcTy.isPointer() ? ", null" : - (SrcTy.isFloatingPoint() ? ", 0.0" : ", 0"); - const char* compareOp = SrcTy.isFloatingPoint() ? "fcmp one " : "icmp ne "; + delete SrcTy; + SrcTy = new TypeInfo("i64", ULongTy); + } else if (DstTy->isBool()) { + // cast type %x to bool was previously defined as setne type %x, null + // The cast semantic is now to truncate, not compare so we must retain + // the original intent by replacing the cast with a setne + const char* comparator = SrcTy->isPointer() ? ", null" : + (SrcTy->isFloatingPoint() ? ", 0.0" : + (SrcTy->isBool() ? ", false" : ", 0")); + const char* compareOp = SrcTy->isFloatingPoint() ? "fcmp one " : "icmp ne "; if (isConst) { Result = "(" + Source + comparator + ")"; Result = compareOp + Result; @@ -218,33 +217,32 @@ static std::string getCastUpgrade( ResolveType(DstTy); std::string Opcode(getCastOpcode(Source, SrcTy, DstTy)); if (isConst) - Result += Opcode + "( " + Source + " to " + *DstTy.newTy + ")"; + Result += Opcode + "( " + Source + " to " + DstTy->getNewTy() + ")"; else - Result += Opcode + " " + Source + " to " + *DstTy.newTy; + Result += Opcode + " " + Source + " to " + DstTy->getNewTy(); return Result; } -const char* getDivRemOpcode(const std::string& opcode, const TypeInfo& TI) { +const char* getDivRemOpcode(const std::string& opcode, TypeInfo* TI) { const char* op = opcode.c_str(); - TypeInfo Ty = TI; - ResolveType(Ty); - if (Ty.isPacked()) - Ty.oldTy = Ty.getElementType(); + const TypeInfo* Ty = ResolveType(TI); + if (Ty->isPacked()) + Ty = Ty->getElementType(); if (opcode == "div") - if (Ty.isFloatingPoint()) + if (Ty->isFloatingPoint()) op = "fdiv"; - else if (Ty.isUnsigned()) + else if (Ty->isUnsigned()) op = "udiv"; - else if (Ty.isSigned()) + else if (Ty->isSigned()) op = "sdiv"; else yyerror("Invalid type for div instruction"); else if (opcode == "rem") - if (Ty.isFloatingPoint()) + if (Ty->isFloatingPoint()) op = "frem"; - else if (Ty.isUnsigned()) + else if (Ty->isUnsigned()) op = "urem"; - else if (Ty.isSigned()) + else if (Ty->isSigned()) op = "srem"; else yyerror("Invalid type for rem instruction"); @@ -252,7 +250,7 @@ const char* getDivRemOpcode(const std::string& opcode, const TypeInfo& TI) { } std::string -getCompareOp(const std::string& setcc, const TypeInfo& TI) { +getCompareOp(const std::string& setcc, const TypeInfo* TI) { assert(setcc.length() == 5); char cc1 = setcc[3]; char cc2 = setcc[4]; @@ -261,20 +259,20 @@ getCompareOp(const std::string& setcc, const TypeInfo& TI) { std::string result("xcmp xxx"); result[6] = cc1; result[7] = cc2; - if (TI.isFloatingPoint()) { + if (TI->isFloatingPoint()) { result[0] = 'f'; result[5] = 'o'; if (cc1 == 'n') result[5] = 'u'; // NE maps to unordered else result[5] = 'o'; // everything else maps to ordered - } else if (TI.isIntegral() || TI.isPointer()) { + } else if (TI->isIntegral() || TI->isPointer()) { result[0] = 'i'; if ((cc1 == 'e' && cc2 == 'q') || (cc1 == 'n' && cc2 == 'e')) result.erase(5,1); - else if (TI.isSigned()) + else if (TI->isSigned()) result[5] = 's'; - else if (TI.isUnsigned() || TI.isPointer() || TI.isBool()) + else if (TI->isUnsigned() || TI->isPointer() || TI->isBool()) result[5] = 'u'; else yyerror("Invalid integral type for setcc"); @@ -282,16 +280,87 @@ getCompareOp(const std::string& setcc, const TypeInfo& TI) { return result; } +static TypeInfo* getFunctionReturnType(TypeInfo* PFTy) { + ResolveType(PFTy); + if (PFTy->isPointer()) { + TypeInfo* ElemTy = PFTy->getElementType(); + ResolveType(ElemTy); + if (ElemTy->isFunction()) + return ElemTy->getResultType()->clone(); + } else if (PFTy->isFunction()) { + return PFTy->getResultType()->clone(); + } + return PFTy->clone(); +} + +static TypeInfo* getGEPIndexedType(TypeInfo* PTy, ValueList* idxs) { + ResolveType(PTy); + assert(PTy->isPointer() && "GEP Operand is not a pointer?"); + TypeInfo* Result = PTy->getElementType(); // just skip first index + ResolveType(Result); + for (unsigned i = 1; i < idxs->size(); ++i) { + if (Result->isComposite()) { + Result = Result->getIndexedType((*idxs)[i]); + ResolveType(Result); + } else + yyerror("Invalid type for index"); + } + return Result->getPointerType(); +} + +static std::string makeUniqueName(const std::string *Name, bool isSigned) { + const char *suffix = ".u"; + if (isSigned) + suffix = ".s"; + if ((*Name)[Name->size()-1] == '"') { + std::string Result(*Name); + Result.insert(Name->size()-1, suffix); + return Result; + } + return *Name + suffix; +} + +// This function handles appending .u or .s to integer value names that +// were previously unsigned or signed, respectively. This avoids name +// collisions since the unsigned and signed type planes have collapsed +// into a single signless type plane. +static std::string getUniqueName(const std::string *Name, TypeInfo* Ty) { + // If its not a symbolic name, don't modify it, probably a constant val. + if ((*Name)[0] != '%' && (*Name)[0] != '"') + return *Name; + // If its a numeric reference, just leave it alone. + if (isdigit((*Name)[1])) + return *Name; + + // Resolve the type + ResolveType(Ty); + + // Default the result to the current name + std::string Result = *Name; + + if (Ty->isInteger()) { + // If its an integer type, make the name unique + Result = makeUniqueName(Name, Ty->isSigned()); + } else if (Ty->isPointer()) { + while (Ty->isPointer()) + Ty = Ty->getElementType(); + if (Ty->isInteger()) + Result = makeUniqueName(Name, Ty->isSigned()); + } + return Result; +} + %} // %file-prefix="UpgradeParser" %union { std::string* String; - TypeInfo Type; + TypeInfo* Type; ValueInfo Value; ConstInfo Const; ValueList* ValList; + TypeList* TypeVec; } %token VOID BOOL SBYTE UBYTE SHORT USHORT INT UINT LONG ULONG @@ -322,19 +391,20 @@ getCompareOp(const std::string& setcc, const TypeInfo& TI) { %type OptAssign OptLinkage OptCallingConv OptAlign OptCAlign %type SectionString OptSection GlobalVarAttributes GlobalVarAttribute -%type ArgTypeListI ConstExpr DefinitionList +%type ConstExpr DefinitionList %type ConstPool TargetDefinition LibrariesDefinition LibList OptName %type ArgVal ArgListH ArgList FunctionHeaderH BEGIN FunctionHeader END -%type Function FunctionProto BasicBlock TypeListI -%type InstructionList BBTerminatorInst JumpTable Inst PHIList -%type OptTailCall InstVal OptVolatile Unwind -%type MemoryInst SymbolicValueRef OptSideEffect GlobalType +%type Function FunctionProto BasicBlock +%type InstructionList BBTerminatorInst JumpTable Inst +%type OptTailCall OptVolatile Unwind +%type SymbolicValueRef OptSideEffect GlobalType %type FnDeclareLinkage BasicBlockList BigOrLittle AsmBlock %type Name ConstValueRef ConstVector External %type ShiftOps SetCondOps LogicalOps ArithmeticOps CastOps %type IPredicates FPredicates %type ValueRefList ValueRefListE IndexList +%type TypeListI ArgTypeListI %type IntType SIntType UIntType FPType TypesV Types %type PrimType UpRTypesV UpRTypes @@ -342,7 +412,7 @@ getCompareOp(const std::string& setcc, const TypeInfo& TI) { %type IntVal EInt64Val %type ConstVal -%type ValueRef ResolvedVal +%type ValueRef ResolvedVal InstVal PHIList MemoryInst %start Module @@ -456,68 +526,79 @@ PrimType : BOOL | SBYTE | UBYTE | SHORT | USHORT | INT | UINT ; PrimType : LONG | ULONG | FLOAT | DOUBLE | LABEL; UpRTypes : OPAQUE { - $$.newTy = $1; - $$.oldTy = OpaqueTy; + $$ = new TypeInfo($1, OpaqueTy); } | SymbolicValueRef { - $$.newTy = $1; - $$.oldTy = UnresolvedTy; + $$ = new TypeInfo($1, UnresolvedTy); } | PrimType { $$ = $1; } | '\\' EUINT64VAL { // Type UpReference $2->insert(0, "\\"); - $$.newTy = $2; - $$.oldTy = NumericTy; + $$ = new TypeInfo($2, NumericTy); } | UpRTypesV '(' ArgTypeListI ')' { // Function derived type? - *$1.newTy += "( " + *$3 + " )"; - delete $3; - $$.newTy = $1.newTy; - $$.oldTy = FunctionTy; + std::string newTy( $1->getNewTy() + "("); + for (unsigned i = 0; i < $3->size(); ++i) { + if (i != 0) + newTy += ", "; + if ((*$3)[i]->isVoid()) + newTy += "..."; + else + newTy += (*$3)[i]->getNewTy(); + } + newTy += ")"; + $$ = new TypeInfo(new std::string(newTy), $1, $3); + EnumeratedTypes.push_back(*$$); } | '[' EUINT64VAL 'x' UpRTypes ']' { // Sized array type? $2->insert(0,"[ "); - *$2 += " x " + *$4.newTy + " ]"; - delete $4.newTy; - $$.newTy = $2; - $$.oldTy = ArrayTy; - $$.elemTy = $4.oldTy; + *$2 += " x " + $4->getNewTy() + " ]"; + uint64_t elems = atoi($2->c_str()); + $$ = new TypeInfo($2, ArrayTy, $4, elems); + EnumeratedTypes.push_back(*$$); } | '<' EUINT64VAL 'x' UpRTypes '>' { // Packed array type? $2->insert(0,"< "); - *$2 += " x " + *$4.newTy + " >"; - delete $4.newTy; - $$.newTy = $2; - $$.oldTy = PackedTy; - $$.elemTy = $4.oldTy; + *$2 += " x " + $4->getNewTy() + " >"; + uint64_t elems = atoi($2->c_str()); + $$ = new TypeInfo($2, PackedTy, $4, elems); + EnumeratedTypes.push_back(*$$); } | '{' TypeListI '}' { // Structure type? - $2->insert(0, "{ "); - *$2 += " }"; - $$.newTy = $2; - $$.oldTy = StructTy; + std::string newTy("{"); + for (unsigned i = 0; i < $2->size(); ++i) { + if (i != 0) + newTy += ", "; + newTy += (*$2)[i]->getNewTy(); + } + newTy += "}"; + $$ = new TypeInfo(new std::string(newTy), StructTy, $2); + EnumeratedTypes.push_back(*$$); } | '{' '}' { // Empty structure type? - $$.newTy = new std::string("{}"); - $$.oldTy = StructTy; + $$ = new TypeInfo(new std::string("{}"), StructTy, new TypeList()); + EnumeratedTypes.push_back(*$$); } | '<' '{' TypeListI '}' '>' { // Packed Structure type? - $3->insert(0, "<{ "); - *$3 += " }>"; - $$.newTy = $3; - $$.oldTy = StructTy; + std::string newTy("<{"); + for (unsigned i = 0; i < $3->size(); ++i) { + if (i != 0) + newTy += ", "; + newTy += (*$3)[i]->getNewTy(); + } + newTy += "}>"; + $$ = new TypeInfo(new std::string(newTy), PackedStructTy, $3); + EnumeratedTypes.push_back(*$$); } | '<' '{' '}' '>' { // Empty packed structure type? - $$.newTy = new std::string("<{}>"); - $$.oldTy = StructTy; + $$ = new TypeInfo(new std::string("<{}>"), PackedStructTy, new TypeList()); + EnumeratedTypes.push_back(*$$); } | UpRTypes '*' { // Pointer type? - *$1.newTy += '*'; - $$.elemTy = $1.oldTy; - $1.oldTy = PointerTy; - $$ = $1; + $$ = $1->getPointerType(); + EnumeratedTypes.push_back(*$$); }; // TypeList - Used for struct declarations and as a basis for function type @@ -525,27 +606,29 @@ UpRTypes // TypeListI : UpRTypes { - $$ = $1.newTy; + $$ = new TypeList(); + $$->push_back($1); } | TypeListI ',' UpRTypes { - *$1 += ", " + *$3.newTy; - delete $3.newTy; $$ = $1; + $$->push_back($3); }; // ArgTypeList - List of types for a function type declaration... ArgTypeListI : TypeListI | TypeListI ',' DOTDOTDOT { - *$1 += ", ..."; - delete $3; $$ = $1; + $$->push_back(new TypeInfo("void",VoidTy)); + delete $3; } | DOTDOTDOT { - $$ = $1; + $$ = new TypeList(); + $$->push_back(new TypeInfo("void",VoidTy)); + delete $1; } | /*empty*/ { - $$ = new std::string(); + $$ = new TypeList(); }; // ConstVal - The various declarations that go into the constant pool. This @@ -556,95 +639,96 @@ ArgTypeListI // ConstVal: Types '[' ConstVector ']' { // Nonempty unsized arr $$.type = $1; - $$.cnst = new std::string(*$1.newTy); + $$.cnst = new std::string($1->getNewTy()); *$$.cnst += " [ " + *$3 + " ]"; delete $3; } | Types '[' ']' { $$.type = $1; - $$.cnst = new std::string(*$1.newTy); + $$.cnst = new std::string($1->getNewTy()); *$$.cnst += "[ ]"; } | Types 'c' STRINGCONSTANT { $$.type = $1; - $$.cnst = new std::string(*$1.newTy); + $$.cnst = new std::string($1->getNewTy()); *$$.cnst += " c" + *$3; delete $3; } | Types '<' ConstVector '>' { // Nonempty unsized arr $$.type = $1; - $$.cnst = new std::string(*$1.newTy); + $$.cnst = new std::string($1->getNewTy()); *$$.cnst += " < " + *$3 + " >"; delete $3; } | Types '{' ConstVector '}' { $$.type = $1; - $$.cnst = new std::string(*$1.newTy); + $$.cnst = new std::string($1->getNewTy()); *$$.cnst += " { " + *$3 + " }"; delete $3; } | Types '{' '}' { $$.type = $1; - $$.cnst = new std::string(*$1.newTy); + $$.cnst = new std::string($1->getNewTy()); *$$.cnst += " {}"; } | Types NULL_TOK { $$.type = $1; - $$.cnst = new std::string(*$1.newTy); + $$.cnst = new std::string($1->getNewTy()); *$$.cnst += " " + *$2; delete $2; } | Types UNDEF { $$.type = $1; - $$.cnst = new std::string(*$1.newTy); + $$.cnst = new std::string($1->getNewTy()); *$$.cnst += " " + *$2; delete $2; } | Types SymbolicValueRef { + std::string Name = getUniqueName($2,$1); $$.type = $1; - $$.cnst = new std::string(*$1.newTy); - *$$.cnst += " " + *$2; + $$.cnst = new std::string($1->getNewTy()); + *$$.cnst += " " + Name; delete $2; } | Types ConstExpr { $$.type = $1; - $$.cnst = new std::string(*$1.newTy); + $$.cnst = new std::string($1->getNewTy()); *$$.cnst += " " + *$2; delete $2; } | Types ZEROINITIALIZER { $$.type = $1; - $$.cnst = new std::string(*$1.newTy); + $$.cnst = new std::string($1->getNewTy()); *$$.cnst += " " + *$2; delete $2; } | SIntType EInt64Val { // integral constants $$.type = $1; - $$.cnst = new std::string(*$1.newTy); + $$.cnst = new std::string($1->getNewTy()); *$$.cnst += " " + *$2; delete $2; } | UIntType EUINT64VAL { // integral constants $$.type = $1; - $$.cnst = new std::string(*$1.newTy); + $$.cnst = new std::string($1->getNewTy()); *$$.cnst += " " + *$2; delete $2; } | BOOL TRUETOK { // Boolean constants $$.type = $1; - $$.cnst = new std::string(*$1.newTy); + $$.cnst = new std::string($1->getNewTy()); *$$.cnst += " " + *$2; delete $2; } | BOOL FALSETOK { // Boolean constants $$.type = $1; - $$.cnst = new std::string(*$1.newTy); + $$.cnst = new std::string($1->getNewTy()); *$$.cnst += " " + *$2; delete $2; } | FPType FPVAL { // Float & Double constants $$.type = $1; - $$.cnst = new std::string(*$1.newTy); + $$.cnst = new std::string($1->getNewTy()); *$$.cnst += " " + *$2; delete $2; }; @@ -652,17 +736,16 @@ ConstVal: Types '[' ConstVector ']' { // Nonempty unsized arr ConstExpr: CastOps '(' ConstVal TO Types ')' { std::string source = *$3.cnst; - TypeInfo DstTy = $5; - ResolveType(DstTy); + TypeInfo* DstTy = ResolveType($5); if (*$1 == "cast") { // Call getCastUpgrade to upgrade the old cast - $$ = new std::string(getCastUpgrade(source, $3.type, $5, true)); + $$ = new std::string(getCastUpgrade(source, $3.type, DstTy, true)); } else { // Nothing to upgrade, just create the cast constant expr $$ = new std::string(*$1); - *$$ += "( " + source + " to " + *$5.newTy + ")"; + *$$ += "( " + source + " to " + $5->getNewTy() + ")"; } - delete $1; $3.destroy(); delete $4; $5.destroy(); + delete $1; $3.destroy(); delete $4; delete $5; } | GETELEMENTPTR '(' ConstVal IndexList ')' { *$1 += "(" + *$3.cnst; @@ -711,7 +794,7 @@ ConstExpr: CastOps '(' ConstVal TO Types ')' { | ShiftOps '(' ConstVal ',' ConstVal ')' { const char* shiftop = $1->c_str(); if (*$1 == "shr") - shiftop = ($3.type.isUnsigned()) ? "lshr" : "ashr"; + shiftop = ($3.type->isUnsigned()) ? "lshr" : "ashr"; $$ = new std::string(shiftop); *$$ += "(" + *$3.cnst + "," + *$5.cnst + ")"; delete $1; $3.destroy(); $5.destroy(); @@ -783,15 +866,13 @@ External : EXTERNAL | UNINITIALIZED { $$ = $1; *$$ = "external"; } // ConstPool - Constants with optional names assigned to them. ConstPool : ConstPool OptAssign TYPE TypesV { - EnumeratedTypes.push_back($4); + EnumeratedTypes.push_back(*$4); if (!$2->empty()) { - NamedTypes[*$2].newTy = new std::string(*$4.newTy); - NamedTypes[*$2].oldTy = $4.oldTy; - NamedTypes[*$2].elemTy = $4.elemTy; + NamedTypes[*$2] = *$4; *O << *$2 << " = "; } - *O << "type " << *$4.newTy << '\n'; - delete $2; delete $3; $4.destroy(); + *O << "type " << $4->getNewTy() << '\n'; + delete $2; delete $3; $$ = 0; } | ConstPool FunctionProto { // Function prototypes can be in const pool @@ -806,38 +887,42 @@ ConstPool : ConstPool OptAssign TYPE TypesV { } | ConstPool OptAssign OptLinkage GlobalType ConstVal GlobalVarAttributes { if (!$2->empty()) { - *O << *$2 << " = "; - Globals[*$2] = $5.type.clone(); + std::string Name = getUniqueName($2,$5.type); + *O << Name << " = "; + Globals[Name] = *$5.type; } *O << *$3 << ' ' << *$4 << ' ' << *$5.cnst << ' ' << *$6 << '\n'; - delete $2; delete $3; delete $4; $5.destroy(); delete $6; + delete $2; delete $3; delete $4; delete $6; $$ = 0; } | ConstPool OptAssign External GlobalType Types GlobalVarAttributes { if (!$2->empty()) { - *O << *$2 << " = "; - Globals[*$2] = $5.clone(); + std::string Name = getUniqueName($2,$5); + *O << Name << " = "; + Globals[Name] = *$5; } - *O << *$3 << ' ' << *$4 << ' ' << *$5.newTy << ' ' << *$6 << '\n'; - delete $2; delete $3; delete $4; $5.destroy(); delete $6; + *O << *$3 << ' ' << *$4 << ' ' << $5->getNewTy() << ' ' << *$6 << '\n'; + delete $2; delete $3; delete $4; delete $6; $$ = 0; } | ConstPool OptAssign DLLIMPORT GlobalType Types GlobalVarAttributes { if (!$2->empty()) { - *O << *$2 << " = "; - Globals[*$2] = $5.clone(); + std::string Name = getUniqueName($2,$5); + *O << Name << " = "; + Globals[Name] = *$5; } - *O << *$3 << ' ' << *$4 << ' ' << *$5.newTy << ' ' << *$6 << '\n'; - delete $2; delete $3; delete $4; $5.destroy(); delete $6; + *O << *$3 << ' ' << *$4 << ' ' << $5->getNewTy() << ' ' << *$6 << '\n'; + delete $2; delete $3; delete $4; delete $6; $$ = 0; } | ConstPool OptAssign EXTERN_WEAK GlobalType Types GlobalVarAttributes { if (!$2->empty()) { - *O << *$2 << " = "; - Globals[*$2] = $5.clone(); + std::string Name = getUniqueName($2,$5); + *O << Name << " = "; + Globals[Name] = *$5; } - *O << *$3 << ' ' << *$4 << ' ' << *$5.newTy << ' ' << *$6 << '\n'; - delete $2; delete $3; delete $4; $5.destroy(); delete $6; + *O << *$3 << ' ' << *$4 << ' ' << $5->getNewTy() << ' ' << *$6 << '\n'; + delete $2; delete $3; delete $4; delete $6; $$ = 0; } | ConstPool TARGET TargetDefinition { @@ -909,9 +994,11 @@ Name : VAR_ID | STRINGCONSTANT; OptName : Name | /*empty*/ { $$ = new std::string(); }; ArgVal : Types OptName { - $$ = $1.newTy; - if (!$2->empty()) - *$$ += " " + *$2; + $$ = new std::string($1->getNewTy()); + if (!$2->empty()) { + std::string Name = getUniqueName($2, $1); + *$$ += " " + Name; + } delete $2; }; @@ -941,14 +1028,13 @@ FunctionHeaderH if (!$1->empty()) { *$1 += " "; } - *$1 += *$2.newTy + " " + *$3 + "(" + *$5 + ")"; + *$1 += $2->getNewTy() + " " + *$3 + "(" + *$5 + ")"; if (!$7->empty()) { *$1 += " " + *$7; } if (!$8->empty()) { *$1 += " " + *$8; } - $2.destroy(); delete $3; delete $5; delete $7; @@ -978,6 +1064,7 @@ Function : FunctionHeader BasicBlockList END { if ($2) *O << *$2; *O << *$3 << "\n\n"; + delete $1; delete $2; delete $3; $$ = 0; }; @@ -1029,14 +1116,12 @@ ValueRef : SymbolicValueRef { $$.val = $1; $$.constant = false; - $$.type.newTy = 0; - $$.type.oldTy = UnresolvedTy; + $$.type = new TypeInfo(); } | ConstValueRef { $$.val = $1; $$.constant = true; - $$.type.newTy = 0; - $$.type.oldTy = UnresolvedTy; + $$.type = new TypeInfo(); } ; @@ -1044,9 +1129,12 @@ ValueRef // type immediately preceeds the value reference, and allows complex constant // pool references (for things like: 'ret [2 x int] [ int 12, int 42]') ResolvedVal : Types ValueRef { + std::string Name = getUniqueName($2.val, $1); $$ = $2; + delete $$.val; + delete $$.type; + $$.val = new std::string($1->getNewTy() + " " + Name); $$.type = $1; - $$.val->insert(0, *$1.newTy + " "); }; BasicBlockList : BasicBlockList BasicBlock { @@ -1086,42 +1174,48 @@ BBTerminatorInst : RET ResolvedVal { // Return with a result... $$ = 0; } | RET VOID { // Return with no result... - *O << " " << *$1 << ' ' << *$2.newTy << '\n'; - delete $1; $2.destroy(); + *O << " " << *$1 << ' ' << $2->getNewTy() << '\n'; + delete $1; delete $2; $$ = 0; } | BR LABEL ValueRef { // Unconditional Branch... - *O << " " << *$1 << ' ' << *$2.newTy << ' ' << *$3.val << '\n'; - delete $1; $2.destroy(); $3.destroy(); + *O << " " << *$1 << ' ' << $2->getNewTy() << ' ' << *$3.val << '\n'; + delete $1; delete $2; $3.destroy(); $$ = 0; } // Conditional Branch... | BR BOOL ValueRef ',' LABEL ValueRef ',' LABEL ValueRef { - *O << " " << *$1 << ' ' << *$2.newTy << ' ' << *$3.val << ", " - << *$5.newTy << ' ' << *$6.val << ", " << *$8.newTy << ' ' + std::string Name = getUniqueName($3.val, $2); + *O << " " << *$1 << ' ' << $2->getNewTy() << ' ' << Name << ", " + << $5->getNewTy() << ' ' << *$6.val << ", " << $8->getNewTy() << ' ' << *$9.val << '\n'; - delete $1; $2.destroy(); $3.destroy(); $5.destroy(); $6.destroy(); - $8.destroy(); $9.destroy(); + delete $1; delete $2; $3.destroy(); delete $5; $6.destroy(); + delete $8; $9.destroy(); $$ = 0; } | SWITCH IntType ValueRef ',' LABEL ValueRef '[' JumpTable ']' { - *O << " " << *$1 << ' ' << *$2.newTy << ' ' << *$3.val << ", " - << *$5.newTy << ' ' << *$6.val << " [" << *$8 << " ]\n"; - delete $1; $2.destroy(); $3.destroy(); $5.destroy(); $6.destroy(); + std::string Name = getUniqueName($3.val, $2); + *O << " " << *$1 << ' ' << $2->getNewTy() << ' ' << Name << ", " + << $5->getNewTy() << ' ' << *$6.val << " [" << *$8 << " ]\n"; + delete $1; delete $2; $3.destroy(); delete $5; $6.destroy(); delete $8; $$ = 0; } | SWITCH IntType ValueRef ',' LABEL ValueRef '[' ']' { - *O << " " << *$1 << ' ' << *$2.newTy << ' ' << *$3.val << ", " - << *$5.newTy << ' ' << *$6.val << "[]\n"; - delete $1; $2.destroy(); $3.destroy(); $5.destroy(); $6.destroy(); + std::string Name = getUniqueName($3.val, $2); + *O << " " << *$1 << ' ' << $2->getNewTy() << ' ' << Name << ", " + << $5->getNewTy() << ' ' << *$6.val << "[]\n"; + delete $1; delete $2; $3.destroy(); delete $5; $6.destroy(); $$ = 0; } | OptAssign INVOKE OptCallingConv TypesV ValueRef '(' ValueRefListE ')' TO LABEL ValueRef Unwind LABEL ValueRef { + TypeInfo* ResTy = getFunctionReturnType($4); *O << " "; - if (!$1->empty()) - *O << *$1 << " = "; - *O << *$2 << ' ' << *$3 << ' ' << *$4.newTy << ' ' << *$5.val << " ("; + if (!$1->empty()) { + std::string Name = getUniqueName($1, ResTy); + *O << Name << " = "; + } + *O << *$2 << ' ' << *$3 << ' ' << $4->getNewTy() << ' ' << *$5.val << " ("; for (unsigned i = 0; i < $7->size(); ++i) { ValueInfo& VI = (*$7)[i]; *O << *VI.val; @@ -1129,10 +1223,10 @@ BBTerminatorInst : RET ResolvedVal { // Return with a result... *O << ", "; VI.destroy(); } - *O << ") " << *$9 << ' ' << *$10.newTy << ' ' << *$11.val << ' ' - << *$12 << ' ' << *$13.newTy << ' ' << *$14.val << '\n'; - delete $1; delete $2; delete $3; $4.destroy(); $5.destroy(); delete $7; - delete $9; $10.destroy(); $11.destroy(); delete $12; $13.destroy(); + *O << ") " << *$9 << ' ' << $10->getNewTy() << ' ' << *$11.val << ' ' + << *$12 << ' ' << $13->getNewTy() << ' ' << *$14.val << '\n'; + delete $1; delete $2; delete $3; delete $4; $5.destroy(); delete $7; + delete $9; delete $10; $11.destroy(); delete $12; delete $13; $14.destroy(); $$ = 0; } @@ -1148,14 +1242,15 @@ BBTerminatorInst : RET ResolvedVal { // Return with a result... }; JumpTable : JumpTable IntType ConstValueRef ',' LABEL ValueRef { - *$1 += " " + *$2.newTy + " " + *$3 + ", " + *$5.newTy + " " + *$6.val; - $2.destroy(); delete $3; $5.destroy(); $6.destroy(); + *$1 += " " + $2->getNewTy() + " " + *$3 + ", " + $5->getNewTy() + " " + + *$6.val; + delete $2; delete $3; delete $5; $6.destroy(); $$ = $1; } | IntType ConstValueRef ',' LABEL ValueRef { - $2->insert(0, *$1.newTy + " " ); - *$2 += ", " + *$4.newTy + " " + *$5.val; - $1.destroy(); $4.destroy(); $5.destroy(); + $2->insert(0, $1->getNewTy() + " " ); + *$2 += ", " + $4->getNewTy() + " " + *$5.val; + delete $1; delete $4; $5.destroy(); $$ = $2; }; @@ -1167,38 +1262,41 @@ Inst $1->insert(0, "; "); // don't actually delete it, just comment it out delete deleteUselessCastName; } else { - *$1 += " = "; + // Get a unique name for the name of this value, based on its type. + *$1 = getUniqueName($1, $2.type) + " = "; } } - *$1 += *$2; - delete $2; + *$1 += *$2.val; + $2.destroy(); deleteUselessCastFlag = false; $$ = $1; }; PHIList : Types '[' ValueRef ',' ValueRef ']' { // Used for PHI nodes - $3.val->insert(0, *$1.newTy + "["); - *$3.val += "," + *$5.val + "]"; - $1.destroy(); $5.destroy(); - $$ = new std::string(*$3.val); - $3.destroy(); + std::string Name = getUniqueName($3.val, $1); + Name.insert(0, $1->getNewTy() + "["); + Name += "," + *$5.val + "]"; + $$.val = new std::string(Name); + $$.type = $1; + $3.destroy(); $5.destroy(); } | PHIList ',' '[' ValueRef ',' ValueRef ']' { - *$1 += ", [" + *$4.val + "," + *$6.val + "]"; + std::string Name = getUniqueName($4.val, $1.type); + *$1.val += ", [" + Name + "," + *$6.val + "]"; $4.destroy(); $6.destroy(); $$ = $1; }; ValueRefList - : ResolvedVal { + : ResolvedVal { $$ = new ValueList(); $$->push_back($1); } | ValueRefList ',' ResolvedVal { - $1->push_back($3); $$ = $1; + $$->push_back($3); }; // ValueRefListE - Just like ValueRefList, except that it may also be empty! @@ -1218,61 +1316,77 @@ OptTailCall InstVal : ArithmeticOps Types ValueRef ',' ValueRef { const char* op = getDivRemOpcode(*$1, $2); - $$ = new std::string(op); - *$$ += " " + *$2.newTy + " " + *$3.val + ", " + *$5.val; - delete $1; $2.destroy(); $3.destroy(); $5.destroy(); + std::string Name1 = getUniqueName($3.val, $2); + std::string Name2 = getUniqueName($5.val, $2); + $$.val = new std::string(op); + *$$.val += " " + $2->getNewTy() + " " + Name1 + ", " + Name2; + $$.type = $2; + delete $1; $3.destroy(); $5.destroy(); } | LogicalOps Types ValueRef ',' ValueRef { - *$1 += " " + *$2.newTy + " " + *$3.val + ", " + *$5.val; - $2.destroy(); $3.destroy(); $5.destroy(); - $$ = $1; + std::string Name1 = getUniqueName($3.val, $2); + std::string Name2 = getUniqueName($5.val, $2); + *$1 += " " + $2->getNewTy() + " " + Name1 + ", " + Name2; + $$.val = $1; + $$.type = $2; + $3.destroy(); $5.destroy(); } | SetCondOps Types ValueRef ',' ValueRef { + std::string Name1 = getUniqueName($3.val, $2); + std::string Name2 = getUniqueName($5.val, $2); *$1 = getCompareOp(*$1, $2); - *$1 += " " + *$2.newTy + " " + *$3.val + ", " + *$5.val; - $2.destroy(); $3.destroy(); $5.destroy(); - $$ = $1; + *$1 += " " + $2->getNewTy() + " " + Name1 + ", " + Name2; + $$.val = $1; + $$.type = new TypeInfo("bool",BoolTy); + $3.destroy(); $5.destroy(); } | ICMP IPredicates Types ValueRef ',' ValueRef { - *$1 += " " + *$2 + " " + *$3.newTy + " " + *$4.val + "," + *$6.val; + std::string Name1 = getUniqueName($4.val, $3); + std::string Name2 = getUniqueName($6.val, $3); + *$1 += " " + *$2 + " " + $3->getNewTy() + " " + Name1 + "," + Name2; + $$.val = $1; + $$.type = new TypeInfo("bool",BoolTy); delete $2; $4.destroy(); $6.destroy(); - $$ = $1; } | FCMP FPredicates Types ValueRef ',' ValueRef { - *$1 += " " + *$2 + " " + *$3.newTy + " " + *$4.val + "," + *$6.val; + std::string Name1 = getUniqueName($4.val, $3); + std::string Name2 = getUniqueName($6.val, $3); + *$1 += " " + *$2 + " " + $3->getNewTy() + " " + Name1 + "," + Name2; + $$.val = $1; + $$.type = new TypeInfo("bool",BoolTy); delete $2; $4.destroy(); $6.destroy(); - $$ = $1; } | NOT ResolvedVal { - *$1 += " " + *$2.val; - $2.destroy(); - $$ = $1; + $$ = $2; + $$.val->insert(0, *$1 + " "); + delete $1; } | ShiftOps ResolvedVal ',' ResolvedVal { const char* shiftop = $1->c_str(); if (*$1 == "shr") - shiftop = ($2.type.isUnsigned()) ? "lshr" : "ashr"; - $$ = new std::string(shiftop); - *$$ += " " + *$2.val + ", " + *$4.val; - delete $1; $2.destroy(); $4.destroy(); + shiftop = ($2.type->isUnsigned()) ? "lshr" : "ashr"; + $$.val = new std::string(shiftop); + *$$.val += " " + *$2.val + ", " + *$4.val; + $$.type = $2.type; + delete $1; delete $2.val; $4.destroy(); } | CastOps ResolvedVal TO Types { std::string source = *$2.val; - TypeInfo SrcTy = $2.type; - TypeInfo DstTy = $4; - ResolveType(DstTy); - $$ = new std::string(); + TypeInfo* SrcTy = $2.type; + TypeInfo* DstTy = ResolveType($4); + $$.val = new std::string(); if (*$1 == "cast") { - *$$ += getCastUpgrade(source, SrcTy, DstTy, false); + *$$.val += getCastUpgrade(source, SrcTy, DstTy, false); } else { - *$$ += *$1 + " " + source + " to " + *DstTy.newTy; + *$$.val += *$1 + " " + source + " to " + DstTy->getNewTy(); } + $$.type = $4; // Check to see if this is a useless cast of a value to the same name // and the same type. Such casts will probably cause redefinition errors // when assembled and perform no code gen action so just remove them. if (*$1 == "cast" || *$1 == "bitcast") - if ($2.type.isInteger() && $4.isInteger() && - $2.type.getBitWidth() == $4.getBitWidth()) { + if ($2.type->isInteger() && DstTy->isInteger() && + $2.type->getBitWidth() == DstTy->getBitWidth()) { deleteUselessCastFlag = true; // Flag the "Inst" rule deleteUselessCastName = new std::string(*$2.val); // save the name size_t pos = deleteUselessCastName->find_first_of("%\"",0); @@ -1282,44 +1396,51 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef { } } delete $1; $2.destroy(); - delete $3; $4.destroy(); + delete $3; } | SELECT ResolvedVal ',' ResolvedVal ',' ResolvedVal { *$1 += " " + *$2.val + ", " + *$4.val + ", " + *$6.val; - $2.destroy(); $4.destroy(); $6.destroy(); - $$ = $1; + $$.val = $1; + $$.type = $4.type; + $2.destroy(); delete $4.val; $6.destroy(); } | VAARG ResolvedVal ',' Types { - *$1 += " " + *$2.val + ", " + *$4.newTy; - $2.destroy(); $4.destroy(); - $$ = $1; + *$1 += " " + *$2.val + ", " + $4->getNewTy(); + $$.val = $1; + $$.type = $4; + $2.destroy(); } | EXTRACTELEMENT ResolvedVal ',' ResolvedVal { *$1 += " " + *$2.val + ", " + *$4.val; - $2.destroy(); $4.destroy(); - $$ = $1; + $$.val = $1; + ResolveType($2.type); + $$.type = $2.type->getElementType()->clone(); + delete $2.val; $4.destroy(); } | INSERTELEMENT ResolvedVal ',' ResolvedVal ',' ResolvedVal { *$1 += " " + *$2.val + ", " + *$4.val + ", " + *$6.val; - $2.destroy(); $4.destroy(); $6.destroy(); - $$ = $1; + $$.val = $1; + $$.type = $2.type; + delete $2.val; $4.destroy(); $6.destroy(); } | SHUFFLEVECTOR ResolvedVal ',' ResolvedVal ',' ResolvedVal { *$1 += " " + *$2.val + ", " + *$4.val + ", " + *$6.val; - $2.destroy(); $4.destroy(); $6.destroy(); - $$ = $1; + $$.val = $1; + $$.type = $2.type; + delete $2.val; $4.destroy(); $6.destroy(); } | PHI_TOK PHIList { - *$1 += " " + *$2; - delete $2; - $$ = $1; + *$1 += " " + *$2.val; + $$.val = $1; + $$.type = $2.type; + delete $2.val; } | OptTailCall OptCallingConv TypesV ValueRef '(' ValueRefListE ')' { if (!$2->empty()) *$1 += " " + *$2; if (!$1->empty()) *$1 += " "; - *$1 += *$3.newTy + " " + *$4.val + "("; + *$1 += $3->getNewTy() + " " + *$4.val + "("; for (unsigned i = 0; i < $6->size(); ++i) { ValueInfo& VI = (*$6)[i]; *$1 += *VI.val; @@ -1328,8 +1449,9 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef { VI.destroy(); } *$1 += ")"; - delete $2; $3.destroy(); $4.destroy(); delete $6; - $$ = $1; + $$.val = $1; + $$.type = getFunctionReturnType($3); + delete $2; delete $3; $4.destroy(); delete $6; } | MemoryInst ; @@ -1346,74 +1468,85 @@ OptVolatile ; MemoryInst : MALLOC Types OptCAlign { - *$1 += " " + *$2.newTy; + *$1 += " " + $2->getNewTy(); if (!$3->empty()) *$1 += " " + *$3; - $2.destroy(); delete $3; - $$ = $1; + $$.val = $1; + $$.type = $2->getPointerType(); + delete $2; delete $3; } | MALLOC Types ',' UINT ValueRef OptCAlign { - *$1 += " " + *$2.newTy + ", " + *$4.newTy + " " + *$5.val; + std::string Name = getUniqueName($5.val, $4); + *$1 += " " + $2->getNewTy() + ", " + $4->getNewTy() + " " + Name; if (!$6->empty()) *$1 += " " + *$6; - $2.destroy(); $4.destroy(); $5.destroy(); delete $6; - $$ = $1; + $$.val = $1; + $$.type = $2->getPointerType(); + delete $2; delete $4; $5.destroy(); delete $6; } | ALLOCA Types OptCAlign { - *$1 += " " + *$2.newTy; + *$1 += " " + $2->getNewTy(); if (!$3->empty()) *$1 += " " + *$3; - $2.destroy(); delete $3; - $$ = $1; + $$.val = $1; + $$.type = $2->getPointerType(); + delete $2; delete $3; } | ALLOCA Types ',' UINT ValueRef OptCAlign { - *$1 += " " + *$2.newTy + ", " + *$4.newTy + " " + *$5.val; + std::string Name = getUniqueName($5.val, $4); + *$1 += " " + $2->getNewTy() + ", " + $4->getNewTy() + " " + Name; if (!$6->empty()) *$1 += " " + *$6; - $2.destroy(); $4.destroy(); $5.destroy(); delete $6; - $$ = $1; + $$.val = $1; + $$.type = $2->getPointerType(); + delete $2; delete $4; $5.destroy(); delete $6; } | FREE ResolvedVal { *$1 += " " + *$2.val; + $$.val = $1; + $$.type = new TypeInfo("void", VoidTy); $2.destroy(); - $$ = $1; } | OptVolatile LOAD Types ValueRef { + std::string Name = getUniqueName($4.val, $3); if (!$1->empty()) *$1 += " "; - *$1 += *$2 + " " + *$3.newTy + " " + *$4.val; - delete $2; $3.destroy(); $4.destroy(); - $$ = $1; + *$1 += *$2 + " " + $3->getNewTy() + " " + Name; + $$.val = $1; + $$.type = $3->getElementType()->clone(); + delete $2; delete $3; $4.destroy(); } | OptVolatile STORE ResolvedVal ',' Types ValueRef { + std::string Name = getUniqueName($6.val, $5); if (!$1->empty()) *$1 += " "; - *$1 += *$2 + " " + *$3.val + ", " + *$5.newTy + " " + *$6.val; - delete $2; $3.destroy(); $5.destroy(); $6.destroy(); - $$ = $1; + *$1 += *$2 + " " + *$3.val + ", " + $5->getNewTy() + " " + Name; + $$.val = $1; + $$.type = new TypeInfo("void", VoidTy); + delete $2; $3.destroy(); delete $5; $6.destroy(); } | GETELEMENTPTR Types ValueRef IndexList { + std::string Name = getUniqueName($3.val, $2); // Upgrade the indices for (unsigned i = 0; i < $4->size(); ++i) { ValueInfo& VI = (*$4)[i]; - if (VI.type.isUnsigned() && !VI.isConstant() && - VI.type.getBitWidth() < 64) { + if (VI.type->isUnsigned() && !VI.isConstant() && + VI.type->getBitWidth() < 64) { std::string* old = VI.val; *O << " %gep_upgrade" << unique << " = zext " << *old << " to i64\n"; VI.val = new std::string("i64 %gep_upgrade" + llvm::utostr(unique++)); - VI.type.oldTy = ULongTy; - delete old; + VI.type->setOldTy(ULongTy); } } - *$1 += " " + *$2.newTy + " " + *$3.val; + *$1 += " " + $2->getNewTy() + " " + Name; for (unsigned i = 0; i < $4->size(); ++i) { ValueInfo& VI = (*$4)[i]; *$1 += ", " + *VI.val; - VI.destroy(); } - $2.destroy(); $3.destroy(); delete $4; - $$ = $1; + $$.val = $1; + $$.type = getGEPIndexedType($2,$4); + $3.destroy(); delete $4; }; %%