diff options
author | Reid Spencer <rspencer@reidspencer.com> | 2006-12-31 05:40:12 +0000 |
---|---|---|
committer | Reid Spencer <rspencer@reidspencer.com> | 2006-12-31 05:40:12 +0000 |
commit | e1553cc95601f3d5c5c807f482085857dd7937a8 (patch) | |
tree | b128cb594fde87225bfd7e6afd8f2487517785cd | |
parent | 79e21d338c60b4b5a5746fc45e37ea0310606aee (diff) |
For PR950:
Major reorganization. This patch introduces the signedness changes for
the new integer types (i8, i16, i32, i64) which replace the old signed
versions (ubyte, sbyte, ushort, short, etc). This patch also implements
the function type parameter attributes feature. Together these conspired
to introduce new reduce/reduce errors into the grammar. Consequently, it
was necessary to introduce a new keyword into the grammar in order to
disambiguate. Without this, yacc would make incorrect shift/reduce and
reduce/reduce decisions and fail to parse the intended assembly.
Changes in assembly:
1. The "implementation" keyword is superfluous but still supported. You
can use it as a sentry which will ensure there are no remaining up
reference types. However, this is optional as those checks are also
performed elsewhere.
2. Parameter attributes are now implemented using an at sign to
indicate the attribute. The attributes are placed after the type
in a function declaration or after the argument value in a function
call. For example:
i8 @sext %myfunc(i16 @zext)
call i8 @sext %myfunc(i16 @zext %someVal)
The facility is available for supporting additional attributes and
they can be combined using the @(attr1,attr2,attr3) syntax. Right
now the only two supported are @sext and @zext
3. Functions must now be defined with the "define" keyword which is
analagous to the "declare" keyword for function declarations. The
introduction of this keyword disambiguates situations where a
named result type is confused with a new type or gvar definition.
For example:
%MyType = type i16
%MyType %func(%MyType) { ... }
With the introduction of optional parameter attributes between
the function name and the function result type, yacc will pick
the wrong rule to reduce unless it is disambiguated with "define"
before the function definition, as in:
define %MyType @zext %func(%MyType %someArg) { ... }
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@32781 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/AsmParser/Lexer.l | 12 | ||||
-rw-r--r-- | lib/AsmParser/llvmAsmParser.y | 654 |
2 files changed, 413 insertions, 253 deletions
diff --git a/lib/AsmParser/Lexer.l b/lib/AsmParser/Lexer.l index 2f681a6aef..58d21c3775 100644 --- a/lib/AsmParser/Lexer.l +++ b/lib/AsmParser/Lexer.l @@ -235,14 +235,10 @@ x86_fastcallcc { return X86_FASTCALLCC_TOK; } void { RET_TY(Type::VoidTy, VOID); } bool { RET_TY(Type::BoolTy, BOOL); } -sbyte { RET_TY(Type::SByteTy, SBYTE); } -ubyte { RET_TY(Type::UByteTy, UBYTE); } -short { RET_TY(Type::ShortTy, SHORT); } -ushort { RET_TY(Type::UShortTy,USHORT);} -int { RET_TY(Type::IntTy, INT); } -uint { RET_TY(Type::UIntTy, UINT); } -long { RET_TY(Type::LongTy, LONG); } -ulong { RET_TY(Type::ULongTy, ULONG); } +i8 { RET_TY(Type::Int8Ty, INT8); } +i16 { RET_TY(Type::Int16Ty, INT16); } +i32 { RET_TY(Type::Int32Ty, INT32); } +i64 { RET_TY(Type::Int64Ty, INT64); } float { RET_TY(Type::FloatTy, FLOAT); } double { RET_TY(Type::DoubleTy,DOUBLE);} label { RET_TY(Type::LabelTy, LABEL); } diff --git a/lib/AsmParser/llvmAsmParser.y b/lib/AsmParser/llvmAsmParser.y index 8f2df71937..0eba227a2d 100644 --- a/lib/AsmParser/llvmAsmParser.y +++ b/lib/AsmParser/llvmAsmParser.y @@ -19,12 +19,16 @@ #include "llvm/Module.h" #include "llvm/SymbolTable.h" #include "llvm/Support/GetElementPtrTypeIterator.h" +#include "llvm/Support/CommandLine.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/Streams.h" #include <algorithm> #include <list> #include <utility> +#ifndef NDEBUG +#define YYDEBUG 1 +#endif // The following is a gross hack. In order to rid the libAsmParser library of // exceptions, we have to have a way of getting the yyparse function to go into @@ -47,6 +51,11 @@ int yyparse(); namespace llvm { std::string CurFilename; +#if YYDEBUG +static cl::opt<bool> +Debug("debug-yacc", cl::desc("Print yacc debug state changes"), + cl::Hidden, cl::init(false)); +#endif } using namespace llvm; @@ -71,6 +80,7 @@ static GlobalVariable *CurGV; // destroyed when the function is completed. // typedef std::vector<Value *> ValueList; // Numbered defs + static void ResolveDefinitions(std::map<const Type *,ValueList> &LateResolvers, std::map<const Type *,ValueList> *FutureLateResolvers = 0); @@ -804,34 +814,12 @@ static PATypeHolder HandleUpRefs(const Type *ty) { return Ty; } -// common code from the two 'RunVMAsmParser' functions -static Module* RunParser(Module * M) { - - llvmAsmlineno = 1; // Reset the current line number... - CurModule.CurrentModule = M; - - // Check to make sure the parser succeeded - if (yyparse()) { - if (ParserResult) - delete ParserResult; - return 0; - } - - // Check to make sure that parsing produced a result - if (!ParserResult) - return 0; - - // Reset ParserResult variable while saving its value for the result. - Module *Result = ParserResult; - ParserResult = 0; - - return Result; -} - //===----------------------------------------------------------------------===// // RunVMAsmParser - Define an interface to this parser //===----------------------------------------------------------------------===// // +static Module* RunParser(Module * M); + Module *llvm::RunVMAsmParser(const std::string &Filename, FILE *F) { set_scan_file(F); @@ -855,19 +843,21 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) { %union { llvm::Module *ModuleVal; llvm::Function *FunctionVal; - std::pair<llvm::PATypeHolder*, char*> *ArgVal; llvm::BasicBlock *BasicBlockVal; llvm::TerminatorInst *TermInstVal; llvm::Instruction *InstVal; llvm::Constant *ConstVal; const llvm::Type *PrimType; + std::list<llvm::PATypeHolder> *TypeList; llvm::PATypeHolder *TypeVal; llvm::Value *ValueVal; - - std::vector<std::pair<llvm::PATypeHolder*,char*> > *ArgList; std::vector<llvm::Value*> *ValueList; - std::list<llvm::PATypeHolder> *TypeList; + llvm::ArgListType *ArgList; + llvm::TypeWithAttrs TypeWithAttrs; + llvm::TypeWithAttrsList *TypeWithAttrsList; + llvm::ValueRefList *ValueRefList; + // Represent the RHS of PHI node std::list<std::pair<llvm::Value*, llvm::BasicBlock*> > *PHIList; @@ -875,6 +865,7 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) { std::vector<llvm::Constant*> *ConstVector; llvm::GlobalValue::LinkageTypes Linkage; + llvm::FunctionType::ParameterAttributes ParamAttrs; int64_t SInt64Val; uint64_t UInt64Val; int SIntVal; @@ -895,7 +886,7 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) { llvm::FCmpInst::Predicate FPredicate; } -%type <ModuleVal> Module +%type <ModuleVal> Module %type <FunctionVal> Function FunctionProto FunctionHeader BasicBlockList %type <BasicBlockVal> BasicBlock InstructionList %type <TermInstVal> BBTerminatorInst @@ -903,17 +894,19 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) { %type <ConstVal> ConstVal ConstExpr %type <ConstVector> ConstVector %type <ArgList> ArgList ArgListH -%type <ArgVal> ArgVal %type <PHIList> PHIList -%type <ValueList> ValueRefList ValueRefListE // For call param lists -%type <ValueList> IndexList // For GEP derived indices -%type <TypeList> TypeListI ArgTypeListI +%type <ValueRefList> ValueRefList // For call param lists & GEP indices +%type <ValueList> IndexList // For GEP indices +%type <TypeList> TypeListI +%type <TypeWithAttrsList> ArgTypeList ArgTypeListI +%type <TypeWithAttrs> ArgType ResultType %type <JumpTable> JumpTable %type <BoolVal> GlobalType // GLOBAL or CONSTANT? %type <BoolVal> OptVolatile // 'volatile' or not %type <BoolVal> OptTailCall // TAIL CALL or plain CALL. %type <BoolVal> OptSideEffect // 'sideeffect' or not. -%type <Linkage> FunctionLinkage GVInternalLinkage GVExternalLinkage +%type <Linkage> GVInternalLinkage GVExternalLinkage +%type <Linkage> FunctionDefineLinkage FunctionDeclareLinkage %type <Endianness> BigOrLittle // ValueRef - Unresolved reference to a definition or BB @@ -933,9 +926,9 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) { %token <FPVal> FPVAL // Float or Double constant // Built in types... -%type <TypeVal> Types TypesV UpRTypes UpRTypesV -%type <PrimType> SIntType UIntType IntType FPType PrimType // Classifications -%token <PrimType> VOID BOOL SBYTE UBYTE SHORT USHORT INT UINT LONG ULONG +%type <TypeVal> Types +%type <PrimType> IntType FPType PrimType // Classifications +%token <PrimType> VOID BOOL INT8 INT16 INT32 INT64 %token <PrimType> FLOAT DOUBLE LABEL %token TYPE @@ -946,7 +939,7 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) { %token IMPLEMENTATION ZEROINITIALIZER TRUETOK FALSETOK BEGINTOK ENDTOK %token DECLARE DEFINE GLOBAL CONSTANT SECTION VOLATILE -%token TO DOTDOTDOT NULL_TOK UNDEF CONST INTERNAL LINKONCE WEAK APPENDING +%token TO DOTDOTDOT NULL_TOK UNDEF INTERNAL LINKONCE WEAK APPENDING %token DLLIMPORT DLLEXPORT EXTERN_WEAK %token OPAQUE NOT EXTERNAL TARGET TRIPLE ENDIAN POINTERSIZE LITTLE BIG ALIGN %token DEPLIBS CALL TAIL ASM_TOK MODULE SIDEEFFECT @@ -954,6 +947,7 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) { %token X86_STDCALLCC_TOK X86_FASTCALLCC_TOK %token DATALAYOUT %type <UIntVal> OptCallingConv +%type <ParamAttrs> OptParamAttrs ParamAttrList ParamAttr // Basic Block Terminating Operators %token <TermOpVal> RET BR SWITCH INVOKE UNWIND UNREACHABLE @@ -1024,9 +1018,7 @@ FPredicates // These are some types that allow classification if we only want a particular // thing... for example, only a signed, unsigned, or integral type. -SIntType : LONG | INT | SHORT | SBYTE; -UIntType : ULONG | UINT | USHORT | UBYTE; -IntType : SIntType | UIntType; +IntType : INT64 | INT32 | INT16 | INT8; FPType : FLOAT | DOUBLE; // OptAssign - Value producing statements have an optional assignment component @@ -1053,18 +1045,18 @@ GVExternalLinkage | EXTERNAL { $$ = GlobalValue::ExternalLinkage; } ; -FnDeclareLinkage - : /*empty*/ { /*default*/ } - | DLLIMPORT { CurFun.Linkage = GlobalValue::DLLImportLinkage; } - | EXTERN_WEAK { CurFun.Linkage = GlobalValue::ExternalWeakLinkage; } +FunctionDeclareLinkage + : /*empty*/ { $$ = GlobalValue::ExternalLinkage; } + | DLLIMPORT { $$ = GlobalValue::DLLImportLinkage; } + | EXTERN_WEAK { $$ = GlobalValue::ExternalWeakLinkage; } ; -FunctionLinkage - : INTERNAL { $$ = GlobalValue::InternalLinkage; } +FunctionDefineLinkage + : /*empty*/ { $$ = GlobalValue::ExternalLinkage; } + | INTERNAL { $$ = GlobalValue::InternalLinkage; } | LINKONCE { $$ = GlobalValue::LinkOnceLinkage; } | WEAK { $$ = GlobalValue::WeakLinkage; } | DLLEXPORT { $$ = GlobalValue::DLLExportLinkage; } - | /*empty*/ { $$ = GlobalValue::ExternalLinkage; } ; OptCallingConv : /*empty*/ { $$ = CallingConv::C; } | @@ -1081,6 +1073,21 @@ OptCallingConv : /*empty*/ { $$ = CallingConv::C; } | CHECK_FOR_ERROR }; +ParamAttr : ZEXT { $$ = FunctionType::ZExtAttribute; } + | SEXT { $$ = FunctionType::SExtAttribute; } + ; + +ParamAttrList : ParamAttr { $$ = $1; } + | ParamAttrList ',' ParamAttr { + $$ = FunctionType::ParameterAttributes($1 | $3); + } + ; + +OptParamAttrs : /* empty */ { $$ = FunctionType::NoAttributeSet; } + | '@' ParamAttr { $$ = $2; } + | '@' '(' ParamAttrList ')' { $$ = $3; } + ; + // OptAlign/OptCAlign - An optional alignment, and an optional alignment with // a comma before it. OptAlign : /*empty*/ { $$ = 0; } | @@ -1129,43 +1136,34 @@ GlobalVarAttribute : SectionString { //===----------------------------------------------------------------------===// // Types includes all predefined types... except void, because it can only be -// used in specific contexts (function returning void for example). To have -// access to it, a user must explicitly use TypesV. -// - -// TypesV includes all of 'Types', but it also includes the void type. -TypesV : Types | VOID { $$ = new PATypeHolder($1); }; -UpRTypesV : UpRTypes | VOID { $$ = new PATypeHolder($1); }; - -Types : UpRTypes { - if (!UpRefs.empty()) - GEN_ERROR("Invalid upreference in type: " + (*$1)->getDescription()); - $$ = $1; - CHECK_FOR_ERROR - }; - +// used in specific contexts (function returning void for example). // Derived types are added later... // -PrimType : BOOL | SBYTE | UBYTE | SHORT | USHORT | INT | UINT ; -PrimType : LONG | ULONG | FLOAT | DOUBLE | LABEL ; -UpRTypes : OPAQUE { +PrimType : BOOL | INT8 | INT16 | INT32 | INT64 | FLOAT | DOUBLE | LABEL ; + +Types + : OPAQUE { $$ = new PATypeHolder(OpaqueType::get()); CHECK_FOR_ERROR } | PrimType { $$ = new PATypeHolder($1); CHECK_FOR_ERROR - }; -UpRTypes : SymbolicValueRef { // Named types are also simple types... - const Type* tmp = getTypeVal($1); - CHECK_FOR_ERROR - $$ = new PATypeHolder(tmp); -}; - -// Include derived types in the Types production. -// -UpRTypes : '\\' EUINT64VAL { // Type UpReference + } + | Types '*' { // Pointer type? + if (*$1 == Type::LabelTy) + GEN_ERROR("Cannot form a pointer to a basic block"); + $$ = new PATypeHolder(HandleUpRefs(PointerType::get(*$1))); + delete $1; + CHECK_FOR_ERROR + } + | SymbolicValueRef { // Named types are also simple types... + const Type* tmp = getTypeVal($1); + CHECK_FOR_ERROR + $$ = new PATypeHolder(tmp); + } + | '\\' EUINT64VAL { // Type UpReference if ($2 > (uint64_t)~0U) GEN_ERROR("Value out of range!"); OpaqueType *OT = OpaqueType::get(); // Use temporary placeholder UpRefs.push_back(UpRefRecord((unsigned)$2, OT)); // Add to vector... @@ -1173,25 +1171,48 @@ UpRTypes : '\\' EUINT64VAL { // Type UpReference UR_OUT("New Upreference!\n"); CHECK_FOR_ERROR } - | UpRTypesV '(' ArgTypeListI ')' { // Function derived type? + | Types OptParamAttrs '(' ArgTypeListI ')' { std::vector<const Type*> Params; - for (std::list<llvm::PATypeHolder>::iterator I = $3->begin(), - E = $3->end(); I != E; ++I) - Params.push_back(*I); + std::vector<FunctionType::ParameterAttributes> Attrs; + Attrs.push_back($2); + for (TypeWithAttrsList::iterator I=$4->begin(), E=$4->end(); I != E; ++I) { + Params.push_back(I->Ty->get()); + if (I->Ty->get() != Type::VoidTy) + Attrs.push_back(I->Attrs); + } bool isVarArg = Params.size() && Params.back() == Type::VoidTy; if (isVarArg) Params.pop_back(); - $$ = new PATypeHolder(HandleUpRefs(FunctionType::get(*$1,Params,isVarArg))); - delete $3; // Delete the argument list - delete $1; // Delete the return type handle + FunctionType *FT = FunctionType::get(*$1, Params, isVarArg, Attrs); + delete $4; // Delete the argument list + delete $1; // Delete the return type handle + $$ = new PATypeHolder(HandleUpRefs(FT)); CHECK_FOR_ERROR } - | '[' EUINT64VAL 'x' UpRTypes ']' { // Sized array type? + | VOID OptParamAttrs '(' ArgTypeListI ')' { + std::vector<const Type*> Params; + std::vector<FunctionType::ParameterAttributes> Attrs; + Attrs.push_back($2); + for (TypeWithAttrsList::iterator I=$4->begin(), E=$4->end(); I != E; ++I) { + Params.push_back(I->Ty->get()); + if (I->Ty->get() != Type::VoidTy) + Attrs.push_back(I->Attrs); + } + bool isVarArg = Params.size() && Params.back() == Type::VoidTy; + if (isVarArg) Params.pop_back(); + + FunctionType *FT = FunctionType::get($1, Params, isVarArg, Attrs); + delete $4; // Delete the argument list + $$ = new PATypeHolder(HandleUpRefs(FT)); + CHECK_FOR_ERROR + } + + | '[' EUINT64VAL 'x' Types ']' { // Sized array type? $$ = new PATypeHolder(HandleUpRefs(ArrayType::get(*$4, (unsigned)$2))); delete $4; CHECK_FOR_ERROR } - | '<' EUINT64VAL 'x' UpRTypes '>' { // Packed array type? + | '<' EUINT64VAL 'x' Types '>' { // Packed array type? const llvm::Type* ElemTy = $4->get(); if ((unsigned)$2 != $2) GEN_ERROR("Unsigned result not equal to signed result"); @@ -1231,39 +1252,72 @@ UpRTypes : '\\' EUINT64VAL { // Type UpReference $$ = new PATypeHolder(StructType::get(std::vector<const Type*>(), true)); CHECK_FOR_ERROR } - | UpRTypes '*' { // Pointer type? - if (*$1 == Type::LabelTy) - GEN_ERROR("Cannot form a pointer to a basic block"); - $$ = new PATypeHolder(HandleUpRefs(PointerType::get(*$1))); - delete $1; - CHECK_FOR_ERROR - }; + ; -// TypeList - Used for struct declarations and as a basis for function type -// declaration type lists -// -TypeListI : UpRTypes { - $$ = new std::list<PATypeHolder>(); - $$->push_back(*$1); delete $1; +ArgType + : Types OptParamAttrs { + $$.Ty = $1; + $$.Attrs = $2; + } + ; + +ResultType + : Types OptParamAttrs { + if (!UpRefs.empty()) + GEN_ERROR("Invalid upreference in type: " + (*$1)->getDescription()); + if (!(*$1)->isFirstClassType()) + GEN_ERROR("LLVM functions cannot return aggregate types!"); + $$.Ty = $1; + $$.Attrs = $2; + } + | VOID OptParamAttrs { + $$.Ty = new PATypeHolder(Type::VoidTy); + $$.Attrs = $2; + } + ; + +ArgTypeList : ArgType { + $$ = new TypeWithAttrsList(); + $$->push_back($1); CHECK_FOR_ERROR } - | TypeListI ',' UpRTypes { - ($$=$1)->push_back(*$3); delete $3; + | ArgTypeList ',' ArgType { + ($$=$1)->push_back($3); CHECK_FOR_ERROR - }; + } + ; -// ArgTypeList - List of types for a function type declaration... -ArgTypeListI : TypeListI - | TypeListI ',' DOTDOTDOT { - ($$=$1)->push_back(Type::VoidTy); +ArgTypeListI + : ArgTypeList + | ArgTypeList ',' DOTDOTDOT { + $$=$1; + TypeWithAttrs TWA; TWA.Attrs = FunctionType::NoAttributeSet; + TWA.Ty = new PATypeHolder(Type::VoidTy); + $$->push_back(TWA); CHECK_FOR_ERROR } | DOTDOTDOT { - ($$ = new std::list<PATypeHolder>())->push_back(Type::VoidTy); + $$ = new TypeWithAttrsList; + TypeWithAttrs TWA; TWA.Attrs = FunctionType::NoAttributeSet; + TWA.Ty = new PATypeHolder(Type::VoidTy); + $$->push_back(TWA); CHECK_FOR_ERROR } | /*empty*/ { + $$ = new TypeWithAttrsList(); + CHECK_FOR_ERROR + }; + +// TypeList - Used for struct declarations and as a basis for function type +// declaration type lists +// +TypeListI : Types { $$ = new std::list<PATypeHolder>(); + $$->push_back(*$1); delete $1; + CHECK_FOR_ERROR + } + | TypeListI ',' Types { + ($$=$1)->push_back(*$3); delete $3; CHECK_FOR_ERROR }; @@ -1274,6 +1328,8 @@ ArgTypeListI : TypeListI // ResolvedVal, ValueRef and ConstValueRef productions. // ConstVal: Types '[' ConstVector ']' { // Nonempty unsized arr + if (!UpRefs.empty()) + GEN_ERROR("Invalid upreference in type: " + (*$1)->getDescription()); const ArrayType *ATy = dyn_cast<ArrayType>($1->get()); if (ATy == 0) GEN_ERROR("Cannot make array constant with type: '" + @@ -1300,6 +1356,8 @@ ConstVal: Types '[' ConstVector ']' { // Nonempty unsized arr CHECK_FOR_ERROR } | Types '[' ']' { + if (!UpRefs.empty()) + GEN_ERROR("Invalid upreference in type: " + (*$1)->getDescription()); const ArrayType *ATy = dyn_cast<ArrayType>($1->get()); if (ATy == 0) GEN_ERROR("Cannot make array constant with type: '" + @@ -1314,6 +1372,8 @@ ConstVal: Types '[' ConstVector ']' { // Nonempty unsized arr CHECK_FOR_ERROR } | Types 'c' STRINGCONSTANT { + if (!UpRefs.empty()) + GEN_ERROR("Invalid upreference in type: " + (*$1)->getDescription()); const ArrayType *ATy = dyn_cast<ArrayType>($1->get()); if (ATy == 0) GEN_ERROR("Cannot make array constant with type: '" + @@ -1327,13 +1387,10 @@ ConstVal: Types '[' ConstVector ']' { // Nonempty unsized arr itostr((int)(EndStr-$3)) + " when array has size " + itostr(NumElements) + "!"); std::vector<Constant*> Vals; - if (ETy == Type::SByteTy) { - for (signed char *C = (signed char *)$3; C != (signed char *)EndStr; ++C) - Vals.push_back(ConstantInt::get(ETy, *C)); - } else if (ETy == Type::UByteTy) { + if (ETy == Type::Int8Ty) { for (unsigned char *C = (unsigned char *)$3; - C != (unsigned char*)EndStr; ++C) - Vals.push_back(ConstantInt::get(ETy, *C)); + C != (unsigned char*)EndStr; ++C) + Vals.push_back(ConstantInt::get(ETy, *C)); } else { free($3); GEN_ERROR("Cannot build string arrays of non byte sized elements!"); @@ -1344,6 +1401,8 @@ ConstVal: Types '[' ConstVector ']' { // Nonempty unsized arr CHECK_FOR_ERROR } | Types '<' ConstVector '>' { // Nonempty unsized arr + if (!UpRefs.empty()) + GEN_ERROR("Invalid upreference in type: " + (*$1)->getDescription()); const PackedType *PTy = dyn_cast<PackedType>($1->get()); if (PTy == 0) GEN_ERROR("Cannot make packed constant with type: '" + @@ -1391,6 +1450,8 @@ ConstVal: Types '[' ConstVector ']' { // Nonempty unsized arr CHECK_FOR_ERROR } | Types '{' '}' { + if (!UpRefs.empty()) + GEN_ERROR("Invalid upreference in type: " + (*$1)->getDescription()); const StructType *STy = dyn_cast<StructType>($1->get()); if (STy == 0) GEN_ERROR("Cannot make struct constant with type: '" + @@ -1404,6 +1465,8 @@ ConstVal: Types '[' ConstVector ']' { // Nonempty unsized arr CHECK_FOR_ERROR } | Types NULL_TOK { + if (!UpRefs.empty()) + GEN_ERROR("Invalid upreference in type: " + (*$1)->getDescription()); const PointerType *PTy = dyn_cast<PointerType>($1->get()); if (PTy == 0) GEN_ERROR("Cannot make null pointer constant with type: '" + @@ -1414,11 +1477,15 @@ ConstVal: Types '[' ConstVector ']' { // Nonempty unsized arr CHECK_FOR_ERROR } | Types UNDEF { + if (!UpRefs.empty()) + GEN_ERROR("Invalid upreference in type: " + (*$1)->getDescription()); $$ = UndefValue::get($1->get()); delete $1; CHECK_FOR_ERROR } | Types SymbolicValueRef { + if (!UpRefs.empty()) + GEN_ERROR("Invalid upreference in type: " + (*$1)->getDescription()); const PointerType *Ty = dyn_cast<PointerType>($1->get()); if (Ty == 0) GEN_ERROR("Global const reference must be a pointer type!"); @@ -1480,6 +1547,8 @@ ConstVal: Types '[' ConstVector ']' { // Nonempty unsized arr CHECK_FOR_ERROR } | Types ConstExpr { + if (!UpRefs.empty()) + GEN_ERROR("Invalid upreference in type: " + (*$1)->getDescription()); if ($1->get() != $2->getType()) GEN_ERROR("Mismatched types for constant expression!"); $$ = $2; @@ -1487,6 +1556,8 @@ ConstVal: Types '[' ConstVector ']' { // Nonempty unsized arr CHECK_FOR_ERROR } | Types ZEROINITIALIZER { + if (!UpRefs.empty()) + GEN_ERROR("Invalid upreference in type: " + (*$1)->getDescription()); const Type *Ty = $1->get(); if (isa<FunctionType>(Ty) || Ty == Type::LabelTy || isa<OpaqueType>(Ty)) GEN_ERROR("Cannot create a null initialized value of this type!"); @@ -1494,25 +1565,13 @@ ConstVal: Types '[' ConstVector ']' { // Nonempty unsized arr delete $1; CHECK_FOR_ERROR } - | SIntType ESINT64VAL { // integral constants - if (!ConstantInt::isValueValidForType($1, $2)) - GEN_ERROR("Constant value doesn't fit in type!"); - $$ = ConstantInt::get($1, $2); - CHECK_FOR_ERROR - } - | SIntType EUINT64VAL { // integral constants - if (!ConstantInt::isValueValidForType($1, $2)) - GEN_ERROR("Constant value doesn't fit in type!"); - $$ = ConstantInt::get($1, $2); - CHECK_FOR_ERROR - } - | UIntType EUINT64VAL { // integral constants + | IntType ESINT64VAL { // integral constants if (!ConstantInt::isValueValidForType($1, $2)) GEN_ERROR("Constant value doesn't fit in type!"); $$ = ConstantInt::get($1, $2); CHECK_FOR_ERROR } - | UIntType ESINT64VAL { + | IntType EUINT64VAL { // integral constants if (!ConstantInt::isValueValidForType($1, $2)) GEN_ERROR("Constant value doesn't fit in type!"); $$ = ConstantInt::get($1, $2); @@ -1535,6 +1594,8 @@ ConstVal: Types '[' ConstVector ']' { // Nonempty unsized arr ConstExpr: CastOps '(' ConstVal TO Types ')' { + if (!UpRefs.empty()) + GEN_ERROR("Invalid upreference in type: " + (*$5)->getDescription()); Constant *Val = $3; const Type *Ty = $5->get(); if (!Val->getType()->isFirstClassType()) @@ -1603,8 +1664,8 @@ ConstExpr: CastOps '(' ConstVal TO Types ')' { $$ = ConstantExpr::getFCmp($2, $4, $6); } | ShiftOps '(' ConstVal ',' ConstVal ')' { - if ($5->getType() != Type::UByteTy) - GEN_ERROR("Shift count for shift constant must be unsigned byte!"); + if ($5->getType() != Type::Int8Ty) + GEN_ERROR("Shift count for shift constant must be i8 type!"); if (!$3->getType()->isInteger()) GEN_ERROR("Shift constant expression requires integer operand!"); CHECK_FOR_ERROR; @@ -1695,7 +1756,9 @@ Definition } CHECK_FOR_ERROR } - | OptAssign TYPE TypesV { + | OptAssign TYPE Types { + if (!UpRefs.empty()) + GEN_ERROR("Invalid upreference in type: " + (*$3)->getDescription()); // Eagerly resolve types. This is not an optimization, this is a // requirement that is due to the fact that we could have this: // @@ -1717,6 +1780,17 @@ Definition delete $3; CHECK_FOR_ERROR } + | OptAssign TYPE VOID { + ResolveTypeTo($1, $3); + + if (!setTypeName($3, $1) && !$1) { + CHECK_FOR_ERROR + // If this is a named type that is not a redefinition, add it to the slot + // table. + CurModule.Types.push_back($3); + } + CHECK_FOR_ERROR + } | OptAssign GlobalType ConstVal { /* "Externally Visible" Linkage */ if ($3 == 0) GEN_ERROR("Global value initializer is not a constant!"); @@ -1735,6 +1809,8 @@ Definition CurGV = 0; } | OptAssign GVExternalLinkage GlobalType Types { + if (!UpRefs.empty()) + GEN_ERROR("Invalid upreference in type: " + (*$4)->getDescription()); CurGV = ParseGlobalVariable($1, $2, $3, *$4, 0); CHECK_FOR_ERROR delete $4; @@ -1813,23 +1889,24 @@ LibList : LibList ',' STRINGCONSTANT { Name : VAR_ID | STRINGCONSTANT; OptName : Name | /*empty*/ { $$ = 0; }; -ArgVal : Types OptName { - if (*$1 == Type::VoidTy) - GEN_ERROR("void typed arguments are invalid!"); - $$ = new std::pair<PATypeHolder*, char*>($1, $2); - CHECK_FOR_ERROR -}; - -ArgListH : ArgListH ',' ArgVal { +ArgListH : ArgListH ',' Types OptParamAttrs OptName { + if (!UpRefs.empty()) + GEN_ERROR("Invalid upreference in type: " + (*$3)->getDescription()); + if (*$3 == Type::VoidTy) + GEN_ERROR("void typed arguments are invalid!"); + ArgListEntry E; E.Attrs = $4; E.Ty = $3; E.Name = $5; $$ = $1; - $1->push_back(*$3); - delete $3; + $1->push_back(E); CHECK_FOR_ERROR } - | ArgVal { - $$ = new std::vector<std::pair<PATypeHolder*,char*> >(); - $$->push_back(*$1); - delete $1; + | Types OptParamAttrs OptName { + if (!UpRefs.empty()) + GEN_ERROR("Invalid upreference in type: " + (*$1)->getDescription()); + if (*$1 == Type::VoidTy) + GEN_ERROR("void typed arguments are invalid!"); + ArgListEntry E; E.Attrs = $2; E.Ty = $1; E.Name = $3; + $$ = new ArgListType; + $$->push_back(E); CHECK_FOR_ERROR }; @@ -1839,13 +1916,20 @@ ArgList : ArgListH { } | ArgListH ',' DOTDOTDOT { $$ = $1; - $$->push_back(std::pair<PATypeHolder*, - char*>(new PATypeHolder(Type::VoidTy), 0)); + struct ArgListEntry E; + E.Ty = new PATypeHolder(Type::VoidTy); + E.Name = 0; + E.Attrs = FunctionType::NoAttributeSet; + $$->push_back(E); CHECK_FOR_ERROR } | DOTDOTDOT { - $$ = new std::vector<std::pair<PATypeHolder*,char*> >(); - $$->push_back(std::make_pair(new PATypeHolder(Type::VoidTy), (char*)0)); + $$ = new ArgListType; + struct ArgListEntry E; + E.Ty = new PATypeHolder(Type::VoidTy); + E.Name = 0; + E.Attrs = FunctionType::NoAttributeSet; + $$->push_back(E); CHECK_FOR_ERROR } | /* empty */ { @@ -1853,28 +1937,31 @@ ArgList : ArgListH { CHECK_FOR_ERROR }; -FunctionHeaderH : OptCallingConv TypesV Name '(' ArgList ')' +FunctionHeaderH : OptCallingConv ResultType Name '(' ArgList ')' OptSection OptAlign { UnEscapeLexed($3); std::string FunctionName($3); free($3); // Free strdup'd memory! - if (!(*$2)->isFirstClassType() && *$2 != Type::VoidTy) - GEN_ERROR("LLVM functions cannot return aggregate types!"); - std::vector<const Type*> ParamTypeList; + std::vector<FunctionType::ParameterAttributes> ParamAttrs; + ParamAttrs.push_back($2.Attrs); if ($5) { // If there are arguments... - for (std::vector<std::pair<PATypeHolder*,char*> >::iterator I = $5->begin(); - I != $5->end(); ++I) - ParamTypeList.push_back(I->first->get()); + for (ArgListType::iterator I = $5->begin(); I != $5->end(); ++I) { + const Type* Ty = I->Ty->get(); + ParamTypeList.push_back(Ty); + if (Ty != Type::VoidTy) + ParamAttrs.push_back(I->Attrs); + } } bool isVarArg = ParamTypeList.size() && ParamTypeList.back() == Type::VoidTy; if (isVarArg) ParamTypeList.pop_back(); - const FunctionType *FT = FunctionType::get(*$2, ParamTypeList, isVarArg); + FunctionType *FT = FunctionType::get(*$2.Ty, ParamTypeList, isVarArg, + ParamAttrs); const PointerType *PFT = PointerType::get(FT); - delete $2; + delete $2.Ty; ValID ID; if (!FunctionName.empty()) { @@ -1928,19 +2015,19 @@ FunctionHeaderH : OptCallingConv TypesV Name '(' ArgList ')' // Add all of the arguments we parsed to the function... if ($5) { // Is null if empty... if (isVarArg) { // Nuke the last entry - assert($5->back().first->get() == Type::VoidTy && $5->back().second == 0&& + assert($5->back().Ty->get() == Type::VoidTy && $5->back().Name == 0&& "Not a varargs marker!"); - delete $5->back().first; + delete $5->back().Ty; $5->pop_back(); // Delete the last entry } Function::arg_iterator ArgIt = Fn->arg_begin(); - for (std::vector<std::pair<PATypeHolder*,char*> >::iterator I = $5->begin(); - I != $5->end(); ++I, ++ArgIt) { - delete I->first; // Delete the typeholder... - - setValueName(ArgIt, I->second); // Insert arg into symtab... + unsigned Idx = 1; + for (ArgListType::iterator I = $5->begin(); I != $5->end(); ++I, ++ArgIt) { + delete I->Ty; // Delete the typeholder... + setValueName(ArgIt, I->Name); // Insert arg into symtab... CHECK_FOR_ERROR InsertValue(ArgIt); + Idx++; } delete $5; // We're now done with the argument list @@ -1950,7 +2037,7 @@ FunctionHeaderH : OptCallingConv TypesV Name '(' ArgList ')' BEGIN : BEGINTOK | '{'; // Allow BEGIN or '{' to start a function -FunctionHeader : FunctionLinkage FunctionHeaderH BEGIN { +FunctionHeader : FunctionDefineLinkage FunctionHeaderH BEGIN { $$ = CurFun.CurrentFunction; // Make sure that we keep track of the linkage type even if there was a @@ -1965,7 +2052,8 @@ Function : BasicBlockList END { CHECK_FOR_ERROR }; -FunctionProto : FnDeclareLinkage FunctionHeaderH { +FunctionProto : FunctionDeclareLinkage FunctionHeaderH { + CurFun.CurrentFunction->setLinkage($1); $$ = CurFun.CurrentFunction; CurFun.FunctionDone(); CHECK_FOR_ERROR @@ -2076,9 +2164,13 @@ ValueRef : SymbolicValueRef | ConstValueRef; // type immediately preceeds the value reference, and allows complex constant // pool references (for things like: 'ret [2 x int] [ int 12, int 42]') ResolvedVal : Types ValueRef { - $$ = getVal(*$1, $2); delete $1; + if (!UpRefs.empty()) + GEN_ERROR("Invalid upreference in type: " + (*$1)->getDescription()); + $$ = getVal(*$1, $2); + delete $1; CHECK_FOR_ERROR - }; + } + ; BasicBlockList : BasicBlockList BasicBlock { $$ = $1; @@ -2188,25 +2280,27 @@ BBTerminatorInst : RET ResolvedVal { // Return with a result... $$ = S; CHECK_FOR_ERROR } - | INVOKE OptCallingConv TypesV ValueRef '(' ValueRefListE ')' + | INVOKE OptCallingConv ResultType ValueRef '(' ValueRefList ')' TO LABEL ValueRef UNWIND LABEL ValueRef { - const PointerType *PFTy; - const FunctionType *Ty; - if (!(PFTy = dyn_cast<PointerType>($3->get())) || + // Handle the short syntax + const PointerType *PFTy = 0; + const FunctionType *Ty = 0; + if (!(PFTy = dyn_cast<PointerType>($3.Ty->get())) || !(Ty = dyn_cast<FunctionType>(PFTy->getElementType()))) { // Pull out the types of all of the arguments... std::vector<const Type*> ParamTypes; - if ($6) { - for (std::vector<Value*>::iterator I = $6->begin(), E = $6->end(); - I != E; ++I) - ParamTypes.push_back((*I)->getType()); + FunctionType::ParamAttrsList ParamAttrs; + ParamAttrs.push_back($3.Attrs); + for (ValueRefList::iterator I = $6->begin(), E = $6->end(); I != E; ++I) { + const Type *Ty = I->Val->getType(); + if (Ty == Type::VoidTy) + GEN_ERROR("Short call syntax cannot be used with varargs"); + ParamTypes.push_back(Ty); + ParamAttrs.push_back(I->Attrs); } - bool isVarArg = ParamTypes.size() && ParamTypes.back() == Type::VoidTy; - if (isVarArg) ParamTypes.pop_back(); - - Ty = FunctionType::get($3->get(), ParamTypes, isVarArg); + Ty = FunctionType::get($3.Ty->get(), ParamTypes, false, ParamAttrs); PFTy = PointerType::get(Ty); } @@ -2217,30 +2311,39 @@ BBTerminatorInst : RET ResolvedVal { // Return with a result... BasicBlock *Except = getBBVal($13); CHECK_FOR_ERROR - // Create the call node... - if (!$6) { // Has no arguments? - $$ = new InvokeInst(V, Normal, Except, std::vector<Value*>()); + // Check the arguments + ValueList Args; + if ($6->empty()) { // Has no arguments? + // Make sure no arguments is a good thing! + if (Ty->getNumParams() != 0) + GEN_ERROR("No arguments passed to a function that " + "expects arguments!"); } else { // Has arguments? // Loop through FunctionType's arguments and ensure they are specified // correctly! - // FunctionType::param_iterator I = Ty->param_begin(); FunctionType::param_iterator E = Ty->param_end(); - std::vector<Value*>::iterator ArgI = $6->begin(), ArgE = $6->end(); + ValueRefList::iterator ArgI = $6->begin(), ArgE = $6->end(); - for (; ArgI != ArgE && I != E; ++ArgI, ++I) - if ((*ArgI)->getType() != *I) - GEN_ERROR("Parameter " +(*ArgI)->getName()+ " is not of type '" + + for (; ArgI != ArgE && I != E; ++ArgI, ++I) { + if (ArgI->Val->getType() != *I) + GEN_ERROR("Parameter " + ArgI->Val->getName()+ " is not of type '" + (*I)->getDescription() + "'!"); + Args.push_back(ArgI->Val); + } - if (I != E || (ArgI != ArgE && !Ty->isVarArg())) + if (Ty->isVarArg()) { + if (I == E) + for (; ArgI != ArgE; ++ArgI) + Args.push_back(ArgI->Val); // push the remaining varargs + } else if (I != E || ArgI != ArgE) GEN_ERROR("Invalid number of parameters detected!"); - - $$ = new InvokeInst(V, Normal, Except, *$6); } - cast<InvokeInst>($$)->setCallingConv($2); - - delete $3; + + // Create the InvokeInst + InvokeInst *II = new InvokeInst(V, Normal, Except, Args); + II->setCallingConv($2 |