summaryrefslogtreecommitdiffstats
path: root/llvm/lib/AsmParser
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/AsmParser')
-rw-r--r--llvm/lib/AsmParser/LLParser.cpp184
-rw-r--r--llvm/lib/AsmParser/LLParser.h25
2 files changed, 155 insertions, 54 deletions
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index fc7fceb2a26..082637bf0b8 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -2237,8 +2237,8 @@ bool LLParser::PerFunctionState::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
/// exists but does not have the right type.
-Value *LLParser::PerFunctionState::GetVal(const std::string &Name,
- Type *Ty, LocTy Loc) {
+Value *LLParser::PerFunctionState::GetVal(const std::string &Name, Type *Ty,
+ LocTy Loc, OperatorConstraint OC) {
// Look this name up in the normal function symbol table.
Value *Val = F.getValueSymbolTable().lookup(Name);
@@ -2253,6 +2253,24 @@ Value *LLParser::PerFunctionState::GetVal(const std::string &Name,
// If we have the value in the symbol table or fwd-ref table, return it.
if (Val) {
+ // Check operator constraints.
+ switch (OC) {
+ case OC_None:
+ // no constraint
+ break;
+ case OC_CatchPad:
+ if (!isa<CatchPadInst>(Val)) {
+ P.Error(Loc, "'%" + Name + "' is not a catchpad");
+ return nullptr;
+ }
+ break;
+ case OC_CleanupPad:
+ if (!isa<CleanupPadInst>(Val)) {
+ P.Error(Loc, "'%" + Name + "' is not a cleanuppad");
+ return nullptr;
+ }
+ break;
+ }
if (Val->getType() == Ty) return Val;
if (Ty->isLabelTy())
P.Error(Loc, "'%" + Name + "' is not a basic block");
@@ -2270,17 +2288,31 @@ Value *LLParser::PerFunctionState::GetVal(const std::string &Name,
// Otherwise, create a new forward reference for this value and remember it.
Value *FwdVal;
- if (Ty->isLabelTy())
+ if (Ty->isLabelTy()) {
+ assert(!OC);
FwdVal = BasicBlock::Create(F.getContext(), Name, &F);
- else
+ } else if (!OC) {
FwdVal = new Argument(Ty, Name);
+ } else {
+ switch (OC) {
+ case OC_CatchPad:
+ FwdVal = CatchPadInst::Create(&F.getEntryBlock(), &F.getEntryBlock(), {},
+ Name);
+ break;
+ case OC_CleanupPad:
+ FwdVal = CleanupPadInst::Create(F.getContext(), {}, Name);
+ break;
+ default:
+ llvm_unreachable("unexpected constraint");
+ }
+ }
ForwardRefVals[Name] = std::make_pair(FwdVal, Loc);
return FwdVal;
}
-Value *LLParser::PerFunctionState::GetVal(unsigned ID, Type *Ty,
- LocTy Loc) {
+Value *LLParser::PerFunctionState::GetVal(unsigned ID, Type *Ty, LocTy Loc,
+ OperatorConstraint OC) {
// Look this name up in the normal function symbol table.
Value *Val = ID < NumberedVals.size() ? NumberedVals[ID] : nullptr;
@@ -2295,6 +2327,24 @@ Value *LLParser::PerFunctionState::GetVal(unsigned ID, Type *Ty,
// If we have the value in the symbol table or fwd-ref table, return it.
if (Val) {
+ // Check operator constraint.
+ switch (OC) {
+ case OC_None:
+ // no constraint
+ break;
+ case OC_CatchPad:
+ if (!isa<CatchPadInst>(Val)) {
+ P.Error(Loc, "'%" + Twine(ID) + "' is not a catchpad");
+ return nullptr;
+ }
+ break;
+ case OC_CleanupPad:
+ if (!isa<CleanupPadInst>(Val)) {
+ P.Error(Loc, "'%" + Twine(ID) + "' is not a cleanuppad");
+ return nullptr;
+ }
+ break;
+ }
if (Val->getType() == Ty) return Val;
if (Ty->isLabelTy())
P.Error(Loc, "'%" + Twine(ID) + "' is not a basic block");
@@ -2311,10 +2361,23 @@ Value *LLParser::PerFunctionState::GetVal(unsigned ID, Type *Ty,
// Otherwise, create a new forward reference for this value and remember it.
Value *FwdVal;
- if (Ty->isLabelTy())
+ if (Ty->isLabelTy()) {
+ assert(!OC);
FwdVal = BasicBlock::Create(F.getContext(), "", &F);
- else
+ } else if (!OC) {
FwdVal = new Argument(Ty);
+ } else {
+ switch (OC) {
+ case OC_CatchPad:
+ FwdVal = CatchPadInst::Create(&F.getEntryBlock(), &F.getEntryBlock(), {});
+ break;
+ case OC_CleanupPad:
+ FwdVal = CleanupPadInst::Create(F.getContext(), {});
+ break;
+ default:
+ llvm_unreachable("unexpected constraint");
+ }
+ }
ForwardRefValIDs[ID] = std::make_pair(FwdVal, Loc);
return FwdVal;
@@ -2346,11 +2409,24 @@ bool LLParser::PerFunctionState::SetInstName(int NameID,
std::map<unsigned, std::pair<Value*, LocTy> >::iterator FI =
ForwardRefValIDs.find(NameID);
if (FI != ForwardRefValIDs.end()) {
- if (FI->second.first->getType() != Inst->getType())
+ Value *Sentinel = FI->second.first;
+ if (Sentinel->getType() != Inst->getType())
return P.Error(NameLoc, "instruction forward referenced with type '" +
getTypeString(FI->second.first->getType()) + "'");
- FI->second.first->replaceAllUsesWith(Inst);
- delete FI->second.first;
+ // Check operator constraints. We only put cleanuppads or catchpads in
+ // the forward value map if the value is constrained to match.
+ if (isa<CatchPadInst>(Sentinel)) {
+ if (!isa<CatchPadInst>(Inst))
+ return P.Error(FI->second.second,
+ "'%" + Twine(NameID) + "' is not a catchpad");
+ } else if (isa<CleanupPadInst>(Sentinel)) {
+ if (!isa<CleanupPadInst>(Inst))
+ return P.Error(FI->second.second,
+ "'%" + Twine(NameID) + "' is not a cleanuppad");
+ }
+
+ Sentinel->replaceAllUsesWith(Inst);
+ delete Sentinel;
ForwardRefValIDs.erase(FI);
}
@@ -2362,11 +2438,24 @@ bool LLParser::PerFunctionState::SetInstName(int NameID,
std::map<std::string, std::pair<Value*, LocTy> >::iterator
FI = ForwardRefVals.find(NameStr);
if (FI != ForwardRefVals.end()) {
- if (FI->second.first->getType() != Inst->getType())
+ Value *Sentinel = FI->second.first;
+ if (Sentinel->getType() != Inst->getType())
return P.Error(NameLoc, "instruction forward referenced with type '" +
getTypeString(FI->second.first->getType()) + "'");
- FI->second.first->replaceAllUsesWith(Inst);
- delete FI->second.first;
+ // Check operator constraints. We only put cleanuppads or catchpads in
+ // the forward value map if the value is constrained to match.
+ if (isa<CatchPadInst>(Sentinel)) {
+ if (!isa<CatchPadInst>(Inst))
+ return P.Error(FI->second.second,
+ "'%" + NameStr + "' is not a catchpad");
+ } else if (isa<CleanupPadInst>(Sentinel)) {
+ if (!isa<CleanupPadInst>(Inst))
+ return P.Error(FI->second.second,
+ "'%" + NameStr + "' is not a cleanuppad");
+ }
+
+ Sentinel->replaceAllUsesWith(Inst);
+ delete Sentinel;
ForwardRefVals.erase(FI);
}
@@ -4007,18 +4096,30 @@ bool LLParser::ParseMetadata(Metadata *&MD, PerFunctionState *PFS) {
//===----------------------------------------------------------------------===//
bool LLParser::ConvertValIDToValue(Type *Ty, ValID &ID, Value *&V,
- PerFunctionState *PFS) {
+ PerFunctionState *PFS,
+ OperatorConstraint OC) {
if (Ty->isFunctionTy())
return Error(ID.Loc, "functions are not values, refer to them as pointers");
+ if (OC && ID.Kind != ValID::t_LocalID && ID.Kind != ValID::t_LocalName) {
+ switch (OC) {
+ case OC_CatchPad:
+ return Error(ID.Loc, "Catchpad value required in this position");
+ case OC_CleanupPad:
+ return Error(ID.Loc, "Cleanuppad value required in this position");
+ default:
+ llvm_unreachable("Unexpected constraint kind");
+ }
+ }
+
switch (ID.Kind) {
case ValID::t_LocalID:
if (!PFS) return Error(ID.Loc, "invalid use of function-local name");
- V = PFS->GetVal(ID.UIntVal, Ty, ID.Loc);
+ V = PFS->GetVal(ID.UIntVal, Ty, ID.Loc, OC);
return V == nullptr;
case ValID::t_LocalName:
if (!PFS) return Error(ID.Loc, "invalid use of function-local name");
- V = PFS->GetVal(ID.StrVal, Ty, ID.Loc);
+ V = PFS->GetVal(ID.StrVal, Ty, ID.Loc, OC);
return V == nullptr;
case ValID::t_InlineAsm: {
assert(ID.FTy);
@@ -4140,11 +4241,11 @@ bool LLParser::parseConstantValue(Type *Ty, Constant *&C) {
}
}
-bool LLParser::ParseValue(Type *Ty, Value *&V, PerFunctionState *PFS) {
+bool LLParser::ParseValue(Type *Ty, Value *&V, PerFunctionState *PFS,
+ OperatorConstraint OC) {
V = nullptr;
ValID ID;
- return ParseValID(ID, PFS) ||
- ConvertValIDToValue(Ty, ID, V, PFS);
+ return ParseValID(ID, PFS) || ConvertValIDToValue(Ty, ID, V, PFS, OC);
}
bool LLParser::ParseTypeAndValue(Value *&V, PerFunctionState *PFS) {
@@ -4985,7 +5086,7 @@ bool LLParser::ParseResume(Instruction *&Inst, PerFunctionState &PFS) {
bool LLParser::ParseExceptionArgs(SmallVectorImpl<Value *> &Args,
PerFunctionState &PFS) {
- if (ParseToken(lltok::lsquare, "expected '[' in cleanuppad"))
+ if (ParseToken(lltok::lsquare, "expected '[' in catchpad/cleanuppad"))
return true;
while (Lex.getKind() != lltok::rsquare) {
@@ -5016,16 +5117,12 @@ bool LLParser::ParseExceptionArgs(SmallVectorImpl<Value *> &Args,
}
/// ParseCleanupRet
-/// ::= 'cleanupret' ('void' | TypeAndValue) unwind ('to' 'caller' | TypeAndValue)
+/// ::= 'cleanupret' Value unwind ('to' 'caller' | TypeAndValue)
bool LLParser::ParseCleanupRet(Instruction *&Inst, PerFunctionState &PFS) {
- Type *RetTy = nullptr;
- Value *RetVal = nullptr;
- if (ParseType(RetTy, /*AllowVoid=*/true))
- return true;
+ Value *CleanupPad = nullptr;
- if (!RetTy->isVoidTy())
- if (ParseValue(RetTy, RetVal, PFS))
- return true;
+ if (ParseValue(Type::getTokenTy(Context), CleanupPad, PFS, OC_CleanupPad))
+ return true;
if (ParseToken(lltok::kw_unwind, "expected 'unwind' in cleanupret"))
return true;
@@ -5041,39 +5138,32 @@ bool LLParser::ParseCleanupRet(Instruction *&Inst, PerFunctionState &PFS) {
}
}
- Inst = CleanupReturnInst::Create(Context, RetVal, UnwindBB);
+ Inst = CleanupReturnInst::Create(cast<CleanupPadInst>(CleanupPad), UnwindBB);
return false;
}
/// ParseCatchRet
-/// ::= 'catchret' ('void' | TypeAndValue) 'to' TypeAndValue
+/// ::= 'catchret' Value 'to' TypeAndValue
bool LLParser::ParseCatchRet(Instruction *&Inst, PerFunctionState &PFS) {
- Type *RetTy = nullptr;
- Value *RetVal = nullptr;
+ Value *CatchPad = nullptr;
- if (ParseType(RetTy, /*AllowVoid=*/true))
+ if (ParseValue(Type::getTokenTy(Context), CatchPad, PFS, OC_CatchPad))
return true;
- if (!RetTy->isVoidTy())
- if (ParseValue(RetTy, RetVal, PFS))
- return true;
-
BasicBlock *BB;
if (ParseToken(lltok::kw_to, "expected 'to' in catchret") ||
ParseTypeAndBasicBlock(BB, PFS))
return true;
- Inst = CatchReturnInst::Create(BB, RetVal);
+ Inst = CatchReturnInst::Create(cast<CatchPadInst>(CatchPad), BB);
return false;
}
/// ParseCatchPad
-/// ::= 'catchpad' Type ParamList 'to' TypeAndValue 'unwind' TypeAndValue
+/// ::= 'catchpad' ParamList 'to' TypeAndValue 'unwind' TypeAndValue
bool LLParser::ParseCatchPad(Instruction *&Inst, PerFunctionState &PFS) {
- Type *RetType = nullptr;
-
SmallVector<Value *, 8> Args;
- if (ParseType(RetType, /*AllowVoid=*/true) || ParseExceptionArgs(Args, PFS))
+ if (ParseExceptionArgs(Args, PFS))
return true;
BasicBlock *NormalBB, *UnwindBB;
@@ -5083,7 +5173,7 @@ bool LLParser::ParseCatchPad(Instruction *&Inst, PerFunctionState &PFS) {
ParseTypeAndBasicBlock(UnwindBB, PFS))
return true;
- Inst = CatchPadInst::Create(RetType, NormalBB, UnwindBB, Args);
+ Inst = CatchPadInst::Create(NormalBB, UnwindBB, Args);
return false;
}
@@ -5115,13 +5205,11 @@ bool LLParser::ParseTerminatePad(Instruction *&Inst, PerFunctionState &PFS) {
/// ParseCleanupPad
/// ::= 'cleanuppad' ParamList
bool LLParser::ParseCleanupPad(Instruction *&Inst, PerFunctionState &PFS) {
- Type *RetType = nullptr;
-
SmallVector<Value *, 8> Args;
- if (ParseType(RetType, /*AllowVoid=*/true) || ParseExceptionArgs(Args, PFS))
+ if (ParseExceptionArgs(Args, PFS))
return true;
- Inst = CleanupPadInst::Create(RetType, Args);
+ Inst = CleanupPadInst::Create(Context, Args);
return false;
}
diff --git a/llvm/lib/AsmParser/LLParser.h b/llvm/lib/AsmParser/LLParser.h
index 96fb06a1f29..8b7e9560a69 100644
--- a/llvm/lib/AsmParser/LLParser.h
+++ b/llvm/lib/AsmParser/LLParser.h
@@ -108,6 +108,14 @@ namespace llvm {
unsigned MDKind, MDSlot;
};
+ /// Indicates which operator an operand allows (for the few operands that
+ /// may only reference a certain operator).
+ enum OperatorConstraint {
+ OC_None = 0, // No constraint
+ OC_CatchPad, // Must be CatchPadInst
+ OC_CleanupPad // Must be CleanupPadInst
+ };
+
SmallVector<Instruction*, 64> InstsWithTBAATag;
// Type resolution handling data structures. The location is set when we
@@ -329,8 +337,10 @@ namespace llvm {
/// GetVal - Get a value with the specified name or ID, creating a
/// forward reference record if needed. This can return null if the value
/// exists but does not have the right type.
- Value *GetVal(const std::string &Name, Type *Ty, LocTy Loc);
- Value *GetVal(unsigned ID, Type *Ty, LocTy Loc);
+ Value *GetVal(const std::string &Name, Type *Ty, LocTy Loc,
+ OperatorConstraint OC = OC_None);
+ Value *GetVal(unsigned ID, Type *Ty, LocTy Loc,
+ OperatorConstraint OC = OC_None);
/// SetInstName - After an instruction is parsed and inserted into its
/// basic block, this installs its name.
@@ -352,12 +362,15 @@ namespace llvm {
};
bool ConvertValIDToValue(Type *Ty, ValID &ID, Value *&V,
- PerFunctionState *PFS);
+ PerFunctionState *PFS,
+ OperatorConstraint OC = OC_None);
bool parseConstantValue(Type *Ty, Constant *&C);
- bool ParseValue(Type *Ty, Value *&V, PerFunctionState *PFS);
- bool ParseValue(Type *Ty, Value *&V, PerFunctionState &PFS) {
- return ParseValue(Ty, V, &PFS);
+ bool ParseValue(Type *Ty, Value *&V, PerFunctionState *PFS,
+ OperatorConstraint OC = OC_None);
+ bool ParseValue(Type *Ty, Value *&V, PerFunctionState &PFS,
+ OperatorConstraint OC = OC_None) {
+ return ParseValue(Ty, V, &PFS, OC);
}
bool ParseValue(Type *Ty, Value *&V, LocTy &Loc,
PerFunctionState &PFS) {
OpenPOWER on IntegriCloud