%{
#include "ParserInternals.h"
-#include "llvm/SymbolTable.h"
+#include "llvm/Instructions.h"
#include "llvm/Module.h"
-#include "llvm/iTerminators.h"
-#include "llvm/iMemory.h"
-#include "llvm/iOperators.h"
-#include "llvm/iPHINode.h"
+#include "llvm/SymbolTable.h"
#include "llvm/Support/GetElementPtrTypeIterator.h"
-#include "Support/STLExtras.h"
+#include "llvm/ADT/STLExtras.h"
#include <algorithm>
#include <iostream>
#include <list>
// GlobalRefs - This maintains a mapping between <Type, ValID>'s and forward
// references to global values. Global values may be referenced before they
// are defined, and if so, the temporary object that they represent is held
- // here. This is used for forward references of ConstantPointerRefs.
+ // here. This is used for forward references of GlobalValues.
//
typedef std::map<std::pair<const PointerType *,
ValID>, GlobalValue*> GlobalRefsType;
}
return Ret;
}
-
- // DeclareNewGlobalValue - Called every time a new GV has been defined. This
- // is used to remove things from the forward declaration map, resolving them
- // to the correct thing as needed.
- //
- void DeclareNewGlobalValue(GlobalValue *GV, ValID D) {
- // Check to see if there is a forward reference to this global variable...
- // if there is, eliminate it and patch the reference to use the new def'n.
- GlobalRefsType::iterator I =
- GlobalRefs.find(std::make_pair(GV->getType(), D));
-
- if (I != GlobalRefs.end()) {
- GlobalValue *OldGV = I->second; // Get the placeholder...
- I->first.second.destroy(); // Free string memory if necessary
-
- // Replace all uses of the placeholder with the new GV
- OldGV->replaceAllUsesWith(GV);
-
- // Remove OldGV from the module...
- if (GlobalVariable *GVar = dyn_cast<GlobalVariable>(OldGV))
- CurrentModule->getGlobalList().erase(GVar);
- else
- CurrentModule->getFunctionList().erase(cast<Function>(OldGV));
-
- // Remove the map entry for the global now that it has been created...
- GlobalRefs.erase(I);
- }
- }
-
} CurModule;
static struct PerFunctionInfo {
// Resolve all forward references now.
ResolveDefinitions(LateResolveValues, &CurModule.LateResolveValues);
- // Make sure to resolve any constant expr references that might exist within
- // the function we just declared itself.
- ValID FID;
- if (CurrentFunction->hasName()) {
- FID = ValID::create((char*)CurrentFunction->getName().c_str());
- } else {
- // Figure out which slot number if is...
- ValueList &List = CurModule.Values[CurrentFunction->getType()];
- for (unsigned i = 0; ; ++i) {
- assert(i < List.size() && "Function not found!");
- if (List[i] == CurrentFunction) {
- FID = ValID::create((int)i);
- break;
- }
- }
- }
- CurModule.DeclareNewGlobalValue(CurrentFunction, FID);
-
Values.clear(); // Clear out function local definitions
Types.clear(); // Clear out function local types
CurrentFunction = 0;
static const Type *getTypeVal(const ValID &D, bool DoNotImprovise = false) {
switch (D.Type) {
- case ValID::NumberVal: { // Is it a numbered definition?
- unsigned Num = (unsigned)D.Num;
-
+ case ValID::NumberVal: // Is it a numbered definition?
// Module constants occupy the lowest numbered slots...
- if (Num < CurModule.Types.size())
- return CurModule.Types[Num];
-
- Num -= CurModule.Types.size();
-
- // Check that the number is within bounds...
- if (Num <= CurFun.Types.size())
- return CurFun.Types[Num];
+ if ((unsigned)D.Num < CurModule.Types.size())
+ return CurModule.Types[(unsigned)D.Num];
break;
- }
- case ValID::NameVal: { // Is it a named definition?
- std::string Name(D.Name);
- SymbolTable *SymTab = 0;
- Type *N = 0;
- if (inFunctionScope()) {
- SymTab = &CurFun.CurrentFunction->getSymbolTable();
- N = SymTab->lookupType(Name);
+ case ValID::NameVal: // Is it a named definition?
+ if (const Type *N = CurModule.CurrentModule->getTypeByName(D.Name)) {
+ D.destroy(); // Free old strdup'd memory...
+ return N;
}
-
- if (N == 0) {
- // Symbol table doesn't automatically chain yet... because the function
- // hasn't been added to the module...
- //
- SymTab = &CurModule.CurrentModule->getSymbolTable();
- N = SymTab->lookupType(Name);
- if (N == 0) break;
- }
-
- D.destroy(); // Free old strdup'd memory...
- return cast<Type>(N);
- }
+ break;
default:
ThrowException("Internal parser error: Invalid symbol type reference!");
}
case ValID::ConstUIntVal: // Is it an unsigned const pool reference?
if (!ConstantUInt::isValueValidForType(Ty, D.UConstPool64)) {
if (!ConstantSInt::isValueValidForType(Ty, D.ConstPool64)) {
- ThrowException("Integral constant '" + utostr(D.UConstPool64) +
+ ThrowException("Integral constant '" + utostr(D.UConstPool64) +
"' is invalid or out of range!");
} else { // This is really a signed reference. Transmogrify.
- return ConstantSInt::get(Ty, D.ConstPool64);
+ return ConstantSInt::get(Ty, D.ConstPool64);
}
} else {
return ConstantUInt::get(Ty, D.UConstPool64);
ThrowException("Cannot create a a non pointer null!");
return ConstantPointerNull::get(cast<PointerType>(Ty));
+ case ValID::ConstUndefVal: // Is it an undef value?
+ return UndefValue::get(Ty);
+
case ValID::ConstantVal: // Fully resolved constant?
if (D.ConstantValue->getType() != Ty)
ThrowException("Constant expression type different from required type!");
break;
case ValID::NameVal: // Is it a named definition?
Name = ID.Name;
- if (Value *N = lookupInSymbolTable(Type::LabelTy, Name))
+ if (Value *N = CurFun.CurrentFunction->
+ getSymbolTable().lookup(Type::LabelTy, Name))
BB = cast<BasicBlock>(N);
break;
}
CurFun.CurrentFunction->getBasicBlockList().remove(BB);
CurFun.CurrentFunction->getBasicBlockList().push_back(BB);
}
-
+ ID.destroy();
return BB;
}
// resolver table
InsertValue(V, *FutureLateResolvers);
} else {
- if (DID.Type == ValID::NameVal)
- ThrowException("Reference to an invalid definition: '" +DID.getName()+
- "' of type '" + V->getType()->getDescription() + "'",
- PHI->second.second);
- else
- ThrowException("Reference to an invalid definition: #" +
- itostr(DID.Num) + " of type '" +
- V->getType()->getDescription() + "'",
- PHI->second.second);
+ if (DID.Type == ValID::NameVal)
+ ThrowException("Reference to an invalid definition: '" +DID.getName()+
+ "' of type '" + V->getType()->getDescription() + "'",
+ PHI->second.second);
+ else
+ ThrowException("Reference to an invalid definition: #" +
+ itostr(DID.Num) + " of type '" +
+ V->getType()->getDescription() + "'",
+ PHI->second.second);
}
}
}
if (isa<FunctionType>(Ty))
ThrowException("Cannot declare global vars of function type!");
- // If this global has a name, check to see if there is already a definition
- // of this global in the module. If so, merge as appropriate. Note that
- // this is really just a hack around problems in the CFE. :(
+ const PointerType *PTy = PointerType::get(Ty);
+
std::string Name;
if (NameStr) {
Name = NameStr; // Copy string
free(NameStr); // Free old string
+ }
+
+ // See if this global value was forward referenced. If so, recycle the
+ // object.
+ ValID ID;
+ if (!Name.empty()) {
+ ID = ValID::create((char*)Name.c_str());
+ } else {
+ ID = ValID::create((int)CurModule.Values[PTy].size());
+ }
- SymbolTable &ST = CurModule.CurrentModule->getSymbolTable();
- if (Value *Existing = ST.lookup(Ty, Name)) {
- // We are a simple redefinition of a value, check to see if it is defined
- // the same as the old one...
- GlobalVariable *EGV = cast<GlobalVariable>(Existing);
+ if (GlobalValue *FWGV = CurModule.GetForwardRefForGlobal(PTy, ID)) {
+ // Move the global to the end of the list, from whereever it was
+ // previously inserted.
+ GlobalVariable *GV = cast<GlobalVariable>(FWGV);
+ CurModule.CurrentModule->getGlobalList().remove(GV);
+ CurModule.CurrentModule->getGlobalList().push_back(GV);
+ GV->setInitializer(Initializer);
+ GV->setLinkage(Linkage);
+ GV->setConstant(isConstantGlobal);
+ InsertValue(GV, CurModule.Values);
+ return;
+ }
+ // If this global has a name, check to see if there is already a definition
+ // of this global in the module. If so, merge as appropriate. Note that
+ // this is really just a hack around problems in the CFE. :(
+ if (!Name.empty()) {
+ // We are a simple redefinition of a value, check to see if it is defined
+ // the same as the old one.
+ if (GlobalVariable *EGV =
+ CurModule.CurrentModule->getGlobalVariable(Name, Ty)) {
// We are allowed to redefine a global variable in two circumstances:
// 1. If at least one of the globals is uninitialized or
// 2. If both initializers have the same value.
return;
}
- ThrowException("Redefinition of value named '" + Name + "' in the '" +
- Ty->getDescription() + "' type plane!");
+ ThrowException("Redefinition of global variable named '" + Name +
+ "' in the '" + Ty->getDescription() + "' type plane!");
}
}
- const PointerType *PTy = PointerType::get(Ty);
-
- // See if this global value was forward referenced. If so, recycle the
- // object.
- ValID ID;
- if (!Name.empty()) {
- ID = ValID::create((char*)Name.c_str());
- } else {
- ID = ValID::create((int)CurModule.Values[PTy].size());
- }
-
- if (GlobalValue *FWGV = CurModule.GetForwardRefForGlobal(PTy, ID)) {
- // Move the global to the end of the list, from whereever it was
- // previously inserted.
- GlobalVariable *GV = cast<GlobalVariable>(FWGV);
- CurModule.CurrentModule->getGlobalList().remove(GV);
- CurModule.CurrentModule->getGlobalList().push_back(GV);
- GV->setInitializer(Initializer);
- GV->setLinkage(Linkage);
- GV->setConstant(isConstantGlobal);
- } else {
- // Otherwise there is no existing GV to use, create one now.
+ // Otherwise there is no existing GV to use, create one now.
+ GlobalVariable *GV =
new GlobalVariable(Ty, isConstantGlobal, Linkage, Initializer, Name,
CurModule.CurrentModule);
- }
+ InsertValue(GV, CurModule.Values);
}
// setTypeName - Set the specified type to the name given. The name may be
// allowed to be redefined in the specified context. If the name is a new name
// for the type plane, it is inserted and false is returned.
static bool setTypeName(const Type *T, char *NameStr) {
+ assert(!inFunctionScope() && "Can't give types function-local names!");
if (NameStr == 0) return false;
std::string Name(NameStr); // Copy string
if (T == Type::VoidTy)
ThrowException("Can't assign name '" + Name + "' to the void type!");
- SymbolTable &ST = inFunctionScope() ?
- CurFun.CurrentFunction->getSymbolTable() :
- CurModule.CurrentModule->getSymbolTable();
+ // Set the type name, checking for conflicts as we do so.
+ bool AlreadyExists = CurModule.CurrentModule->addTypeName(Name, T);
+
+ if (AlreadyExists) { // Inserting a name that is already defined???
+ const Type *Existing = CurModule.CurrentModule->getTypeByName(Name);
+ assert(Existing && "Conflict but no matching type?");
- // Inserting a name that is already defined???
- if (Type *Existing = ST.lookupType(Name)) {
// There is only one case where this is allowed: when we are refining an
// opaque type. In this case, Existing will be an opaque type.
if (const OpaqueType *OpTy = dyn_cast<OpaqueType>(Existing)) {
// Any other kind of (non-equivalent) redefinition is an error.
ThrowException("Redefinition of type named '" + Name + "' in the '" +
- T->getDescription() + "' type plane!");
+ T->getDescription() + "' type plane!");
}
- // Okay, its a newly named type. Set its name.
- if (!Name.empty()) ST.insert(Name, T);
-
return false;
}
for (unsigned i = 0; i != UpRefs.size(); ++i) {
UR_OUT(" UR#" << i << " - TypeContains(" << Ty->getDescription() << ", "
- << UpRefs[i].second->getDescription() << ") = "
- << (TypeContains(Ty, UpRefs[i].second) ? "true" : "false") << "\n");
+ << UpRefs[i].second->getDescription() << ") = "
+ << (TypeContains(Ty, UpRefs[i].second) ? "true" : "false") << "\n");
if (TypeContains(Ty, UpRefs[i].LastContainedTy)) {
// Decrement level of upreference
unsigned Level = --UpRefs[i].NestingLevel;
UR_OUT(" * Type '" << OldName << "' refined upreference to: "
<< (const void*)Ty << ", " << Ty->getDescription() << "\n");
}
- UpRefs.erase(UpRefs.begin()+i); // Remove from upreference list...
+ UpRefs.erase(UpRefs.begin()+i); // Remove from upreference list...
--i; // Do not skip the next element...
}
}
%token IMPLEMENTATION ZEROINITIALIZER TRUETOK FALSETOK BEGINTOK ENDTOK
%token DECLARE GLOBAL CONSTANT VOLATILE
-%token TO DOTDOTDOT NULL_TOK CONST INTERNAL LINKONCE WEAK APPENDING
-%token OPAQUE NOT EXTERNAL TARGET ENDIAN POINTERSIZE LITTLE BIG
+%token TO DOTDOTDOT NULL_TOK UNDEF CONST INTERNAL LINKONCE WEAK APPENDING
+%token OPAQUE NOT EXTERNAL TARGET TRIPLE ENDIAN POINTERSIZE LITTLE BIG
+%token DEPLIBS
// Basic Block Terminating Operators
-%token <TermOpVal> RET BR SWITCH INVOKE UNWIND
+%token <TermOpVal> RET BR SWITCH INVOKE UNWIND UNREACHABLE
// Binary Operators
-%type <BinaryOpVal> BinaryOps // all the binary operators
%type <BinaryOpVal> ArithmeticOps LogicalOps SetCondOps // Binops Subcatagories
%token <BinaryOpVal> ADD SUB MUL DIV REM AND OR XOR
%token <BinaryOpVal> SETLE SETGE SETLT SETGT SETEQ SETNE // Binary Comarators
ArithmeticOps: ADD | SUB | MUL | DIV | REM;
LogicalOps : AND | OR | XOR;
SetCondOps : SETLE | SETGE | SETLT | SETGT | SETEQ | SETNE;
-BinaryOps : ArithmeticOps | LogicalOps | SetCondOps;
ShiftOps : SHL | SHR;
| UpRTypesV '(' ArgTypeListI ')' { // Function derived type?
std::vector<const Type*> Params;
mapto($3->begin(), $3->end(), std::back_inserter(Params),
- std::mem_fun_ref(&PATypeHolder::get));
+ std::mem_fun_ref(&PATypeHolder::get));
bool isVarArg = Params.size() && Params.back() == Type::VoidTy;
if (isVarArg) Params.pop_back();
$$ = new PATypeHolder(HandleUpRefs(ArrayType::get(*$4, (unsigned)$2)));
delete $4;
}
+ | '<' EUINT64VAL 'x' UpRTypes '>' { // Packed array type?
+ const llvm::Type* ElemTy = $4->get();
+ if ((unsigned)$2 != $2) {
+ ThrowException("Unsigned result not equal to signed result");
+ }
+ if(!ElemTy->isPrimitiveType()) {
+ ThrowException("Elemental type of a PackedType must be primitive");
+ }
+ $$ = new PATypeHolder(HandleUpRefs(PackedType::get(*$4, (unsigned)$2)));
+ delete $4;
+ }
| '{' TypeListI '}' { // Structure type?
std::vector<const Type*> Elements;
mapto($2->begin(), $2->end(), std::back_inserter(Elements),
- std::mem_fun_ref(&PATypeHolder::get));
+ std::mem_fun_ref(&PATypeHolder::get));
$$ = new PATypeHolder(HandleUpRefs(StructType::get(Elements)));
delete $2;
// Verify that we have the correct size...
if (NumElements != -1 && NumElements != (int)$3->size())
ThrowException("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 " +
+ itostr(NumElements) + "!");
// Verify all elements are correct type!
for (unsigned i = 0; i < $3->size(); i++) {
if (ETy != (*$3)[i]->getType())
- ThrowException("Element #" + utostr(i) + " is not of type '" +
- ETy->getDescription() +"' as required!\nIt is of type '"+
- (*$3)[i]->getType()->getDescription() + "'.");
+ ThrowException("Element #" + utostr(i) + " is not of type '" +
+ ETy->getDescription() +"' as required!\nIt is of type '"+
+ (*$3)[i]->getType()->getDescription() + "'.");
}
$$ = ConstantArray::get(ATy, *$3);
int NumElements = ATy->getNumElements();
if (NumElements != -1 && NumElements != 0)
ThrowException("Type mismatch: constant sized array initialized with 0"
- " arguments, but has size of " + itostr(NumElements) +"!");
+ " arguments, but has size of " + itostr(NumElements) +"!");
$$ = ConstantArray::get(ATy, std::vector<Constant*>());
delete $1;
}
char *EndStr = UnEscapeLexed($3, true);
if (NumElements != -1 && NumElements != (EndStr-$3))
ThrowException("Can't build string constant of size " +
- itostr((int)(EndStr-$3)) +
- " when array has size " + itostr(NumElements) + "!");
+ itostr((int)(EndStr-$3)) +
+ " when array has size " + itostr(NumElements) + "!");
std::vector<Constant*> Vals;
if (ETy == Type::SByteTy) {
for (char *C = $3; C != EndStr; ++C)
- Vals.push_back(ConstantSInt::get(ETy, *C));
+ Vals.push_back(ConstantSInt::get(ETy, *C));
} else if (ETy == Type::UByteTy) {
for (char *C = $3; C != EndStr; ++C)
- Vals.push_back(ConstantUInt::get(ETy, (unsigned char)*C));
+ Vals.push_back(ConstantUInt::get(ETy, (unsigned char)*C));
} else {
free($3);
ThrowException("Cannot build string arrays of non byte sized elements!");
$$ = ConstantArray::get(ATy, Vals);
delete $1;
}
+ | Types '<' ConstVector '>' { // Nonempty unsized arr
+ const PackedType *PTy = dyn_cast<PackedType>($1->get());
+ if (PTy == 0)
+ ThrowException("Cannot make packed constant with type: '" +
+ (*$1)->getDescription() + "'!");
+ const Type *ETy = PTy->getElementType();
+ int NumElements = PTy->getNumElements();
+
+ // Verify that we have the correct size...
+ if (NumElements != -1 && NumElements != (int)$3->size())
+ ThrowException("Type mismatch: constant sized packed initialized with " +
+ utostr($3->size()) + " arguments, but has size of " +
+ itostr(NumElements) + "!");
+
+ // Verify all elements are correct type!
+ for (unsigned i = 0; i < $3->size(); i++) {
+ if (ETy != (*$3)[i]->getType())
+ ThrowException("Element #" + utostr(i) + " is not of type '" +
+ ETy->getDescription() +"' as required!\nIt is of type '"+
+ (*$3)[i]->getType()->getDescription() + "'.");
+ }
+
+ $$ = ConstantPacked::get(PTy, *$3);
+ delete $1; delete $3;
+ }
| Types '{' ConstVector '}' {
const StructType *STy = dyn_cast<StructType>($1->get());
if (STy == 0)
$$ = ConstantPointerNull::get(PTy);
delete $1;
}
+ | Types UNDEF {
+ $$ = UndefValue::get($1->get());
+ delete $1;
+ }
| Types SymbolicValueRef {
const PointerType *Ty = dyn_cast<PointerType>($1->get());
if (Ty == 0)
ThrowException("Global const reference must be a pointer type!");
// ConstExprs can exist in the body of a function, thus creating
- // ConstantPointerRefs whenever they refer to a variable. Because we are in
+ // GlobalValues whenever they refer to a variable. Because we are in
// the context of a function, getValNonImprovising will search the functions
// symbol table instead of the module symbol table for the global symbol,
// which throws things all off. To get around this, we just tell
// First check to see if the forward references value is already created!
PerModuleInfo::GlobalRefsType::iterator I =
- CurModule.GlobalRefs.find(std::make_pair(PT, $2));
+ CurModule.GlobalRefs.find(std::make_pair(PT, $2));
if (I != CurModule.GlobalRefs.end()) {
- V = I->second; // Placeholder already exists, use it...
+ V = I->second; // Placeholder already exists, use it...
$2.destroy();
} else {
std::string Name;
+ if ($2.Type == ValID::NameVal) Name = $2.Name;
+
+ // Create the forward referenced global.
+ GlobalValue *GV;
+ if (const FunctionType *FTy =
+ dyn_cast<FunctionType>(PT->getElementType())) {
+ GV = new Function(FTy, GlobalValue::ExternalLinkage, Name,
+ CurModule.CurrentModule);
+ } else {
+ GV = new GlobalVariable(PT->getElementType(), false,
+ GlobalValue::ExternalLinkage, 0,
+ Name, CurModule.CurrentModule);
+ }
- /// FIXME: We shouldn't be creating global vars as forward refs for
- /// functions at all here!
- if (!isa<FunctionType>(PT->getElementType()))
- if ($2.Type == ValID::NameVal) Name = $2.Name;
-
- // Create a placeholder for the global variable reference...
- GlobalVariable *GV = new GlobalVariable(PT->getElementType(), false,
- GlobalValue::ExternalLinkage,0,
- Name, CurModule.CurrentModule);
-
- // Keep track of the fact that we have a forward ref to recycle it
- CurModule.GlobalRefs.insert(std::make_pair(std::make_pair(PT, $2), GV));
- V = GV;
+ // Keep track of the fact that we have a forward ref to recycle it
+ CurModule.GlobalRefs.insert(std::make_pair(std::make_pair(PT, $2), GV));
+ V = GV;
}
}
- GlobalValue *GV = cast<GlobalValue>(V);
- $$ = ConstantPointerRef::get(GV);
+ $$ = cast<GlobalValue>(V);
delete $1; // Free the type handle
}
| Types ConstExpr {
ThrowException("Select operand types must match!");
$$ = ConstantExpr::getSelect($3, $5, $7);
}
- | BinaryOps '(' ConstVal ',' ConstVal ')' {
+ | ArithmeticOps '(' ConstVal ',' ConstVal ')' {
if ($3->getType() != $5->getType())
ThrowException("Binary operator types must match!");
+ // HACK: llvm 1.3 and earlier used to emit invalid pointer constant exprs.
+ // To retain backward compatibility with these early compilers, we emit a
+ // cast to the appropriate integer type automatically if we are in the
+ // broken case. See PR424 for more information.
+ if (!isa<PointerType>($3->getType())) {
+ $$ = ConstantExpr::get($1, $3, $5);
+ } else {
+ const Type *IntPtrTy = 0;
+ switch (CurModule.CurrentModule->getPointerSize()) {
+ case Module::Pointer32: IntPtrTy = Type::IntTy; break;
+ case Module::Pointer64: IntPtrTy = Type::LongTy; break;
+ default: ThrowException("invalid pointer binary constant expr!");
+ }
+ $$ = ConstantExpr::get($1, ConstantExpr::getCast($3, IntPtrTy),
+ ConstantExpr::getCast($5, IntPtrTy));
+ $$ = ConstantExpr::getCast($$, $3->getType());
+ }
+ }
+ | LogicalOps '(' ConstVal ',' ConstVal ')' {
+ if ($3->getType() != $5->getType())
+ ThrowException("Logical operator types must match!");
+ if (!$3->getType()->isIntegral())
+ ThrowException("Logical operands must have integral types!");
+ $$ = ConstantExpr::get($1, $3, $5);
+ }
+ | SetCondOps '(' ConstVal ',' ConstVal ')' {
+ if ($3->getType() != $5->getType())
+ ThrowException("setcc operand types must match!");
$$ = ConstantExpr::get($1, $3, $5);
}
| ShiftOps '(' ConstVal ',' ConstVal ')' {
}
| ConstPool TARGET TargetDefinition {
}
+ | ConstPool DEPLIBS '=' LibrariesDefinition {
+ }
| /* empty: end of list */ {
};
CurModule.CurrentModule->setPointerSize(Module::Pointer64);
else
ThrowException("Invalid pointer size: '" + utostr($3) + "'!");
+ }
+ | TRIPLE '=' STRINGCONSTANT {
+ CurModule.CurrentModule->setTargetTriple($3);
+ free($3);
};
+LibrariesDefinition : '[' LibList ']';
+
+LibList : LibList ',' STRINGCONSTANT {
+ CurModule.CurrentModule->addLibrary($3);
+ free($3);
+ }
+ | STRINGCONSTANT {
+ CurModule.CurrentModule->addLibrary($1);
+ free($1);
+ }
+ | /* empty: end of list */ {
+ }
+ ;
//===----------------------------------------------------------------------===//
// Rules to match Function Headers
FunctionHeaderH : TypesV Name '(' ArgList ')' {
UnEscapeLexed($2);
std::string FunctionName($2);
+ free($2); // Free strdup'd memory!
if (!(*$1)->isFirstClassType() && *$1 != Type::VoidTy)
ThrowException("LLVM functions cannot return aggregate types!");
const PointerType *PFT = PointerType::get(FT);
delete $1;
+ ValID ID;
+ if (!FunctionName.empty()) {
+ ID = ValID::create((char*)FunctionName.c_str());
+ } else {
+ ID = ValID::create((int)CurModule.Values[PFT].size());
+ }
+
Function *Fn = 0;
- // Is the function already in symtab?
- if ((Fn = CurModule.CurrentModule->getFunction(FunctionName, FT))) {
- // Yes it is. If this is the case, either we need to be a forward decl,
- // or it needs to be.
+ // 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
+ // previously inserted.
+ Fn = cast<Function>(FWRef);
+ CurModule.CurrentModule->getFunctionList().remove(Fn);
+ CurModule.CurrentModule->getFunctionList().push_back(Fn);
+ } else if (!FunctionName.empty() && // Merge with an earlier prototype?
+ (Fn = CurModule.CurrentModule->getFunction(FunctionName, FT))) {
+ // If this is the case, either we need to be a forward decl, or it needs
+ // to be.
if (!CurFun.isDeclare && !Fn->isExternal())
ThrowException("Redefinition of function '" + FunctionName + "'!");
- // Make sure to strip off any argument names so we can't get conflicts...
- for (Function::aiterator AI = Fn->abegin(), AE = Fn->aend(); AI != AE; ++AI)
- AI->setName("");
+ // Make sure to strip off any argument names so we can't get conflicts.
+ if (Fn->isExternal())
+ for (Function::aiterator AI = Fn->abegin(), AE = Fn->aend();
+ AI != AE; ++AI)
+ AI->setName("");
} else { // Not already defined?
Fn = new Function(FT, GlobalValue::ExternalLinkage, FunctionName,
CurModule.CurrentModule);
InsertValue(Fn, CurModule.Values);
- CurModule.DeclareNewGlobalValue(Fn, ValID::create($2));
}
- free($2); // Free strdup'd memory!
CurFun.FunctionStart(Fn);
| NULL_TOK {
$$ = ValID::createNull();
}
+ | UNDEF {
+ $$ = ValID::createUndef();
+ }
+ | '<' ConstVector '>' { // Nonempty unsized packed vector
+ const Type *ETy = (*$2)[0]->getType();
+ int NumElements = $2->size();
+
+ PackedType* pt = PackedType::get(ETy, NumElements);
+ PATypeHolder* PTy = new PATypeHolder(
+ HandleUpRefs(
+ PackedType::get(
+ ETy,
+ NumElements)
+ )
+ );
+
+ // Verify all elements are correct type!
+ for (unsigned i = 0; i < $2->size(); i++) {
+ if (ETy != (*$2)[i]->getType())
+ ThrowException("Element #" + utostr(i) + " is not of type '" +
+ ETy->getDescription() +"' as required!\nIt is of type '" +
+ (*$2)[i]->getType()->getDescription() + "'.");
+ }
+
+ $$ = ValID::create(ConstantPacked::get(pt, *$2));
+ delete PTy; delete $2;
+ }
| ConstExpr {
$$ = ValID::create($1);
};
}
| /* empty */ {
$$ = CurBB = getBBVal(ValID::create((int)CurFun.NextBBNum++), true);
+
+ // Make sure to move the basic block to the correct location in the
+ // function, instead of leaving it inserted wherever it was first
+ // referenced.
+ CurFun.CurrentFunction->getBasicBlockList().remove(CurBB);
+ CurFun.CurrentFunction->getBasicBlockList().push_back(CurBB);
}
| LABELSTR {
$$ = CurBB = getBBVal(ValID::create($1), true);
+
+ // Make sure to move the basic block to the correct location in the
+ // function, instead of leaving it inserted wherever it was first
+ // referenced.
+ CurFun.CurrentFunction->getBasicBlockList().remove(CurBB);
+ CurFun.CurrentFunction->getBasicBlockList().push_back(CurBB);
};
BBTerminatorInst : RET ResolvedVal { // Return with a result...
std::vector<Value*>::iterator ArgI = $5->begin(), ArgE = $5->end();
for (; ArgI != ArgE && I != E; ++ArgI, ++I)
- if ((*ArgI)->getType() != *I)
- ThrowException("Parameter " +(*ArgI)->getName()+ " is not of type '" +
- (*I)->getDescription() + "'!");
+ if ((*ArgI)->getType() != *I)
+ ThrowException("Parameter " +(*ArgI)->getName()+ " is not of type '" +
+ (*I)->getDescription() + "'!");
if (I != E || (ArgI != ArgE && !Ty->isVarArg()))
- ThrowException("Invalid number of parameters detected!");
+ ThrowException("Invalid number of parameters detected!");
$$ = new InvokeInst(V, Normal, Except, *$5);
}
}
| UNWIND {
$$ = new UnwindInst();
+ }
+ | UNREACHABLE {
+ $$ = new UnreachableInst();
};
ValueRefListE : ValueRefList | /*empty*/ { $$ = 0; };
InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
- if (!(*$2)->isInteger() && !(*$2)->isFloatingPoint())
- ThrowException("Arithmetic operator requires integer or FP operands!");
+ if (!(*$2)->isInteger() && !(*$2)->isFloatingPoint() &&
+ !isa<PackedType>((*$2).get()))
+ ThrowException(
+ "Arithmetic operator requires integer, FP, or packed operands!");
+ if(isa<PackedType>((*$2).get()) && $1 == Instruction::Rem) {
+ ThrowException(
+ "Rem not supported on packed types!");
+ }
$$ = BinaryOperator::create($1, getVal(*$2, $3), getVal(*$2, $5));
if ($$ == 0)
ThrowException("binary operator returned null!");
delete $2;
}
| SetCondOps Types ValueRef ',' ValueRef {
+ if(isa<PackedType>((*$2).get())) {
+ ThrowException(
+ "PackedTypes currently not supported in setcc instructions!");
+ }
$$ = new SetCondInst($1, getVal(*$2, $3), getVal(*$2, $5));
if ($$ == 0)
ThrowException("binary operator returned null!");
$$->op_reserve($2->size()*2);
while ($2->begin() != $2->end()) {
if ($2->front().first->getType() != Ty)
- ThrowException("All elements of a PHI node must be of the same type!");
+ ThrowException("All elements of a PHI node must be of the same type!");
cast<PHINode>($$)->addIncoming($2->front().first, $2->front().second);
$2->pop_front();
}
std::vector<Value*>::iterator ArgI = $5->begin(), ArgE = $5->end();
for (; ArgI != ArgE && I != E; ++ArgI, ++I)
- if ((*ArgI)->getType() != *I)
- ThrowException("Parameter " +(*ArgI)->getName()+ " is not of type '" +
- (*I)->getDescription() + "'!");
+ if ((*ArgI)->getType() != *I)
+ ThrowException("Parameter " +(*ArgI)->getName()+ " is not of type '" +
+ (*I)->getDescription() + "'!");
if (I != E || (ArgI != ArgE && !Ty->isVarArg()))
- ThrowException("Invalid number of parameters detected!");
+ ThrowException("Invalid number of parameters detected!");
$$ = new CallInst(V, *$5);
}
| OptVolatile LOAD Types ValueRef {
if (!isa<PointerType>($3->get()))
ThrowException("Can't load from nonpointer type: " +
- (*$3)->getDescription());
+ (*$3)->getDescription());
+ if (!cast<PointerType>($3->get())->getElementType()->isFirstClassType())
+ ThrowException("Can't load from pointer of non-first-class type: " +
+ (*$3)->getDescription());
$$ = new LoadInst(getVal(*$3, $4), "", $1);
delete $3;
}