diff --git a/tools/llvm-upgrade/UpgradeInternals.h b/tools/llvm-upgrade/UpgradeInternals.h index bbf67378282..0e004007960 100644 --- a/tools/llvm-upgrade/UpgradeInternals.h +++ b/tools/llvm-upgrade/UpgradeInternals.h @@ -21,6 +21,7 @@ #include "llvm/Instructions.h" #include "llvm/ADT/StringExtras.h" #include +#include // Global variables exported from the lexer. @@ -32,12 +33,10 @@ extern int Upgradelineno; namespace llvm { - class Module; Module* UpgradeAssembly(const std::string &infile, std::istream& in, bool debug, bool addAttrs); - extern std::istream* LexInput; // UnEscapeLexed - Run through the specified buffer and change \xx codes to the @@ -59,6 +58,88 @@ struct InlineAsmDescriptor { : AsmString(as), Constraints(c), HasSideEffects(HSE) {} }; +/// This class keeps track of the signedness of a type or value. It allows the +/// signedness of a composite type to be captured in a relatively simple form. +/// This is needed in order to retain the signedness of pre LLVM 2.0 types so +/// they can be upgraded properly. Signedness of composite types must be +/// captured in order to accurately get the signedness of a value through a +/// GEP instruction. +/// @brief Class to track signedness of types and values. +struct Signedness { + /// The basic kinds of signedness values. + enum Kind { + Signless, ///< The type doesn't have any sign. + Unsigned, ///< The type is an unsigned integer. + Signed, ///< The type is a signed integer. + Named, ///< The type is a named type (probably forward ref or up ref). + Composite ///< The type is composite (struct, array, pointer). + }; + +private: + /// @brief Keeps track of Signedness for composite types + typedef std::vector SignVector; + Kind kind; ///< The kind of signedness node + union { + SignVector *sv; ///< The vector of Signedness for composite types + std::string *name; ///< The name of the type for named types. + }; +public: + /// The Signedness class is used as a member of a union so it cannot have + /// a constructor or assignment operator. This function suffices. + /// @brief Copy one signedness value to another + void copy(const Signedness &that); + /// The Signedness class is used as a member of a union so it cannot have + /// a destructor. + /// @brief Release memory, if any allocated. + void destroy(); + + /// @brief Make a Signless node. + void makeSignless() { kind = Signless; sv = 0; } + /// @brief Make a Signed node. + void makeSigned() { kind = Signed; sv = 0; } + /// @brief Make an Unsigned node. + void makeUnsigned() { kind = Unsigned; sv = 0; } + /// @brief Make a Named node. + void makeNamed(const std::string& nm){ + kind = Named; name = new std::string(nm); + } + /// @brief Make an empty Composite node. + void makeComposite() { kind = Composite; sv = new SignVector(); } + /// @brief Make an Composite node, with the first element given. + void makeComposite(const Signedness &S) { + kind = Composite; + sv = new SignVector(); + sv->push_back(S); + } + /// @brief Add an element to a Composite node. + void add(const Signedness &S) { + assert(isComposite() && "Must be composite to use add"); + sv->push_back(S); + } + bool operator<(const Signedness &that) const; + bool operator==(const Signedness &that) const; + bool isSigned() const { return kind == Signed; } + bool isUnsigned() const { return kind == Unsigned; } + bool isSignless() const { return kind == Signless; } + bool isNamed() const { return kind == Named; } + bool isComposite() const { return kind == Composite; } + /// This is used by GetElementPtr to extract the sign of an element. + /// @brief Get a specific element from a Composite node. + Signedness get(uint64_t idx) const { + assert(isComposite() && "Invalid Signedness type for get()"); + assert(sv && idx < sv->size() && "Invalid index"); + return (*sv)[idx]; + } + /// @brief Get the name from a Named node. + const std::string& getName() const { + assert(isNamed() && "Can't get name from non-name Sign"); + return *name; + } +#ifndef NDEBUG + void dump() const; +#endif +}; + // ValID - Represents a reference of a definition of some sort. This may either // be a numeric reference or a symbolic (%var) reference. This is just a @@ -82,41 +163,58 @@ struct ValID { Constant *ConstantValue; // Fully resolved constant for ConstantVal case. InlineAsmDescriptor *IAD; }; + Signedness S; static ValID create(int Num) { - ValID D; D.Type = NumberVal; D.Num = Num; return D; + ValID D; D.Type = NumberVal; D.Num = Num; D.S.makeSignless(); + return D; } static ValID create(char *Name) { - ValID D; D.Type = NameVal; D.Name = Name; return D; + ValID D; D.Type = NameVal; D.Name = Name; D.S.makeSignless(); + return D; } static ValID create(int64_t Val) { - ValID D; D.Type = ConstSIntVal; D.ConstPool64 = Val; return D; + ValID D; D.Type = ConstSIntVal; D.ConstPool64 = Val; + D.S.makeSigned(); + return D; } static ValID create(uint64_t Val) { - ValID D; D.Type = ConstUIntVal; D.UConstPool64 = Val; return D; + ValID D; D.Type = ConstUIntVal; D.UConstPool64 = Val; + D.S.makeUnsigned(); + return D; } static ValID create(double Val) { - ValID D; D.Type = ConstFPVal; D.ConstPoolFP = Val; return D; + ValID D; D.Type = ConstFPVal; D.ConstPoolFP = Val; + D.S.makeSignless(); + return D; } static ValID createNull() { - ValID D; D.Type = ConstNullVal; return D; + ValID D; D.Type = ConstNullVal; + D.S.makeSignless(); + return D; } static ValID createUndef() { - ValID D; D.Type = ConstUndefVal; return D; + ValID D; D.Type = ConstUndefVal; + D.S.makeSignless(); + return D; } static ValID createZeroInit() { - ValID D; D.Type = ConstZeroVal; return D; + ValID D; D.Type = ConstZeroVal; + D.S.makeSignless(); + return D; } static ValID create(Constant *Val) { - ValID D; D.Type = ConstantVal; D.ConstantValue = Val; return D; + ValID D; D.Type = ConstantVal; D.ConstantValue = Val; + D.S.makeSignless(); + return D; } static ValID createInlineAsm(const std::string &AsmString, @@ -125,6 +223,7 @@ struct ValID { ValID D; D.Type = InlineAsmVal; D.IAD = new InlineAsmDescriptor(AsmString, Constraints, HasSideEffects); + D.S.makeSignless(); return D; } @@ -221,10 +320,6 @@ namespace OldCallingConv { }; } -/// An enumeration for defining the Signedness of a type or value. Signless -/// means the signedness is not relevant to the type or value. -enum Signedness { Signless, Unsigned, Signed }; - /// These structures are used as the semantic values returned from various /// productions in the grammar. They simply bundle an LLVM IR object with /// its Signedness value. These help track signedness through the various @@ -232,31 +327,67 @@ enum Signedness { Signless, Unsigned, Signed }; struct TypeInfo { const llvm::Type *T; Signedness S; + bool operator<(const TypeInfo& that) const { + if (this == &that) + return false; + if (T < that.T) + return true; + if (T == that.T) { + bool result = S < that.S; +//#define TYPEINFO_DEBUG +#ifdef TYPEINFO_DEBUG + std::cerr << (result?"true ":"false ") << T->getDescription() << " ("; + S.dump(); + std::cerr << ") < " << that.T->getDescription() << " ("; + that.S.dump(); + std::cerr << ")\n"; +#endif + return result; + } + return false; + } + bool operator==(const TypeInfo& that) const { + if (this == &that) + return true; + return T == that.T && S == that.S; + } + void destroy() { S.destroy(); } }; struct PATypeInfo { llvm::PATypeHolder* PAT; Signedness S; + void destroy() { S.destroy(); delete PAT; } }; struct ConstInfo { llvm::Constant* C; Signedness S; + void destroy() { S.destroy(); } }; struct ValueInfo { llvm::Value* V; Signedness S; + void destroy() { S.destroy(); } }; struct InstrInfo { llvm::Instruction *I; Signedness S; + void destroy() { S.destroy(); } +}; + +struct TermInstInfo { + llvm::TerminatorInst *TI; + Signedness S; + void destroy() { S.destroy(); } }; struct PHIListInfo { std::list > *P; Signedness S; + void destroy() { S.destroy(); delete P; } }; } // End llvm namespace diff --git a/tools/llvm-upgrade/UpgradeLexer.l b/tools/llvm-upgrade/UpgradeLexer.l index ebab6db9c0c..300cf5cc1aa 100644 --- a/tools/llvm-upgrade/UpgradeLexer.l +++ b/tools/llvm-upgrade/UpgradeLexer.l @@ -51,7 +51,12 @@ #define RET_TY(sym,NewTY,sign) \ Upgradelval.PrimType.T = NewTY; \ - Upgradelval.PrimType.S = sign; \ + switch (sign) { \ + case 0: Upgradelval.PrimType.S.makeSignless(); break; \ + case 1: Upgradelval.PrimType.S.makeUnsigned(); break; \ + case 2: Upgradelval.PrimType.S.makeSigned(); break; \ + default: assert(0 && "Invalid sign kind"); break; \ + }\ return sym namespace llvm { @@ -238,24 +243,24 @@ coldcc { return COLDCC_TOK; } x86_stdcallcc { return X86_STDCALLCC_TOK; } x86_fastcallcc { return X86_FASTCALLCC_TOK; } -sbyte { RET_TY(SBYTE, Type::Int8Ty, Signed); } -ubyte { RET_TY(UBYTE, Type::Int8Ty, Unsigned); } -i8 { RET_TY(UBYTE, Type::Int8Ty, Unsigned); } -short { RET_TY(SHORT, Type::Int16Ty, Signed); } -ushort { RET_TY(USHORT, Type::Int16Ty, Unsigned); } -i16 { RET_TY(USHORT, Type::Int16Ty, Unsigned); } -int { RET_TY(INT, Type::Int32Ty, Signed); } -uint { RET_TY(UINT, Type::Int32Ty, Unsigned); } -i32 { RET_TY(UINT, Type::Int32Ty, Unsigned); } -long { RET_TY(LONG, Type::Int64Ty, Signed); } -ulong { RET_TY(ULONG, Type::Int64Ty, Unsigned); } -i64 { RET_TY(ULONG, Type::Int64Ty, Unsigned); } -void { RET_TY(VOID, Type::VoidTy, Signless ); } -bool { RET_TY(BOOL, Type::Int1Ty, Unsigned ); } -i1 { RET_TY(BOOL, Type::Int1Ty, Unsigned ); } -float { RET_TY(FLOAT, Type::FloatTy, Signless ); } -double { RET_TY(DOUBLE, Type::DoubleTy,Signless); } -label { RET_TY(LABEL, Type::LabelTy, Signless ); } +sbyte { RET_TY(SBYTE, Type::Int8Ty, 2); } +ubyte { RET_TY(UBYTE, Type::Int8Ty, 1); } +i8 { RET_TY(UBYTE, Type::Int8Ty, 1); } +short { RET_TY(SHORT, Type::Int16Ty, 2); } +ushort { RET_TY(USHORT, Type::Int16Ty, 1); } +i16 { RET_TY(USHORT, Type::Int16Ty, 1); } +int { RET_TY(INT, Type::Int32Ty, 2); } +uint { RET_TY(UINT, Type::Int32Ty, 1); } +i32 { RET_TY(UINT, Type::Int32Ty, 1); } +long { RET_TY(LONG, Type::Int64Ty, 2); } +ulong { RET_TY(ULONG, Type::Int64Ty, 1); } +i64 { RET_TY(ULONG, Type::Int64Ty, 1); } +void { RET_TY(VOID, Type::VoidTy, 0); } +bool { RET_TY(BOOL, Type::Int1Ty, 1); } +i1 { RET_TY(BOOL, Type::Int1Ty, 1); } +float { RET_TY(FLOAT, Type::FloatTy, 0); } +double { RET_TY(DOUBLE, Type::DoubleTy,0); } +label { RET_TY(LABEL, Type::LabelTy, 0); } type { return TYPE; } opaque { return OPAQUE; } diff --git a/tools/llvm-upgrade/UpgradeParser.y b/tools/llvm-upgrade/UpgradeParser.y index 75d85e33691..9dabc23d751 100644 --- a/tools/llvm-upgrade/UpgradeParser.y +++ b/tools/llvm-upgrade/UpgradeParser.y @@ -67,7 +67,7 @@ static GlobalVariable *CurGV; // typedef std::vector ValueList; // Numbered defs -typedef std::pair RenameMapKey; +typedef std::pair RenameMapKey; typedef std::map RenameMapType; static void @@ -78,7 +78,10 @@ static struct PerModuleInfo { Module *CurrentModule; std::map Values; // Module level numbered definitions std::map LateResolveValues; - std::vector Types; + std::vector Types; + std::vector TypeSigns; + std::map NamedTypeSigns; + std::map NamedValueSigns; std::map LateResolveTypes; static Module::Endianness Endian; static Module::PointerSize PointerSize; @@ -135,6 +138,9 @@ static struct PerModuleInfo { Values.clear(); // Clear out function local definitions Types.clear(); + TypeSigns.clear(); + NamedTypeSigns.clear(); + NamedValueSigns.clear(); CurrentModule = 0; } @@ -208,6 +214,24 @@ static struct PerFunctionInfo { static bool inFunctionScope() { return CurFun.CurrentFunction != 0; } +/// This function is just a utility to make a Key value for the rename map. +/// The Key is a combination of the name, type, Signedness of the original +/// value (global/function). This just constructs the key and ensures that +/// named Signedness values are resolved to the actual Signedness. +/// @brief Make a key for the RenameMaps +static RenameMapKey makeRenameMapKey(const std::string &Name, const Type* Ty, + const Signedness &Sign) { + TypeInfo TI; + TI.T = Ty; + if (Sign.isNamed()) + // Don't allow Named Signedness nodes because they won't match. The actual + // Signedness must be looked up in the NamedTypeSigns map. + TI.S.copy(CurModule.NamedTypeSigns[Sign.getName()]); + else + TI.S.copy(Sign); + return std::make_pair(Name, TI); +} + //===----------------------------------------------------------------------===// // Code to handle definitions of all the types @@ -233,7 +257,6 @@ static const Type *getType(const ValID &D, bool DoNotImprovise = false) { break; case ValID::NameVal: // Is it a named definition? if (const Type *N = CurModule.CurrentModule->getTypeByName(D.Name)) { - D.destroy(); // Free old strdup'd memory... return N; } break; @@ -248,7 +271,6 @@ static const Type *getType(const ValID &D, bool DoNotImprovise = false) { // if (DoNotImprovise) return 0; // Do we just want a null to be returned? - if (inFunctionScope()) { if (D.Type == ValID::NameVal) { error("Reference to an undefined type: '" + D.getName() + "'"); @@ -266,13 +288,94 @@ static const Type *getType(const ValID &D, bool DoNotImprovise = false) { Type *Typ = OpaqueType::get(); CurModule.LateResolveTypes.insert(std::make_pair(D, Typ)); return Typ; - } +} + +/// This is like the getType method except that instead of looking up the type +/// for a given ID, it looks up that type's sign. +/// @brief Get the signedness of a referenced type +static Signedness getTypeSign(const ValID &D) { + switch (D.Type) { + case ValID::NumberVal: // Is it a numbered definition? + // Module constants occupy the lowest numbered slots... + if ((unsigned)D.Num < CurModule.TypeSigns.size()) { + return CurModule.TypeSigns[(unsigned)D.Num]; + } + break; + case ValID::NameVal: { // Is it a named definition? + std::map::const_iterator I = + CurModule.NamedTypeSigns.find(D.Name); + if (I != CurModule.NamedTypeSigns.end()) + return I->second; + // Perhaps its a named forward .. just cache the name + Signedness S; + S.makeNamed(D.Name); + return S; + } + default: + break; + } + // If we don't find it, its signless + Signedness S; + S.makeSignless(); + return S; +} + +/// This function is analagous to getElementType in LLVM. It provides the same +/// function except that it looks up the Signedness instead of the type. This is +/// used when processing GEP instructions that need to extract the type of an +/// indexed struct/array/ptr member. +/// @brief Look up an element's sign. +static Signedness getElementSign(const ValueInfo& VI, + const std::vector &Indices) { + const Type *Ptr = VI.V->getType(); + assert(isa(Ptr) && "Need pointer type"); + + unsigned CurIdx = 0; + Signedness S(VI.S); + while (const CompositeType *CT = dyn_cast(Ptr)) { + if (CurIdx == Indices.size()) + break; + + Value *Index = Indices[CurIdx++]; + assert(!isa(CT) || CurIdx == 1 && "Invalid type"); + Ptr = CT->getTypeAtIndex(Index); + if (const Type* Ty = Ptr->getForwardedType()) + Ptr = Ty; + assert(S.isComposite() && "Bad Signedness type"); + if (isa(CT)) { + S = S.get(cast(Index)->getZExtValue()); + } else { + S = S.get(0UL); + } + if (S.isNamed()) + S = CurModule.NamedTypeSigns[S.getName()]; + } + Signedness Result; + Result.makeComposite(S); + return Result; +} + +/// This function just translates a ConstantInfo into a ValueInfo and calls +/// getElementSign(ValueInfo,...). Its just a convenience. +/// @brief ConstantInfo version of getElementSign. +static Signedness getElementSign(const ConstInfo& CI, + const std::vector &Indices) { + ValueInfo VI; + VI.V = CI.C; + VI.S.copy(CI.S); + std::vector Idx; + for (unsigned i = 0; i < Indices.size(); ++i) + Idx.push_back(Indices[i]); + Signedness result = getElementSign(VI, Idx); + VI.destroy(); + return result; +} /// This function determines if two function types differ only in their use of /// the sret parameter attribute in the first argument. If they are identical /// in all other respects, it returns true. Otherwise, it returns false. -bool FuncTysDifferOnlyBySRet(const FunctionType *F1, - const FunctionType *F2) { +static bool FuncTysDifferOnlyBySRet(const FunctionType *F1, + const FunctionType *F2) { if (F1->getReturnType() != F2->getReturnType() || F1->getNumParams() != F2->getNumParams() || F1->getParamAttrs(0) != F2->getParamAttrs(0)) @@ -287,10 +390,27 @@ bool FuncTysDifferOnlyBySRet(const FunctionType *F1, return true; } +/// This function determines if the type of V and Ty differ only by the SRet +/// parameter attribute. This is a more generalized case of +/// FuncTysDIfferOnlyBySRet since it doesn't require FunctionType arguments. +static bool TypesDifferOnlyBySRet(Value *V, const Type* Ty) { + if (V->getType() == Ty) + return true; + const PointerType *PF1 = dyn_cast(Ty); + const PointerType *PF2 = dyn_cast(V->getType()); + if (PF1 && PF2) { + const FunctionType* FT1 = dyn_cast(PF1->getElementType()); + const FunctionType* FT2 = dyn_cast(PF2->getElementType()); + if (FT1 && FT2) + return FuncTysDifferOnlyBySRet(FT1, FT2); + } + return false; +} + // The upgrade of csretcc to sret param attribute may have caused a function // to not be found because the param attribute changed the type of the called // function. This helper function, used in getExistingValue, detects that -// situation and returns V if it occurs and 0 otherwise. +// situation and bitcasts the function to the correct type. static Value* handleSRetFuncTypeMerge(Value *V, const Type* Ty) { // Handle degenerate cases if (!V) @@ -298,23 +418,21 @@ static Value* handleSRetFuncTypeMerge(Value *V, const Type* Ty) { if (V->getType() == Ty) return V; - Value* Result = 0; const PointerType *PF1 = dyn_cast(Ty); const PointerType *PF2 = dyn_cast(V->getType()); if (PF1 && PF2) { - const FunctionType *FT1 = - dyn_cast(PF1->getElementType()); - const FunctionType *FT2 = - dyn_cast(PF2->getElementType()); + const FunctionType *FT1 = dyn_cast(PF1->getElementType()); + const FunctionType *FT2 = dyn_cast(PF2->getElementType()); if (FT1 && FT2 && FuncTysDifferOnlyBySRet(FT1, FT2)) if (FT2->paramHasAttr(1, FunctionType::StructRetAttribute)) - Result = V; + return V; else if (Constant *C = dyn_cast(V)) - Result = ConstantExpr::getBitCast(C, PF1); + return ConstantExpr::getBitCast(C, PF1); else - Result = new BitCastInst(V, PF1, "upgrd.cast", CurBB); + return new BitCastInst(V, PF1, "upgrd.cast", CurBB); + } - return Result; + return 0; } // getExistingValue - Look up the value specified by the provided type and @@ -350,9 +468,8 @@ static Value *getExistingValue(const Type *Ty, const ValID &D) { case ValID::NameVal: { // Is it a named definition? // Get the name out of the ID - std::string Name(D.Name); - Value* V = 0; - RenameMapKey Key = std::make_pair(Name, Ty); + RenameMapKey Key = makeRenameMapKey(D.Name, Ty, D.S); + Value *V = 0; if (inFunctionScope()) { // See if the name was renamed RenameMapType::const_iterator I = CurFun.RenameMap.find(Key); @@ -360,10 +477,12 @@ static Value *getExistingValue(const Type *Ty, const ValID &D) { if (I != CurFun.RenameMap.end()) LookupName = I->second; else - LookupName = Name; + LookupName = D.Name; ValueSymbolTable &SymTab = CurFun.CurrentFunction->getValueSymbolTable(); V = SymTab.lookup(LookupName); - V = handleSRetFuncTypeMerge(V, Ty); + if (V && V->getType() != Ty) + V = handleSRetFuncTypeMerge(V, Ty); + assert((!V || TypesDifferOnlyBySRet(V, Ty)) && "Found wrong type"); } if (!V) { RenameMapType::const_iterator I = CurModule.RenameMap.find(Key); @@ -371,9 +490,11 @@ static Value *getExistingValue(const Type *Ty, const ValID &D) { if (I != CurModule.RenameMap.end()) LookupName = I->second; else - LookupName = Name; + LookupName = D.Name; V = CurModule.CurrentModule->getValueSymbolTable().lookup(LookupName); - V = handleSRetFuncTypeMerge(V, Ty); + if (V && V->getType() != Ty) + V = handleSRetFuncTypeMerge(V, Ty); + assert((!V || TypesDifferOnlyBySRet(V, Ty)) && "Found wrong type"); } if (!V) return 0; @@ -506,14 +627,13 @@ static BasicBlock *getBBVal(const ValID &ID, bool isDefinition = false) { break; case ValID::NameVal: // Is it a named definition? Name = ID.Name; - if (Value *N = CurFun.CurrentFunction-> - getValueSymbolTable().lookup(Name)) { + if (Value *N = CurFun.CurrentFunction->getValueSymbolTable().lookup(Name)) { if (N->getType() != Type::LabelTy) { // Register names didn't use to conflict with basic block names // because of type planes. Now they all have to be unique. So, we just // rename the register and treat this name as if no basic block // had been found. - RenameMapKey Key = std::make_pair(N->getName(),N->getType()); + RenameMapKey Key = makeRenameMapKey(ID.Name, N->getType(), ID.S); N->setName(makeNameUnique(N->getName())); CurModule.RenameMap[Key] = N->getName(); BB = 0; @@ -624,19 +744,33 @@ ResolveDefinitions(std::map &LateResolvers, LateResolvers.clear(); } -// 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 ResolveTypeTo(char *Name, const Type *ToTy) { +/// This function is used for type resolution and upref handling. When a type +/// becomes concrete, this function is called to adjust the signedness for the +/// concrete type. +static void ResolveTypeSign(const Type* oldTy, const Signedness &Sign) { + std::string TyName = CurModule.CurrentModule->getTypeName(oldTy); + if (!TyName.empty()) + CurModule.NamedTypeSigns[TyName] = Sign; +} + +/// 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 ResolveTypeTo(char *Name, const Type *ToTy, const Signedness& Sign){ ValID D; - if (Name) D = ValID::create(Name); - else D = ValID::create((int)CurModule.Types.size()); + if (Name) + D = ValID::create(Name); + else + D = ValID::create((int)CurModule.Types.size()); + D.S.copy(Sign); + + CurModule.NamedTypeSigns[Name] = Sign; std::map::iterator I = CurModule.LateResolveTypes.find(D); if (I != CurModule.LateResolveTypes.end()) { - ((DerivedType*)I->second.get())->refineAbstractTypeTo(ToTy); + const Type *OldTy = I->second.get(); + ((DerivedType*)OldTy)->refineAbstractTypeTo(ToTy); CurModule.LateResolveTypes.erase(I); } } @@ -696,12 +830,12 @@ static inline bool TypeHasInteger(const Type *Ty) { // null potentially, in which case this is a noop. The string passed in is // assumed to be a malloc'd string buffer, and is free'd by this function. // -static void setValueName(Value *V, char *NameStr) { +static void setValueName(const ValueInfo &V, char *NameStr) { if (NameStr) { std::string Name(NameStr); // Copy string free(NameStr); // Free old string - if (V->getType() == Type::VoidTy) { + if (V.V->getType() == Type::VoidTy) { error("Can't assign name '" + Name + "' to value with void type"); return; } @@ -714,13 +848,13 @@ static void setValueName(Value *V, char *NameStr) { if (Existing) { // An existing value of the same name was found. This might have happened // because of the integer type planes collapsing in LLVM 2.0. - if (Existing->getType() == V->getType() && + if (Existing->getType() == V.V->getType() && !TypeHasInteger(Existing->getType())) { // If the type does not contain any integers in them then this can't be // a type plane collapsing issue. It truly is a redefinition and we // should error out as the assembly is invalid. error("Redefinition of value named '" + Name + "' of type '" + - V->getType()->getDescription() + "'"); + V.V->getType()->getDescription() + "'"); return; } // In LLVM 2.0 we don't allow names to be re-used for any values in a @@ -734,13 +868,13 @@ static void setValueName(Value *V, char *NameStr) { // We're changing the name but it will probably be used by other // instructions as operands later on. Consequently we have to retain // a mapping of the renaming that we're doing. - RenameMapKey Key = std::make_pair(Name,V->getType()); + RenameMapKey Key = makeRenameMapKey(Name, V.V->getType(), V.S); CurFun.RenameMap[Key] = NewName; Name = NewName; } // Set the name. - V->setName(Name); + V.V->setName(Name); } } @@ -749,7 +883,8 @@ static void setValueName(Value *V, char *NameStr) { static GlobalVariable * ParseGlobalVariable(char *NameStr,GlobalValue::LinkageTypes Linkage, bool isConstantGlobal, const Type *Ty, - Constant *Initializer) { + Constant *Initializer, + const Signedness &Sign) { if (isa(Ty)) error("Cannot declare global vars of function type"); @@ -769,6 +904,7 @@ ParseGlobalVariable(char *NameStr,GlobalValue::LinkageTypes Linkage, } else { ID = ValID::create((int)CurModule.Values[PTy].size()); } + ID.S.makeComposite(Sign); if (GlobalValue *FWGV = CurModule.GetForwardRefForGlobal(PTy, ID)) { // Move the global to the end of the list, from whereever it was @@ -794,13 +930,7 @@ ParseGlobalVariable(char *NameStr,GlobalValue::LinkageTypes Linkage, // There is alread a global of the same name which means there is a // conflict. Let's see what we can do about it. std::string NewName(makeNameUnique(Name)); - if (Linkage == GlobalValue::InternalLinkage) { - // The linkage type is internal so just warn about the rename without - // invoking "scarey language" about linkage failures. GVars with - // InternalLinkage can be renamed at will. - warning("Global variable '" + Name + "' was renamed to '"+ - NewName + "'"); - } else { + if (Linkage != GlobalValue::InternalLinkage) { // The linkage of this gval is external so we can't reliably rename // it because it could potentially create a linking problem. // However, we can't leave the name conflict in the output either or @@ -811,7 +941,7 @@ ParseGlobalVariable(char *NameStr,GlobalValue::LinkageTypes Linkage, } // Put the renaming in the global rename map - RenameMapKey Key = std::make_pair(Name,PointerType::get(Ty)); + RenameMapKey Key = makeRenameMapKey(Name, PointerType::get(Ty), ID.S); CurModule.RenameMap[Key] = NewName; // Rename it @@ -824,6 +954,8 @@ ParseGlobalVariable(char *NameStr,GlobalValue::LinkageTypes Linkage, new GlobalVariable(Ty, isConstantGlobal, Linkage, Initializer, Name, CurModule.CurrentModule); InsertValue(GV, CurModule.Values); + // Remember the sign of this global. + CurModule.NamedValueSigns[Name] = ID.S; return GV; } @@ -834,21 +966,26 @@ ParseGlobalVariable(char *NameStr,GlobalValue::LinkageTypes Linkage, // This function returns true if the type has already been defined, but is // allowed to be redefined in the specified context. If the name is a new name // for the type plane, it is inserted and false is returned. -static bool setTypeName(const Type *T, char *NameStr) { +static bool setTypeName(const PATypeInfo& TI, char *NameStr) { assert(!inFunctionScope() && "Can't give types function-local names"); if (NameStr == 0) return false; std::string Name(NameStr); // Copy string free(NameStr); // Free old string + const Type* Ty = TI.PAT->get(); + // We don't allow assigning names to void type - if (T == Type::VoidTy) { + if (Ty == Type::VoidTy) { error("Can't assign name '" + Name + "' to the void type"); return false; } // Set the type name, checking for conflicts as we do so. - bool AlreadyExists = CurModule.CurrentModule->addTypeName(Name, T); + bool AlreadyExists = CurModule.CurrentModule->addTypeName(Name, Ty); + + // Save the sign information for later use + CurModule.NamedTypeSigns[Name] = TI.S; if (AlreadyExists) { // Inserting a name that is already defined??? const Type *Existing = CurModule.CurrentModule->getTypeByName(Name); @@ -858,7 +995,7 @@ static bool setTypeName(const Type *T, char *NameStr) { // opaque type. In this case, Existing will be an opaque type. if (const OpaqueType *OpTy = dyn_cast(Existing)) { // We ARE replacing an opaque type! - const_cast(OpTy)->refineAbstractTypeTo(T); + const_cast(OpTy)->refineAbstractTypeTo(Ty); return true; } @@ -866,11 +1003,11 @@ static bool setTypeName(const Type *T, char *NameStr) { // the redefinition is identical to the original. This will be so if // Existing and T point to the same Type object. In this one case we // allow the equivalent redefinition. - if (Existing == T) return true; // Yes, it's equal. + if (Existing == Ty) return true; // Yes, it's equal. // Any other kind of (non-equivalent) redefinition is an error. error("Redefinition of type named '" + Name + "' in the '" + - T->getDescription() + "' type plane"); + Ty->getDescription() + "' type plane"); } return false; @@ -902,7 +1039,7 @@ namespace { OpaqueType *UpRefTy; UpRefRecord(unsigned NL, OpaqueType *URTy) - : NestingLevel(NL), LastContainedTy(URTy), UpRefTy(URTy) {} + : NestingLevel(NL), LastContainedTy(URTy), UpRefTy(URTy) { } }; } @@ -916,7 +1053,7 @@ static std::vector UpRefs; /// count reaches zero, the upreferenced type is the type that is passed in: /// thus we can complete the cycle. /// -static PATypeHolder HandleUpRefs(const Type *ty) { +static PATypeHolder HandleUpRefs(const Type *ty, const Signedness& Sign) { // If Ty isn't abstract, or if there are no up-references in it, then there is // nothing to resolve here. if (!ty->isAbstract() || UpRefs.empty()) return ty; @@ -932,10 +1069,11 @@ static PATypeHolder HandleUpRefs(const Type *ty) { // this variable. OpaqueType *TypeToResolve = 0; - for (unsigned i = 0; i != UpRefs.size(); ++i) { + unsigned i = 0; + for (; i != UpRefs.size(); ++i) { UR_OUT(" UR#" << i << " - TypeContains(" << Ty->getDescription() << ", " - << UpRefs[i].second->getDescription() << ") = " - << (TypeContains(Ty, UpRefs[i].second) ? "true" : "false") << "\n"); + << UpRefs[i].UpRefTy->getDescription() << ") = " + << (TypeContains(Ty, UpRefs[i].UpRefTy) ? "true" : "false") << "\n"); if (TypeContains(Ty, UpRefs[i].LastContainedTy)) { // Decrement level of upreference unsigned Level = --UpRefs[i].NestingLevel; @@ -946,8 +1084,9 @@ static PATypeHolder HandleUpRefs(const Type *ty) { TypeToResolve = UpRefs[i].UpRefTy; } else { UR_OUT(" * Resolving upreference for " - << UpRefs[i].second->getDescription() << "\n"; - std::string OldName = UpRefs[i].UpRefTy->getDescription()); + << UpRefs[i].UpRefTy->getDescription() << "\n"; + std::string OldName = UpRefs[i].UpRefTy->getDescription()); + ResolveTypeSign(UpRefs[i].UpRefTy, Sign); UpRefs[i].UpRefTy->refineAbstractTypeTo(TypeToResolve); UR_OUT(" * Type '" << OldName << "' refined upreference to: " << (const void*)Ty << ", " << Ty->getDescription() << "\n"); @@ -960,14 +1099,113 @@ static PATypeHolder HandleUpRefs(const Type *ty) { if (TypeToResolve) { UR_OUT(" * Resolving upreference for " - << UpRefs[i].second->getDescription() << "\n"; + << UpRefs[i].UpRefTy->getDescription() << "\n"; std::string OldName = TypeToResolve->getDescription()); + ResolveTypeSign(TypeToResolve, Sign); TypeToResolve->refineAbstractTypeTo(Ty); } return Ty; } +bool Signedness::operator<(const Signedness &that) const { + if (isNamed()) { + if (that.isNamed()) + return *(this->name) < *(that.name); + else + return CurModule.NamedTypeSigns[*name] < that; + } else if (that.isNamed()) { + return *this < CurModule.NamedTypeSigns[*that.name]; + } + + if (isComposite() && that.isComposite()) { + if (sv->size() == that.sv->size()) { + SignVector::const_iterator thisI = sv->begin(), thisE = sv->end(); + SignVector::const_iterator thatI = that.sv->begin(), + thatE = that.sv->end(); + for (; thisI != thisE; ++thisI, ++thatI) { + if (*thisI < *thatI) + return true; + else if (!(*thisI == *thatI)) + return false; + } + return false; + } + return sv->size() < that.sv->size(); + } + return kind < that.kind; +} + +bool Signedness::operator==(const Signedness &that) const { + if (isNamed()) + if (that.isNamed()) + return *(this->name) == *(that.name); + else + return CurModule.NamedTypeSigns[*(this->name)] == that; + else if (that.isNamed()) + return *this == CurModule.NamedTypeSigns[*(that.name)]; + if (isComposite() && that.isComposite()) { + if (sv->size() == that.sv->size()) { + SignVector::const_iterator thisI = sv->begin(), thisE = sv->end(); + SignVector::const_iterator thatI = that.sv->begin(), + thatE = that.sv->end(); + for (; thisI != thisE; ++thisI, ++thatI) { + if (!(*thisI == *thatI)) + return false; + } + return true; + } + return false; + } + return kind == that.kind; +} + +void Signedness::copy(const Signedness &that) { + if (that.isNamed()) { + kind = Named; + name = new std::string(*that.name); + } else if (that.isComposite()) { + kind = Composite; + sv = new SignVector(); + *sv = *that.sv; + } else { + kind = that.kind; + sv = 0; + } +} + +void Signedness::destroy() { + if (isNamed()) { + delete name; + } else if (isComposite()) { + delete sv; + } +} + +void Signedness::dump() const { + if (isComposite()) { + if (sv->size() == 1) { + (*sv)[0].dump(); + std::cerr << "*"; + } else { + std::cerr << "{ " ; + for (unsigned i = 0; i < sv->size(); ++i) { + if (i != 0) + std::cerr << ", "; + (*sv)[i].dump(); + } + std::cerr << "} " ; + } + } else if (isNamed()) { + std::cerr << *name; + } else if (isSigned()) { + std::cerr << "S"; + } else if (isUnsigned()) { + std::cerr << "U"; + } else + std::cerr << "."; +} + static inline Instruction::TermOps getTermOp(TermOps op) { switch (op) { @@ -982,7 +1220,7 @@ getTermOp(TermOps op) { } static inline Instruction::BinaryOps -getBinaryOp(BinaryOps op, const Type *Ty, Signedness Sign) { +getBinaryOp(BinaryOps op, const Type *Ty, const Signedness& Sign) { switch (op) { default : assert(0 && "Invalid OldBinaryOps"); case SetEQ : @@ -1003,7 +1241,7 @@ getBinaryOp(BinaryOps op, const Type *Ty, Signedness Sign) { isFP = PTy->getElementType()->isFloatingPoint(); if (isFP) return Instruction::FDiv; - else if (Sign == Signed) + else if (Sign.isSigned()) return Instruction::SDiv; return Instruction::UDiv; } @@ -1020,7 +1258,7 @@ getBinaryOp(BinaryOps op, const Type *Ty, Signedness Sign) { // Select correct opcode if (isFP) return Instruction::FRem; - else if (Sign == Signed) + else if (Sign.isSigned()) return Instruction::SRem; return Instruction::URem; } @@ -1031,7 +1269,7 @@ getBinaryOp(BinaryOps op, const Type *Ty, Signedness Sign) { case AShrOp : return Instruction::AShr; case ShlOp : return Instruction::Shl; case ShrOp : - if (Sign == Signed) + if (Sign.isSigned()) return Instruction::AShr; return Instruction::LShr; case AndOp : return Instruction::And; @@ -1042,8 +1280,8 @@ getBinaryOp(BinaryOps op, const Type *Ty, Signedness Sign) { static inline Instruction::OtherOps getCompareOp(BinaryOps op, unsigned short &predicate, const Type* &Ty, - Signedness Sign) { - bool isSigned = Sign == Signed; + const Signedness &Sign) { + bool isSigned = Sign.isSigned(); bool isFP = Ty->isFloatingPoint(); switch (op) { default : assert(0 && "Invalid OldSetCC"); @@ -1123,7 +1361,7 @@ static inline Instruction::MemoryOps getMemoryOp(MemoryOps op) { } static inline Instruction::OtherOps -getOtherOp(OtherOps op, Signedness Sign) { +getOtherOp(OtherOps op, const Signedness &Sign) { switch (op) { default : assert(0 && "Invalid OldOtherOps"); case PHIOp : return Instruction::PHI; @@ -1141,8 +1379,8 @@ getOtherOp(OtherOps op, Signedness Sign) { } static inline Value* -getCast(CastOps op, Value *Src, Signedness SrcSign, const Type *DstTy, - Signedness DstSign, bool ForceInstruction = false) { +getCast(CastOps op, Value *Src, const Signedness &SrcSign, const Type *DstTy, + const Signedness &DstSign, bool ForceInstruction = false) { Instruction::CastOps Opcode; const Type* SrcTy = Src->getType(); if (op == CastOp) { @@ -1179,7 +1417,8 @@ getCast(CastOps op, Value *Src, Signedness SrcSign, const Type *DstTy, } // Determine the opcode to use by calling CastInst::getCastOpcode Opcode = - CastInst::getCastOpcode(Src, SrcSign == Signed, DstTy, DstSign == Signed); + CastInst::getCastOpcode(Src, SrcSign.isSigned(), DstTy, + DstSign.isSigned()); } else switch (op) { default: assert(0 && "Invalid cast token"); @@ -1271,7 +1510,7 @@ const Type* upgradeGEPIndices(const Type* PTy, // all indices for SequentialType elements. We must retain the same // semantic (zext) for unsigned types. if (const IntegerType *Ity = dyn_cast(Index->getType())) - if (Ity->getBitWidth() < 64 && (*Indices)[i].S == Unsigned) { + if (Ity->getBitWidth() < 64 && (*Indices)[i].S.isUnsigned()) { if (CIndices) Index = ConstantExpr::getCast(Instruction::ZExt, cast(Index), Type::Int64Ty); @@ -1456,7 +1695,7 @@ using namespace llvm; llvm::Function *FunctionVal; std::pair *ArgVal; llvm::BasicBlock *BasicBlockVal; - llvm::TerminatorInst *TermInstVal; + llvm::TermInstInfo TermInstVal; llvm::InstrInfo InstVal; llvm::ConstInfo ConstVal; llvm::ValueInfo ValueVal; @@ -1769,7 +2008,7 @@ TypesV : Types | VOID { $$.PAT = new PATypeHolder($1.T); - $$.S = Signless; + $$.S.makeSignless(); } ; @@ -1777,7 +2016,7 @@ UpRTypesV : UpRTypes | VOID { $$.PAT = new PATypeHolder($1.T); - $$.S = Signless; + $$.S.makeSignless(); } ; @@ -1798,16 +2037,16 @@ PrimType UpRTypes : PrimType { $$.PAT = new PATypeHolder($1.T); - $$.S = $1.S; + $$.S.copy($1.S); } | OPAQUE { $$.PAT = new PATypeHolder(OpaqueType::get()); - $$.S = Signless; + $$.S.makeSignless(); } | SymbolicValueRef { // Named types are also simple types... + $$.S.copy(getTypeSign($1)); const Type* tmp = getType($1); $$.PAT = new PATypeHolder(tmp); - $$.S = Signless; // FIXME: what if its signed? } | '\\' EUINT64VAL { // Type UpReference if ($2 > (uint64_t)~0U) @@ -1815,14 +2054,16 @@ UpRTypes OpaqueType *OT = OpaqueType::get(); // Use temporary placeholder UpRefs.push_back(UpRefRecord((unsigned)$2, OT)); // Add to vector... $$.PAT = new PATypeHolder(OT); - $$.S = Signless; + $$.S.makeSignless(); UR_OUT("New Upreference!\n"); } | UpRTypesV '(' ArgTypeListI ')' { // Function derived type? + $$.S.makeComposite($1.S); std::vector Params; for (std::list::iterator I = $3->begin(), E = $3->end(); I != E; ++I) { Params.push_back(I->PAT->get()); + $$.S.add(I->S); } FunctionType::ParamAttrsList ParamAttrs; bool isVarArg = Params.size() && Params.back() == Type::VoidTy; @@ -1830,63 +2071,67 @@ UpRTypes $$.PAT = new PATypeHolder( HandleUpRefs(FunctionType::get($1.PAT->get(), Params, isVarArg, - ParamAttrs))); - $$.S = $1.S; - delete $1.PAT; // Delete the return type handle + ParamAttrs), $$.S)); + delete $1.PAT; // Delete the return type handle delete $3; // Delete the argument list } | '[' EUINT64VAL 'x' UpRTypes ']' { // Sized array type? + $$.S.makeComposite($4.S); $$.PAT = new PATypeHolder(HandleUpRefs(ArrayType::get($4.PAT->get(), - (unsigned)$2))); - $$.S = $4.S; + (unsigned)$2), $$.S)); delete $4.PAT; } | '<' EUINT64VAL 'x' UpRTypes '>' { // Vector type? - const llvm::Type* ElemTy = $4.PAT->get(); - if ((unsigned)$2 != $2) - error("Unsigned result not equal to signed result"); - if (!(ElemTy->isInteger() || ElemTy->isFloatingPoint())) - error("Elements of a VectorType must be integer or floating point"); - if (!isPowerOf2_32($2)) - error("VectorType length should be a power of 2"); - $$.PAT = new PATypeHolder(HandleUpRefs(VectorType::get(ElemTy, - (unsigned)$2))); - $$.S = $4.S; - delete $4.PAT; + const llvm::Type* ElemTy = $4.PAT->get(); + if ((unsigned)$2 != $2) + error("Unsigned result not equal to signed result"); + if (!(ElemTy->isInteger() || ElemTy->isFloatingPoint())) + error("Elements of a VectorType must be integer or floating point"); + if (!isPowerOf2_32($2)) + error("VectorType length should be a power of 2"); + $$.S.makeComposite($4.S); + $$.PAT = new PATypeHolder(HandleUpRefs(VectorType::get(ElemTy, + (unsigned)$2), $$.S)); + delete $4.PAT; } | '{' TypeListI '}' { // Structure type? std::vector Elements; + $$.S.makeComposite(); for (std::list::iterator I = $2->begin(), - E = $2->end(); I != E; ++I) + E = $2->end(); I != E; ++I) { Elements.push_back(I->PAT->get()); - $$.PAT = new PATypeHolder(HandleUpRefs(StructType::get(Elements))); - $$.S = Signless; + $$.S.add(I->S); + } + $$.PAT = new PATypeHolder(HandleUpRefs(StructType::get(Elements), $$.S)); delete $2; } | '{' '}' { // Empty structure type? $$.PAT = new PATypeHolder(StructType::get(std::vector())); - $$.S = Signless; + $$.S.makeComposite(); } | '<' '{' TypeListI '}' '>' { // Packed Structure type? + $$.S.makeComposite(); std::vector Elements; for (std::list::iterator I = $3->begin(), E = $3->end(); I != E; ++I) { Elements.push_back(I->PAT->get()); + $$.S.add(I->S); delete I->PAT; } - $$.PAT = new PATypeHolder(HandleUpRefs(StructType::get(Elements, true))); - $$.S = Signless; + $$.PAT = new PATypeHolder(HandleUpRefs(StructType::get(Elements, true), + $$.S)); delete $3; } | '<' '{' '}' '>' { // Empty packed structure type? $$.PAT = new PATypeHolder(StructType::get(std::vector(),true)); - $$.S = Signless; + $$.S.makeComposite(); } | UpRTypes '*' { // Pointer type? if ($1.PAT->get() == Type::LabelTy) error("Cannot form a pointer to a basic block"); - $$.PAT = new PATypeHolder(HandleUpRefs(PointerType::get($1.PAT->get()))); - $$.S = $1.S; + $$.S.makeComposite($1.S); + $$.PAT = new PATypeHolder(HandleUpRefs(PointerType::get($1.PAT->get()), + $$.S)); delete $1.PAT; } ; @@ -1910,14 +2155,14 @@ ArgTypeListI | TypeListI ',' DOTDOTDOT { PATypeInfo VoidTI; VoidTI.PAT = new PATypeHolder(Type::VoidTy); - VoidTI.S = Signless; + VoidTI.S.makeSignless(); ($$=$1)->push_back(VoidTI); } | DOTDOTDOT { $$ = new std::list(); PATypeInfo VoidTI; VoidTI.PAT = new PATypeHolder(Type::VoidTy); - VoidTI.S = Signless; + VoidTI.S.makeSignless(); $$->push_back(VoidTI); } | /*empty*/ { @@ -1958,7 +2203,7 @@ ConstVal Elems.push_back(C); } $$.C = ConstantArray::get(ATy, Elems); - $$.S = $1.S; + $$.S.copy($1.S); delete $1.PAT; delete $3; } @@ -1972,7 +2217,7 @@ ConstVal error("Type mismatch: constant sized array initialized with 0" " arguments, but has size of " + itostr(NumElements) +""); $$.C = ConstantArray::get(ATy, std::vector()); - $$.S = $1.S; + $$.S.copy($1.S); delete $1.PAT; } | Types 'c' STRINGCONSTANT { @@ -1995,7 +2240,7 @@ ConstVal Vals.push_back(ConstantInt::get(ETy, *C)); free($3); $$.C = ConstantArray::get(ATy, Vals); - $$.S = $1.S; + $$.S.copy($1.S); delete $1.PAT; } | Types '<' ConstVector '>' { // Nonempty unsized arr @@ -2022,7 +2267,7 @@ ConstVal Elems.push_back(C); } $$.C = ConstantVector::get(PTy, Elems); - $$.S = $1.S; + $$.S.copy($1.S); delete $1.PAT; delete $3; } @@ -2044,7 +2289,7 @@ ConstVal Fields.push_back(C); } $$.C = ConstantStruct::get(STy, Fields); - $$.S = $1.S; + $$.S.copy($1.S); delete $1.PAT; delete $3; } @@ -2056,7 +2301,7 @@ ConstVal if (STy->getNumContainedTypes() != 0) error("Illegal number of initializers for structure type"); $$.C = ConstantStruct::get(STy, std::vector()); - $$.S = $1.S; + $$.S.copy($1.S); delete $1.PAT; } | Types '<' '{' ConstVector '}' '>' { @@ -2077,7 +2322,7 @@ ConstVal Fields.push_back(C); } $$.C = ConstantStruct::get(STy, Fields); - $$.S = $1.S; + $$.S.copy($1.S); delete $1.PAT; delete $4; } @@ -2089,7 +2334,7 @@ ConstVal if (STy->getNumContainedTypes() != 0) error("Illegal number of initializers for packed structure type"); $$.C = ConstantStruct::get(STy, std::vector()); - $$.S = $1.S; + $$.S.copy($1.S); delete $1.PAT; } | Types NULL_TOK { @@ -2098,12 +2343,12 @@ ConstVal error("Cannot make null pointer constant with type: '" + $1.PAT->get()->getDescription() + "'"); $$.C = ConstantPointerNull::get(PTy); - $$.S = $1.S; + $$.S.copy($1.S); delete $1.PAT; } | Types UNDEF { $$.C = UndefValue::get($1.PAT->get()); - $$.S = $1.S; + $$.S.copy($1.S); delete $1.PAT; } | Types SymbolicValueRef { @@ -2121,6 +2366,7 @@ ConstVal // Function *SavedCurFn = CurFun.CurrentFunction; CurFun.CurrentFunction = 0; + $2.S.copy($1.S); Value *V = getExistingValue(Ty, $2); CurFun.CurrentFunction = SavedCurFn; @@ -2161,14 +2407,14 @@ ConstVal } } $$.C = cast(V); - $$.S = $1.S; + $$.S.copy($1.S); delete $1.PAT; // Free the type handle } | Types ConstExpr { if ($1.PAT->get() != $2.C->getType()) error("Mismatched types for constant expression"); $$ = $2; - $$.S = $1.S; + $$.S.copy($1.S); delete $1.PAT; } | Types ZEROINITIALIZER { @@ -2176,7 +2422,7 @@ ConstVal if (isa(Ty) || Ty == Type::LabelTy || isa(Ty)) error("Cannot create a null initialized value of this type"); $$.C = Constant::getNullValue(Ty); - $$.S = $1.S; + $$.S.copy($1.S); delete $1.PAT; } | SIntType EINT64VAL { // integral constants @@ -2184,28 +2430,28 @@ ConstVal if (!ConstantInt::isValueValidForType(Ty, $2)) error("Constant value doesn't fit in type"); $$.C = ConstantInt::get(Ty, $2); - $$.S = Signed; + $$.S.makeSigned(); } | UIntType EUINT64VAL { // integral constants const Type *Ty = $1.T; if (!ConstantInt::isValueValidForType(Ty, $2)) error("Constant value doesn't fit in type"); $$.C = ConstantInt::get(Ty, $2); - $$.S = Unsigned; + $$.S.makeUnsigned(); } | BOOL TRUETOK { // Boolean constants $$.C = ConstantInt::get(Type::Int1Ty, true); - $$.S = Unsigned; + $$.S.makeUnsigned(); } | BOOL FALSETOK { // Boolean constants $$.C = ConstantInt::get(Type::Int1Ty, false); - $$.S = Unsigned; + $$.S.makeUnsigned(); } | FPType FPVAL { // Float & Double constants if (!ConstantFP::isValueValidForType($1.T, $2)) error("Floating point constant invalid for type"); $$.C = ConstantFP::get($1.T, $2); - $$.S = Signless; + $$.S.makeSignless(); } ; @@ -2213,8 +2459,8 @@ ConstExpr : CastOps '(' ConstVal TO Types ')' { const Type* SrcTy = $3.C->getType(); const Type* DstTy = $5.PAT->get(); - Signedness SrcSign = $3.S; - Signedness DstSign = $5.S; + Signedness SrcSign($3.S); + Signedness DstSign($5.S); if (!SrcTy->isFirstClassType()) error("cast constant expression from a non-primitive type: '" + SrcTy->getDescription() + "'"); @@ -2222,7 +2468,7 @@ ConstExpr error("cast constant expression to a non-primitive type: '" + DstTy->getDescription() + "'"); $$.C = cast(getCast($1, $3.C, SrcSign, DstTy, DstSign)); - $$.S = DstSign; + $$.S.copy(DstSign); delete $5.PAT; } | GETELEMENTPTR '(' ConstVal IndexList ')' { @@ -2236,7 +2482,7 @@ ConstExpr delete $4; $$.C = ConstantExpr::getGetElementPtr($3.C, &CIndices[0], CIndices.size()); - $$.S = Signless; + $$.S.copy(getElementSign($3, CIndices)); } | SELECT '(' ConstVal ',' ConstVal ',' ConstVal ')' { if (!$3.C->getType()->isInteger() || @@ -2245,7 +2491,7 @@ ConstExpr if ($5.C->getType() != $7.C->getType()) error("Select operand types must match"); $$.C = ConstantExpr::getSelect($3.C, $5.C, $7.C); - $$.S = Unsigned; + $$.S.copy($5.S); } | ArithmeticOps '(' ConstVal ',' ConstVal ')' { const Type *Ty = $3.C->getType(); @@ -2273,7 +2519,7 @@ ConstExpr ConstantExpr::getCast(Instruction::PtrToInt, $5.C, IntPtrTy)); $$.C = ConstantExpr::getCast(Instruction::IntToPtr, $$.C, Ty); } - $$.S = $3.S; + $$.S.copy($3.S); } | LogicalOps '(' ConstVal ',' ConstVal ')' { const Type* Ty = $3.C->getType(); @@ -2286,7 +2532,7 @@ ConstExpr } Instruction::BinaryOps Opcode = getBinaryOp($1, Ty, $3.S); $$.C = ConstantExpr::get(Opcode, $3.C, $5.C); - $$.S = $3.S; + $$.S.copy($3.S); } | SetCondOps '(' ConstVal ',' ConstVal ')' { const Type* Ty = $3.C->getType(); @@ -2295,19 +2541,19 @@ ConstExpr unsigned short pred; Instruction::OtherOps Opcode = getCompareOp($1, pred, Ty, $3.S); $$.C = ConstantExpr::getCompare(Opcode, $3.C, $5.C); - $$.S = Unsigned; + $$.S.makeUnsigned(); } | ICMP IPredicates '(' ConstVal ',' ConstVal ')' { if ($4.C->getType() != $6.C->getType()) error("icmp operand types must match"); $$.C = ConstantExpr::getCompare($2, $4.C, $6.C); - $$.S = Unsigned; + $$.S.makeUnsigned(); } | FCMP FPredicates '(' ConstVal ',' ConstVal ')' { if ($4.C->getType() != $6.C->getType()) error("fcmp operand types must match"); $$.C = ConstantExpr::getCompare($2, $4.C, $6.C); - $$.S = Unsigned; + $$.S.makeUnsigned(); } | ShiftOps '(' ConstVal ',' ConstVal ')' { if (!$5.C->getType()->isInteger() || @@ -2318,25 +2564,25 @@ ConstExpr error("Shift constant expression requires integer operand"); Constant *ShiftAmt = ConstantExpr::getZExt($5.C, Ty); $$.C = ConstantExpr::get(getBinaryOp($1, Ty, $3.S), $3.C, ShiftAmt); - $$.S = $3.S; + $$.S.copy($3.S); } | EXTRACTELEMENT '(' ConstVal ',' ConstVal ')' { if (!ExtractElementInst::isValidOperands($3.C, $5.C)) error("Invalid extractelement operands"); $$.C = ConstantExpr::getExtractElement($3.C, $5.C); - $$.S = $3.S; + $$.S.copy($3.S.get(0)); } | INSERTELEMENT '(' ConstVal ',' ConstVal ',' ConstVal ')' { if (!InsertElementInst::isValidOperands($3.C, $5.C, $7.C)) error("Invalid insertelement operands"); $$.C = ConstantExpr::getInsertElement($3.C, $5.C, $7.C); - $$.S = $3.S; + $$.S.copy($3.S); } | SHUFFLEVECTOR '(' ConstVal ',' ConstVal ',' ConstVal ')' { if (!ShuffleVectorInst::isValidOperands($3.C, $5.C, $7.C)) error("Invalid shufflevector operands"); $$.C = ConstantExpr::getShuffleVector($3.C, $5.C, $7.C); - $$.S = $3.S; + $$.S.copy($3.S); } ; @@ -2405,13 +2651,13 @@ ConstPool // If types are not resolved eagerly, then the two types will not be // determined to be the same type! // - const Type* Ty = $4.PAT->get(); - ResolveTypeTo($2, Ty); + ResolveTypeTo($2, $4.PAT->get(), $4.S); - if (!setTypeName(Ty, $2) && !$2) { - // If this is a named type that is not a redefinition, add it to the slot - // table. - CurModule.Types.push_back(Ty); + if (!setTypeName($4, $2) && !$2) { + // If this is a numbered type that is not a redefinition, add it to the + // slot table. + CurModule.Types.push_back($4.PAT->get()); + CurModule.TypeSigns.push_back($4.S); } delete $4.PAT; } @@ -2422,20 +2668,22 @@ ConstPool | ConstPool OptAssign OptLinkage GlobalType ConstVal { if ($5.C == 0) error("Global value initializer is not a constant"); - CurGV = ParseGlobalVariable($2, $3, $4, $5.C->getType(), $5.C); + CurGV = ParseGlobalVariable($2, $3, $4, $5.C->getType(), $5.C, $5.S); } GlobalVarAttributes { CurGV = 0; } | ConstPool OptAssign EXTERNAL GlobalType Types { const Type *Ty = $5.PAT->get(); - CurGV = ParseGlobalVariable($2, GlobalValue::ExternalLinkage, $4, Ty, 0); + CurGV = ParseGlobalVariable($2, GlobalValue::ExternalLinkage, $4, Ty, 0, + $5.S); delete $5.PAT; } GlobalVarAttributes { CurGV = 0; } | ConstPool OptAssign DLLIMPORT GlobalType Types { const Type *Ty = $5.PAT->get(); - CurGV = ParseGlobalVariable($2, GlobalValue::DLLImportLinkage, $4, Ty, 0); + CurGV = ParseGlobalVariable($2, GlobalValue::DLLImportLinkage, $4, Ty, 0, + $5.S); delete $5.PAT; } GlobalVarAttributes { CurGV = 0; @@ -2443,7 +2691,8 @@ ConstPool | ConstPool OptAssign EXTERN_WEAK GlobalType Types { const Type *Ty = $5.PAT->get(); CurGV = - ParseGlobalVariable($2, GlobalValue::ExternalWeakLinkage, $4, Ty, 0); + ParseGlobalVariable($2, GlobalValue::ExternalWeakLinkage, $4, Ty, 0, + $5.S); delete $5.PAT; } GlobalVarAttributes { CurGV = 0; @@ -2553,14 +2802,14 @@ ArgList $$ = $1; PATypeInfo VoidTI; VoidTI.PAT = new PATypeHolder(Type::VoidTy); - VoidTI.S = Signless; + VoidTI.S.makeSignless(); $$->push_back(std::pair(VoidTI, 0)); } | DOTDOTDOT { $$ = new std::vector >(); PATypeInfo VoidTI; VoidTI.PAT = new PATypeHolder(Type::VoidTy); - VoidTI.S = Signless; + VoidTI.S.makeSignless(); $$->push_back(std::pair(VoidTI, 0)); } | /* empty */ { $$ = 0; } @@ -2577,6 +2826,8 @@ FunctionHeaderH if (!RetTy->isFirstClassType() && RetTy != Type::VoidTy) error("LLVM functions cannot return aggregate types"); + Signedness FTySign; + FTySign.makeComposite($2.S); std::vector ParamTyList; // In LLVM 2.0 the signatures of three varargs intrinsics changed to take @@ -2592,6 +2843,7 @@ FunctionHeaderH I = $5->begin(), E = $5->end(); I != E; ++I) { const Type *Ty = I->first.PAT->get(); ParamTyList.push_back(Ty); + FTySign.add(I->first.S); } } @@ -2618,6 +2870,7 @@ FunctionHeaderH } else { ID = ValID::create((int)CurModule.Values[PFT].size()); } + ID.S.makeComposite(FTySign); Function *Fn = 0; Module* M = CurModule.CurrentModule; @@ -2644,14 +2897,16 @@ FunctionHeaderH std::string NewName(makeNameUnique(FunctionName)); if (Conflict->hasInternalLinkage()) { Conflict->setName(NewName); - RenameMapKey Key = std::make_pair(FunctionName,Conflict->getType()); + RenameMapKey Key = + makeRenameMapKey(FunctionName, Conflict->getType(), ID.S); CurModule.RenameMap[Key] = NewName; Fn = new Function(FT, CurFun.Linkage, FunctionName, M); InsertValue(Fn, CurModule.Values); } else { Fn = new Function(FT, CurFun.Linkage, NewName, M); InsertValue(Fn, CurModule.Values); - RenameMapKey Key = std::make_pair(FunctionName,PFT); + RenameMapKey Key = + makeRenameMapKey(FunctionName, PFT, ID.S); CurModule.RenameMap[Key] = NewName; } } else { @@ -2673,9 +2928,11 @@ FunctionHeaderH // type plane. After PR411 was fixed, this is no loner the case. // To resolve this we must rename one of the two. if (Conflict->hasInternalLinkage()) { - // We can safely renamed the Conflict. + // We can safely rename the Conflict. + RenameMapKey Key = + makeRenameMapKey(Conflict->getName(), Conflict->getType(), + CurModule.NamedValueSigns[Conflict->getName()]); Conflict->setName(makeNameUnique(Conflict->getName())); - RenameMapKey Key = std::make_pair(FunctionName,Conflict->getType()); CurModule.RenameMap[Key] = Conflict->getName(); Fn = new Function(FT, CurFun.Linkage, FunctionName, M); InsertValue(Fn, CurModule.Values); @@ -2684,7 +2941,7 @@ FunctionHeaderH std::string NewName = makeNameUnique(FunctionName); Fn = new Function(FT, CurFun.Linkage, NewName, M); InsertValue(Fn, CurModule.Values); - RenameMapKey Key = std::make_pair(FunctionName,PFT); + RenameMapKey Key = makeRenameMapKey(FunctionName, PFT, ID.S); CurModule.RenameMap[Key] = NewName; } else { // We can't quietly rename either of these things, but we must @@ -2695,7 +2952,7 @@ FunctionHeaderH "' may cause linkage errors"); Fn = new Function(FT, CurFun.Linkage, NewName, M); InsertValue(Fn, CurModule.Values); - RenameMapKey Key = std::make_pair(FunctionName,PFT); + RenameMapKey Key = makeRenameMapKey(FunctionName, PFT, ID.S); CurModule.RenameMap[Key] = NewName; } } else { @@ -2734,7 +2991,8 @@ FunctionHeaderH std::vector >::iterator E = $5->end(); for ( ; I != E && ArgIt != ArgEnd; ++I, ++ArgIt) { delete I->first.PAT; // Delete the typeholder... - setValueName(ArgIt, I->second); // Insert arg into symtab... + ValueInfo VI; VI.V = ArgIt; VI.S.copy(I->first.S); + setValueName(VI, I->second); // Insert arg into symtab... InsertValue(ArgIt); } delete $5; // We're now done with the argument list @@ -2791,11 +3049,17 @@ OptSideEffect ConstValueRef // A reference to a direct constant - : ESINT64VAL { $$ = ValID::create($1); } + : ESINT64VAL { $$ = ValID::create($1); } | EUINT64VAL { $$ = ValID::create($1); } | FPVAL { $$ = ValID::create($1); } - | TRUETOK { $$ = ValID::create(ConstantInt::get(Type::Int1Ty, true)); } - | FALSETOK { $$ = ValID::create(ConstantInt::get(Type::Int1Ty, false)); } + | TRUETOK { + $$ = ValID::create(ConstantInt::get(Type::Int1Ty, true)); + $$.S.makeUnsigned(); + } + | FALSETOK { + $$ = ValID::create(ConstantInt::get(Type::Int1Ty, false)); + $$.S.makeUnsigned(); + } | NULL_TOK { $$ = ValID::createNull(); } | UNDEF { $$ = ValID::createUndef(); } | ZEROINITIALIZER { $$ = ValID::createZeroInit(); } @@ -2803,8 +3067,8 @@ ConstValueRef const Type *ETy = (*$2)[0].C->getType(); int NumElements = $2->size(); VectorType* pt = VectorType::get(ETy, NumElements); - PATypeHolder* PTy = new PATypeHolder( - HandleUpRefs(VectorType::get(ETy, NumElements))); + $$.S.makeComposite((*$2)[0].S); + PATypeHolder* PTy = new PATypeHolder(HandleUpRefs(pt, $$.S)); // Verify all elements are correct type! std::vector Elems; @@ -2822,6 +3086,7 @@ ConstValueRef } | ConstExpr { $$ = ValID::create($1.C); + $$.S.copy($1.S); } | ASM_TOK OptSideEffect STRINGCONSTANT ',' STRINGCONSTANT { char *End = UnEscapeLexed($3, true); @@ -2834,12 +3099,11 @@ ConstValueRef } ; -// SymbolicValueRef - Reference to one of two ways of symbolically refering to -// another value. +// SymbolicValueRef - Reference to one of two ways of symbolically refering to // another value. // SymbolicValueRef - : INTVAL { $$ = ValID::create($1); } - | Name { $$ = ValID::create($1); } + : INTVAL { $$ = ValID::create($1); $$.S.makeSignless(); } + | Name { $$ = ValID::create($1); $$.S.makeSignless(); } ; // ValueRef - A reference to a definition... either constant or symbolic @@ -2854,8 +3118,9 @@ ValueRef ResolvedVal : Types ValueRef { const Type *Ty = $1.PAT->get(); - $$.S = $1.S; + $2.S.copy($1.S); $$.V = getVal(Ty, $2); + $$.S.copy($1.S); delete $1.PAT; } ; @@ -2874,9 +3139,10 @@ BasicBlockList // BasicBlock : InstructionList OptAssign BBTerminatorInst { - setValueName($3, $2); - InsertValue($3); - $1->getInstList().push_back($3); + ValueInfo VI; VI.V = $3.TI; VI.S.copy($3.S); + setValueName(VI, $2); + InsertValue($3.TI); + $1->getInstList().push_back($3.TI); InsertValue($1); $$ = $1; } @@ -2889,7 +3155,7 @@ InstructionList $$ = $1; } | /* empty */ { - $$ = CurBB = getBBVal(ValID::create((int)CurFun.NextBBNum++), true); + $$ = CurBB = getBBVal(ValID::create((int)CurFun.NextBBNum++),true); // Make sure to move the basic block to the correct location in the // function, instead of leaving it inserted wherever it was first // referenced. @@ -2912,26 +3178,36 @@ Unwind : UNWIND | EXCEPT; BBTerminatorInst : RET ResolvedVal { // Return with a result... - $$ = new ReturnInst($2.V); + $$.TI = new ReturnInst($2.V); + $$.S.makeSignless(); } | RET VOID { // Return with no result... - $$ = new ReturnInst(); + $$.TI = new ReturnInst(); + $$.S.makeSignless(); } | BR LABEL ValueRef { // Unconditional Branch... BasicBlock* tmpBB = getBBVal($3); - $$ = new BranchInst(tmpBB); + $$.TI = new BranchInst(tmpBB); + $$.S.makeSignless(); } // Conditional Branch... | BR BOOL ValueRef ',' LABEL ValueRef ',' LABEL ValueRef { + $6.S.makeSignless(); + $9.S.makeSignless(); BasicBlock* tmpBBA = getBBVal($6); BasicBlock* tmpBBB = getBBVal($9); + $3.S.makeUnsigned(); Value* tmpVal = getVal(Type::Int1Ty, $3); - $$ = new BranchInst(tmpBBA, tmpBBB, tmpVal); + $$.TI = new BranchInst(tmpBBA, tmpBBB, tmpVal); + $$.S.makeSignless(); } | SWITCH IntType ValueRef ',' LABEL ValueRef '[' JumpTable ']' { + $3.S.copy($2.S); Value* tmpVal = getVal($2.T, $3); + $6.S.makeSignless(); BasicBlock* tmpBB = getBBVal($6); SwitchInst *S = new SwitchInst(tmpVal, tmpBB, $8->size()); - $$ = S; + $$.TI = S; + $$.S.makeSignless(); std::vector >::iterator I = $8->begin(), E = $8->end(); for (; I != E; ++I) { @@ -2943,24 +3219,31 @@ BBTerminatorInst delete $8; } | SWITCH IntType ValueRef ',' LABEL ValueRef '[' ']' { + $3.S.copy($2.S); Value* tmpVal = getVal($2.T, $3); + $6.S.makeSignless(); BasicBlock* tmpBB = getBBVal($6); SwitchInst *S = new SwitchInst(tmpVal, tmpBB, 0); - $$ = S; + $$.TI = S; + $$.S.makeSignless(); } | INVOKE OptCallingConv TypesV ValueRef '(' ValueRefListE ')' TO LABEL ValueRef Unwind LABEL ValueRef { const PointerType *PFTy; const FunctionType *Ty; + Signedness FTySign; if (!(PFTy = dyn_cast($3.PAT->get())) || !(Ty = dyn_cast(PFTy->getElementType()))) { // Pull out the types of all of the arguments... std::vector ParamTypes; + FTySign.makeComposite($3.S); if ($6) { for (std::vector::iterator I = $6->begin(), E = $6->end(); - I != E; ++I) + I != E; ++I) { ParamTypes.push_back((*I).V->getType()); + FTySign.add(I->S); + } } FunctionType::ParamAttrsList ParamAttrs; if ($2 == OldCallingConv::CSRet) { @@ -2971,14 +3254,19 @@ BBTerminatorInst if (isVarArg) ParamTypes.pop_back(); Ty = FunctionType::get($3.PAT->get(), ParamTypes, isVarArg, ParamAttrs); PFTy = PointerType::get(Ty); + $$.S.copy($3.S); + } else { + FTySign = $3.S; + $$.S.copy($3.S.get(0)); // 0th element of FuncTy sign is result ty } + $4.S.makeComposite(FTySign); Value *V = getVal(PFTy, $4); // Get the function we're calling... BasicBlock *Normal = getBBVal($10); BasicBlock *Except = getBBVal($13); // Create the call node... if (!$6) { // Has no arguments? - $$ = new InvokeInst(V, Normal, Except, 0, 0); + $$.TI = new InvokeInst(V, Normal, Except, 0, 0); } else { // Has arguments? // Loop through FunctionType's arguments and ensure they are specified // correctly! @@ -2998,38 +3286,44 @@ BBTerminatorInst if (I != E || (ArgI != ArgE && !Ty->isVarArg())) error("Invalid number of parameters detected"); - $$ = new InvokeInst(V, Normal, Except, &Args[0], Args.size()); + $$.TI = new InvokeInst(V, Normal, Except, &Args[0], Args.size()); } - cast($$)->setCallingConv(upgradeCallingConv($2)); + cast($$.TI)->setCallingConv(upgradeCallingConv($2)); delete $3.PAT; delete $6; } | Unwind { - $$ = new UnwindInst(); + $$.TI = new UnwindInst(); + $$.S.makeSignless(); } | UNREACHABLE { - $$ = new UnreachableInst(); + $$.TI = new UnreachableInst(); + $$.S.makeSignless(); } ; JumpTable : JumpTable IntType ConstValueRef ',' LABEL ValueRef { $$ = $1; + $3.S.copy($2.S); Constant *V = cast(getExistingValue($2.T, $3)); if (V == 0) error("May only switch on a constant pool value"); + $6.S.makeSignless(); BasicBlock* tmpBB = getBBVal($6); $$->push_back(std::make_pair(V, tmpBB)); } | IntType ConstValueRef ',' LABEL ValueRef { $$ = new std::vector >(); + $2.S.copy($1.S); Constant *V = cast(getExistingValue($1.T, $2)); if (V == 0) error("May only switch on a constant pool value"); + $5.S.makeSignless(); BasicBlock* tmpBB = getBBVal($5); $$->push_back(std::make_pair(V, tmpBB)); } @@ -3057,9 +3351,10 @@ Inst omit = true; if (omit) { $$.I = 0; - $$.S = Signless; + $$.S.makeSignless(); } else { - setValueName($2.I, $1); + ValueInfo VI; VI.V = $2.I; VI.S.copy($2.S); + setValueName(VI, $1); InsertValue($2.I); $$ = $2; } @@ -3067,15 +3362,19 @@ Inst PHIList : Types '[' ValueRef ',' ValueRef ']' { // Used for PHI nodes $$.P = new std::list >(); - $$.S = $1.S; + $$.S.copy($1.S); + $3.S.copy($1.S); Value* tmpVal = getVal($1.PAT->get(), $3); + $5.S.makeSignless(); BasicBlock* tmpBB = getBBVal($5); $$.P->push_back(std::make_pair(tmpVal, tmpBB)); delete $1.PAT; } | PHIList ',' '[' ValueRef ',' ValueRef ']' { $$ = $1; + $4.S.copy($1.S); Value* tmpVal = getVal($1.P->front().first->getType(), $4); + $6.S.makeSignless(); BasicBlock* tmpBB = getBBVal($6); $1.P->push_back(std::make_pair(tmpVal, tmpBB)); } @@ -3107,6 +3406,8 @@ OptTailCall InstVal : ArithmeticOps Types ValueRef ',' ValueRef { + $3.S.copy($2.S); + $5.S.copy($2.S); const Type* Ty = $2.PAT->get(); if (!Ty->isInteger() && !Ty->isFloatingPoint() && !isa(Ty)) error("Arithmetic operator requires integer, FP, or packed operands"); @@ -3120,10 +3421,12 @@ InstVal $$.I = BinaryOperator::create(Opcode, val1, val2); if ($$.I == 0) error("binary operator returned null"); - $$.S = $2.S; + $$.S.copy($2.S); delete $2.PAT; } | LogicalOps Types ValueRef ',' ValueRef { + $3.S.copy($2.S); + $5.S.copy($2.S); const Type *Ty = $2.PAT->get(); if (!Ty->isInteger()) { if (!isa(Ty) || @@ -3136,10 +3439,12 @@ InstVal $$.I = BinaryOperator::create(Opcode, tmpVal1, tmpVal2); if ($$.I == 0) error("binary operator returned null"); - $$.S = $2.S; + $$.S.copy($2.S); delete $2.PAT; } | SetCondOps Types ValueRef ',' ValueRef { + $3.S.copy($2.S); + $5.S.copy($2.S); const Type* Ty = $2.PAT->get(); if(isa(Ty)) error("VectorTypes currently not supported in setcc instructions"); @@ -3150,10 +3455,12 @@ InstVal $$.I = CmpInst::create(Opcode, pred, tmpVal1, tmpVal2); if ($$.I == 0) error("binary operator returned null"); - $$.S = Unsigned; + $$.S.makeUnsigned(); delete $2.PAT; } | ICMP IPredicates Types ValueRef ',' ValueRef { + $4.S.copy($3.S); + $6.S.copy($3.S); const Type *Ty = $3.PAT->get(); if (isa(Ty)) error("VectorTypes currently not supported in icmp instructions"); @@ -3162,10 +3469,12 @@ InstVal Value* tmpVal1 = getVal(Ty, $4); Value* tmpVal2 = getVal(Ty, $6); $$.I = new ICmpInst($2, tmpVal1, tmpVal2); - $$.S = Unsigned; + $$.S.makeUnsigned(); delete $3.PAT; } | FCMP FPredicates Types ValueRef ',' ValueRef { + $4.S.copy($3.S); + $6.S.copy($3.S); const Type *Ty = $3.PAT->get(); if (isa(Ty)) error("VectorTypes currently not supported in fcmp instructions"); @@ -3174,7 +3483,7 @@ InstVal Value* tmpVal1 = getVal(Ty, $4); Value* tmpVal2 = getVal(Ty, $6); $$.I = new FCmpInst($2, tmpVal1, tmpVal2); - $$.S = Unsigned; + $$.S.makeUnsigned(); delete $3.PAT; } | NOT ResolvedVal { @@ -3186,7 +3495,7 @@ InstVal $$.I = BinaryOperator::create(Instruction::Xor, $2.V, Ones); if ($$.I == 0) error("Could not create a xor instruction"); - $$.S = $2.S; + $$.S.copy($2.S); } | ShiftOps ResolvedVal ',' ResolvedVal { if (!$4.V->getType()->isInteger() || @@ -3204,7 +3513,7 @@ InstVal else ShiftAmt = $4.V; $$.I = BinaryOperator::create(getBinaryOp($1, Ty, $2.S), $2.V, ShiftAmt); - $$.S = $2.S; + $$.S.copy($2.S); } | CastOps ResolvedVal TO Types { const Type *DstTy = $4.PAT->get(); @@ -3212,7 +3521,7 @@ InstVal error("cast instruction to a non-primitive type: '" + DstTy->getDescription() + "'"); $$.I = cast(getCast($1, $2.V, $2.S, DstTy, $4.S, true)); - $$.S = $4.S; + $$.S.copy($4.S); delete $4.PAT; } | SELECT ResolvedVal ',' ResolvedVal ',' ResolvedVal { @@ -3222,13 +3531,13 @@ InstVal if ($4.V->getType() != $6.V->getType()) error("select value types should match"); $$.I = new SelectInst($2.V, $4.V, $6.V); - $$.S = $2.S; + $$.S.copy($4.S); } | VAARG ResolvedVal ',' Types { const Type *Ty = $4.PAT->get(); NewVarArgs = true; $$.I = new VAArgInst($2.V, Ty); - $$.S = $4.S; + $$.S.copy($4.S); delete $4.PAT; } | VAARG_old ResolvedVal ',' Types { @@ -3249,7 +3558,7 @@ InstVal CurBB->getInstList().push_back(bar); CurBB->getInstList().push_back(new StoreInst(bar, foo)); $$.I = new VAArgInst(foo, DstTy); - $$.S = $4.S; + $$.S.copy($4.S); delete $4.PAT; } | VANEXT_old ResolvedVal ',' Types { @@ -3273,26 +3582,26 @@ InstVal Instruction* tmp = new VAArgInst(foo, DstTy); CurBB->getInstList().push_back(tmp); $$.I = new LoadInst(foo); - $$.S = $4.S; + $$.S.copy($4.S); delete $4.PAT; } | EXTRACTELEMENT ResolvedVal ',' ResolvedVal { if (!ExtractElementInst::isValidOperands($2.V, $4.V)) error("Invalid extractelement operands"); $$.I = new ExtractElementInst($2.V, $4.V); - $$.S = $2.S; + $$.S.copy($2.S.get(0)); } | INSERTELEMENT ResolvedVal ',' ResolvedVal ',' ResolvedVal { if (!InsertElementInst::isValidOperands($2.V, $4.V, $6.V)) error("Invalid insertelement operands"); $$.I = new InsertElementInst($2.V, $4.V, $6.V); - $$.S = $2.S; + $$.S.copy($2.S); } | SHUFFLEVECTOR ResolvedVal ',' ResolvedVal ',' ResolvedVal { if (!ShuffleVectorInst::isValidOperands($2.V, $4.V, $6.V)) error("Invalid shufflevector operands"); $$.I = new ShuffleVectorInst($2.V, $4.V, $6.V); - $$.S = $2.S; + $$.S.copy($2.S); } | PHI_TOK PHIList { const Type *Ty = $2.P->front().first->getType(); @@ -3307,22 +3616,25 @@ InstVal $2.P->pop_front(); } $$.I = PHI; - $$.S = $2.S; + $$.S.copy($2.S); delete $2.P; // Free the list... } | OptTailCall OptCallingConv TypesV ValueRef '(' ValueRefListE ')' { - // Handle the short call syntax const PointerType *PFTy; const FunctionType *FTy; + Signedness FTySign; if (!(PFTy = dyn_cast($3.PAT->get())) || !(FTy = dyn_cast(PFTy->getElementType()))) { // Pull out the types of all of the arguments... std::vector ParamTypes; + FTySign.makeComposite($3.S); if ($6) { for (std::vector::iterator I = $6->begin(), E = $6->end(); - I != E; ++I) + I != E; ++I) { ParamTypes.push_back((*I).V->getType()); + FTySign.add(I->S); + } } FunctionType::ParamAttrsList ParamAttrs; @@ -3339,7 +3651,12 @@ InstVal FTy = FunctionType::get(RetTy, ParamTypes, isVarArg, ParamAttrs); PFTy = PointerType::get(FTy); + $$.S.copy($3.S); + } else { + FTySign = $3.S; + $$.S.copy($3.S.get(0)); // 0th element of FuncTy signedness is result sign } + $4.S.makeComposite(FTySign); // First upgrade any intrinsic calls. std::vector Args; @@ -3351,7 +3668,6 @@ InstVal // If we got an upgraded intrinsic if (Inst) { $$.I = Inst; - $$.S = Signless; } else { // Get the function we're calling Value *V = getVal(PFTy, $4); @@ -3383,7 +3699,6 @@ InstVal CI->setTailCall($1); CI->setCallingConv(upgradeCallingConv($2)); $$.I = CI; - $$.S = $3.S; } delete $3.PAT; delete $6; @@ -3408,25 +3723,27 @@ OptVolatile MemoryInst : MALLOC Types OptCAlign { const Type *Ty = $2.PAT->get(); - $$.S = $2.S; + $$.S.makeComposite($2.S); $$.I = new MallocInst(Ty, 0, $3); delete $2.PAT; } | MALLOC Types ',' UINT ValueRef OptCAlign { const Type *Ty = $2.PAT->get(); - $$.S = $2.S; + $5.S.makeUnsigned(); + $$.S.makeComposite($2.S); $$.I = new MallocInst(Ty, getVal($4.T, $5), $6); delete $2.PAT; } | ALLOCA Types OptCAlign { const Type *Ty = $2.PAT->get(); - $$.S = $2.S; + $$.S.makeComposite($2.S); $$.I = new AllocaInst(Ty, 0, $3); delete $2.PAT; } | ALLOCA Types ',' UINT ValueRef OptCAlign { const Type *Ty = $2.PAT->get(); - $$.S = $2.S; + $5.S.makeUnsigned(); + $$.S.makeComposite($4.S); $$.I = new AllocaInst(Ty, getVal($4.T, $5), $6); delete $2.PAT; } @@ -3435,11 +3752,11 @@ MemoryInst if (!isa(PTy)) error("Trying to free nonpointer type '" + PTy->getDescription() + "'"); $$.I = new FreeInst($2.V); - $$.S = Signless; + $$.S.makeSignless(); } | OptVolatile LOAD Types ValueRef { const Type* Ty = $3.PAT->get(); - $$.S = $3.S; + $4.S.copy($3.S); if (!isa(Ty)) error("Can't load from nonpointer type: " + Ty->getDescription()); if (!cast(Ty)->getElementType()->isFirstClassType()) @@ -3447,9 +3764,11 @@ MemoryInst Ty->getDescription()); Value* tmpVal = getVal(Ty, $4); $$.I = new LoadInst(tmpVal, "", $1); + $$.S.copy($3.S.get(0)); delete $3.PAT; } | OptVolatile STORE ResolvedVal ',' Types ValueRef { + $6.S.copy($5.S); const PointerType *PTy = dyn_cast($5.PAT->get()); if (!PTy) error("Can't store to a nonpointer type: " + @@ -3471,10 +3790,11 @@ MemoryInst } } $$.I = new StoreInst(StoreVal, tmpVal, $1); - $$.S = Signless; + $$.S.makeSignless(); delete $5.PAT; } | GETELEMENTPTR Types ValueRef IndexList { + $3.S.copy($2.S); const Type* Ty = $2.PAT->get(); if (!isa(Ty)) error("getelementptr insn requires pointer operand"); @@ -3484,7 +3804,8 @@ MemoryInst Value* tmpVal = getVal(Ty, $3); $$.I = new GetElementPtrInst(tmpVal, &VIndices[0], VIndices.size()); - $$.S = Signless; + ValueInfo VI; VI.V = tmpVal; VI.S.copy($2.S); + $$.S.copy(getElementSign(VI, VIndices)); delete $2.PAT; delete $4; };