diff options
-rw-r--r-- | tools/llvm-upgrade/UpgradeInternals.h | 161 | ||||
-rw-r--r-- | tools/llvm-upgrade/UpgradeLexer.l | 43 | ||||
-rw-r--r-- | tools/llvm-upgrade/UpgradeParser.y | 755 |
3 files changed, 708 insertions, 251 deletions
diff --git a/tools/llvm-upgrade/UpgradeInternals.h b/tools/llvm-upgrade/UpgradeInternals.h index bbf6737828..0e00400796 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 <list> +#include <iostream> // 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<Signedness> 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<std::pair<llvm::Value*, llvm::BasicBlock*> > *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 ebab6db9c0..300cf5cc1a 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 75d85e3369..9dabc23d75 100644 --- a/tools/llvm-upgrade/UpgradeParser.y +++ b/tools/llvm-upgrade/UpgradeParser.y @@ -67,7 +67,7 @@ static GlobalVariable *CurGV; // typedef std::vector<Value *> ValueList; // Numbered defs -typedef std::pair<std::string,const Type*> RenameMapKey; +typedef std::pair<std::string,TypeInfo> RenameMapKey; typedef std::map<RenameMapKey,std::string> RenameMapType; static void @@ -78,7 +78,10 @@ static struct PerModuleInfo { Module *CurrentModule; std::map<const Type *, ValueList> Values; // Module level numbered definitions std::map<const Type *,ValueList> LateResolveValues; - std::vector<PATypeHolder> Types; + std::vector<PATypeHolder> Types; + std::vector<Signedness> TypeSigns; + std::map<std::string,Signedness> NamedTypeSigns; + std::map<std::string,Signedness> NamedValueSigns; std::map<ValID, PATypeHolder> 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<std::string,Signedness>::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<Value*> &Indices) { + const Type *Ptr = VI.V->getType(); + assert(isa<PointerType>(Ptr) && "Need pointer type"); + + unsigned CurIdx = 0; + Signedness S(VI.S); + while (const CompositeType *CT = dyn_cast<CompositeType>(Ptr)) { + if (CurIdx == Indices.size()) + break; + + Value *Index = Indices[CurIdx++]; + assert(!isa<PointerType>(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<StructType>(CT)) { + S = S.get(cast<ConstantInt>(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<Constant*> &Indices) { + ValueInfo VI; + VI.V = CI.C; + VI.S.copy(CI.S); + std::vector<Value*> 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<PointerType>(Ty); + const PointerType *PF2 = dyn_cast<PointerType>(V->getType()); + if (PF1 && PF2) { + const FunctionType* FT1 = dyn_cast<FunctionType>(PF1->getElementType()); + const FunctionType* FT2 = dyn_cast<FunctionType>(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<PointerType>(Ty); const PointerType *PF2 = dyn_cast<PointerType>(V->getType()); if (PF1 && PF2) { - const FunctionType *FT1 = - dyn_cast<FunctionType>(PF1->getElementType()); - const FunctionType *FT2 = - dyn_cast<FunctionType>(PF2->getElementType()); + const FunctionType *FT1 = dyn_cast<FunctionType>(PF1->getElementType()); + const FunctionType *FT2 = dyn_cast<FunctionType>(PF2->getElementType()); if (FT1 && FT2 && FuncTysDifferOnlyBySRet(FT1, FT2)) if (FT2->paramHasAttr(1, FunctionType::StructRetAttribute)) - Result = V; + return V; else if (Constant *C = dyn_cast<Constant>(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<const Type*,ValueList> &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<ValID, PATypeHolder>::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<FunctionType>(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<OpaqueType>(Existing)) { // We ARE replacing an opaque type! - const_cast<OpaqueType*>(OpTy)->refineAbstractTypeTo(T); + const_cast<OpaqueType*>(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<UpRefRecord> 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; |