llvm-6502/tools/llvm-upgrade/ParserInternals.h
Reid Spencer 2b8036e2c8 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.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@32810 91177308-0d34-0410-b5e6-96231b3b80d8
2007-01-02 05:44:33 +00:00

257 lines
7.8 KiB
C++

//===-- ParserInternals.h - Definitions internal to the parser --*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by Reid Spencer and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This header file defines the variables that are shared between the lexer,
// the parser, and the main program.
//
//===----------------------------------------------------------------------===//
#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...
extern std::string CurFileName;
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;
extern unsigned SizeOfPointer;
int yyerror(const char *ErrorMsg) ;
/// This enum is used to keep track of the original (1.9) type used to form
/// a type. These are needed for type upgrades and to determine how to upgrade
/// signed instructions with signless operands.
enum Types {
BoolTy, SByteTy, UByteTy, ShortTy, UShortTy, IntTy, UIntTy, LongTy, ULongTy,
FloatTy, DoubleTy, PointerTy, PackedTy, ArrayTy, StructTy, PackedStructTy,
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
/// it can be used by the parser for upgrade decisions.
/// For example if "uint" is encountered then the "first" field will be set
/// 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 {
TypeInfo()
: newTy(0), oldTy(UnresolvedTy), elemTy(0), resultTy(0), elements(0),
nelems(0) {
}
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;
}
bool isUnsigned() const {
return oldTy == UByteTy || oldTy == UShortTy ||
oldTy == UIntTy || oldTy == ULongTy;
}
bool isSignless() const { return !isSigned() && !isUnsigned(); }
bool isInteger() const { return isSigned() || isUnsigned(); }
bool isIntegral() const { return oldTy == BoolTy || isInteger(); }
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;
}
unsigned getBitWidth() const {
switch (oldTy) {
default:
case LabelTy:
case VoidTy : return 0;
case BoolTy : return 1;
case SByteTy: case UByteTy : return 8;
case ShortTy: case UShortTy : return 16;
case IntTy: case UIntTy: case FloatTy: return 32;
case LongTy: case ULongTy: case DoubleTy : return 64;
case PointerTy: return SizeOfPointer; // global var
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;
}
}
}
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; delete type; }
};
typedef std::vector<ValueInfo> ValueList;
inline void ValueInfo::destroy() { delete val; delete type; }
#endif