aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorReid Spencer <rspencer@reidspencer.com>2006-12-31 05:40:12 +0000
committerReid Spencer <rspencer@reidspencer.com>2006-12-31 05:40:12 +0000
commite1553cc95601f3d5c5c807f482085857dd7937a8 (patch)
treeb128cb594fde87225bfd7e6afd8f2487517785cd
parent79e21d338c60b4b5a5746fc45e37ea0310606aee (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.l12
-rw-r--r--lib/AsmParser/llvmAsmParser.y654
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