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

@ -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