//===-- llvmAsmParser.y - Parser for llvm assembly files --------*- C++ -*-===//
-//
+//
// The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
+//
//===----------------------------------------------------------------------===//
//
// This file implements the bison parser for LLVM assembly languages files.
%{
#include "ParserInternals.h"
-#include "llvm/SymbolTable.h"
+#include "llvm/CallingConv.h"
+#include "llvm/InlineAsm.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/Assembly/AutoUpgrade.h"
#include "llvm/Support/GetElementPtrTypeIterator.h"
-#include "Support/STLExtras.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/MathExtras.h"
+#include <algorithm>
+#include <iostream>
#include <list>
#include <utility>
-#include <algorithm>
int yyerror(const char *ErrorMsg); // Forward declarations to prevent "implicit
int yylex(); // declaration" of xxx warnings.
int yyparse();
namespace llvm {
+ std::string CurFilename;
+}
+using namespace llvm;
static Module *ParserResult;
-std::string CurFilename;
// DEBUG_UPREFS - Define this symbol if you want to enable debugging output
// relating to upreferences in the input stream.
#define YYERROR_VERBOSE 1
-// HACK ALERT: This variable is used to implement the automatic conversion of
-// variable argument instructions from their old to new forms. When this
-// compatiblity "Feature" is removed, this should be too.
-//
-static BasicBlock *CurBB;
static bool ObsoleteVarArgs;
+static bool NewVarArgs;
+static BasicBlock *CurBB;
+static GlobalVariable *CurGV;
// This contains info used when building the body of a function. It is
// destroyed when the function is completed.
//
typedef std::vector<Value *> ValueList; // Numbered defs
-static void ResolveDefinitions(std::map<unsigned,ValueList> &LateResolvers,
- std::map<unsigned,ValueList> *FutureLateResolvers = 0);
+static void
+ResolveDefinitions(std::map<const Type *,ValueList> &LateResolvers,
+ std::map<const Type *,ValueList> *FutureLateResolvers = 0);
static struct PerModuleInfo {
Module *CurrentModule;
- std::map<unsigned,ValueList> Values; // Module level numbered definitions
- std::map<unsigned,ValueList> LateResolveValues;
+ std::map<const Type *, ValueList> Values; // Module level numbered definitions
+ std::map<const Type *,ValueList> LateResolveValues;
std::vector<PATypeHolder> Types;
std::map<ValID, PATypeHolder> LateResolveTypes;
+ /// PlaceHolderInfo - When temporary placeholder objects are created, remember
+ /// how they were referenced and one which line of the input they came from so
+ /// that we can resolve them later and print error messages as appropriate.
+ std::map<Value*, std::pair<ValID, int> > PlaceHolderInfo;
+
// 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;
//
if (!GlobalRefs.empty()) {
std::string UndefinedReferences = "Unresolved global references exist:\n";
-
+
for (GlobalRefsType::iterator I = GlobalRefs.begin(), E =GlobalRefs.end();
I != E; ++I) {
UndefinedReferences += " " + I->first.first->getDescription() + " " +
ThrowException(UndefinedReferences);
}
+ // Look for intrinsic functions and CallInst that need to be upgraded
+ for (Module::iterator FI = CurrentModule->begin(),
+ FE = CurrentModule->end(); FI != FE; )
+ UpgradeCallsToIntrinsic(FI++);
+
Values.clear(); // Clear out function local definitions
Types.clear();
CurrentModule = 0;
}
-
- // 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) {
+ // GetForwardRefForGlobal - Check to see if there is a forward reference
+ // for this global. If so, remove it from the GlobalRefs map and return it.
+ // If not, just return null.
+ GlobalValue *GetForwardRefForGlobal(const PointerType *PTy, ValID ID) {
// 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));
-
+ GlobalRefsType::iterator I = GlobalRefs.find(std::make_pair(PTy, ID));
+ GlobalValue *Ret = 0;
if (I != GlobalRefs.end()) {
- GlobalValue *OldGV = I->second; // Get the placeholder...
- I->first.second.destroy(); // Free string memory if necessary
-
- // Loop over all of the uses of the GlobalValue. The only thing they are
- // allowed to be is ConstantPointerRef's.
- assert(OldGV->hasOneUse() && "Only one reference should exist!");
- User *U = OldGV->use_back(); // Must be a ConstantPointerRef...
- ConstantPointerRef *CPR = cast<ConstantPointerRef>(U);
-
- // Change the const pool reference to point to the real global variable
- // now. This should drop a use from the OldGV.
- CPR->replaceUsesOfWithOnConstant(OldGV, GV);
- assert(OldGV->use_empty() && "All uses should be gone now!");
-
- // 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...
+ Ret = I->second;
GlobalRefs.erase(I);
}
+ return Ret;
}
-
} CurModule;
static struct PerFunctionInfo {
Function *CurrentFunction; // Pointer to current function being created
- std::map<unsigned,ValueList> Values; // Keep track of numbered definitions
- std::map<unsigned,ValueList> LateResolveValues;
- std::vector<PATypeHolder> Types;
- std::map<ValID, PATypeHolder> LateResolveTypes;
- SymbolTable LocalSymtab;
+ std::map<const Type*, ValueList> Values; // Keep track of #'d definitions
+ std::map<const Type*, ValueList> LateResolveValues;
bool isDeclare; // Is this function a forward declararation?
+ /// BBForwardRefs - When we see forward references to basic blocks, keep
+ /// track of them here.
+ std::map<BasicBlock*, std::pair<ValID, int> > BBForwardRefs;
+ std::vector<BasicBlock*> NumberedBlocks;
+ unsigned NextBBNum;
+
inline PerFunctionInfo() {
CurrentFunction = 0;
isDeclare = false;
inline void FunctionStart(Function *M) {
CurrentFunction = M;
+ NextBBNum = 0;
}
void FunctionDone() {
- // If we could not resolve some blocks at parsing time (forward branches)
- // resolve the branches now...
- ResolveDefinitions(LateResolveValues, &CurModule.LateResolveValues);
+ NumberedBlocks.clear();
- // 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 {
- unsigned Slot = CurrentFunction->getType()->getUniqueID();
- // Figure out which slot number if is...
- ValueList &List = CurModule.Values[Slot];
- 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);
+ // Any forward referenced blocks left?
+ if (!BBForwardRefs.empty())
+ ThrowException("Undefined reference to label " +
+ BBForwardRefs.begin()->first->getName());
+
+ // Resolve all forward references now.
+ ResolveDefinitions(LateResolveValues, &CurModule.LateResolveValues);
Values.clear(); // Clear out function local definitions
- Types.clear(); // Clear out function local types
- LocalSymtab.clear(); // Clear out function local symbol table
CurrentFunction = 0;
isDeclare = false;
}
// Code to handle definitions of all the types
//===----------------------------------------------------------------------===//
-static int InsertValue(Value *D,
- std::map<unsigned,ValueList> &ValueTab = CurFun.Values) {
- if (D->hasName()) return -1; // Is this a numbered definition?
+static int InsertValue(Value *V,
+ std::map<const Type*,ValueList> &ValueTab = CurFun.Values) {
+ if (V->hasName()) return -1; // Is this a numbered definition?
// Yes, insert the value into the value table...
- unsigned type = D->getType()->getUniqueID();
- //printf("Values[%d][%d] = %d\n", type, ValueTab[type].size(), D);
- ValueList &List = ValueTab[type];
- List.push_back(D);
+ ValueList &List = ValueTab[V->getType()];
+ List.push_back(V);
return List.size()-1;
}
-// TODO: FIXME when Type are not const
-static void InsertType(const Type *Ty, std::vector<PATypeHolder> &Types) {
- Types.push_back(Ty);
-}
-
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;
- Value *N = 0;
- if (inFunctionScope()) {
- SymTab = &CurFun.CurrentFunction->getSymbolTable();
- N = SymTab->lookupType(Name);
- }
-
- 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;
+ 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;
}
-
- D.destroy(); // Free old strdup'd memory...
- return cast<Type>(N);
- }
+ break;
default:
ThrowException("Internal parser error: Invalid symbol type reference!");
}
//
if (DoNotImprovise) return 0; // Do we just want a null to be returned?
- std::map<ValID, PATypeHolder> &LateResolver = inFunctionScope() ?
- CurFun.LateResolveTypes : CurModule.LateResolveTypes;
-
- std::map<ValID, PATypeHolder>::iterator I = LateResolver.find(D);
- if (I != LateResolver.end()) {
- return I->second;
+
+ if (inFunctionScope()) {
+ if (D.Type == ValID::NameVal)
+ ThrowException("Reference to an undefined type: '" + D.getName() + "'");
+ else
+ ThrowException("Reference to an undefined type: #" + itostr(D.Num));
}
+ std::map<ValID, PATypeHolder>::iterator I =CurModule.LateResolveTypes.find(D);
+ if (I != CurModule.LateResolveTypes.end())
+ return I->second;
+
Type *Typ = OpaqueType::get();
- LateResolver.insert(std::make_pair(D, Typ));
+ CurModule.LateResolveTypes.insert(std::make_pair(D, Typ));
return Typ;
-}
+ }
static Value *lookupInSymbolTable(const Type *Ty, const std::string &Name) {
- SymbolTable &SymTab =
+ SymbolTable &SymTab =
inFunctionScope() ? CurFun.CurrentFunction->getSymbolTable() :
CurModule.CurrentModule->getSymbolTable();
return SymTab.lookup(Ty, Name);
switch (D.Type) {
case ValID::NumberVal: { // Is it a numbered definition?
- unsigned type = Ty->getUniqueID();
unsigned Num = (unsigned)D.Num;
// Module constants occupy the lowest numbered slots...
- std::map<unsigned,ValueList>::iterator VI = CurModule.Values.find(type);
+ std::map<const Type*,ValueList>::iterator VI = CurModule.Values.find(Ty);
if (VI != CurModule.Values.end()) {
- if (Num < VI->second.size())
+ if (Num < VI->second.size())
return VI->second[Num];
Num -= VI->second.size();
}
// Make sure that our type is within bounds
- VI = CurFun.Values.find(type);
+ VI = CurFun.Values.find(Ty);
if (VI == CurFun.Values.end()) return 0;
// Check that the number is within bounds...
if (VI->second.size() <= Num) return 0;
-
+
return VI->second[Num];
}
return N;
}
- // Check to make sure that "Ty" is an integral type, and that our
+ // Check to make sure that "Ty" is an integral type, and that our
// value will fit into the specified type...
case ValID::ConstSIntVal: // Is it a constant pool reference??
if (!ConstantSInt::isValueValidForType(Ty, D.ConstPool64))
ThrowException("Signed integral constant '" +
- itostr(D.ConstPool64) + "' is invalid for type '" +
+ itostr(D.ConstPool64) + "' is invalid for type '" +
Ty->getDescription() + "'!");
return ConstantSInt::get(Ty, D.ConstPool64);
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);
if (!ConstantFP::isValueValidForType(Ty, D.ConstPoolFP))
ThrowException("FP constant invalid for type!!");
return ConstantFP::get(Ty, D.ConstPoolFP);
-
+
case ValID::ConstNullVal: // Is it a null value?
if (!isa<PointerType>(Ty))
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::ConstZeroVal: // Is it a zero value?
+ return Constant::getNullValue(Ty);
case ValID::ConstantVal: // Fully resolved constant?
if (D.ConstantValue->getType() != Ty)
ThrowException("Constant expression type different from required type!");
return D.ConstantValue;
+ case ValID::InlineAsmVal: { // Inline asm expression
+ const PointerType *PTy = dyn_cast<PointerType>(Ty);
+ const FunctionType *FTy =
+ PTy ? dyn_cast<FunctionType>(PTy->getElementType()) : 0;
+ if (!FTy || !InlineAsm::Verify(FTy, D.IAD->Constraints))
+ ThrowException("Invalid type for asm constraint string!");
+ InlineAsm *IA = InlineAsm::get(FTy, D.IAD->AsmString, D.IAD->Constraints,
+ D.IAD->HasSideEffects);
+ D.destroy(); // Free InlineAsmDescriptor.
+ return IA;
+ }
default:
assert(0 && "Unhandled case!");
return 0;
return 0;
}
-
// getVal - This function is identical to getValNonImprovising, except that if a
// value is not already defined, it "improvises" by creating a placeholder var
// that looks and acts just like the requested variable. When the value is
// defined later, all uses of the placeholder variable are replaced with the
// real thing.
//
-static Value *getVal(const Type *Ty, const ValID &D) {
- assert(Ty != Type::TypeTy && "Should use getTypeVal for types!");
+static Value *getVal(const Type *Ty, const ValID &ID) {
+ if (Ty == Type::LabelTy)
+ ThrowException("Cannot use a basic block here");
- // See if the value has already been defined...
- Value *V = getValNonImprovising(Ty, D);
+ // See if the value has already been defined.
+ Value *V = getValNonImprovising(Ty, ID);
if (V) return V;
+ if (!Ty->isFirstClassType() && !isa<OpaqueType>(Ty))
+ ThrowException("Invalid use of a composite type!");
+
// If we reached here, we referenced either a symbol that we don't know about
// or an id number that hasn't been read yet. We may be referencing something
// forward, so just create an entry to be resolved later and get to it...
//
- Value *d = 0;
- switch (Ty->getPrimitiveID()) {
- case Type::LabelTyID: d = new BBPlaceHolder(Ty, D); break;
- default: d = new ValuePlaceHolder(Ty, D); break;
- }
+ 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,
+ llvmAsmlineno)));
- assert(d != 0 && "How did we not make something?");
if (inFunctionScope())
- InsertValue(d, CurFun.LateResolveValues);
- else
- InsertValue(d, CurModule.LateResolveValues);
- return d;
+ InsertValue(V, CurFun.LateResolveValues);
+ else
+ InsertValue(V, CurModule.LateResolveValues);
+ return V;
+}
+
+/// getBBVal - This is used for two purposes:
+/// * If isDefinition is true, a new basic block with the specified ID is being
+/// defined.
+/// * If isDefinition is true, this is a reference to a basic block, which may
+/// or may not be a forward reference.
+///
+static BasicBlock *getBBVal(const ValID &ID, bool isDefinition = false) {
+ assert(inFunctionScope() && "Can't get basic block at global scope!");
+
+ std::string Name;
+ BasicBlock *BB = 0;
+ switch (ID.Type) {
+ default: ThrowException("Illegal label reference " + ID.getName());
+ case ValID::NumberVal: // Is it a numbered definition?
+ if (unsigned(ID.Num) >= CurFun.NumberedBlocks.size())
+ CurFun.NumberedBlocks.resize(ID.Num+1);
+ BB = CurFun.NumberedBlocks[ID.Num];
+ break;
+ case ValID::NameVal: // Is it a named definition?
+ Name = ID.Name;
+ if (Value *N = CurFun.CurrentFunction->
+ getSymbolTable().lookup(Type::LabelTy, Name))
+ BB = cast<BasicBlock>(N);
+ break;
+ }
+
+ // See if the block has already been defined.
+ if (BB) {
+ // If this is the definition of the block, make sure the existing value was
+ // just a forward reference. If it was a forward reference, there will be
+ // an entry for it in the PlaceHolderInfo map.
+ if (isDefinition && !CurFun.BBForwardRefs.erase(BB))
+ // The existing value was a definition, not a forward reference.
+ ThrowException("Redefinition of label " + ID.getName());
+
+ ID.destroy(); // Free strdup'd memory.
+ return BB;
+ }
+
+ // Otherwise this block has not been seen before.
+ BB = new BasicBlock("", CurFun.CurrentFunction);
+ if (ID.Type == ValID::NameVal) {
+ BB->setName(ID.Name);
+ } else {
+ CurFun.NumberedBlocks[ID.Num] = BB;
+ }
+
+ // If this is not a definition, keep track of it so we can use it as a forward
+ // reference.
+ if (!isDefinition) {
+ // Remember where this forward reference came from.
+ CurFun.BBForwardRefs[BB] = std::make_pair(ID, llvmAsmlineno);
+ } else {
+ // The forward declaration could have been inserted anywhere in the
+ // function: insert it into the correct place now.
+ CurFun.CurrentFunction->getBasicBlockList().remove(BB);
+ CurFun.CurrentFunction->getBasicBlockList().push_back(BB);
+ }
+ ID.destroy();
+ return BB;
}
// and back patchs after we are done.
//
-// ResolveDefinitions - If we could not resolve some defs at parsing
-// time (forward branches, phi functions for loops, etc...) resolve the
+// ResolveDefinitions - If we could not resolve some defs at parsing
+// time (forward branches, phi functions for loops, etc...) resolve the
// defs now...
//
-static void ResolveDefinitions(std::map<unsigned,ValueList> &LateResolvers,
- std::map<unsigned,ValueList> *FutureLateResolvers) {
+static void
+ResolveDefinitions(std::map<const Type*,ValueList> &LateResolvers,
+ std::map<const Type*,ValueList> *FutureLateResolvers) {
// Loop over LateResolveDefs fixing up stuff that couldn't be resolved
- for (std::map<unsigned,ValueList>::iterator LRI = LateResolvers.begin(),
+ for (std::map<const Type*,ValueList>::iterator LRI = LateResolvers.begin(),
E = LateResolvers.end(); LRI != E; ++LRI) {
ValueList &List = LRI->second;
while (!List.empty()) {
Value *V = List.back();
List.pop_back();
- assert(!isa<Type>(V) && "Types should be in LateResolveTypes!");
- ValID &DID = getValIDFromPlaceHolder(V);
- Value *TheRealValue =
- getValNonImprovising(Type::getUniqueIDType(LRI->first), DID);
+ std::map<Value*, std::pair<ValID, int> >::iterator PHI =
+ CurModule.PlaceHolderInfo.find(V);
+ assert(PHI != CurModule.PlaceHolderInfo.end() && "Placeholder error!");
+
+ ValID &DID = PHI->second.first;
+
+ Value *TheRealValue = getValNonImprovising(LRI->first, DID);
if (TheRealValue) {
V->replaceAllUsesWith(TheRealValue);
delete V;
+ CurModule.PlaceHolderInfo.erase(PHI);
} else if (FutureLateResolvers) {
// Functions have their unresolved items forwarded to the module late
// resolver table
InsertValue(V, *FutureLateResolvers);
} else {
- if (DID.Type == ValID::NameVal)
- ThrowException("Reference to an invalid definition: '" +DID.getName()+
- "' of type '" + V->getType()->getDescription() + "'",
- getLineNumFromPlaceHolder(V));
- else
- ThrowException("Reference to an invalid definition: #" +
- itostr(DID.Num) + " of type '" +
- V->getType()->getDescription() + "'",
- getLineNumFromPlaceHolder(V));
+ 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);
}
}
}
// refering to the number can be resolved. Do this now.
//
static void ResolveTypeTo(char *Name, const Type *ToTy) {
- std::vector<PATypeHolder> &Types = inFunctionScope() ?
- CurFun.Types : CurModule.Types;
+ ValID D;
+ if (Name) D = ValID::create(Name);
+ else D = ValID::create((int)CurModule.Types.size());
- ValID D;
- if (Name) D = ValID::create(Name);
- else D = ValID::create((int)Types.size());
-
- std::map<ValID, PATypeHolder> &LateResolver = inFunctionScope() ?
- CurFun.LateResolveTypes : CurModule.LateResolveTypes;
-
- std::map<ValID, PATypeHolder>::iterator I = LateResolver.find(D);
- if (I != LateResolver.end()) {
- ((DerivedType*)I->second.get())->refineAbstractTypeTo(ToTy);
- LateResolver.erase(I);
- }
+ std::map<ValID, PATypeHolder>::iterator I =
+ CurModule.LateResolveTypes.find(D);
+ if (I != CurModule.LateResolveTypes.end()) {
+ ((DerivedType*)I->second.get())->refineAbstractTypeTo(ToTy);
+ CurModule.LateResolveTypes.erase(I);
+ }
}
-// ResolveTypes - At this point, all types should be resolved. Any that aren't
-// are errors.
+// setValueName - Set the specified value to the name given. The name may be
+// null potentially, in which case this is a noop. The string passed in is
+// assumed to be a malloc'd string buffer, and is free'd by this function.
//
-static void ResolveTypes(std::map<ValID, PATypeHolder> &LateResolveTypes) {
- if (!LateResolveTypes.empty()) {
- const ValID &DID = LateResolveTypes.begin()->first;
+static void setValueName(Value *V, char *NameStr) {
+ if (NameStr) {
+ std::string Name(NameStr); // Copy string
+ free(NameStr); // Free old string
- if (DID.Type == ValID::NameVal)
- ThrowException("Reference to an invalid type: '" +DID.getName() + "'");
- else
- ThrowException("Reference to an invalid type: #" + itostr(DID.Num));
+ if (V->getType() == Type::VoidTy)
+ ThrowException("Can't assign name '" + Name+"' to value with void type!");
+
+ assert(inFunctionScope() && "Must be in function scope!");
+ SymbolTable &ST = CurFun.CurrentFunction->getSymbolTable();
+ if (ST.lookup(V->getType(), Name))
+ ThrowException("Redefinition of value named '" + Name + "' in the '" +
+ V->getType()->getDescription() + "' type plane!");
+
+ // Set the name.
+ V->setName(Name);
}
}
+/// ParseGlobalVariable - Handle parsing of a global. If Initializer is null,
+/// this is a declaration, otherwise it is a definition.
+static GlobalVariable *
+ParseGlobalVariable(char *NameStr,GlobalValue::LinkageTypes Linkage,
+ bool isConstantGlobal, const Type *Ty,
+ Constant *Initializer) {
+ if (isa<FunctionType>(Ty))
+ ThrowException("Cannot declare global vars of function type!");
+
+ 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());
+ }
+
+ 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 GV;
+ }
+
+ // 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.
+ //
+ if (!EGV->hasInitializer() || !Initializer ||
+ EGV->getInitializer() == Initializer) {
+
+ // Make sure the existing global version gets the initializer! Make
+ // sure that it also gets marked const if the new version is.
+ if (Initializer && !EGV->hasInitializer())
+ EGV->setInitializer(Initializer);
+ if (isConstantGlobal)
+ EGV->setConstant(true);
+ EGV->setLinkage(Linkage);
+ return EGV;
+ }
-// setValueName - Set the specified value to the name given. The name may be
+ ThrowException("Redefinition of global variable named '" + Name +
+ "' in the '" + Ty->getDescription() + "' type plane!");
+ }
+ }
+
+ // 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);
+ return GV;
+}
+
+// setTypeName - Set the specified type to the name given. The name may be
// null potentially, in which case this is a noop. The string passed in is
// assumed to be a malloc'd string buffer, and is freed by this function.
//
-// This function returns true if the value has already been defined, but is
+// This function returns true if the type has already been defined, but is
// allowed to be redefined in the specified context. If the name is a new name
-// for the typeplane, false is returned.
-//
-static bool setValueName(Value *V, char *NameStr) {
+// 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
free(NameStr); // Free old string
- if (V->getType() == Type::VoidTy)
- ThrowException("Can't assign name '" + Name +
- "' to a null valued instruction!");
+ // We don't allow assigning names to void type
+ 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?");
- Value *Existing = ST.lookup(V->getType(), Name);
- if (Existing) { // Inserting a name that is already defined???
// 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 Type *Ty = dyn_cast<Type>(Existing)) {
- if (const OpaqueType *OpTy = dyn_cast<OpaqueType>(Ty)) {
- // We ARE replacing an opaque type!
- ((OpaqueType*)OpTy)->refineAbstractTypeTo(cast<Type>(V));
- return true;
- }
+ if (const OpaqueType *OpTy = dyn_cast<OpaqueType>(Existing)) {
+ // We ARE replacing an opaque type!
+ const_cast<OpaqueType*>(OpTy)->refineAbstractTypeTo(T);
+ return true;
}
- // Otherwise, we are a simple redefinition of a value, check to see if it
- // is defined the same as the old one...
- if (const Type *Ty = dyn_cast<Type>(Existing)) {
- if (Ty == cast<Type>(V)) return true; // Yes, it's equal.
- // std::cerr << "Type: " << Ty->getDescription() << " != "
- // << cast<Type>(V)->getDescription() << "!\n";
- } else if (const Constant *C = dyn_cast<Constant>(Existing)) {
- if (C == V) return true; // Constants are equal to themselves
- } else if (GlobalVariable *EGV = dyn_cast<GlobalVariable>(Existing)) {
- // 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.
- //
- if (GlobalVariable *GV = dyn_cast<GlobalVariable>(V)) {
- if (!EGV->hasInitializer() || !GV->hasInitializer() ||
- EGV->getInitializer() == GV->getInitializer()) {
-
- // Make sure the existing global version gets the initializer! Make
- // sure that it also gets marked const if the new version is.
- if (GV->hasInitializer() && !EGV->hasInitializer())
- EGV->setInitializer(GV->getInitializer());
- if (GV->isConstant())
- EGV->setConstant(true);
- EGV->setLinkage(GV->getLinkage());
-
- delete GV; // Destroy the duplicate!
- return true; // They are equivalent!
- }
- }
- }
+ // Otherwise, this is an attempt to redefine a type. That's okay if
+ // the redefinition is identical to the original. This will be so if
+ // Existing and T point to the same Type object. In this one case we
+ // allow the equivalent redefinition.
+ if (Existing == T) return true; // Yes, it's equal.
- ThrowException("Redefinition of value named '" + Name + "' in the '" +
- V->getType()->getDescription() + "' type plane!");
+ // Any other kind of (non-equivalent) redefinition is an error.
+ ThrowException("Redefinition of type named '" + Name + "' in the '" +
+ T->getDescription() + "' type plane!");
}
- // Set the name
- V->setName(Name, &ST);
-
- // If we're in function scope
- if (inFunctionScope()) {
- // Look up the symbol in the function's local symboltable
- Existing = CurFun.LocalSymtab.lookup(V->getType(),Name);
-
- // If it already exists
- if (Existing) {
- // Bail
- ThrowException("Redefinition of value named '" + Name + "' in the '" +
- V->getType()->getDescription() + "' type plane!");
-
- // otherwise, since it doesn't exist
- } else {
- // Insert it.
- CurFun.LocalSymtab.insert(V);
- }
- }
return false;
}
-
//===----------------------------------------------------------------------===//
// Code for handling upreferences in type names...
//
// TypeContains - Returns true if Ty directly contains E in it.
//
static bool TypeContains(const Type *Ty, const Type *E) {
- return find(Ty->subtype_begin(), Ty->subtype_end(), E) != Ty->subtype_end();
+ return std::find(Ty->subtype_begin(), Ty->subtype_end(),
+ E) != Ty->subtype_end();
}
namespace {
// NestingLevel - The number of nesting levels that need to be popped before
// this type is resolved.
unsigned NestingLevel;
-
+
// LastContainedTy - This is the type at the current binding level for the
// type. Every time we reduce the nesting level, this gets updated.
const Type *LastContainedTy;
static PATypeHolder HandleUpRefs(const Type *ty) {
if (!ty->isAbstract()) return ty;
PATypeHolder Ty(ty);
- UR_OUT("Type '" << Ty->getDescription() <<
+ UR_OUT("Type '" << Ty->getDescription() <<
"' newly formed. Resolving upreferences.\n" <<
UpRefs.size() << " upreferences active!\n");
OpaqueType *TypeToResolve = 0;
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");
+ UR_OUT(" UR#" << i << " - TypeContains(" << Ty->getDescription() << ", "
+ << 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;
UpRefs[i].LastContainedTy = Ty;
UR_OUT(" Uplevel Ref Level = " << Level << "\n");
- if (Level == 0) { // Upreference should be resolved!
+ if (Level == 0) { // Upreference should be resolved!
if (!TypeToResolve) {
TypeToResolve = UpRefs[i].UpRefTy;
} else {
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...
}
}
}
-//===----------------------------------------------------------------------===//
-// RunVMAsmParser - Define an interface to this parser
-//===----------------------------------------------------------------------===//
-//
-Module *RunVMAsmParser(const std::string &Filename, FILE *F) {
- llvmAsmin = F;
- CurFilename = Filename;
+// common code from the two 'RunVMAsmParser' functions
+ static Module * RunParser(Module * M) {
+
llvmAsmlineno = 1; // Reset the current line number...
ObsoleteVarArgs = false;
+ NewVarArgs = false;
- // Allocate a new module to read
- CurModule.CurrentModule = new Module(Filename);
-
- try {
- yyparse(); // Parse the file.
- } catch (...) {
- // Clear the symbol table so it doesn't complain when it
- // gets destructed
- CurFun.LocalSymtab.clear();
- throw;
- }
+ CurModule.CurrentModule = M;
+ yyparse(); // Parse the file, potentially throwing exception
Module *Result = ParserResult;
+ ParserResult = 0;
- // Check to see if they called va_start but not va_arg..
- if (!ObsoleteVarArgs)
- if (Function *F = Result->getNamedFunction("llvm.va_start"))
- if (F->asize() == 1) {
- std::cerr << "WARNING: this file uses obsolete features. "
- << "Assemble and disassemble to update it.\n";
- ObsoleteVarArgs = true;
- }
-
+ //Not all functions use vaarg, so make a second check for ObsoleteVarArgs
+ {
+ Function* F;
+ if ((F = Result->getNamedFunction("llvm.va_start"))
+ && F->getFunctionType()->getNumParams() == 0)
+ ObsoleteVarArgs = true;
+ if((F = Result->getNamedFunction("llvm.va_copy"))
+ && F->getFunctionType()->getNumParams() == 1)
+ ObsoleteVarArgs = true;
+ }
- if (ObsoleteVarArgs) {
- // If the user is making use of obsolete varargs intrinsics, adjust them for
- // the user.
- if (Function *F = Result->getNamedFunction("llvm.va_start")) {
- assert(F->asize() == 1 && "Obsolete va_start takes 1 argument!");
+ if (ObsoleteVarArgs && NewVarArgs)
+ ThrowException("This file is corrupt: it uses both new and old style varargs");
- const Type *RetTy = F->getFunctionType()->getParamType(0);
- RetTy = cast<PointerType>(RetTy)->getElementType();
- Function *NF = Result->getOrInsertFunction("llvm.va_start", RetTy, 0);
+ if(ObsoleteVarArgs) {
+ if(Function* F = Result->getNamedFunction("llvm.va_start")) {
+ if (F->arg_size() != 0)
+ ThrowException("Obsolete va_start takes 0 argument!");
+ //foo = va_start()
+ // ->
+ //bar = alloca typeof(foo)
+ //va_start(bar)
+ //foo = load bar
+
+ const Type* RetTy = Type::getPrimitiveType(Type::VoidTyID);
+ const Type* ArgTy = F->getFunctionType()->getReturnType();
+ const Type* ArgTyPtr = PointerType::get(ArgTy);
+ Function* NF = Result->getOrInsertFunction("llvm.va_start",
+ RetTy, ArgTyPtr, (Type *)0);
+
while (!F->use_empty()) {
- CallInst *CI = cast<CallInst>(F->use_back());
- Value *V = new CallInst(NF, "", CI);
- new StoreInst(V, CI->getOperand(1), CI);
+ CallInst* CI = cast<CallInst>(F->use_back());
+ AllocaInst* bar = new AllocaInst(ArgTy, 0, "vastart.fix.1", CI);
+ new CallInst(NF, bar, "", CI);
+ Value* foo = new LoadInst(bar, "vastart.fix.2", CI);
+ CI->replaceAllUsesWith(foo);
CI->getParent()->getInstList().erase(CI);
}
Result->getFunctionList().erase(F);
}
- if (Function *F = Result->getNamedFunction("llvm.va_end")) {
- assert(F->asize() == 1 && "Obsolete va_end takes 1 argument!");
- const Type *ArgTy = F->getFunctionType()->getParamType(0);
- ArgTy = cast<PointerType>(ArgTy)->getElementType();
- Function *NF = Result->getOrInsertFunction("llvm.va_end", Type::VoidTy,
- ArgTy, 0);
+ if(Function* F = Result->getNamedFunction("llvm.va_end")) {
+ if(F->arg_size() != 1)
+ ThrowException("Obsolete va_end takes 1 argument!");
+
+ //vaend foo
+ // ->
+ //bar = alloca 1 of typeof(foo)
+ //vaend bar
+ const Type* RetTy = Type::getPrimitiveType(Type::VoidTyID);
+ const Type* ArgTy = F->getFunctionType()->getParamType(0);
+ const Type* ArgTyPtr = PointerType::get(ArgTy);
+ Function* NF = Result->getOrInsertFunction("llvm.va_end",
+ RetTy, ArgTyPtr, (Type *)0);
while (!F->use_empty()) {
- CallInst *CI = cast<CallInst>(F->use_back());
- Value *V = new LoadInst(CI->getOperand(1), "", CI);
- new CallInst(NF, V, "", CI);
+ CallInst* CI = cast<CallInst>(F->use_back());
+ AllocaInst* bar = new AllocaInst(ArgTy, 0, "vaend.fix.1", CI);
+ new StoreInst(CI->getOperand(1), bar, CI);
+ new CallInst(NF, bar, "", CI);
CI->getParent()->getInstList().erase(CI);
}
Result->getFunctionList().erase(F);
}
- if (Function *F = Result->getNamedFunction("llvm.va_copy")) {
- assert(F->asize() == 2 && "Obsolete va_copy takes 2 argument!");
- const Type *ArgTy = F->getFunctionType()->getParamType(0);
- ArgTy = cast<PointerType>(ArgTy)->getElementType();
- Function *NF = Result->getOrInsertFunction("llvm.va_copy", ArgTy,
- ArgTy, 0);
+ if(Function* F = Result->getNamedFunction("llvm.va_copy")) {
+ if(F->arg_size() != 1)
+ ThrowException("Obsolete va_copy takes 1 argument!");
+ //foo = vacopy(bar)
+ // ->
+ //a = alloca 1 of typeof(foo)
+ //b = alloca 1 of typeof(foo)
+ //store bar -> b
+ //vacopy(a, b)
+ //foo = load a
+
+ const Type* RetTy = Type::getPrimitiveType(Type::VoidTyID);
+ const Type* ArgTy = F->getFunctionType()->getReturnType();
+ const Type* ArgTyPtr = PointerType::get(ArgTy);
+ Function* NF = Result->getOrInsertFunction("llvm.va_copy",
+ RetTy, ArgTyPtr, ArgTyPtr,
+ (Type *)0);
while (!F->use_empty()) {
- CallInst *CI = cast<CallInst>(F->use_back());
- Value *V = new CallInst(NF, CI->getOperand(2), "", CI);
- new StoreInst(V, CI->getOperand(1), CI);
+ CallInst* CI = cast<CallInst>(F->use_back());
+ AllocaInst* a = new AllocaInst(ArgTy, 0, "vacopy.fix.1", CI);
+ AllocaInst* b = new AllocaInst(ArgTy, 0, "vacopy.fix.2", CI);
+ new StoreInst(CI->getOperand(1), b, CI);
+ new CallInst(NF, a, b, "", CI);
+ Value* foo = new LoadInst(a, "vacopy.fix.3", CI);
+ CI->replaceAllUsesWith(foo);
CI->getParent()->getInstList().erase(CI);
}
Result->getFunctionList().erase(F);
}
}
- llvmAsmin = stdin; // F is about to go away, don't use it anymore...
- ParserResult = 0;
-
return Result;
+
+ }
+
+//===----------------------------------------------------------------------===//
+// RunVMAsmParser - Define an interface to this parser
+//===----------------------------------------------------------------------===//
+//
+Module *llvm::RunVMAsmParser(const std::string &Filename, FILE *F) {
+ set_scan_file(F);
+
+ CurFilename = Filename;
+ return RunParser(new Module(CurFilename));
}
-} // End llvm namespace
+Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) {
+ set_scan_string(AsmString);
-using namespace llvm;
+ CurFilename = "from_memory";
+ if (M == NULL) {
+ return RunParser(new Module (CurFilename));
+ } else {
+ return RunParser(M);
+ }
+}
%}
std::vector<std::pair<llvm::PATypeHolder*,char*> > *ArgList;
std::vector<llvm::Value*> *ValueList;
std::list<llvm::PATypeHolder> *TypeList;
+ // Represent the RHS of PHI node
std::list<std::pair<llvm::Value*,
- llvm::BasicBlock*> > *PHIList; // Represent the RHS of PHI node
+ llvm::BasicBlock*> > *PHIList;
std::vector<std::pair<llvm::Constant*, llvm::BasicBlock*> > *JumpTable;
std::vector<llvm::Constant*> *ConstVector;
%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> OptLinkage
%type <Endianness> BigOrLittle
%token <StrVal> VAR_ID LABELSTR STRINGCONSTANT
%type <StrVal> Name OptName OptAssign
-
+%type <UIntVal> OptAlign OptCAlign
+%type <StrVal> OptSection SectionString
%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 DECLARE GLOBAL CONSTANT SECTION VOLATILE
+%token TO DOTDOTDOT NULL_TOK UNDEF CONST INTERNAL LINKONCE WEAK APPENDING
+%token OPAQUE NOT EXTERNAL TARGET TRIPLE ENDIAN POINTERSIZE LITTLE BIG ALIGN
+%token DEPLIBS CALL TAIL ASM_TOK MODULE SIDEEFFECT
+%token CC_TOK CCC_TOK FASTCC_TOK COLDCC_TOK
+%type <UIntVal> OptCallingConv
-// Basic Block Terminating Operators
-%token <TermOpVal> RET BR SWITCH INVOKE UNWIND
+// Basic Block Terminating Operators
+%token <TermOpVal> RET BR SWITCH INVOKE UNWIND UNREACHABLE
-// Binary Operators
-%type <BinaryOpVal> BinaryOps // all the binary operators
+// 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
// Other Operators
%type <OtherOpVal> ShiftOps
-%token <OtherOpVal> PHI_TOK CALL CAST SELECT SHL SHR VAARG VANEXT
-%token VA_ARG // FIXME: OBSOLETE
+%token <OtherOpVal> PHI_TOK CAST SELECT SHL SHR VAARG
+%token <OtherOpVal> EXTRACTELEMENT INSERTELEMENT
+%token VAARG_old VANEXT_old //OBSOLETE
+
%start Module
%%
$$ = (int64_t)$1;
};
-// Operations that are notably excluded from this list include:
+// Operations that are notably excluded from this list include:
// RET, BR, & SWITCH because they end basic blocks and are treated specially.
//
ArithmeticOps: ADD | SUB | MUL | DIV | REM;
LogicalOps : AND | OR | XOR;
SetCondOps : SETLE | SETGE | SETLT | SETGT | SETEQ | SETNE;
-BinaryOps : ArithmeticOps | LogicalOps | SetCondOps;
ShiftOps : SHL | SHR;
OptAssign : Name '=' {
$$ = $1;
}
- | /*empty*/ {
- $$ = 0;
+ | /*empty*/ {
+ $$ = 0;
};
OptLinkage : INTERNAL { $$ = GlobalValue::InternalLinkage; } |
APPENDING { $$ = GlobalValue::AppendingLinkage; } |
/*empty*/ { $$ = GlobalValue::ExternalLinkage; };
+OptCallingConv : /*empty*/ { $$ = CallingConv::C; } |
+ CCC_TOK { $$ = CallingConv::C; } |
+ FASTCC_TOK { $$ = CallingConv::Fast; } |
+ COLDCC_TOK { $$ = CallingConv::Cold; } |
+ CC_TOK EUINT64VAL {
+ if ((unsigned)$2 != $2)
+ ThrowException("Calling conv too large!");
+ $$ = $2;
+ };
+
+// OptAlign/OptCAlign - An optional alignment, and an optional alignment with
+// a comma before it.
+OptAlign : /*empty*/ { $$ = 0; } |
+ ALIGN EUINT64VAL {
+ $$ = $2;
+ if ($$ != 0 && !isPowerOf2_32($$))
+ ThrowException("Alignment must be a power of two!");
+};
+OptCAlign : /*empty*/ { $$ = 0; } |
+ ',' ALIGN EUINT64VAL {
+ $$ = $3;
+ if ($$ != 0 && !isPowerOf2_32($$))
+ ThrowException("Alignment must be a power of two!");
+};
+
+
+SectionString : SECTION STRINGCONSTANT {
+ for (unsigned i = 0, e = strlen($2); i != e; ++i)
+ if ($2[i] == '"' || $2[i] == '\\')
+ ThrowException("Invalid character in section name!");
+ $$ = $2;
+};
+
+OptSection : /*empty*/ { $$ = 0; } |
+ SectionString { $$ = $1; };
+
+// GlobalVarAttributes - Used to pass the attributes string on a global. CurGV
+// is set to be the global we are processing.
+//
+GlobalVarAttributes : /* empty */ {} |
+ ',' GlobalVarAttribute GlobalVarAttributes {};
+GlobalVarAttribute : SectionString {
+ CurGV->setSection($1);
+ free($1);
+ }
+ | ALIGN EUINT64VAL {
+ if ($2 != 0 && !isPowerOf2_32($2))
+ ThrowException("Alignment must be a power of two!");
+ CurGV->setAlignment($2);
+ };
+
//===----------------------------------------------------------------------===//
// Types includes all predefined types... except void, because it can only be
// used in specific contexts (function returning void for example). To have
}
| 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));
+ for (std::list<llvm::PATypeHolder>::iterator I = $3->begin(),
+ E = $3->end(); I != E; ++I)
+ Params.push_back(*I);
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");
+ if (!isPowerOf2_32($2))
+ ThrowException("Vector length should be a power of 2!");
+ $$ = 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));
+ for (std::list<llvm::PATypeHolder>::iterator I = $2->begin(),
+ E = $2->end(); I != E; ++I)
+ Elements.push_back(*I);
$$ = 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));
+ for (signed char *C = (signed char *)$3; C != (signed char *)EndStr; ++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));
+ for (unsigned char *C = (unsigned char *)$3;
+ C != (unsigned char*)EndStr; ++C)
+ Vals.push_back(ConstantUInt::get(ETy, *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 {
- // Create a placeholder for the global variable reference...
- GlobalVariable *GV = new GlobalVariable(PT->getElementType(),
- false,
- GlobalValue::ExternalLinkage);
- // 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));
-
- // Must temporarily push this value into the module table...
- CurModule.CurrentModule->getGlobalList().push_back(GV);
- V = GV;
+ 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);
+ }
+
+ // 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 {
delete $1;
}
| Types ZEROINITIALIZER {
- $$ = Constant::getNullValue($1->get());
+ const Type *Ty = $1->get();
+ if (isa<FunctionType>(Ty) || Ty == Type::LabelTy || isa<OpaqueType>(Ty))
+ ThrowException("Cannot create a null initialized value of this type!");
+ $$ = Constant::getNullValue(Ty);
delete $1;
};
$$ = ConstantBool::False;
}
| FPType FPVAL { // Float & Double constants
+ if (!ConstantFP::isValueValidForType($1, $2))
+ ThrowException("Floating point constant invalid for type!!");
$$ = ConstantFP::get($1, $2);
};
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()) {
+ if (!isa<PackedType>($3->getType()) ||
+ !cast<PackedType>($3->getType())->getElementType()->isIntegral())
+ ThrowException("Logical operator requires integral operands!");
+ }
+ $$ = 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 ')' {
if (!$3->getType()->isInteger())
ThrowException("Shift constant expression requires integer operand!");
$$ = ConstantExpr::get($1, $3, $5);
+ }
+ | EXTRACTELEMENT '(' ConstVal ',' ConstVal ')' {
+ if (!isa<PackedType>($3->getType()))
+ ThrowException("First operand of extractelement must be "
+ "packed type!");
+ if ($5->getType() != Type::UIntTy)
+ ThrowException("Second operand of extractelement must be uint!");
+ $$ = ConstantExpr::getExtractElement($3, $5);
};
-
// ConstVector - A list of comma separated constants.
ConstVector : ConstVector ',' ConstVal {
($$ = $1)->push_back($3);
| FunctionList FunctionProto {
$$ = $1;
}
+ | FunctionList MODULE ASM_TOK AsmBlock {
+ $$ = $1;
+ }
| FunctionList IMPLEMENTATION {
$$ = $1;
}
| ConstPool {
$$ = CurModule.CurrentModule;
- // Resolve circular types before we parse the body of the module
- ResolveTypes(CurModule.LateResolveTypes);
+ // Emit an error if there are any unresolved types left.
+ if (!CurModule.LateResolveTypes.empty()) {
+ const ValID &DID = CurModule.LateResolveTypes.begin()->first;
+ if (DID.Type == ValID::NameVal)
+ ThrowException("Reference to an undefined type: '"+DID.getName() + "'");
+ else
+ ThrowException("Reference to an undefined type: #" + itostr(DID.Num));
+ }
};
// ConstPool - Constants with optional names assigned to them.
-ConstPool : ConstPool OptAssign CONST ConstVal {
- if (!setValueName($4, $2))
- InsertValue($4);
- }
- | ConstPool OptAssign TYPE TypesV { // Types can be defined in the const pool
+ConstPool : ConstPool OptAssign TYPE TypesV {
// Eagerly resolve types. This is not an optimization, this is a
// requirement that is due to the fact that we could have this:
//
// If types are not resolved eagerly, then the two types will not be
// determined to be the same type!
//
- ResolveTypeTo($2, $4->get());
-
- // TODO: FIXME when Type are not const
- if (!setValueName(const_cast<Type*>($4->get()), $2)) {
- // If this is not a redefinition of a type...
- if (!$2) {
- InsertType($4->get(),
- inFunctionScope() ? CurFun.Types : CurModule.Types);
- }
+ ResolveTypeTo($2, *$4);
+
+ if (!setTypeName(*$4, $2) && !$2) {
+ // If this is a named type that is not a redefinition, add it to the slot
+ // table.
+ CurModule.Types.push_back(*$4);
}
delete $4;
}
| ConstPool FunctionProto { // Function prototypes can be in const pool
}
+ | ConstPool MODULE ASM_TOK AsmBlock { // Asm blocks can be in the const pool
+ }
| ConstPool OptAssign OptLinkage GlobalType ConstVal {
- const Type *Ty = $5->getType();
- // Global declarations appear in Constant Pool
- Constant *Initializer = $5;
- if (Initializer == 0)
- ThrowException("Global value initializer is not a constant!");
-
- GlobalVariable *GV = new GlobalVariable(Ty, $4, $3, Initializer);
- if (!setValueName(GV, $2)) { // If not redefining...
- CurModule.CurrentModule->getGlobalList().push_back(GV);
- int Slot = InsertValue(GV, CurModule.Values);
-
- if (Slot != -1) {
- CurModule.DeclareNewGlobalValue(GV, ValID::create(Slot));
- } else {
- CurModule.DeclareNewGlobalValue(GV, ValID::create(
- (char*)GV->getName().c_str()));
- }
- }
+ if ($5 == 0) ThrowException("Global value initializer is not a constant!");
+ CurGV = ParseGlobalVariable($2, $3, $4, $5->getType(), $5);
+ } GlobalVarAttributes {
+ CurGV = 0;
}
| ConstPool OptAssign EXTERNAL GlobalType Types {
- const Type *Ty = *$5;
- // Global declarations appear in Constant Pool
- GlobalVariable *GV = new GlobalVariable(Ty,$4,GlobalValue::ExternalLinkage);
- if (!setValueName(GV, $2)) { // If not redefining...
- CurModule.CurrentModule->getGlobalList().push_back(GV);
- int Slot = InsertValue(GV, CurModule.Values);
-
- if (Slot != -1) {
- CurModule.DeclareNewGlobalValue(GV, ValID::create(Slot));
- } else {
- assert(GV->hasName() && "Not named and not numbered!?");
- CurModule.DeclareNewGlobalValue(GV, ValID::create(
- (char*)GV->getName().c_str()));
- }
- }
+ CurGV = ParseGlobalVariable($2, GlobalValue::ExternalLinkage,
+ $4, *$5, 0);
delete $5;
+ } GlobalVarAttributes {
+ CurGV = 0;
}
| ConstPool TARGET TargetDefinition {
}
+ | ConstPool DEPLIBS '=' LibrariesDefinition {
+ }
| /* empty: end of list */ {
};
+AsmBlock : STRINGCONSTANT {
+ const std::string &AsmSoFar = CurModule.CurrentModule->getModuleInlineAsm();
+ char *EndStr = UnEscapeLexed($1, true);
+ std::string NewAsm($1, EndStr);
+ free($1);
+
+ if (AsmSoFar.empty())
+ CurModule.CurrentModule->setModuleInlineAsm(NewAsm);
+ else
+ CurModule.CurrentModule->setModuleInlineAsm(AsmSoFar+"\n"+NewAsm);
+};
BigOrLittle : BIG { $$ = Module::BigEndian; };
BigOrLittle : LITTLE { $$ = Module::LittleEndian; };
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
$$ = 0;
};
-FunctionHeaderH : TypesV Name '(' ArgList ')' {
- UnEscapeLexed($2);
- std::string FunctionName($2);
+FunctionHeaderH : OptCallingConv TypesV Name '(' ArgList ')'
+ OptSection OptAlign {
+ UnEscapeLexed($3);
+ std::string FunctionName($3);
+ free($3); // Free strdup'd memory!
- if (!(*$1)->isFirstClassType() && *$1 != Type::VoidTy)
+ if (!(*$2)->isFirstClassType() && *$2 != Type::VoidTy)
ThrowException("LLVM functions cannot return aggregate types!");
std::vector<const Type*> ParamTypeList;
- if ($4) { // If there are arguments...
- for (std::vector<std::pair<PATypeHolder*,char*> >::iterator I = $4->begin();
- I != $4->end(); ++I)
+ 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());
}
bool isVarArg = ParamTypeList.size() && ParamTypeList.back() == Type::VoidTy;
if (isVarArg) ParamTypeList.pop_back();
- const FunctionType *FT = FunctionType::get(*$1, ParamTypeList, isVarArg);
+ const FunctionType *FT = FunctionType::get(*$2, ParamTypeList, isVarArg);
const PointerType *PFT = PointerType::get(FT);
- delete $1;
+ delete $2;
+
+ 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::arg_iterator AI = Fn->arg_begin(), AE = Fn->arg_end();
+ 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);
+ Fn->setCallingConv($1);
+ Fn->setAlignment($8);
+ if ($7) {
+ Fn->setSection($7);
+ free($7);
+ }
// Add all of the arguments we parsed to the function...
- if ($4) { // Is null if empty...
+ if ($5) { // Is null if empty...
if (isVarArg) { // Nuke the last entry
- assert($4->back().first->get() == Type::VoidTy && $4->back().second == 0&&
+ assert($5->back().first->get() == Type::VoidTy && $5->back().second == 0&&
"Not a varargs marker!");
- delete $4->back().first;
- $4->pop_back(); // Delete the last entry
+ delete $5->back().first;
+ $5->pop_back(); // Delete the last entry
}
- Function::aiterator ArgIt = Fn->abegin();
- for (std::vector<std::pair<PATypeHolder*, char*> >::iterator I =$4->begin();
- I != $4->end(); ++I, ++ArgIt) {
+ 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...
- if (setValueName(ArgIt, I->second)) // Insert arg into symtab...
- assert(0 && "No arg redef allowed!");
-
+ setValueName(ArgIt, I->second); // Insert arg into symtab...
InsertValue(ArgIt);
}
- delete $4; // We're now done with the argument list
+ delete $5; // We're now done with the argument list
}
};
// Make sure that we keep track of the linkage type even if there was a
// previous "declare".
$$->setLinkage($1);
-
- // Resolve circular types before we parse the body of the function.
- ResolveTypes(CurFun.LateResolveTypes);
};
END : ENDTOK | '}'; // Allow end of '}' to end a function
// Rules to match Basic Blocks
//===----------------------------------------------------------------------===//
+OptSideEffect : /* empty */ {
+ $$ = false;
+ }
+ | SIDEEFFECT {
+ $$ = true;
+ };
+
ConstValueRef : ESINT64VAL { // A reference to a direct constant
$$ = ValID::create($1);
}
| NULL_TOK {
$$ = ValID::createNull();
}
+ | UNDEF {
+ $$ = ValID::createUndef();
+ }
+ | ZEROINITIALIZER { // A vector zero constant.
+ $$ = ValID::createZeroInit();
+ }
+ | '<' 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);
+ }
+ | ASM_TOK OptSideEffect STRINGCONSTANT ',' STRINGCONSTANT {
+ char *End = UnEscapeLexed($3, true);
+ std::string AsmStr = std::string($3, End);
+ End = UnEscapeLexed($5, true);
+ std::string Constraints = std::string($5, End);
+ $$ = ValID::createInlineAsm(AsmStr, Constraints, $2);
+ free($3);
+ free($5);
};
// SymbolicValueRef - Reference to one of two ways of symbolically refering to
};
BasicBlockList : BasicBlockList BasicBlock {
- ($$ = $1)->getBasicBlockList().push_back($2);
+ $$ = $1;
}
| FunctionHeader BasicBlock { // Do not allow functions with 0 basic blocks
- ($$ = $1)->getBasicBlockList().push_back($2);
+ $$ = $1;
};
// br, br/cc, switch, ret
//
BasicBlock : InstructionList OptAssign BBTerminatorInst {
- if (setValueName($3, $2)) { assert(0 && "No redefn allowed!"); }
+ setValueName($3, $2);
InsertValue($3);
$1->getInstList().push_back($3);
InsertValue($1);
$$ = $1;
- }
- | LABELSTR InstructionList OptAssign BBTerminatorInst {
- if (setValueName($4, $3)) { assert(0 && "No redefn allowed!"); }
- InsertValue($4);
-
- $2->getInstList().push_back($4);
- if (setValueName($2, $1)) { assert(0 && "No label redef allowed!"); }
-
- InsertValue($2);
- $$ = $2;
};
InstructionList : InstructionList Inst {
$$ = $1;
}
| /* empty */ {
- $$ = CurBB = new BasicBlock();
+ $$ = 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.
+ Function::BasicBlockListType &BBL =
+ CurFun.CurrentFunction->getBasicBlockList();
+ BBL.splice(BBL.end(), BBL, $$);
+ }
+ | 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.
+ Function::BasicBlockListType &BBL =
+ CurFun.CurrentFunction->getBasicBlockList();
+ BBL.splice(BBL.end(), BBL, $$);
};
BBTerminatorInst : RET ResolvedVal { // Return with a result...
$$ = new ReturnInst();
}
| BR LABEL ValueRef { // Unconditional Branch...
- $$ = new BranchInst(cast<BasicBlock>(getVal(Type::LabelTy, $3)));
+ $$ = new BranchInst(getBBVal($3));
} // Conditional Branch...
| BR BOOL ValueRef ',' LABEL ValueRef ',' LABEL ValueRef {
- $$ = new BranchInst(cast<BasicBlock>(getVal(Type::LabelTy, $6)),
- cast<BasicBlock>(getVal(Type::LabelTy, $9)),
- getVal(Type::BoolTy, $3));
+ $$ = new BranchInst(getBBVal($6), getBBVal($9), getVal(Type::BoolTy, $3));
}
| SWITCH IntType ValueRef ',' LABEL ValueRef '[' JumpTable ']' {
- SwitchInst *S = new SwitchInst(getVal($2, $3),
- cast<BasicBlock>(getVal(Type::LabelTy, $6)));
+ SwitchInst *S = new SwitchInst(getVal($2, $3), getBBVal($6), $8->size());
$$ = S;
std::vector<std::pair<Constant*,BasicBlock*> >::iterator I = $8->begin(),
E = $8->end();
- for (; I != E; ++I)
- S->addCase(I->first, I->second);
+ for (; I != E; ++I) {
+ if (ConstantInt *CI = dyn_cast<ConstantInt>(I->first))
+ S->addCase(CI, I->second);
+ else
+ ThrowException("Switch case is constant, but not a simple integer!");
+ }
delete $8;
}
| SWITCH IntType ValueRef ',' LABEL ValueRef '[' ']' {
- SwitchInst *S = new SwitchInst(getVal($2, $3),
- cast<BasicBlock>(getVal(Type::LabelTy, $6)));
+ SwitchInst *S = new SwitchInst(getVal($2, $3), getBBVal($6), 0);
$$ = S;
}
- | INVOKE TypesV ValueRef '(' ValueRefListE ')' TO ResolvedVal
- UNWIND ResolvedVal {
+ | INVOKE OptCallingConv TypesV ValueRef '(' ValueRefListE ')'
+ TO LABEL ValueRef UNWIND LABEL ValueRef {
const PointerType *PFTy;
const FunctionType *Ty;
- if (!(PFTy = dyn_cast<PointerType>($2->get())) ||
+ if (!(PFTy = dyn_cast<PointerType>($3->get())) ||
!(Ty = dyn_cast<FunctionType>(PFTy->getElementType()))) {
// Pull out the types of all of the arguments...
std::vector<const Type*> ParamTypes;
- if ($5) {
- for (std::vector<Value*>::iterator I = $5->begin(), E = $5->end();
+ if ($6) {
+ for (std::vector<Value*>::iterator I = $6->begin(), E = $6->end();
I != E; ++I)
ParamTypes.push_back((*I)->getType());
}
bool isVarArg = ParamTypes.size() && ParamTypes.back() == Type::VoidTy;
if (isVarArg) ParamTypes.pop_back();
- Ty = FunctionType::get($2->get(), ParamTypes, isVarArg);
+ Ty = FunctionType::get($3->get(), ParamTypes, isVarArg);
PFTy = PointerType::get(Ty);
}
- Value *V = getVal(PFTy, $3); // Get the function we're calling...
-
- BasicBlock *Normal = dyn_cast<BasicBlock>($8);
- BasicBlock *Except = dyn_cast<BasicBlock>($10);
+ Value *V = getVal(PFTy, $4); // Get the function we're calling...
- if (Normal == 0 || Except == 0)
- ThrowException("Invoke instruction without label destinations!");
+ BasicBlock *Normal = getBBVal($10);
+ BasicBlock *Except = getBBVal($13);
// Create the call node...
- if (!$5) { // Has no arguments?
+ if (!$6) { // Has no arguments?
$$ = new InvokeInst(V, Normal, Except, std::vector<Value*>());
} else { // Has arguments?
// Loop through FunctionType's arguments and ensure they are specified
//
FunctionType::param_iterator I = Ty->param_begin();
FunctionType::param_iterator E = Ty->param_end();
- std::vector<Value*>::iterator ArgI = $5->begin(), ArgE = $5->end();
+ std::vector<Value*>::iterator ArgI = $6->begin(), ArgE = $6->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);
+ $$ = new InvokeInst(V, Normal, Except, *$6);
}
- delete $2;
- delete $5;
+ cast<InvokeInst>($$)->setCallingConv($2);
+
+ delete $3;
+ delete $6;
}
| UNWIND {
$$ = new UnwindInst();
+ }
+ | UNREACHABLE {
+ $$ = new UnreachableInst();
};
if (V == 0)
ThrowException("May only switch on a constant pool value!");
- $$->push_back(std::make_pair(V, cast<BasicBlock>(getVal($5, $6))));
+ $$->push_back(std::make_pair(V, getBBVal($6)));
}
| IntType ConstValueRef ',' LABEL ValueRef {
$$ = new std::vector<std::pair<Constant*, BasicBlock*> >();
if (V == 0)
ThrowException("May only switch on a constant pool value!");
- $$->push_back(std::make_pair(V, cast<BasicBlock>(getVal($4, $5))));
+ $$->push_back(std::make_pair(V, getBBVal($5)));
};
Inst : OptAssign InstVal {
// Is this definition named?? if so, assign the name...
- if (setValueName($2, $1)) { assert(0 && "No redefin allowed!"); }
+ setValueName($2, $1);
InsertValue($2);
$$ = $2;
};
PHIList : Types '[' ValueRef ',' ValueRef ']' { // Used for PHI nodes
$$ = new std::list<std::pair<Value*, BasicBlock*> >();
- $$->push_back(std::make_pair(getVal(*$1, $3),
- cast<BasicBlock>(getVal(Type::LabelTy, $5))));
+ $$->push_back(std::make_pair(getVal(*$1, $3), getBBVal($5)));
delete $1;
}
| PHIList ',' '[' ValueRef ',' ValueRef ']' {
$$ = $1;
$1->push_back(std::make_pair(getVal($1->front().first->getType(), $4),
- cast<BasicBlock>(getVal(Type::LabelTy, $6))));
+ getBBVal($6)));
};
// ValueRefListE - Just like ValueRefList, except that it may also be empty!
ValueRefListE : ValueRefList | /*empty*/ { $$ = 0; };
+OptTailCall : TAIL CALL {
+ $$ = true;
+ }
+ | CALL {
+ $$ = false;
+ };
+
+
+
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;
}
| LogicalOps Types ValueRef ',' ValueRef {
- if (!(*$2)->isIntegral())
- ThrowException("Logical operator requires integral operands!");
+ if (!(*$2)->isIntegral()) {
+ if (!isa<PackedType>($2->get()) ||
+ !cast<PackedType>($2->get())->getElementType()->isIntegral())
+ ThrowException("Logical operator requires integral operands!");
+ }
$$ = 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!");
ThrowException("select value types should match!");
$$ = new SelectInst($2, $4, $6);
}
- | VA_ARG ResolvedVal ',' Types {
- // FIXME: This is emulation code for an obsolete syntax. This should be
- // removed at some point.
- if (!ObsoleteVarArgs) {
- std::cerr << "WARNING: this file uses obsolete features. "
- << "Assemble and disassemble to update it.\n";
- ObsoleteVarArgs = true;
- }
-
- // First, load the valist...
- Instruction *CurVAList = new LoadInst($2, "");
- CurBB->getInstList().push_back(CurVAList);
-
- // Emit the vaarg instruction.
- $$ = new VAArgInst(CurVAList, *$4);
-
- // Now we must advance the pointer and update it in memory.
- Instruction *TheVANext = new VANextInst(CurVAList, *$4);
- CurBB->getInstList().push_back(TheVANext);
-
- CurBB->getInstList().push_back(new StoreInst(TheVANext, $2));
- delete $4;
- }
| VAARG ResolvedVal ',' Types {
+ NewVarArgs = true;
$$ = new VAArgInst($2, *$4);
delete $4;
}
- | VANEXT ResolvedVal ',' Types {
- $$ = new VANextInst($2, *$4);
+ | VAARG_old ResolvedVal ',' Types {
+ ObsoleteVarArgs = true;
+ const Type* ArgTy = $2->getType();
+ Function* NF = CurModule.CurrentModule->
+ getOrInsertFunction("llvm.va_copy", ArgTy, ArgTy, (Type *)0);
+
+ //b = vaarg a, t ->
+ //foo = alloca 1 of t
+ //bar = vacopy a
+ //store bar -> foo
+ //b = vaarg foo, t
+ AllocaInst* foo = new AllocaInst(ArgTy, 0, "vaarg.fix");
+ CurBB->getInstList().push_back(foo);
+ CallInst* bar = new CallInst(NF, $2);
+ CurBB->getInstList().push_back(bar);
+ CurBB->getInstList().push_back(new StoreInst(bar, foo));
+ $$ = new VAArgInst(foo, *$4);
+ delete $4;
+ }
+ | VANEXT_old ResolvedVal ',' Types {
+ ObsoleteVarArgs = true;
+ const Type* ArgTy = $2->getType();
+ Function* NF = CurModule.CurrentModule->
+ getOrInsertFunction("llvm.va_copy", ArgTy, ArgTy, (Type *)0);
+
+ //b = vanext a, t ->
+ //foo = alloca 1 of t
+ //bar = vacopy a
+ //store bar -> foo
+ //tmp = vaarg foo, t
+ //b = load foo
+ AllocaInst* foo = new AllocaInst(ArgTy, 0, "vanext.fix");
+ CurBB->getInstList().push_back(foo);
+ CallInst* bar = new CallInst(NF, $2);
+ CurBB->getInstList().push_back(bar);
+ CurBB->getInstList().push_back(new StoreInst(bar, foo));
+ Instruction* tmp = new VAArgInst(foo, *$4);
+ CurBB->getInstList().push_back(tmp);
+ $$ = new LoadInst(foo);
delete $4;
}
+ | EXTRACTELEMENT ResolvedVal ',' ResolvedVal {
+ if (!isa<PackedType>($2->getType()))
+ ThrowException("First operand of extractelement must be "
+ "packed type!");
+ if ($4->getType() != Type::UIntTy)
+ ThrowException("Second operand of extractelement must be uint!");
+ $$ = new ExtractElementInst($2, $4);
+ }
+ | INSERTELEMENT ResolvedVal ',' ResolvedVal ',' ResolvedVal {
+ if (!isa<PackedType>($2->getType()))
+ ThrowException("First operand of insertelement must be "
+ "packed type!");
+ if ($4->getType() !=
+ cast<PackedType>($2->getType())->getElementType())
+ ThrowException("Second operand of insertelement must be "
+ "packed element type!");
+ if ($6->getType() != Type::UIntTy)
+ ThrowException("Third operand of insertelement must be uint!");
+ $$ = new InsertElementInst($2, $4, $6);
+ }
| PHI_TOK PHIList {
const Type *Ty = $2->front().first->getType();
if (!Ty->isFirstClassType())
ThrowException("PHI node operands must be of first class type!");
$$ = new PHINode(Ty);
- $$->op_reserve($2->size()*2);
+ ((PHINode*)$$)->reserveOperandSpace($2->size());
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();
}
delete $2; // Free the list...
- }
- | CALL TypesV ValueRef '(' ValueRefListE ')' {
+ }
+ | OptTailCall OptCallingConv TypesV ValueRef '(' ValueRefListE ')' {
const PointerType *PFTy;
const FunctionType *Ty;
- if (!(PFTy = dyn_cast<PointerType>($2->get())) ||
+ if (!(PFTy = dyn_cast<PointerType>($3->get())) ||
!(Ty = dyn_cast<FunctionType>(PFTy->getElementType()))) {
// Pull out the types of all of the arguments...
std::vector<const Type*> ParamTypes;
- if ($5) {
- for (std::vector<Value*>::iterator I = $5->begin(), E = $5->end();
+ if ($6) {
+ for (std::vector<Value*>::iterator I = $6->begin(), E = $6->end();
I != E; ++I)
ParamTypes.push_back((*I)->getType());
}
bool isVarArg = ParamTypes.size() && ParamTypes.back() == Type::VoidTy;
if (isVarArg) ParamTypes.pop_back();
- Ty = FunctionType::get($2->get(), ParamTypes, isVarArg);
+ if (!(*$3)->isFirstClassType() && *$3 != Type::VoidTy)
+ ThrowException("LLVM functions cannot return aggregate types!");
+
+ Ty = FunctionType::get($3->get(), ParamTypes, isVarArg);
PFTy = PointerType::get(Ty);
}
- Value *V = getVal(PFTy, $3); // Get the function we're calling...
+ Value *V = getVal(PFTy, $4); // Get the function we're calling...
// Create the call node...
- if (!$5) { // Has no arguments?
+ if (!$6) { // Has no arguments?
// Make sure no arguments is a good thing!
if (Ty->getNumParams() != 0)
ThrowException("No arguments passed to a function that "
//
FunctionType::param_iterator I = Ty->param_begin();
FunctionType::param_iterator E = Ty->param_end();
- std::vector<Value*>::iterator ArgI = $5->begin(), ArgE = $5->end();
+ std::vector<Value*>::iterator ArgI = $6->begin(), ArgE = $6->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);
+ $$ = new CallInst(V, *$6);
}
- delete $2;
- delete $5;
+ cast<CallInst>($$)->setTailCall($1);
+ cast<CallInst>($$)->setCallingConv($2);
+ delete $3;
+ delete $6;
}
| MemoryInst {
$$ = $1;
};
-MemoryInst : MALLOC Types {
- $$ = new MallocInst(*$2);
+
+MemoryInst : MALLOC Types OptCAlign {
+ $$ = new MallocInst(*$2, 0, $3);
delete $2;
}
- | MALLOC Types ',' UINT ValueRef {
- $$ = new MallocInst(*$2, getVal($4, $5));
+ | MALLOC Types ',' UINT ValueRef OptCAlign {
+ $$ = new MallocInst(*$2, getVal($4, $5), $6);
delete $2;
}
- | ALLOCA Types {
- $$ = new AllocaInst(*$2);
+ | ALLOCA Types OptCAlign {
+ $$ = new AllocaInst(*$2, 0, $3);
delete $2;
}
- | ALLOCA Types ',' UINT ValueRef {
- $$ = new AllocaInst(*$2, getVal($4, $5));
+ | ALLOCA Types ',' UINT ValueRef OptCAlign {
+ $$ = new AllocaInst(*$2, getVal($4, $5), $6);
delete $2;
}
| FREE ResolvedVal {
| 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;
}