// 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
// an error situation. So, whenever we want an error to occur, the GenerateError
-// function (see bottom of file) sets TriggerError. Then, at the end of each
-// production in the grammer we use CHECK_FOR_ERROR which will invoke YYERROR
-// (a goto) to put YACC in error state. Furthermore, several calls to
+// function (see bottom of file) sets TriggerError. Then, at the end of each
+// production in the grammer we use CHECK_FOR_ERROR which will invoke YYERROR
+// (a goto) to put YACC in error state. Furthermore, several calls to
// GenerateError are made from inside productions and they must simulate the
// previous exception behavior by exiting the production immediately. We have
// replaced these with the GEN_ERROR macro which calls GeneratError and then
-// immediately invokes YYERROR. This would be so much cleaner if it was a
+// immediately invokes YYERROR. This would be so much cleaner if it was a
// recursive descent parser.
static bool TriggerError = false;
#define CHECK_FOR_ERROR { if (TriggerError) { TriggerError = false; YYABORT; } }
//
typedef std::vector<Value *> ValueList; // Numbered defs
-static void
+static void
ResolveDefinitions(ValueList &LateResolvers, ValueList *FutureLateResolvers=0);
static struct PerModuleInfo {
if (!Ty->isAbstract())
return false;
// Traverse the type looking for abstract types. If it isn't abstract then
- // we don't need to traverse that leg of the type.
+ // we don't need to traverse that leg of the type.
std::vector<const Type*> WorkList, SeenList;
WorkList.push_back(Ty);
while (!WorkList.empty()) {
} else if (const SequentialType* SeqTy = dyn_cast<SequentialType>(Ty)) {
const Type* TheTy = SeqTy->getElementType();
if (TheTy->isAbstract() && TheTy != Ty) {
- std::vector<const Type*>::iterator I = SeenList.begin(),
+ std::vector<const Type*>::iterator I = SeenList.begin(),
E = SeenList.end();
for ( ; I != E; ++I)
if (*I == TheTy)
for (unsigned i = 0; i < StrTy->getNumElements(); ++i) {
const Type* TheTy = StrTy->getElementType(i);
if (TheTy->isAbstract() && TheTy != Ty) {
- std::vector<const Type*>::iterator I = SeenList.begin(),
+ std::vector<const Type*>::iterator I = SeenList.begin(),
E = SeenList.end();
for ( ; I != E; ++I)
if (*I == TheTy)
// Code to handle definitions of all the types
//===----------------------------------------------------------------------===//
-static void InsertValue(Value *V, ValueList &ValueTab = CurFun.Values) {
+/// InsertValue - Insert a value into the value table. If it is named, this
+/// returns -1, otherwise it returns the slot number for the value.
+static int InsertValue(Value *V, ValueList &ValueTab = CurFun.Values) {
// Things that have names or are void typed don't get slot numbers
if (V->hasName() || (V->getType() == Type::VoidTy))
- return;
+ return -1;
// In the case of function values, we have to allow for the forward reference
// of basic blocks, which are included in the numbering. Consequently, we keep
- // track of the next insertion location with NextValNum. When a BB gets
+ // track of the next insertion location with NextValNum. When a BB gets
// inserted, it could change the size of the CurFun.Values vector.
if (&ValueTab == &CurFun.Values) {
if (ValueTab.size() <= CurFun.NextValNum)
ValueTab.resize(CurFun.NextValNum+1);
ValueTab[CurFun.NextValNum++] = V;
- return;
- }
+ return CurFun.NextValNum-1;
+ }
// For all other lists, its okay to just tack it on the back of the vector.
ValueTab.push_back(V);
+ return ValueTab.size()-1;
}
static const Type *getTypeVal(const ValID &D, bool DoNotImprovise = false) {
switch (D.Type) {
case ValID::LocalID: { // Is it a numbered definition?
// Check that the number is within bounds.
- if (D.Num >= CurFun.Values.size())
+ if (D.Num >= CurFun.Values.size())
return 0;
Value *Result = CurFun.Values[D.Num];
if (Ty != Result->getType()) {
GenerateError("Numbered value (%" + utostr(D.Num) + ") of type '" +
- Result->getType()->getDescription() + "' does not match "
+ Result->getType()->getDescription() + "' does not match "
"expected type, '" + Ty->getDescription() + "'");
return 0;
}
return Result;
}
case ValID::GlobalID: { // Is it a numbered definition?
- if (D.Num >= CurModule.Values.size())
+ if (D.Num >= CurModule.Values.size())
return 0;
Value *Result = CurModule.Values[D.Num];
if (Ty != Result->getType()) {
GenerateError("Numbered value (@" + utostr(D.Num) + ") of type '" +
- Result->getType()->getDescription() + "' does not match "
+ Result->getType()->getDescription() + "' does not match "
"expected type, '" + Ty->getDescription() + "'");
return 0;
}
return Result;
}
-
+
case ValID::LocalName: { // Is it a named definition?
- if (!inFunctionScope())
+ if (!inFunctionScope())
return 0;
ValueSymbolTable &SymTab = CurFun.CurrentFunction->getValueSymbolTable();
Value *N = SymTab.lookup(D.getName());
- if (N == 0)
+ if (N == 0)
return 0;
if (N->getType() != Ty)
return 0;
-
+
D.destroy(); // Free old strdup'd memory...
return N;
}
case ValID::GlobalName: { // Is it a named definition?
ValueSymbolTable &SymTab = CurModule.CurrentModule->getValueSymbolTable();
Value *N = SymTab.lookup(D.getName());
- if (N == 0)
+ if (N == 0)
return 0;
if (N->getType() != Ty)
return 0;
// This is really a signed reference. Transmogrify.
return ConstantInt::get(Ty, D.ConstPool64, true);
+ case ValID::ConstAPInt: // Is it an unsigned const pool reference?
+ if (!isa<IntegerType>(Ty)) {
+ GenerateError("Integral constant '" + D.getName() +
+ "' is invalid or out of range for type '" +
+ Ty->getDescription() + "'");
+ return 0;
+ }
+
+ {
+ APSInt Tmp = *D.ConstPoolInt;
+ Tmp.extOrTrunc(Ty->getPrimitiveSizeInBits());
+ return ConstantInt::get(Tmp);
+ }
+
case ValID::ConstFPVal: // Is it a floating point const pool reference?
if (!Ty->isFloatingPoint() ||
!ConstantFP::isValueValidForType(Ty, *D.ConstPoolFP)) {
GenerateError("FP constant invalid for type");
return 0;
}
- // Lexer has no type info, so builds all float and double FP constants
+ // Lexer has no type info, so builds all float and double FP constants
// as double. Fix this here. Long double does not need this.
if (&D.ConstPoolFP->getSemantics() == &APFloat::IEEEdouble &&
Ty==Type::FloatTy)
case ValID::ConstZeroVal: // Is it a zero value?
return Constant::getNullValue(Ty);
-
+
case ValID::ConstantVal: // Fully resolved constant?
if (D.ConstantValue->getType() != Ty) {
GenerateError("Constant expression type different from required type");
default:
V = new Argument(Ty);
}
-
+
// Remember where this forward reference came from. FIXME, shouldn't we try
// to recycle these things??
CurModule.PlaceHolderInfo.insert(std::make_pair(V, std::make_pair(ID,
// Erase the forward ref from the map as its no longer "forward"
CurFun.BBForwardRefs.erase(ID);
- // The key has been removed from the map but so we don't want to leave
+ // The key has been removed from the map but so we don't want to leave
// strdup'd memory around so destroy it too.
Tmp.destroy();
assert(ID.Num == CurFun.NextValNum && "Invalid new block number");
InsertValue(BB);
}
- } else {
- // We haven't seen this BB before and its first mention is a definition.
+ } else {
+ // We haven't seen this BB before and its first mention is a definition.
// Just create it and return it.
std::string Name (ID.Type == ValID::LocalName ? ID.getName() : "");
BB = BasicBlock::Create(Name, CurFun.CurrentFunction);
}
/// getBBVal - get an existing BB value or create a forward reference for it.
-///
+///
static BasicBlock *getBBVal(const ValID &ID) {
assert(inFunctionScope() && "Can't get basic block at global scope!");
if (CurFun.Values[ID.Num]->getType()->getTypeID() == Type::LabelTyID)
BB = cast<BasicBlock>(CurFun.Values[ID.Num]);
else
- GenerateError("Reference to label '%" + utostr(ID.Num) +
- "' is actually of type '"+
+ GenerateError("Reference to label '%" + utostr(ID.Num) +
+ "' is actually of type '"+
CurFun.Values[ID.Num]->getType()->getDescription() + "'");
}
} else {
// time (forward branches, phi functions for loops, etc...) resolve the
// defs now...
//
-static void
+static void
ResolveDefinitions(ValueList &LateResolvers, ValueList *FutureLateResolvers) {
// Loop over LateResolveDefs fixing up stuff that couldn't be resolved
while (!LateResolvers.empty()) {
ValID D;
if (Name)
D = ValID::createLocalName(*Name);
- else
+ else
D = ValID::createLocalID(CurModule.Types.size());
std::map<ValID, PATypeHolder>::iterator I =
static bool setTypeName(const Type *T, std::string *NameStr) {
assert(!inFunctionScope() && "Can't give types function-local names!");
if (NameStr == 0) return false;
-
+
std::string Name(*NameStr); // Copy string
delete NameStr; // Free old string
// If Ty isn't abstract, or if there are no up-references in it, then there is
// nothing to resolve here.
if (!ty->isAbstract() || UpRefs.empty()) return ty;
-
+
PATypeHolder Ty(ty);
UR_OUT("Type '" << Ty->getDescription() <<
"' newly formed. Resolving upreferences.\n" <<
llvm::GlobalValue::LinkageTypes Linkage;
llvm::GlobalValue::VisibilityTypes Visibility;
- llvm::ParameterAttributes ParamAttrs;
+ llvm::Attributes ParamAttrs;
llvm::APInt *APIntVal;
int64_t SInt64Val;
uint64_t UInt64Val;
llvm::FCmpInst::Predicate FPredicate;
}
-%type <ModuleVal> Module
+%type <ModuleVal> Module
%type <FunctionVal> Function FunctionProto FunctionHeader BasicBlockList
%type <BasicBlockVal> BasicBlock InstructionList
%type <TermInstVal> BBTerminatorInst
%type <ParamList> ParamList // For call param lists & GEP indices
%type <ValueList> IndexList // For GEP indices
%type <ConstantList> ConstantIndexList // For insertvalue/extractvalue indices
-%type <TypeList> TypeListI
+%type <TypeList> TypeListI
%type <TypeWithAttrsList> ArgTypeList ArgTypeListI
%type <TypeWithAttrs> ArgType
%type <JumpTable> JumpTable
// EUINT64VAL - A positive number within uns. long long range
%token <UInt64Val> EUINT64VAL
-// ESAPINTVAL - A negative number with arbitrary precision
+// ESAPINTVAL - A negative number with arbitrary precision
%token <APIntVal> ESAPINTVAL
-// EUAPINTVAL - A positive number with arbitrary precision
+// EUAPINTVAL - A positive number with arbitrary precision
%token <APIntVal> EUAPINTVAL
%token <UIntVal> LOCALVAL_ID GLOBALVAL_ID // %123 @123
// Built in types...
%type <TypeVal> Types ResultTypes
%type <PrimType> IntType FPType PrimType // Classifications
-%token <PrimType> VOID INTTYPE
+%token <PrimType> VOID INTTYPE
%token <PrimType> FLOAT DOUBLE X86_FP80 FP128 PPC_FP128 LABEL
%token TYPE
-%token<StrVal> LOCALVAR GLOBALVAR LABELSTR
+%token<StrVal> LOCALVAR GLOBALVAR LABELSTR
%token<StrVal> STRINGCONSTANT ATSTRINGCONSTANT PCTSTRINGCONSTANT
%type <StrVal> LocalName OptLocalName OptLocalAssign
%type <StrVal> GlobalName OptGlobalAssign GlobalAssign
%token OPAQUE EXTERNAL TARGET TRIPLE ALIGN ADDRSPACE
%token DEPLIBS CALL TAIL ASM_TOK MODULE SIDEEFFECT
%token CC_TOK CCC_TOK FASTCC_TOK COLDCC_TOK X86_STDCALLCC_TOK X86_FASTCALLCC_TOK
+%token X86_SSECALLCC_TOK
%token DATALAYOUT
-%type <UIntVal> OptCallingConv
-%type <ParamAttrs> OptParamAttrs ParamAttr
+%type <UIntVal> OptCallingConv LocalNumber
+%type <ParamAttrs> OptParamAttrs ParamAttr
%type <ParamAttrs> OptFuncAttrs FuncAttr
+%type <ParamAttrs> OptFuncNotes FuncNote
+%type <ParamAttrs> FuncNoteList
// Basic Block Terminating Operators
%token <TermOpVal> RET BR SWITCH INVOKE UNWIND UNREACHABLE
%token <OtherOpVal> ICMP FCMP VICMP VFCMP
%type <IPredicate> IPredicates
%type <FPredicate> FPredicates
-%token EQ NE SLT SGT SLE SGE ULT UGT ULE UGE
+%token EQ NE SLT SGT SLE SGE ULT UGT ULE UGE
%token OEQ ONE OLT OGT OLE OGE ORD UNO UEQ UNE
// Memory Instructions
%token SIGNEXT ZEROEXT NORETURN INREG SRET NOUNWIND NOALIAS BYVAL NEST
%token READNONE READONLY GC
+// Function Notes
+%token FNNOTE INLINE ALWAYS NEVER OPTIMIZEFORSIZE
+
// Visibility Styles
%token DEFAULT HIDDEN PROTECTED
//
ArithmeticOps: ADD | SUB | MUL | UDIV | SDIV | FDIV | UREM | SREM | FREM;
LogicalOps : SHL | LSHR | ASHR | AND | OR | XOR;
-CastOps : TRUNC | ZEXT | SEXT | FPTRUNC | FPEXT | BITCAST |
+CastOps : TRUNC | ZEXT | SEXT | FPTRUNC | FPEXT | BITCAST |
UITOFP | SITOFP | FPTOUI | FPTOSI | INTTOPTR | PTRTOINT;
-IPredicates
+IPredicates
: EQ { $$ = ICmpInst::ICMP_EQ; } | NE { $$ = ICmpInst::ICMP_NE; }
| SLT { $$ = ICmpInst::ICMP_SLT; } | SGT { $$ = ICmpInst::ICMP_SGT; }
| SLE { $$ = ICmpInst::ICMP_SLE; } | SGE { $$ = ICmpInst::ICMP_SGE; }
| ULT { $$ = ICmpInst::ICMP_ULT; } | UGT { $$ = ICmpInst::ICMP_UGT; }
- | ULE { $$ = ICmpInst::ICMP_ULE; } | UGE { $$ = ICmpInst::ICMP_UGE; }
+ | ULE { $$ = ICmpInst::ICMP_ULE; } | UGE { $$ = ICmpInst::ICMP_UGE; }
;
-FPredicates
+FPredicates
: OEQ { $$ = FCmpInst::FCMP_OEQ; } | ONE { $$ = FCmpInst::FCMP_ONE; }
| OLT { $$ = FCmpInst::FCMP_OLT; } | OGT { $$ = FCmpInst::FCMP_OGT; }
| OLE { $$ = FCmpInst::FCMP_OLE; } | OGE { $$ = FCmpInst::FCMP_OGE; }
| FALSETOK { $$ = FCmpInst::FCMP_FALSE; }
;
-// These are some types that allow classification if we only want a particular
+// These are some types that allow classification if we only want a particular
// thing... for example, only a signed, unsigned, or integral type.
IntType : INTTYPE;
FPType : FLOAT | DOUBLE | PPC_FP128 | FP128 | X86_FP80;
CHECK_FOR_ERROR
};
+LocalNumber : LOCALVAL_ID '=' {
+ $$ = $1;
+ CHECK_FOR_ERROR
+};
+
+
GlobalName : GLOBALVAR | ATSTRINGCONSTANT ;
OptGlobalAssign : GlobalAssign
CHECK_FOR_ERROR
};
-GVInternalLinkage
- : INTERNAL { $$ = GlobalValue::InternalLinkage; }
- | WEAK { $$ = GlobalValue::WeakLinkage; }
+GVInternalLinkage
+ : INTERNAL { $$ = GlobalValue::InternalLinkage; }
+ | WEAK { $$ = GlobalValue::WeakLinkage; }
| LINKONCE { $$ = GlobalValue::LinkOnceLinkage; }
| APPENDING { $$ = GlobalValue::AppendingLinkage; }
- | DLLEXPORT { $$ = GlobalValue::DLLExportLinkage; }
+ | DLLEXPORT { $$ = GlobalValue::DLLExportLinkage; }
| COMMON { $$ = GlobalValue::CommonLinkage; }
;
FunctionDeclareLinkage
: /*empty*/ { $$ = GlobalValue::ExternalLinkage; }
- | DLLIMPORT { $$ = GlobalValue::DLLImportLinkage; }
+ | DLLIMPORT { $$ = GlobalValue::DLLImportLinkage; }
| EXTERN_WEAK { $$ = GlobalValue::ExternalWeakLinkage; }
;
-
+
FunctionDefineLinkage
: /*empty*/ { $$ = GlobalValue::ExternalLinkage; }
| INTERNAL { $$ = GlobalValue::InternalLinkage; }
| LINKONCE { $$ = GlobalValue::LinkOnceLinkage; }
| WEAK { $$ = GlobalValue::WeakLinkage; }
- | DLLEXPORT { $$ = GlobalValue::DLLExportLinkage; }
- ;
+ | DLLEXPORT { $$ = GlobalValue::DLLExportLinkage; }
+ ;
AliasLinkage
: /*empty*/ { $$ = GlobalValue::ExternalLinkage; }
COLDCC_TOK { $$ = CallingConv::Cold; } |
X86_STDCALLCC_TOK { $$ = CallingConv::X86_StdCall; } |
X86_FASTCALLCC_TOK { $$ = CallingConv::X86_FastCall; } |
+ X86_SSECALLCC_TOK { $$ = CallingConv::X86_SSECall; } |
CC_TOK EUINT64VAL {
if ((unsigned)$2 != $2)
GEN_ERROR("Calling conv too large");
| NOALIAS { $$ = ParamAttr::NoAlias; }
| BYVAL { $$ = ParamAttr::ByVal; }
| NEST { $$ = ParamAttr::Nest; }
- | ALIGN EUINT64VAL { $$ =
+ | ALIGN EUINT64VAL { $$ =
ParamAttr::constructAlignmentFromInt($2); }
;
FuncAttr : NORETURN { $$ = ParamAttr::NoReturn; }
| NOUNWIND { $$ = ParamAttr::NoUnwind; }
+ | INREG { $$ = ParamAttr::InReg; }
| ZEROEXT { $$ = ParamAttr::ZExt; }
| SIGNEXT { $$ = ParamAttr::SExt; }
| READNONE { $$ = ParamAttr::ReadNone; }
}
;
+FuncNoteList : FuncNote { $$ = $1; }
+ | FuncNoteList ',' FuncNote {
+ unsigned tmp = $1 | $3;
+ if ($3 == FnAttr::NoInline
+ && ($1 & FnAttr::AlwaysInline))
+ GEN_ERROR("Function Notes may include only one inline notes!")
+ if ($3 == FnAttr::AlwaysInline
+ && ($1 & FnAttr::NoInline))
+ GEN_ERROR("Function Notes may include only one inline notes!")
+ $$ = tmp;
+ CHECK_FOR_ERROR
+ }
+ ;
+
+FuncNote : INLINE '=' NEVER { $$ = FnAttr::NoInline; }
+ | INLINE '=' ALWAYS { $$ = FnAttr::AlwaysInline; }
+ | OPTIMIZEFORSIZE { $$ = FnAttr::OptimizeForSize; }
+ ;
+
+OptFuncNotes : /* empty */ { $$ = FnAttr::None; }
+ | FNNOTE '(' FuncNoteList ')' {
+ $$ = $3;
+ }
+ ;
+
OptGC : /* empty */ { $$ = 0; }
| GC STRINGCONSTANT {
$$ = $2;
CurGV->setSection(*$1);
delete $1;
CHECK_FOR_ERROR
- }
+ }
| ALIGN EUINT64VAL {
if ($2 != 0 && !isPowerOf2_32($2))
GEN_ERROR("Alignment must be a power of two");
//===----------------------------------------------------------------------===//
// Types includes all predefined types... except void, because it can only be
-// used in specific contexts (function returning void for example).
+// used in specific contexts (function returning void for example).
// Derived types are added later...
//
PrimType : INTTYPE | FLOAT | DOUBLE | PPC_FP128 | FP128 | X86_FP80 | LABEL ;
-Types
+Types
: OPAQUE {
$$ = new PATypeHolder(OpaqueType::get());
CHECK_FOR_ERROR
const Type *RetTy = *$1;
if (!FunctionType::isValidReturnType(RetTy))
GEN_ERROR("Invalid result type for LLVM function");
-
+
std::vector<const Type*> Params;
TypeWithAttrsList::iterator I = $3->begin(), E = $3->end();
for (; I != E; ++I ) {
FunctionType *FT = FunctionType::get(RetTy, Params, isVarArg);
delete $3; // Delete the argument list
delete $1; // Delete the return type handle
- $$ = new PATypeHolder(HandleUpRefs(FT));
+ $$ = new PATypeHolder(HandleUpRefs(FT));
CHECK_FOR_ERROR
}
| VOID '(' ArgTypeListI ')' OptFuncAttrs {
FunctionType *FT = FunctionType::get($1, Params, isVarArg);
delete $3; // Delete the argument list
- $$ = new PATypeHolder(HandleUpRefs(FT));
+ $$ = new PATypeHolder(HandleUpRefs(FT));
CHECK_FOR_ERROR
}
}
;
-ArgType
+ArgType
: Types OptParamAttrs {
// Allow but ignore attributes on function types; this permits auto-upgrade.
// FIXME: remove in LLVM 3.0.
- $$.Ty = $1;
+ $$.Ty = $1;
$$.Attrs = ParamAttr::None;
}
;
}
;
-ArgTypeListI
+ArgTypeListI
: ArgTypeList
| ArgTypeList ',' DOTDOTDOT {
$$=$1;
CHECK_FOR_ERROR
};
-// TypeList - Used for struct declarations and as a basis for function type
+// TypeList - Used for struct declarations and as a basis for function type
// declaration type lists
//
TypeListI : Types {
$$ = new std::list<PATypeHolder>();
- $$->push_back(*$1);
+ $$->push_back(*$1);
delete $1;
CHECK_FOR_ERROR
}
| TypeListI ',' Types {
- ($$=$1)->push_back(*$3);
+ ($$=$1)->push_back(*$3);
delete $3;
CHECK_FOR_ERROR
};
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: '" +
+ GEN_ERROR("Cannot make array constant with type: '" +
(*$1)->getDescription() + "'");
const Type *ETy = ATy->getElementType();
- int NumElements = ATy->getNumElements();
+ uint64_t NumElements = ATy->getNumElements();
// Verify that we have the correct size...
- if (NumElements != -1 && NumElements != (int)$3->size())
+ if (NumElements != uint64_t(-1) && NumElements != $3->size())
GEN_ERROR("Type mismatch: constant sized array initialized with " +
- utostr($3->size()) + " arguments, but has size of " +
- itostr(NumElements) + "");
+ utostr($3->size()) + " arguments, but has size of " +
+ utostr(NumElements) + "");
// Verify all elements are correct type!
for (unsigned i = 0; i < $3->size(); i++) {
if (ETy != (*$3)[i]->getType())
- GEN_ERROR("Element #" + utostr(i) + " is not of type '" +
+ GEN_ERROR("Element #" + utostr(i) + " is not of type '" +
ETy->getDescription() +"' as required!\nIt is of type '"+
(*$3)[i]->getType()->getDescription() + "'.");
}
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: '" +
+ GEN_ERROR("Cannot make array constant with type: '" +
(*$1)->getDescription() + "'");
- int NumElements = ATy->getNumElements();
- if (NumElements != -1 && NumElements != 0)
+ uint64_t NumElements = ATy->getNumElements();
+ if (NumElements != uint64_t(-1) && NumElements != 0)
GEN_ERROR("Type mismatch: constant sized array initialized with 0"
- " arguments, but has size of " + itostr(NumElements) +"");
+ " arguments, but has size of " + utostr(NumElements) +"");
$$ = ConstantArray::get(ATy, std::vector<Constant*>());
delete $1;
CHECK_FOR_ERROR
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: '" +
+ GEN_ERROR("Cannot make array constant with type: '" +
(*$1)->getDescription() + "'");
- int NumElements = ATy->getNumElements();
+ uint64_t NumElements = ATy->getNumElements();
const Type *ETy = ATy->getElementType();
- if (NumElements != -1 && NumElements != int($3->length()))
- GEN_ERROR("Can't build string constant of size " +
- itostr((int)($3->length())) +
- " when array has size " + itostr(NumElements) + "");
+ if (NumElements != uint64_t(-1) && NumElements != $3->length())
+ GEN_ERROR("Can't build string constant of size " +
+ utostr($3->length()) +
+ " when array has size " + utostr(NumElements) + "");
std::vector<Constant*> Vals;
if (ETy == Type::Int8Ty) {
- for (unsigned i = 0; i < $3->length(); ++i)
+ for (uint64_t i = 0; i < $3->length(); ++i)
Vals.push_back(ConstantInt::get(ETy, (*$3)[i]));
} else {
delete $3;
GEN_ERROR("Invalid upreference in type: " + (*$1)->getDescription());
const VectorType *PTy = dyn_cast<VectorType>($1->get());
if (PTy == 0)
- GEN_ERROR("Cannot make packed constant with type: '" +
+ GEN_ERROR("Cannot make packed constant with type: '" +
(*$1)->getDescription() + "'");
const Type *ETy = PTy->getElementType();
- int NumElements = PTy->getNumElements();
+ unsigned NumElements = PTy->getNumElements();
// Verify that we have the correct size...
- if (NumElements != -1 && NumElements != (int)$3->size())
+ if (NumElements != unsigned(-1) && NumElements != (unsigned)$3->size())
GEN_ERROR("Type mismatch: constant sized packed initialized with " +
- utostr($3->size()) + " arguments, but has size of " +
- itostr(NumElements) + "");
+ utostr($3->size()) + " arguments, but has size of " +
+ utostr(NumElements) + "");
// Verify all elements are correct type!
for (unsigned i = 0; i < $3->size(); i++) {
if (ETy != (*$3)[i]->getType())
- GEN_ERROR("Element #" + utostr(i) + " is not of type '" +
+ GEN_ERROR("Element #" + utostr(i) + " is not of type '" +
ETy->getDescription() +"' as required!\nIt is of type '"+
(*$3)[i]->getType()->getDescription() + "'.");
}
| Types '{' ConstVector '}' {
const StructType *STy = dyn_cast<StructType>($1->get());
if (STy == 0)
- GEN_ERROR("Cannot make struct constant with type: '" +
+ GEN_ERROR("Cannot make struct constant with type: '" +
(*$1)->getDescription() + "'");
if ($3->size() != STy->getNumContainedTypes())
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: '" +
+ GEN_ERROR("Cannot make struct constant with type: '" +
(*$1)->getDescription() + "'");
if (STy->getNumContainedTypes() != 0)
| Types '<' '{' ConstVector '}' '>' {
const StructType *STy = dyn_cast<StructType>($1->get());
if (STy == 0)
- GEN_ERROR("Cannot make struct constant with type: '" +
+ GEN_ERROR("Cannot make struct constant with type: '" +
(*$1)->getDescription() + "'");
if ($4->size() != STy->getNumContainedTypes())
// Check to ensure that Type is packed
if (!STy->isPacked())
- GEN_ERROR("Vector initializer to non-vector type '" +
+ GEN_ERROR("Vector initializer to non-vector type '" +
STy->getDescription() + "'");
$$ = ConstantStruct::get(STy, *$4);
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: '" +
+ GEN_ERROR("Cannot make struct constant with type: '" +
(*$1)->getDescription() + "'");
if (STy->getNumContainedTypes() != 0)
// Check to ensure that Type is packed
if (!STy->isPacked())
- GEN_ERROR("Vector initializer to non-vector type '" +
+ GEN_ERROR("Vector initializer to non-vector type '" +
STy->getDescription() + "'");
$$ = ConstantStruct::get(STy, std::vector<Constant*>());
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: '" +
+ GEN_ERROR("Cannot make null pointer constant with type: '" +
(*$1)->getDescription() + "'");
$$ = ConstantPointerNull::get(PTy);
// First check to see if the forward references value is already created!
PerModuleInfo::GlobalRefsType::iterator I =
CurModule.GlobalRefs.find(std::make_pair(PT, $2));
-
+
if (I != CurModule.GlobalRefs.end()) {
V = I->second; // Placeholder already exists, use it...
$2.destroy();
// Create the forward referenced global.
GlobalValue *GV;
- if (const FunctionType *FTy =
+ if (const FunctionType *FTy =
dyn_cast<FunctionType>(PT->getElementType())) {
GV = Function::Create(FTy, GlobalValue::ExternalWeakLinkage, Name,
CurModule.CurrentModule);
if (!UpRefs.empty())
GEN_ERROR("Invalid upreference in type: " + (*$1)->getDescription());
if ($1->get() != $2->getType())
- GEN_ERROR("Mismatched types for constant expression: " +
+ GEN_ERROR("Mismatched types for constant expression: " +
(*$1)->getDescription() + " and " + $2->getType()->getDescription());
$$ = $2;
delete $1;
uint32_t BitWidth = cast<IntegerType>($1)->getBitWidth();
if ($2->getBitWidth() > BitWidth) {
GEN_ERROR("Constant value does not fit in type");
- }
+ }
$2->zextOrTrunc(BitWidth);
$$ = ConstantInt::get(*$2);
delete $2;
| FPType FPVAL { // Floating point constants
if (!ConstantFP::isValueValidForType($1, *$2))
GEN_ERROR("Floating point constant invalid for type");
- // Lexer has no type info, so builds all float and double FP constants
+ // Lexer has no type info, so builds all float and double FP constants
// as double. Fix this here. Long double is done right.
if (&$2->getSemantics()==&APFloat::IEEEdouble && $1==Type::FloatTy)
$2->convert(APFloat::IEEEsingle, APFloat::rmNearestTiesToEven);
if (!CastInst::castIsValid($1, $3, DestTy))
GEN_ERROR("invalid cast opcode for cast from '" +
Val->getType()->getDescription() + "' to '" +
- DestTy->getDescription() + "'");
+ DestTy->getDescription() + "'");
$$ = ConstantExpr::getCast($1, $3, DestTy);
delete $5;
}
if ($3->getType() != $5->getType())
GEN_ERROR("Logical operator types must match");
if (!$3->getType()->isInteger()) {
- if (Instruction::isShift($1) || !isa<VectorType>($3->getType()) ||
+ if (!isa<VectorType>($3->getType()) ||
!cast<VectorType>($3->getType())->getElementType()->isInteger())
GEN_ERROR("Logical operator requires integral operands");
}
// GlobalType - Match either GLOBAL or CONSTANT for global declarations...
GlobalType : GLOBAL { $$ = false; } | CONSTANT { $$ = true; };
-// ThreadLocal
+// ThreadLocal
ThreadLocal : THREAD_LOCAL { $$ = true; } | { $$ = false; };
// AliaseeRef - Match either GlobalValue or bitcast to GlobalValue.
GEN_ERROR("invalid cast opcode for cast from '" +
Val->getType()->getDescription() + "' to '" +
DestTy->getDescription() + "'");
-
+
$$ = ConstantExpr::getCast($1, $3, DestTy);
CHECK_FOR_ERROR
delete $5;
// Module rule: Capture the result of parsing the whole file into a result
// variable...
//
-Module
+Module
: DefinitionList {
$$ = ParserResult = CurModule.CurrentModule;
CurModule.ModuleDone();
| DefinitionList Definition
;
-Definition
+Definition
: DEFINE { CurFun.isDeclare = false; } Function {
CurFun.FunctionDone();
CHECK_FOR_ERROR
}
| MODULE ASM_TOK AsmBlock {
CHECK_FOR_ERROR
- }
+ }
| OptLocalAssign TYPE Types {
if (!UpRefs.empty())
GEN_ERROR("Invalid upreference in type: " + (*$3)->getDescription());
}
CHECK_FOR_ERROR
}
- | OptGlobalAssign GVVisibilityStyle ThreadLocal GlobalType ConstVal
- OptAddrSpace {
+ | OptGlobalAssign GVVisibilityStyle ThreadLocal GlobalType ConstVal
+ OptAddrSpace {
/* "Externally Visible" Linkage */
- if ($5 == 0)
+ if ($5 == 0)
GEN_ERROR("Global value initializer is not a constant");
CurGV = ParseGlobalVariable($1, GlobalValue::ExternalLinkage,
$2, $4, $5->getType(), $5, $3, $6);
}
| OptGlobalAssign GVInternalLinkage GVVisibilityStyle ThreadLocal GlobalType
ConstVal OptAddrSpace {
- if ($6 == 0)
+ if ($6 == 0)
GEN_ERROR("Global value initializer is not a constant");
CurGV = ParseGlobalVariable($1, $2, $3, $5, $6->getType(), $6, $4, $7);
CHECK_FOR_ERROR
}
if (Name.empty())
GEN_ERROR("Alias name cannot be empty");
-
+
Constant* Aliasee = $5;
if (Aliasee == 0)
GEN_ERROR(std::string("Invalid aliasee for alias: ") + Name);
CurModule.CurrentModule);
GA->setVisibility($2);
InsertValue(GA, CurModule.Values);
-
-
+
+
// If there was a forward reference of this alias, resolve it now.
-
+
ValID ID;
if (!Name.empty())
ID = ValID::createGlobalName(Name);
else
ID = ValID::createGlobalID(CurModule.Values.size()-1);
-
+
if (GlobalValue *FWGV =
CurModule.GetForwardRefForGlobal(GA->getType(), ID)) {
// Replace uses of the fwdref with the actual alias.
cast<Function>(FWGV)->eraseFromParent();
}
ID.destroy();
-
+
CHECK_FOR_ERROR
}
- | TARGET TargetDefinition {
+ | TARGET TargetDefinition {
CHECK_FOR_ERROR
}
| DEPLIBS '=' LibrariesDefinition {
CHECK_FOR_ERROR
};
-FunctionHeaderH : OptCallingConv ResultTypes GlobalName '(' ArgList ')'
- OptFuncAttrs OptSection OptAlign OptGC {
+FunctionHeaderH : OptCallingConv ResultTypes GlobalName '(' ArgList ')'
+ OptFuncAttrs OptSection OptAlign OptGC OptFuncNotes {
std::string FunctionName(*$3);
delete $3; // Free strdup'd memory!
-
+
// Check the function result for abstractness if this is a define. We should
// have no abstract types at this point
if (!CurFun.isDeclare && CurModule.TypeIsUnresolved($2))
if (!FunctionType::isValidReturnType(*$2))
GEN_ERROR("Invalid result type for LLVM function");
-
+
std::vector<const Type*> ParamTypeList;
- SmallVector<ParamAttrsWithIndex, 8> Attrs;
+ SmallVector<FnAttributeWithIndex, 8> Attrs;
if ($7 != ParamAttr::None)
- Attrs.push_back(ParamAttrsWithIndex::get(0, $7));
+ Attrs.push_back(FnAttributeWithIndex::get(0, $7));
if ($5) { // If there are arguments...
unsigned index = 1;
for (ArgListType::iterator I = $5->begin(); I != $5->end(); ++I, ++index) {
GEN_ERROR("Reference to abstract argument: " + Ty->getDescription());
ParamTypeList.push_back(Ty);
if (Ty != Type::VoidTy && I->Attrs != ParamAttr::None)
- Attrs.push_back(ParamAttrsWithIndex::get(index, I->Attrs));
+ Attrs.push_back(FnAttributeWithIndex::get(index, I->Attrs));
}
}
Function *Fn = 0;
// See if this function was forward referenced. If so, recycle the object.
if (GlobalValue *FWRef = CurModule.GetForwardRefForGlobal(PFT, ID)) {
- // Move the function to the end of the list, from whereever it was
+ // Move the function to the end of the list, from whereever it was
// previously inserted.
Fn = cast<Function>(FWRef);
assert(Fn->getParamAttrs().isEmpty() &&
delete $8;
}
if ($10) {
- Fn->setCollector($10->c_str());
+ Fn->setGC($10->c_str());
delete $10;
}
+ if ($11) {
+ Fn->setNotes($11);
+ }
// Add all of the arguments we parsed to the function...
if ($5) { // Is null if empty...
Function::arg_iterator ArgIt = Fn->arg_begin();
Function::arg_iterator ArgEnd = Fn->arg_end();
unsigned Idx = 1;
- for (ArgListType::iterator I = $5->begin();
+ for (ArgListType::iterator I = $5->begin();
I != $5->end() && ArgIt != ArgEnd; ++I, ++ArgIt) {
delete I->Ty; // Delete the typeholder...
setValueName(ArgIt, I->Name); // Insert arg into symtab...
$$ = ValID::create($1);
CHECK_FOR_ERROR
}
+ | ESAPINTVAL { // arbitrary precision integer constants
+ $$ = ValID::create(*$1, true);
+ delete $1;
+ CHECK_FOR_ERROR
+ }
+ | EUAPINTVAL { // arbitrary precision integer constants
+ $$ = ValID::create(*$1, false);
+ delete $1;
+ CHECK_FOR_ERROR
+ }
| FPVAL { // Perhaps it's an FP constant?
$$ = ValID::create($1);
CHECK_FOR_ERROR
| TRUETOK {
$$ = ValID::create(ConstantInt::getTrue());
CHECK_FOR_ERROR
- }
+ }
| FALSETOK {
$$ = ValID::create(ConstantInt::getFalse());
CHECK_FOR_ERROR
}
| '<' ConstVector '>' { // Nonempty unsized packed vector
const Type *ETy = (*$2)[0]->getType();
- int NumElements = $2->size();
+ unsigned NumElements = $2->size();
if (!ETy->isInteger() && !ETy->isFloatingPoint())
GEN_ERROR("Invalid vector element type: " + ETy->getDescription());
-
+
VectorType* pt = VectorType::get(ETy, NumElements);
- PATypeHolder* PTy = new PATypeHolder(
- HandleUpRefs(
- VectorType::get(
- ETy,
- NumElements)
- )
- );
-
+ PATypeHolder* PTy = new PATypeHolder(HandleUpRefs(pt));
+
// Verify all elements are correct type!
for (unsigned i = 0; i < $2->size(); i++) {
if (ETy != (*$2)[i]->getType())
- GEN_ERROR("Element #" + utostr(i) + " is not of type '" +
+ GEN_ERROR("Element #" + utostr(i) + " is not of type '" +
ETy->getDescription() +"' as required!\nIt is of type '" +
(*$2)[i]->getType()->getDescription() + "'.");
}
delete PTy; delete $2;
CHECK_FOR_ERROR
}
+ | '[' ConstVector ']' { // Nonempty unsized arr
+ const Type *ETy = (*$2)[0]->getType();
+ uint64_t NumElements = $2->size();
+
+ if (!ETy->isFirstClassType())
+ GEN_ERROR("Invalid array element type: " + ETy->getDescription());
+
+ ArrayType *ATy = ArrayType::get(ETy, NumElements);
+ PATypeHolder* PTy = new PATypeHolder(HandleUpRefs(ATy));
+
+ // Verify all elements are correct type!
+ for (unsigned i = 0; i < $2->size(); i++) {
+ if (ETy != (*$2)[i]->getType())
+ GEN_ERROR("Element #" + utostr(i) + " is not of type '" +
+ ETy->getDescription() +"' as required!\nIt is of type '"+
+ (*$2)[i]->getType()->getDescription() + "'.");
+ }
+
+ $$ = ValID::create(ConstantArray::get(ATy, *$2));
+ delete PTy; delete $2;
+ CHECK_FOR_ERROR
+ }
+ | '[' ']' {
+ // Use undef instead of an array because it's inconvenient to determine
+ // the element type at this point, there being no elements to examine.
+ $$ = ValID::createUndef();
+ CHECK_FOR_ERROR
+ }
+ | 'c' STRINGCONSTANT {
+ uint64_t NumElements = $2->length();
+ const Type *ETy = Type::Int8Ty;
+
+ ArrayType *ATy = ArrayType::get(ETy, NumElements);
+
+ std::vector<Constant*> Vals;
+ for (unsigned i = 0; i < $2->length(); ++i)
+ Vals.push_back(ConstantInt::get(ETy, (*$2)[i]));
+ delete $2;
+ $$ = ValID::create(ConstantArray::get(ATy, Vals));
+ CHECK_FOR_ERROR
+ }
+ | '{' ConstVector '}' {
+ std::vector<const Type*> Elements($2->size());
+ for (unsigned i = 0, e = $2->size(); i != e; ++i)
+ Elements[i] = (*$2)[i]->getType();
+
+ const StructType *STy = StructType::get(Elements);
+ PATypeHolder* PTy = new PATypeHolder(HandleUpRefs(STy));
+
+ $$ = ValID::create(ConstantStruct::get(STy, *$2));
+ delete PTy; delete $2;
+ CHECK_FOR_ERROR
+ }
+ | '{' '}' {
+ const StructType *STy = StructType::get(std::vector<const Type*>());
+ $$ = ValID::create(ConstantStruct::get(STy, std::vector<Constant*>()));
+ CHECK_FOR_ERROR
+ }
+ | '<' '{' ConstVector '}' '>' {
+ std::vector<const Type*> Elements($3->size());
+ for (unsigned i = 0, e = $3->size(); i != e; ++i)
+ Elements[i] = (*$3)[i]->getType();
+
+ const StructType *STy = StructType::get(Elements, /*isPacked=*/true);
+ PATypeHolder* PTy = new PATypeHolder(HandleUpRefs(STy));
+
+ $$ = ValID::create(ConstantStruct::get(STy, *$3));
+ delete PTy; delete $3;
+ CHECK_FOR_ERROR
+ }
+ | '<' '{' '}' '>' {
+ const StructType *STy = StructType::get(std::vector<const Type*>(),
+ /*isPacked=*/true);
+ $$ = ValID::create(ConstantStruct::get(STy, std::vector<Constant*>()));
+ CHECK_FOR_ERROR
+ }
| ConstExpr {
$$ = ValID::create($1);
CHECK_FOR_ERROR
ResolvedVal : Types ValueRef {
if (!UpRefs.empty())
GEN_ERROR("Invalid upreference in type: " + (*$1)->getDescription());
- $$ = getVal(*$1, $2);
+ $$ = getVal(*$1, $2);
delete $1;
CHECK_FOR_ERROR
}
ReturnedVal : ResolvedVal {
$$ = new std::vector<Value *>();
- $$->push_back($1);
+ $$->push_back($1);
CHECK_FOR_ERROR
}
| ReturnedVal ',' ResolvedVal {
- ($$=$1)->push_back($3);
+ ($$=$1)->push_back($3);
CHECK_FOR_ERROR
};
$$ = $1;
CHECK_FOR_ERROR
}
- | FunctionHeader BasicBlock { // Do not allow functions with 0 basic blocks
+ | FunctionHeader BasicBlock { // Do not allow functions with 0 basic blocks
$$ = $1;
CHECK_FOR_ERROR
};
-// Basic blocks are terminated by branching instructions:
+// Basic blocks are terminated by branching instructions:
// br, br/cc, switch, ret
//
-BasicBlock : InstructionList OptLocalAssign BBTerminatorInst {
+BasicBlock : InstructionList OptLocalAssign BBTerminatorInst {
setValueName($3, $2);
CHECK_FOR_ERROR
InsertValue($3);
CHECK_FOR_ERROR
};
+BasicBlock : InstructionList LocalNumber BBTerminatorInst {
+ CHECK_FOR_ERROR
+ int ValNum = InsertValue($3);
+ if (ValNum != (int)$2)
+ GEN_ERROR("Result value number %" + utostr($2) +
+ " is incorrect, expected %" + utostr((unsigned)ValNum));
+
+ $1->getInstList().push_back($3);
+ $$ = $1;
+ CHECK_FOR_ERROR
+};
+
+
InstructionList : InstructionList Inst {
if (CastInst *CI1 = dyn_cast<CastInst>($2))
if (CastInst *CI2 = dyn_cast<CastInst>(CI1->getOperand(0)))
};
-BBTerminatorInst :
+BBTerminatorInst :
RET ReturnedVal { // Return with a result...
ValueList &VL = *$2;
assert(!VL.empty() && "Invalid ret operands!");
- $$ = ReturnInst::Create(&VL[0], VL.size());
+ const Type *ReturnType = CurFun.CurrentFunction->getReturnType();
+ if (VL.size() > 1 ||
+ (isa<StructType>(ReturnType) &&
+ (VL.empty() || VL[0]->getType() != ReturnType))) {
+ Value *RV = UndefValue::get(ReturnType);
+ for (unsigned i = 0, e = VL.size(); i != e; ++i) {
+ Instruction *I = InsertValueInst::Create(RV, VL[i], i, "mrv");
+ ($<BasicBlockVal>-1)->getInstList().push_back(I);
+ RV = I;
+ }
+ $$ = ReturnInst::Create(RV);
+ } else {
+ $$ = ReturnInst::Create(VL[0]);
+ }
delete $2;
CHECK_FOR_ERROR
}
CHECK_FOR_ERROR
$$ = BranchInst::Create(tmpBB);
} // Conditional Branch...
- | BR INTTYPE ValueRef ',' LABEL ValueRef ',' LABEL ValueRef {
+ | BR INTTYPE ValueRef ',' LABEL ValueRef ',' LABEL ValueRef {
if (cast<IntegerType>($2)->getBitWidth() != 1)
GEN_ERROR("Branch condition must have type i1");
BasicBlock* tmpBBA = getBBVal($6);
GEN_ERROR("Short call syntax cannot be used with varargs");
ParamTypes.push_back(Ty);
}
-
+
if (!FunctionType::isValidReturnType(*$3))
GEN_ERROR("Invalid result type for LLVM function");
BasicBlock *Except = getBBVal($14);
CHECK_FOR_ERROR
- SmallVector<ParamAttrsWithIndex, 8> Attrs;
+ SmallVector<FnAttributeWithIndex, 8> Attrs;
if ($8 != ParamAttr::None)
- Attrs.push_back(ParamAttrsWithIndex::get(0, $8));
+ Attrs.push_back(FnAttributeWithIndex::get(0, $8));
// Check the arguments
ValueList Args;
(*I)->getDescription() + "'");
Args.push_back(ArgI->Val);
if (ArgI->Attrs != ParamAttr::None)
- Attrs.push_back(ParamAttrsWithIndex::get(index, ArgI->Attrs));
+ Attrs.push_back(FnAttributeWithIndex::get(index, ArgI->Attrs));
}
if (Ty->isVarArg()) {
for (; ArgI != ArgE; ++ArgI, ++index) {
Args.push_back(ArgI->Val); // push the remaining varargs
if (ArgI->Attrs != ParamAttr::None)
- Attrs.push_back(ParamAttrsWithIndex::get(index, ArgI->Attrs));
+ Attrs.push_back(FnAttributeWithIndex::get(index, ArgI->Attrs));
}
} else if (I != E || ArgI != ArgE)
GEN_ERROR("Invalid number of parameters detected");
BasicBlock* tmpBB = getBBVal($5);
CHECK_FOR_ERROR
- $$->push_back(std::make_pair(V, tmpBB));
+ $$->push_back(std::make_pair(V, tmpBB));
};
Inst : OptLocalAssign InstVal {
CHECK_FOR_ERROR
};
+Inst : LocalNumber InstVal {
+ CHECK_FOR_ERROR
+ int ValNum = InsertValue($2);
+
+ if (ValNum != (int)$1)
+ GEN_ERROR("Result value number %" + utostr($1) +
+ " is incorrect, expected %" + utostr((unsigned)ValNum));
+
+ $$ = $2;
+ CHECK_FOR_ERROR
+ };
+
PHIList : Types '[' ValueRef ',' ValueRef ']' { // Used for PHI nodes
if (!UpRefs.empty())
InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
if (!UpRefs.empty())
GEN_ERROR("Invalid upreference in type: " + (*$2)->getDescription());
- if (!(*$2)->isInteger() && !(*$2)->isFloatingPoint() &&
+ if (!(*$2)->isInteger() && !(*$2)->isFloatingPoint() &&
!isa<VectorType>((*$2).get()))
GEN_ERROR(
"Arithmetic operator requires integer, FP, or packed operands");
- Value* val1 = getVal(*$2, $3);
+ Value* val1 = getVal(*$2, $3);
CHECK_FOR_ERROR
Value* val2 = getVal(*$2, $5);
CHECK_FOR_ERROR
if (!UpRefs.empty())
GEN_ERROR("Invalid upreference in type: " + (*$2)->getDescription());
if (!(*$2)->isInteger()) {
- if (Instruction::isShift($1) || !isa<VectorType>($2->get()) ||
+ if (!isa<VectorType>($2->get()) ||
!cast<VectorType>($2->get())->getElementType()->isInteger())
GEN_ERROR("Logical operator requires integral operands");
}
| ICMP IPredicates Types ValueRef ',' ValueRef {
if (!UpRefs.empty())
GEN_ERROR("Invalid upreference in type: " + (*$3)->getDescription());
- if (isa<VectorType>((*$3).get()))
- GEN_ERROR("Vector types not supported by icmp instruction");
Value* tmpVal1 = getVal(*$3, $4);
CHECK_FOR_ERROR
Value* tmpVal2 = getVal(*$3, $6);
| FCMP FPredicates Types ValueRef ',' ValueRef {
if (!UpRefs.empty())
GEN_ERROR("Invalid upreference in type: " + (*$3)->getDescription());
- if (isa<VectorType>((*$3).get()))
- GEN_ERROR("Vector types not supported by fcmp instruction");
Value* tmpVal1 = getVal(*$3, $4);
CHECK_FOR_ERROR
Value* tmpVal2 = getVal(*$3, $6);
CHECK_FOR_ERROR
$$ = CmpInst::Create($1, $2, tmpVal1, tmpVal2);
if ($$ == 0)
- GEN_ERROR("icmp operator returned null");
+ GEN_ERROR("vicmp operator returned null");
delete $3;
}
| VFCMP FPredicates Types ValueRef ',' ValueRef {
CHECK_FOR_ERROR
$$ = CmpInst::Create($1, $2, tmpVal1, tmpVal2);
if ($$ == 0)
- GEN_ERROR("fcmp operator returned null");
+ GEN_ERROR("vfcmp operator returned null");
delete $3;
}
| CastOps ResolvedVal TO Types {
if (!CastInst::castIsValid($1, Val, DestTy))
GEN_ERROR("invalid cast opcode for cast from '" +
Val->getType()->getDescription() + "' to '" +
- DestTy->getDescription() + "'");
+ DestTy->getDescription() + "'");
$$ = CastInst::Create($1, Val, DestTy);
delete $4;
}
| SELECT ResolvedVal ',' ResolvedVal ',' ResolvedVal {
- if ($2->getType() != Type::Int1Ty)
- GEN_ERROR("select condition must be boolean");
+ if (isa<VectorType>($2->getType())) {
+ // vector select
+ if (!isa<VectorType>($4->getType())
+ || !isa<VectorType>($6->getType()) )
+ GEN_ERROR("vector select value types must be vector types");
+ const VectorType* cond_type = cast<VectorType>($2->getType());
+ const VectorType* select_type = cast<VectorType>($4->getType());
+ if (cond_type->getElementType() != Type::Int1Ty)
+ GEN_ERROR("vector select condition element type must be boolean");
+ if (cond_type->getNumElements() != select_type->getNumElements())
+ GEN_ERROR("vector select number of elements must be the same");
+ } else {
+ if ($2->getType() != Type::Int1Ty)
+ GEN_ERROR("select condition must be boolean");
+ }
if ($4->getType() != $6->getType())
- GEN_ERROR("select value types should match");
+ GEN_ERROR("select value types must match");
$$ = SelectInst::Create($2, $4, $6);
CHECK_FOR_ERROR
}
$$ = PHINode::Create(Ty);
((PHINode*)$$)->reserveOperandSpace($2->size());
while ($2->begin() != $2->end()) {
- if ($2->front().first->getType() != Ty)
+ if ($2->front().first->getType() != Ty)
GEN_ERROR("All elements of a PHI node must be of the same type");
cast<PHINode>($$)->addIncoming($2->front().first, $2->front().second);
$2->pop_front();
delete $2; // Free the list...
CHECK_FOR_ERROR
}
- | OptTailCall OptCallingConv ResultTypes ValueRef '(' ParamList ')'
+ | OptTailCall OptCallingConv ResultTypes ValueRef '(' ParamList ')'
OptFuncAttrs {
// Handle the short syntax
}
// Set up the ParamAttrs for the function
- SmallVector<ParamAttrsWithIndex, 8> Attrs;
+ SmallVector<FnAttributeWithIndex, 8> Attrs;
if ($8 != ParamAttr::None)
- Attrs.push_back(ParamAttrsWithIndex::get(0, $8));
- // Check the arguments
+ Attrs.push_back(FnAttributeWithIndex::get(0, $8));
+ // Check the arguments
ValueList Args;
if ($6->empty()) { // Has no arguments?
// Make sure no arguments is a good thing!
(*I)->getDescription() + "'");
Args.push_back(ArgI->Val);
if (ArgI->Attrs != ParamAttr::None)
- Attrs.push_back(ParamAttrsWithIndex::get(index, ArgI->Attrs));
+ Attrs.push_back(FnAttributeWithIndex::get(index, ArgI->Attrs));
}
if (Ty->isVarArg()) {
if (I == E)
for (; ArgI != ArgE; ++ArgI, ++index) {
Args.push_back(ArgI->Val); // push the remaining varargs
if (ArgI->Attrs != ParamAttr::None)
- Attrs.push_back(ParamAttrsWithIndex::get(index, ArgI->Attrs));
+ Attrs.push_back(FnAttributeWithIndex::get(index, ArgI->Attrs));
}
} else if (I != E || ArgI != ArgE)
GEN_ERROR("Invalid number of parameters detected");
}
| FREE ResolvedVal {
if (!isa<PointerType>($2->getType()))
- GEN_ERROR("Trying to free nonpointer type " +
+ GEN_ERROR("Trying to free nonpointer type " +
$2->getType()->getDescription() + "");
$$ = new FreeInst($2);
CHECK_FOR_ERROR
delete $5;
}
| GETRESULT Types ValueRef ',' EUINT64VAL {
- Value *TmpVal = getVal($2->get(), $3);
- if (!GetResultInst::isValidOperands(TmpVal, $5))
- GEN_ERROR("Invalid getresult operands");
- $$ = new GetResultInst(TmpVal, $5);
- delete $2;
+ if (!UpRefs.empty())
+ GEN_ERROR("Invalid upreference in type: " + (*$2)->getDescription());
+ if (!isa<StructType>($2->get()) && !isa<ArrayType>($2->get()))
+ GEN_ERROR("getresult insn requires an aggregate operand");
+ if (!ExtractValueInst::getIndexedType(*$2, $5))
+ GEN_ERROR("Invalid getresult index for type '" +
+ (*$2)->getDescription()+ "'");
+
+ Value *tmpVal = getVal(*$2, $3);
CHECK_FOR_ERROR
+ $$ = ExtractValueInst::Create(tmpVal, $5);
+ delete $2;
}
| GETELEMENTPTR Types ValueRef IndexList {
if (!UpRefs.empty())
Value* tmpVal = getVal(*$2, $3);
CHECK_FOR_ERROR
$$ = GetElementPtrInst::Create(tmpVal, $4->begin(), $4->end());
- delete $2;
+ delete $2;
delete $4;
}
| EXTRACTVALUE Types ValueRef ConstantIndexList {
Value* tmpVal = getVal(*$2, $3);
CHECK_FOR_ERROR
$$ = ExtractValueInst::Create(tmpVal, $4->begin(), $4->end());
- delete $2;
+ delete $2;
delete $4;
}
| INSERTVALUE Types ValueRef ',' Types ValueRef ConstantIndexList {
Value* tmpVal = getVal(*$5, $6);
CHECK_FOR_ERROR
$$ = InsertValueInst::Create(aggVal, tmpVal, $7->begin(), $7->end());
- delete $2;
+ delete $2;
delete $5;
delete $7;
};
std::string errMsg = where + "error: " + std::string(ErrorMsg);
if (yychar != YYEMPTY && yychar != 0) {
errMsg += " while reading token: '";
- errMsg += std::string(LLLgetTokenStart(),
+ errMsg += std::string(LLLgetTokenStart(),
LLLgetTokenStart()+LLLgetTokenLength()) + "'";
}
GenerateError(errMsg);