#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Streams.h"
+#include "llvm/ParamAttrsList.h"
#include <algorithm>
#include <list>
#include <map>
} if (ID.Type == ValID::LocalName) {
std::string Name = ID.getName();
Value *N = CurFun.CurrentFunction->getValueSymbolTable().lookup(Name);
- if (N)
+ if (N) {
if (N->getType()->getTypeID() == Type::LabelTyID)
BB = cast<BasicBlock>(N);
else
GenerateError("Reference to label '" + Name + "' is actually of type '"+
N->getType()->getDescription() + "'");
+ }
} else if (ID.Type == ValID::LocalID) {
if (ID.Num < CurFun.NextValNum && ID.Num < CurFun.Values.size()) {
if (CurFun.Values[ID.Num]->getType()->getTypeID() == Type::LabelTyID)
// ValueRef - Unresolved reference to a definition or BB
%type <ValIDVal> ValueRef ConstValueRef SymbolicValueRef
%type <ValueVal> ResolvedVal // <type> <valref> pair
+%type <ValueList> ReturnedVal
// Tokens and types for handling constant integer values
//
// ESINT64VAL - A negative number within long long range
// Other Operators
%token <OtherOpVal> PHI_TOK SELECT VAARG
%token <OtherOpVal> EXTRACTELEMENT INSERTELEMENT SHUFFLEVECTOR
+%token <OtherOpVal> GETRESULT
// Function Attributes
%token SIGNEXT ZEROEXT NORETURN INREG SRET NOUNWIND NOALIAS BYVAL NEST
| NOALIAS { $$ = ParamAttr::NoAlias; }
| BYVAL { $$ = ParamAttr::ByVal; }
| NEST { $$ = ParamAttr::Nest; }
+ | ALIGN EUINT64VAL { $$ =
+ ParamAttr::constructAlignmentFromInt($2); }
;
OptParamAttrs : /* empty */ { $$ = ParamAttr::None; }
: Types {
if (!UpRefs.empty())
GEN_ERROR("Invalid upreference in type: " + (*$1)->getDescription());
- if (!(*$1)->isFirstClassType())
+ if (!(*$1)->isFirstClassType() && !isa<StructType>($1->get()))
GEN_ERROR("LLVM functions cannot return aggregate types");
$$ = $1;
}
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");
+ GEN_ERROR("Global const reference must be a pointer type " + (*$1)->getDescription());
// ConstExprs can exist in the body of a function, thus creating
// GlobalValues whenever they refer to a variable. Because we are in
}
;
+ReturnedVal : ResolvedVal {
+ $$ = new std::vector<Value *>();
+ $$->push_back($1);
+ CHECK_FOR_ERROR
+ }
+ | ReturnedVal ',' ResolvedVal {
+ ($$=$1)->push_back($3);
+ CHECK_FOR_ERROR
+ };
+
BasicBlockList : BasicBlockList BasicBlock {
$$ = $1;
CHECK_FOR_ERROR
};
-BBTerminatorInst : RET ResolvedVal { // Return with a result...
- $$ = new ReturnInst($2);
+BBTerminatorInst :
+ RET ReturnedVal { // Return with a result...
+ ValueList &VL = *$2;
+ assert(!VL.empty() && "Invalid ret operands!");
+ $$ = new ReturnInst(&VL[0], VL.size());
+ delete $2;
CHECK_FOR_ERROR
}
| RET VOID { // Return with no result...
$$ = new StoreInst($3, tmpVal, $1, $7);
delete $5;
}
+| GETRESULT Types SymbolicValueRef ',' EUINT64VAL {
+ Value *TmpVal = getVal($2->get(), $3);
+ if (!GetResultInst::isValidOperands(TmpVal, $5))
+ GEN_ERROR("Invalid getresult operands");
+ $$ = new GetResultInst(TmpVal, $5);
+ delete $2;
+ CHECK_FOR_ERROR
+ }
| GETELEMENTPTR Types ValueRef IndexList {
if (!UpRefs.empty())
GEN_ERROR("Invalid upreference in type: " + (*$2)->getDescription());