For PR1070:

Revise the upgrade parser to keep track of types more faithfully and use
this information to resolve name conflicts resulting from collapsed type
planes. The type planes have collapsed because the integer types are now
signless so that uint and int became i32. Where two planes existed for uint
and int, only i32 exists. Any variable names depending on the type planes
to pmake the identifier unique would cause a conflict. This patch resolves
that conflict for many but not all cases.

Situations involving the integer types and pointers to them are handled
by this patch.  However, there are corner cases that are not handled
well, such as:

%t1 = type { uint, int }
%t2 = type { int, uint }

void %myfunc(%t1* one, %t2* two) {
  %var = load %t1* one
  %var = load %t2* two
}

In the scenario above, %t1 and %t2 are really the same type: { i32, i32 }
Consequently attempting to name %var twice will yield a redefinition error
when assembled.

While this patch is sufficien to allow the llvm/test suite to pass, More
work needs to be to complete the handling of these corner cases.

llvm-svn: 32810
This commit is contained in:
Reid Spencer 2007-01-02 05:44:33 +00:00
parent 51397401ba
commit 25f4cd093b
3 changed files with 565 additions and 315 deletions

View File

@ -15,9 +15,11 @@
#ifndef PARSER_INTERNALS_H
#define PARSER_INTERNALS_H
#include <llvm/ADT/StringExtras.h>
#include <string>
#include <istream>
#include <vector>
#include <cassert>
// Global variables exported from the lexer...
@ -26,11 +28,15 @@ extern std::string Textin;
extern int Upgradelineno;
extern std::istream* LexInput;
struct TypeInfo;
typedef std::vector<TypeInfo*> TypeList;
void UpgradeAssembly(
const std::string & infile, std::istream& in, std::ostream &out, bool debug,
bool addAttrs);
TypeInfo* ResolveType(TypeInfo*& Ty);
// Globals exported by the parser...
extern char* Upgradetext;
extern int Upgradeleng;
@ -47,6 +53,17 @@ enum Types {
OpaqueTy, VoidTy, LabelTy, FunctionTy, UnresolvedTy, NumericTy
};
/// This type is used to keep track of the signedness of values. Instead
/// of creating llvm::Value directly, the parser will create ValueInfo which
/// associates a Value* with a Signedness indication.
struct ValueInfo {
std::string* val;
TypeInfo* type;
bool constant;
bool isConstant() const { return constant; }
inline void destroy();
};
/// This type is used to keep track of the signedness of the obsolete
/// integer types. Instead of creating an llvm::Type directly, the Lexer will
/// create instances of TypeInfo which retains the signedness indication so
@ -55,20 +72,89 @@ enum Types {
/// to "int32" and the "second" field will be set to "isUnsigned". If the
/// type is not obsolete then "second" will be set to "isSignless".
struct TypeInfo {
std::string* newTy;
Types oldTy;
Types elemTy;
void destroy() const { delete newTy; }
TypeInfo clone() const {
TypeInfo result = *this;
result.newTy = new std::string(*newTy);
return result;
TypeInfo()
: newTy(0), oldTy(UnresolvedTy), elemTy(0), resultTy(0), elements(0),
nelems(0) {
}
Types getElementType() const { return elemTy; }
TypeInfo(const char * newType, Types oldType)
: newTy(0), oldTy(oldType), elemTy(0), resultTy(0), elements(0), nelems(0) {
newTy = new std::string(newType);
}
TypeInfo(std::string *newType, Types oldType, TypeInfo* eTy = 0,
TypeInfo *rTy = 0)
: newTy(newType), oldTy(oldType), elemTy(eTy), resultTy(rTy), elements(0),
nelems(0) {
}
TypeInfo(std::string *newType, Types oldType, TypeInfo *eTy, uint64_t elems)
: newTy(newType), oldTy(oldType), elemTy(eTy), resultTy(0), elements(0),
nelems(elems) {
}
TypeInfo(std::string *newType, Types oldType, TypeList* TL)
: newTy(newType), oldTy(oldType), elemTy(0), resultTy(0), elements(TL),
nelems(0) {
}
TypeInfo(std::string *newType, TypeInfo* resTy, TypeList* TL)
: newTy(newType), oldTy(FunctionTy), elemTy(0), resultTy(resTy),
elements(TL), nelems(0) {
}
TypeInfo(const TypeInfo& that)
: newTy(0), oldTy(that.oldTy), elemTy(0), resultTy(0), elements(0),
nelems(0) {
*this = that;
}
TypeInfo& operator=(const TypeInfo& that) {
oldTy = that.oldTy;
nelems = that.nelems;
if (that.newTy)
newTy = new std::string(*that.newTy);
if (that.elemTy)
elemTy = that.elemTy->clone();
if (that.resultTy)
resultTy = that.resultTy->clone();
if (that.elements) {
elements = new std::vector<TypeInfo*>(that.elements->size());
*elements = *that.elements;
}
return *this;
}
~TypeInfo() {
delete newTy; delete elemTy; delete resultTy; delete elements;
}
TypeInfo* clone() const {
return new TypeInfo(*this);
}
Types getElementTy() const {
if (elemTy) {
return elemTy->oldTy;
}
return UnresolvedTy;
}
const std::string& getNewTy() const { return *newTy; }
void setOldTy(Types Ty) { oldTy = Ty; }
TypeInfo* getResultType() const { return resultTy; }
TypeInfo* getElementType() const { return elemTy; }
TypeInfo* getPointerType() const {
std::string* ty = new std::string(*newTy + "*");
return new TypeInfo(ty, PointerTy, this->clone(), (TypeInfo*)0);
}
bool isUnresolved() const { return oldTy == UnresolvedTy; }
bool isNumeric() const { return oldTy == NumericTy; }
bool isVoid() const { return oldTy == VoidTy; }
bool isBool() const { return oldTy == BoolTy; }
bool isSigned() const {
return oldTy == SByteTy || oldTy == ShortTy ||
oldTy == IntTy || oldTy == LongTy;
@ -79,9 +165,6 @@ struct TypeInfo {
oldTy == UIntTy || oldTy == ULongTy;
}
bool isBool() const {
return oldTy == BoolTy;
}
bool isSignless() const { return !isSigned() && !isUnsigned(); }
bool isInteger() const { return isSigned() || isUnsigned(); }
@ -89,8 +172,14 @@ struct TypeInfo {
bool isFloatingPoint() const { return oldTy == DoubleTy || oldTy == FloatTy; }
bool isPacked() const { return oldTy == PackedTy; }
bool isPointer() const { return oldTy == PointerTy; }
bool isStruct() const { return oldTy == StructTy || oldTy == PackedStructTy; }
bool isArray() const { return oldTy == ArrayTy; }
bool isOther() const {
return !isPacked() && !isPointer() && !isFloatingPoint() && !isIntegral(); }
bool isFunction() const { return oldTy == FunctionTy; }
bool isComposite() const {
return isStruct() || isPointer() || isArray() || isPacked();
}
bool isAttributeCandidate() const {
return isIntegral() && getBitWidth() < 32;
@ -98,6 +187,7 @@ struct TypeInfo {
unsigned getBitWidth() const {
switch (oldTy) {
default:
case LabelTy:
case VoidTy : return 0;
case BoolTy : return 1;
@ -106,32 +196,61 @@ struct TypeInfo {
case IntTy: case UIntTy: case FloatTy: return 32;
case LongTy: case ULongTy: case DoubleTy : return 64;
case PointerTy: return SizeOfPointer; // global var
default:
return 128; /// Struct/Packed/Array --> doesn't matter
case PackedTy:
case ArrayTy:
return nelems * elemTy->getBitWidth();
case StructTy:
case PackedStructTy: {
uint64_t size = 0;
for (unsigned i = 0; i < elements->size(); i++) {
ResolveType((*elements)[i]);
size += (*elements)[i]->getBitWidth();
}
return size;
}
}
}
};
/// This type is used to keep track of the signedness of values. Instead
/// of creating llvm::Value directly, the parser will create ValueInfo which
/// associates a Value* with a Signedness indication.
struct ValueInfo {
std::string* val;
TypeInfo type;
bool constant;
bool isConstant() const { return constant; }
void destroy() { delete val; type.destroy(); }
TypeInfo* getIndexedType(const ValueInfo& VI) {
if (isStruct()) {
if (VI.isConstant() && VI.type->isInteger()) {
size_t pos = VI.val->find(' ') + 1;
if (pos < VI.val->size()) {
uint64_t idx = atoi(VI.val->substr(pos).c_str());
return (*elements)[idx];
} else {
yyerror("Invalid value for constant integer");
return 0;
}
} else {
yyerror("Structure requires constant index");
return 0;
}
}
if (isArray() || isPacked() || isPointer())
return elemTy;
yyerror("Invalid type for getIndexedType");
return 0;
}
private:
std::string* newTy;
Types oldTy;
TypeInfo *elemTy;
TypeInfo *resultTy;
TypeList *elements;
uint64_t nelems;
};
/// This type is used to keep track of the signedness of constants.
struct ConstInfo {
std::string *cnst;
TypeInfo type;
void destroy() { delete cnst; type.destroy(); }
TypeInfo *type;
void destroy() { delete cnst; delete type; }
};
typedef std::vector<ValueInfo> ValueList;
inline void ValueInfo::destroy() { delete val; delete type; }
#endif

View File

@ -48,9 +48,7 @@
return sym
#define RET_TY(sym,OldTY,NewTY,sign) \
Upgradelval.Type.newTy = new std::string(NewTY); \
Upgradelval.Type.oldTy = OldTY; \
Upgradelval.Type.elemTy = VoidTy; \
Upgradelval.Type = new TypeInfo(NewTY, OldTY); \
return sym
#define YY_NEVER_INTERACTIVE 1

File diff suppressed because it is too large Load Diff