full asmparser support for blockaddress. We can now do:

$ llvm-as foo.ll -d -disable-output

which reads and prints the .ll file.  BC encoding is the
next project.  Testcase will go in once that works.



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@85368 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2009-10-28 03:39:23 +00:00
parent 73050e1c38
commit 09d9ef4122
4 changed files with 172 additions and 40 deletions

View File

@ -576,6 +576,7 @@ lltok::Kind LLLexer::LexIdentifier() {
KEYWORD(oge); KEYWORD(ord); KEYWORD(uno); KEYWORD(ueq); KEYWORD(une);
KEYWORD(x);
KEYWORD(blockaddress);
#undef KEYWORD
// Keywords for types.

View File

@ -29,34 +29,6 @@
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
namespace llvm {
/// ValID - Represents a reference of a definition of some sort with no type.
/// There are several cases where we have to parse the value but where the
/// type can depend on later context. This may either be a numeric reference
/// or a symbolic (%var) reference. This is just a discriminated union.
struct ValID {
enum {
t_LocalID, t_GlobalID, // ID in UIntVal.
t_LocalName, t_GlobalName, // Name in StrVal.
t_APSInt, t_APFloat, // Value in APSIntVal/APFloatVal.
t_Null, t_Undef, t_Zero, // No value.
t_EmptyArray, // No value: []
t_Constant, // Value in ConstantVal.
t_InlineAsm, // Value in StrVal/StrVal2/UIntVal.
t_Metadata // Value in MetadataVal.
} Kind;
LLParser::LocTy Loc;
unsigned UIntVal;
std::string StrVal, StrVal2;
APSInt APSIntVal;
APFloat APFloatVal;
Constant *ConstantVal;
MetadataBase *MetadataVal;
ValID() : APFloatVal(0.0) {}
};
}
/// Run: module ::= toplevelentity*
bool LLParser::Run() {
// Prime the lexer.
@ -77,7 +49,7 @@ bool LLParser::ValidateEndOfModule() {
// declaration of "malloc". In that case, iterate over all calls to MallocF
// and get them to call the declared "malloc" instead.
if (MallocF->getName() != "malloc") {
Constant* RealMallocF = M->getFunction("malloc");
Constant *RealMallocF = M->getFunction("malloc");
if (RealMallocF->getType() != MallocF->getType())
RealMallocF = ConstantExpr::getBitCast(RealMallocF, MallocF->getType());
MallocF->replaceAllUsesWith(RealMallocF);
@ -85,7 +57,32 @@ bool LLParser::ValidateEndOfModule() {
MallocF = NULL;
}
}
// If there are entries in ForwardRefBlockAddresses at this point, they are
// references after the function was defined. Resolve those now.
while (!ForwardRefBlockAddresses.empty()) {
// Okay, we are referencing an already-parsed function, resolve them now.
Function *TheFn = 0;
const ValID &Fn = ForwardRefBlockAddresses.begin()->first;
if (Fn.Kind == ValID::t_GlobalName)
TheFn = M->getFunction(Fn.StrVal);
else if (Fn.UIntVal < NumberedVals.size())
TheFn = dyn_cast<Function>(NumberedVals[Fn.UIntVal]);
if (TheFn == 0)
return Error(Fn.Loc, "unknown function referenced by blockaddress");
// Resolve all these references.
if (ResolveForwardRefBlockAddresses(TheFn,
ForwardRefBlockAddresses.begin()->second,
0))
return true;
ForwardRefBlockAddresses.erase(ForwardRefBlockAddresses.begin());
}
if (!ForwardRefTypes.empty())
return Error(ForwardRefTypes.begin()->second.second,
"use of undefined type named '" +
@ -120,6 +117,38 @@ bool LLParser::ValidateEndOfModule() {
return false;
}
bool LLParser::ResolveForwardRefBlockAddresses(Function *TheFn,
std::vector<std::pair<ValID, GlobalValue*> > &Refs,
PerFunctionState *PFS) {
// Loop over all the references, resolving them.
for (unsigned i = 0, e = Refs.size(); i != e; ++i) {
BasicBlock *Res;
if (PFS) {
if (Refs[i].first.Kind == ValID::t_LocalName)
Res = PFS->GetBB(Refs[i].first.StrVal, Refs[i].first.Loc);
else
Res = PFS->GetBB(Refs[i].first.UIntVal, Refs[i].first.Loc);
} else if (Refs[i].first.Kind == ValID::t_LocalID) {
return Error(Refs[i].first.Loc,
"cannot take address of numeric label after it the function is defined");
} else {
Res = dyn_cast_or_null<BasicBlock>(
TheFn->getValueSymbolTable().lookup(Refs[i].first.StrVal));
}
if (Res == 0)
return Error(Refs[i].first.Loc,
"referenced value is not a basic block");
// Get the BlockAddress for this and update references to use it.
BlockAddress *BA = BlockAddress::get(TheFn, Res);
Refs[i].second->replaceAllUsesWith(BA);
Refs[i].second->eraseFromParent();
}
return false;
}
//===----------------------------------------------------------------------===//
// Top-Level Entities
//===----------------------------------------------------------------------===//
@ -1575,8 +1604,9 @@ bool LLParser::ParseArrayVectorType(PATypeHolder &Result, bool isVector) {
// Function Semantic Analysis.
//===----------------------------------------------------------------------===//
LLParser::PerFunctionState::PerFunctionState(LLParser &p, Function &f)
: P(p), F(f) {
LLParser::PerFunctionState::PerFunctionState(LLParser &p, Function &f,
int functionNumber)
: P(p), F(f), FunctionNumber(functionNumber) {
// Insert unnamed arguments into the NumberedVals list.
for (Function::arg_iterator AI = F.arg_begin(), E = F.arg_end();
@ -1606,7 +1636,29 @@ LLParser::PerFunctionState::~PerFunctionState() {
}
}
bool LLParser::PerFunctionState::VerifyFunctionComplete() {
bool LLParser::PerFunctionState::FinishFunction() {
// Check to see if someone took the address of labels in this block.
if (!P.ForwardRefBlockAddresses.empty()) {
ValID FunctionID;
if (!F.getName().empty()) {
FunctionID.Kind = ValID::t_GlobalName;
FunctionID.StrVal = F.getName();
} else {
FunctionID.Kind = ValID::t_GlobalID;
FunctionID.UIntVal = FunctionNumber;
}
std::map<ValID, std::vector<std::pair<ValID, GlobalValue*> > >::iterator
FRBAI = P.ForwardRefBlockAddresses.find(FunctionID);
if (FRBAI != P.ForwardRefBlockAddresses.end()) {
// Resolve all these references.
if (P.ResolveForwardRefBlockAddresses(&F, FRBAI->second, this))
return true;
P.ForwardRefBlockAddresses.erase(FRBAI);
}
}
if (!ForwardRefVals.empty())
return P.Error(ForwardRefVals.begin()->second.second,
"use of undefined value '%" + ForwardRefVals.begin()->first +
@ -1990,6 +2042,35 @@ bool LLParser::ParseValID(ValID &ID) {
return false;
}
case lltok::kw_blockaddress: {
// ValID ::= 'blockaddress' '(' @foo ',' %bar ')'
Lex.Lex();
ValID Fn, Label;
LocTy FnLoc, LabelLoc;
if (ParseToken(lltok::lparen, "expected '(' in block address expression") ||
ParseValID(Fn) ||
ParseToken(lltok::comma, "expected comma in block address expression")||
ParseValID(Label) ||
ParseToken(lltok::rparen, "expected ')' in block address expression"))
return true;
if (Fn.Kind != ValID::t_GlobalID && Fn.Kind != ValID::t_GlobalName)
return Error(Fn.Loc, "expected function name in blockaddress");
if (Label.Kind != ValID::t_LocalID && Label.Kind != ValID::t_LocalName)
return Error(Label.Loc, "expected basic block name in blockaddress");
// Make a global variable as a placeholder for this reference.
GlobalVariable *FwdRef = new GlobalVariable(*M, Type::getInt8Ty(Context),
false, GlobalValue::InternalLinkage,
0, "");
ForwardRefBlockAddresses[Fn].push_back(std::make_pair(Label, FwdRef));
ID.ConstantVal = FwdRef;
ID.Kind = ValID::t_Constant;
return false;
}
case lltok::kw_trunc:
case lltok::kw_zext:
case lltok::kw_sext:
@ -2637,7 +2718,10 @@ bool LLParser::ParseFunctionBody(Function &Fn) {
return TokError("expected '{' in function body");
Lex.Lex(); // eat the {.
PerFunctionState PFS(*this, Fn);
int FunctionNumber = -1;
if (!Fn.hasName()) FunctionNumber = NumberedVals.size()-1;
PerFunctionState PFS(*this, Fn, FunctionNumber);
while (Lex.getKind() != lltok::rbrace && Lex.getKind() != lltok::kw_end)
if (ParseBasicBlock(PFS)) return true;
@ -2646,7 +2730,7 @@ bool LLParser::ParseFunctionBody(Function &Fn) {
Lex.Lex();
// Verify function is ok.
return PFS.VerifyFunctionComplete();
return PFS.FinishFunction();
}
/// ParseBasicBlock

View File

@ -31,8 +31,41 @@ namespace llvm {
class MetadataBase;
class MDString;
class MDNode;
struct ValID;
/// ValID - Represents a reference of a definition of some sort with no type.
/// There are several cases where we have to parse the value but where the
/// type can depend on later context. This may either be a numeric reference
/// or a symbolic (%var) reference. This is just a discriminated union.
struct ValID {
enum {
t_LocalID, t_GlobalID, // ID in UIntVal.
t_LocalName, t_GlobalName, // Name in StrVal.
t_APSInt, t_APFloat, // Value in APSIntVal/APFloatVal.
t_Null, t_Undef, t_Zero, // No value.
t_EmptyArray, // No value: []
t_Constant, // Value in ConstantVal.
t_InlineAsm, // Value in StrVal/StrVal2/UIntVal.
t_Metadata // Value in MetadataVal.
} Kind;
LLLexer::LocTy Loc;
unsigned UIntVal;
std::string StrVal, StrVal2;
APSInt APSIntVal;
APFloat APFloatVal;
Constant *ConstantVal;
MetadataBase *MetadataVal;
ValID() : APFloatVal(0.0) {}
bool operator<(const ValID &RHS) const {
if (Kind == t_LocalID || Kind == t_GlobalID)
return UIntVal < RHS.UIntVal;
assert((Kind == t_LocalName || Kind == t_GlobalName) &&
"Ordering not defined for this ValID kind yet");
return StrVal < RHS.StrVal;
}
};
class LLParser {
public:
typedef LLLexer::LocTy LocTy;
@ -75,7 +108,13 @@ namespace llvm {
std::map<std::string, std::pair<GlobalValue*, LocTy> > ForwardRefVals;
std::map<unsigned, std::pair<GlobalValue*, LocTy> > ForwardRefValIDs;
std::vector<GlobalValue*> NumberedVals;
Function* MallocF;
// References to blockaddress. The key is the function ValID, the value is
// a list of references to blocks in that function.
std::map<ValID, std::vector<std::pair<ValID, GlobalValue*> > >
ForwardRefBlockAddresses;
Function *MallocF;
public:
LLParser(MemoryBuffer *F, SourceMgr &SM, SMDiagnostic &Err, Module *m) :
Context(m->getContext()), Lex(F, SM, Err, m->getContext()),
@ -184,13 +223,17 @@ namespace llvm {
std::map<std::string, std::pair<Value*, LocTy> > ForwardRefVals;
std::map<unsigned, std::pair<Value*, LocTy> > ForwardRefValIDs;
std::vector<Value*> NumberedVals;
/// FunctionNumber - If this is an unnamed function, this is the slot
/// number of it, otherwise it is -1.
int FunctionNumber;
public:
PerFunctionState(LLParser &p, Function &f);
PerFunctionState(LLParser &p, Function &f, int FunctionNumber);
~PerFunctionState();
Function &getFunction() const { return F; }
bool VerifyFunctionComplete();
bool FinishFunction();
/// GetVal - Get a value with the specified name or ID, creating a
/// forward reference record if needed. This can return null if the value
@ -294,6 +337,10 @@ namespace llvm {
bool ParseGetElementPtr(Instruction *&I, PerFunctionState &PFS);
bool ParseExtractValue(Instruction *&I, PerFunctionState &PFS);
bool ParseInsertValue(Instruction *&I, PerFunctionState &PFS);
bool ResolveForwardRefBlockAddresses(Function *TheFn,
std::vector<std::pair<ValID, GlobalValue*> > &Refs,
PerFunctionState *PFS);
};
} // End llvm namespace

View File

@ -117,7 +117,7 @@ namespace lltok {
kw_malloc, kw_alloca, kw_free, kw_load, kw_store, kw_getelementptr,
kw_extractelement, kw_insertelement, kw_shufflevector, kw_getresult,
kw_extractvalue, kw_insertvalue,
kw_extractvalue, kw_insertvalue, kw_blockaddress,
// Unsigned Valued tokens (UIntVal).
GlobalID, // @42