Implement constant pointers, and null specifically in the parser, bytecode writer, and

bytecode reader.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@668 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2001-09-30 22:46:54 +00:00
parent 4cfb153316
commit 1a1cb111fe
5 changed files with 81 additions and 36 deletions

View File

@ -128,6 +128,7 @@ uninitialized { return UNINIT; }
implementation { return IMPLEMENTATION; } implementation { return IMPLEMENTATION; }
\.\.\. { return DOTDOTDOT; } \.\.\. { return DOTDOTDOT; }
string { return STRING; } string { return STRING; }
null { return NULL_TOK; }
void { llvmAsmlval.PrimType = Type::VoidTy ; return VOID; } void { llvmAsmlval.PrimType = Type::VoidTy ; return VOID; }
bool { llvmAsmlval.PrimType = Type::BoolTy ; return BOOL; } bool { llvmAsmlval.PrimType = Type::BoolTy ; return BOOL; }

View File

@ -63,9 +63,11 @@ static inline void ThrowException(const string &message,
// putting classes with ctor's in unions. :( // putting classes with ctor's in unions. :(
// //
struct ValID { struct ValID {
int Type; // 0 = number, 1 = name, 2 = const pool, enum {
// 3 = unsigned const pool, 4 = const string, NumberVal, NameVal, ConstSIntVal, ConstUIntVal, ConstStringVal,
// 5 = const fp ConstFPVal, ConstNullVal
} Type;
union { union {
int Num; // If it's a numeric reference int Num; // If it's a numeric reference
char *Name; // If it's a named reference. Memory must be free'd. char *Name; // If it's a named reference. Memory must be free'd.
@ -75,35 +77,40 @@ struct ValID {
}; };
static ValID create(int Num) { static ValID create(int Num) {
ValID D; D.Type = 0; D.Num = Num; return D; ValID D; D.Type = NumberVal; D.Num = Num; return D;
} }
static ValID create(char *Name) { static ValID create(char *Name) {
ValID D; D.Type = 1; D.Name = Name; return D; ValID D; D.Type = NameVal; D.Name = Name; return D;
} }
static ValID create(int64_t Val) { static ValID create(int64_t Val) {
ValID D; D.Type = 2; D.ConstPool64 = Val; return D; ValID D; D.Type = ConstSIntVal; D.ConstPool64 = Val; return D;
} }
static ValID create(uint64_t Val) { static ValID create(uint64_t Val) {
ValID D; D.Type = 3; D.UConstPool64 = Val; return D; ValID D; D.Type = ConstUIntVal; D.UConstPool64 = Val; return D;
} }
static ValID create_conststr(char *Name) { static ValID create_conststr(char *Name) {
ValID D; D.Type = 4; D.Name = Name; return D; ValID D; D.Type = ConstStringVal; D.Name = Name; return D;
} }
static ValID create(double Val) { static ValID create(double Val) {
ValID D; D.Type = 5; D.ConstPoolFP = Val; return D; ValID D; D.Type = ConstFPVal; D.ConstPoolFP = Val; return D;
}
static ValID createNull() {
ValID D; D.Type = ConstNullVal; return D;
} }
inline void destroy() const { inline void destroy() const {
if (Type == 1 || Type == 4) free(Name); // Free this strdup'd memory... if (Type == NameVal || Type == ConstStringVal)
free(Name); // Free this strdup'd memory...
} }
inline ValID copy() const { inline ValID copy() const {
if (Type != 1 && Type != 4) return *this; if (Type != NameVal && Type != ConstStringVal) return *this;
ValID Result = *this; ValID Result = *this;
Result.Name = strdup(Name); Result.Name = strdup(Name);
return Result; return Result;
@ -111,11 +118,16 @@ struct ValID {
inline string getName() const { inline string getName() const {
switch (Type) { switch (Type) {
case 0: return string("#") + itostr(Num); case NumberVal : return string("#") + itostr(Num);
case 1: return Name; case NameVal : return Name;
case 4: return string("\"") + Name + string("\""); case ConstStringVal: return string("\"") + Name + string("\"");
case 5: return ftostr(ConstPoolFP); case ConstFPVal : return ftostr(ConstPoolFP);
default: return string("%") + itostr(ConstPool64); case ConstNullVal : return "null";
case ConstUIntVal :
case ConstSIntVal : return string("%") + itostr(ConstPool64);
default:
assert(0 && "Unknown value!");
abort();
} }
} }
}; };

View File

@ -180,7 +180,7 @@ static Value *getVal(const Type *Ty, const ValID &D,
assert(Ty != Type::TypeTy && "Should use getTypeVal for types!"); assert(Ty != Type::TypeTy && "Should use getTypeVal for types!");
switch (D.Type) { switch (D.Type) {
case 0: { // Is it a numbered definition? case ValID::NumberVal: { // Is it a numbered definition?
unsigned type = Ty->getUniqueID(); unsigned type = Ty->getUniqueID();
unsigned Num = (unsigned)D.Num; unsigned Num = (unsigned)D.Num;
@ -202,7 +202,7 @@ static Value *getVal(const Type *Ty, const ValID &D,
return CurMeth.Values[type][Num]; return CurMeth.Values[type][Num];
} }
case 1: { // Is it a named definition? case ValID::NameVal: { // Is it a named definition?
string Name(D.Name); string Name(D.Name);
SymbolTable *SymTab = 0; SymbolTable *SymTab = 0;
if (CurMeth.CurrentMethod) if (CurMeth.CurrentMethod)
@ -223,16 +223,17 @@ static Value *getVal(const Type *Ty, const ValID &D,
return N; return N;
} }
case 2: // Is it a constant pool reference?? case ValID::ConstSIntVal: // Is it a constant pool reference??
case 3: // Is it an unsigned const pool reference? case ValID::ConstUIntVal: // Is it an unsigned const pool reference?
case 4: // Is it a string const pool reference? case ValID::ConstStringVal: // Is it a string const pool reference?
case 5:{ // Is it a floating point const pool reference? case ValID::ConstFPVal: // Is it a floating point const pool reference?
case ValID::ConstNullVal: { // Is it a null value?
ConstPoolVal *CPV = 0; ConstPoolVal *CPV = 0;
// Check to make sure that "Ty" is an integral type, and that our // Check to make sure that "Ty" is an integral type, and that our
// value will fit into the specified type... // value will fit into the specified type...
switch (D.Type) { switch (D.Type) {
case 2: case ValID::ConstSIntVal:
if (Ty == Type::BoolTy) { // Special handling for boolean data if (Ty == Type::BoolTy) { // Special handling for boolean data
CPV = ConstPoolBool::get(D.ConstPool64 != 0); CPV = ConstPoolBool::get(D.ConstPool64 != 0);
} else { } else {
@ -243,7 +244,7 @@ static Value *getVal(const Type *Ty, const ValID &D,
CPV = ConstPoolSInt::get(Ty, D.ConstPool64); CPV = ConstPoolSInt::get(Ty, D.ConstPool64);
} }
break; break;
case 3: case ValID::ConstUIntVal:
if (!ConstPoolUInt::isValueValidForType(Ty, D.UConstPool64)) { if (!ConstPoolUInt::isValueValidForType(Ty, D.UConstPool64)) {
if (!ConstPoolSInt::isValueValidForType(Ty, D.ConstPool64)) { if (!ConstPoolSInt::isValueValidForType(Ty, D.ConstPool64)) {
ThrowException("Integral constant pool reference is invalid!"); ThrowException("Integral constant pool reference is invalid!");
@ -254,16 +255,22 @@ static Value *getVal(const Type *Ty, const ValID &D,
CPV = ConstPoolUInt::get(Ty, D.UConstPool64); CPV = ConstPoolUInt::get(Ty, D.UConstPool64);
} }
break; break;
case 4: case ValID::ConstStringVal:
cerr << "FIXME: TODO: String constants [sbyte] not implemented yet!\n"; cerr << "FIXME: TODO: String constants [sbyte] not implemented yet!\n";
abort(); abort();
break; break;
case 5: case ValID::ConstFPVal:
if (!ConstPoolFP::isValueValidForType(Ty, D.ConstPoolFP)) if (!ConstPoolFP::isValueValidForType(Ty, D.ConstPoolFP))
ThrowException("FP constant invalid for type!!"); ThrowException("FP constant invalid for type!!");
else CPV = ConstPoolFP::get(Ty, D.ConstPoolFP);
CPV = ConstPoolFP::get(Ty, D.ConstPoolFP);
break; break;
case ValID::ConstNullVal:
if (!Ty->isPointerType())
ThrowException("Cannot create a a non pointer null!");
CPV = ConstPoolPointer::getNullPointer(Ty->castPointerType());
break;
default:
assert(0 && "Unhandled case!");
} }
assert(CPV && "How did we escape creating a constant??"); assert(CPV && "How did we escape creating a constant??");
return CPV; return CPV;
@ -508,6 +515,7 @@ Module *RunVMAsmParser(const string &Filename, FILE *F) {
PATypeHolder<Type> *TypeVal; PATypeHolder<Type> *TypeVal;
PATypeHolder<ArrayType> *ArrayTypeTy; PATypeHolder<ArrayType> *ArrayTypeTy;
PATypeHolder<StructType> *StructTypeTy; PATypeHolder<StructType> *StructTypeTy;
PATypeHolder<PointerType> *PointerTypeTy;
Value *ValueVal; Value *ValueVal;
list<MethodArgument*> *MethodArgList; list<MethodArgument*> *MethodArgList;
@ -573,13 +581,14 @@ Module *RunVMAsmParser(const string &Filename, FILE *F) {
%token <PrimType> FLOAT DOUBLE TYPE LABEL %token <PrimType> FLOAT DOUBLE TYPE LABEL
%type <ArrayTypeTy> ArrayType ArrayTypeI %type <ArrayTypeTy> ArrayType ArrayTypeI
%type <StructTypeTy> StructType StructTypeI %type <StructTypeTy> StructType StructTypeI
%type <PointerTypeTy> PointerType PointerTypeI
%token <StrVal> VAR_ID LABELSTR STRINGCONSTANT %token <StrVal> VAR_ID LABELSTR STRINGCONSTANT
%type <StrVal> OptVAR_ID OptAssign %type <StrVal> OptVAR_ID OptAssign
%token IMPLEMENTATION TRUE FALSE BEGINTOK END DECLARE GLOBAL CONSTANT UNINIT %token IMPLEMENTATION TRUE FALSE BEGINTOK END DECLARE GLOBAL CONSTANT UNINIT
%token TO DOTDOTDOT STRING %token TO DOTDOTDOT STRING NULL_TOK
// Basic Block Terminating Operators // Basic Block Terminating Operators
%token <TermOpVal> RET BR SWITCH %token <TermOpVal> RET BR SWITCH
@ -692,6 +701,10 @@ StructTypeI : '{' TypeListI '}' { // Structure type?
$$ = newTH(StructType::get(vector<const Type*>())); $$ = newTH(StructType::get(vector<const Type*>()));
} }
PointerTypeI : UpRTypes '*' { // Pointer type?
$$ = newTHC<PointerType>(HandleUpRefs(PointerType::get(*$1)));
delete $1; // Delete the type handle
}
// Include derived types in the Types production. // Include derived types in the Types production.
// //
@ -716,16 +729,15 @@ UpRTypes : '\\' EUINT64VAL { // Type UpReference
| StructTypeI { // Structure type? | StructTypeI { // Structure type?
$$ = newTHC<Type>(*$1); delete $1; $$ = newTHC<Type>(*$1); delete $1;
} }
| UpRTypes '*' { // Pointer type? | PointerTypeI { // Pointer type?
$$ = newTH(HandleUpRefs(PointerType::get(*$1))); $$ = newTHC<Type>(*$1); delete $1;
delete $1; // Delete the type handle
} }
// Define some helpful top level types that do not allow UpReferences to escape // Define some helpful top level types that do not allow UpReferences to escape
// //
ArrayType : ArrayTypeI { TypeDone($$ = $1); } ArrayType : ArrayTypeI { TypeDone($$ = $1); }
StructType : StructTypeI { TypeDone($$ = $1); } StructType : StructTypeI { TypeDone($$ = $1); }
PointerType : PointerTypeI { TypeDone($$ = $1); }
// TypeList - Used for struct declarations and as a basis for method type // TypeList - Used for struct declarations and as a basis for method type
@ -1051,6 +1063,10 @@ ConstValueRef : ESINT64VAL { // A reference to a direct constant
| FALSE { | FALSE {
$$ = ValID::create((int64_t)0); $$ = ValID::create((int64_t)0);
} }
| NULL_TOK {
$$ = ValID::createNull();
}
/* /*
| STRINGCONSTANT { // Quoted strings work too... especially for methods | STRINGCONSTANT { // Quoted strings work too... especially for methods
$$ = ValID::create_conststr($1); $$ = ValID::create_conststr($1);

View File

@ -250,7 +250,7 @@ bool BytecodeParser::parseConstPoolValue(const uchar *&Buf,
} }
case Type::StructTyID: { case Type::StructTyID: {
const StructType *ST = (const StructType*)Ty; const StructType *ST = Ty->castStructType();
const StructType::ElementTypes &ET = ST->getElementTypes(); const StructType::ElementTypes &ET = ST->getElementTypes();
vector<ConstPoolVal *> Elements; vector<ConstPoolVal *> Elements;
@ -267,6 +267,17 @@ bool BytecodeParser::parseConstPoolValue(const uchar *&Buf,
break; break;
} }
case Type::PointerTyID: {
const PointerType *PT = Ty->castPointerType();
unsigned SubClass;
if (read_vbr(Buf, EndBuf, SubClass)) return failure(true);
if (SubClass != 0) return failure(true);
V = ConstPoolPointer::getNullPointer(PT);
break;
}
default: default:
cerr << __FILE__ << ":" << __LINE__ cerr << __FILE__ << ":" << __LINE__
<< ": Don't know how to deserialize constant value of type '" << ": Don't know how to deserialize constant value of type '"

View File

@ -141,6 +141,11 @@ bool BytecodeWriter::outputConstant(const ConstPoolVal *CPV) {
break; break;
} }
case Type::PointerTyID: {
output_vbr((unsigned)0, Out);
break;
}
case Type::FloatTyID: { // Floating point types... case Type::FloatTyID: { // Floating point types...
float Tmp = (float)((const ConstPoolFP*)CPV)->getValue(); float Tmp = (float)((const ConstPoolFP*)CPV)->getValue();
output_data(&Tmp, &Tmp+1, Out); output_data(&Tmp, &Tmp+1, Out);