summaryrefslogtreecommitdiff
path: root/lib/AsmParser/LLParser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/AsmParser/LLParser.cpp')
-rw-r--r--lib/AsmParser/LLParser.cpp284
1 files changed, 109 insertions, 175 deletions
diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp
index b5cbee5085b..2e411733e27 100644
--- a/lib/AsmParser/LLParser.cpp
+++ b/lib/AsmParser/LLParser.cpp
@@ -2315,7 +2315,7 @@ bool LLParser::PerFunctionState::FinishFunction() {
/// 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, OperatorConstraint OC) {
+ LocTy Loc) {
// Look this name up in the normal function symbol table.
Value *Val = F.getValueSymbolTable().lookup(Name);
@@ -2329,24 +2329,6 @@ Value *LLParser::PerFunctionState::GetVal(const std::string &Name, Type *Ty,
// 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");
@@ -2365,30 +2347,16 @@ Value *LLParser::PerFunctionState::GetVal(const std::string &Name, Type *Ty,
// Otherwise, create a new forward reference for this value and remember it.
Value *FwdVal;
if (Ty->isLabelTy()) {
- assert(!OC);
FwdVal = BasicBlock::Create(F.getContext(), Name, &F);
- } 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");
- }
+ FwdVal = new Argument(Ty, Name);
}
ForwardRefVals[Name] = std::make_pair(FwdVal, Loc);
return FwdVal;
}
-Value *LLParser::PerFunctionState::GetVal(unsigned ID, Type *Ty, LocTy Loc,
- OperatorConstraint OC) {
+Value *LLParser::PerFunctionState::GetVal(unsigned ID, Type *Ty, LocTy Loc) {
// Look this name up in the normal function symbol table.
Value *Val = ID < NumberedVals.size() ? NumberedVals[ID] : nullptr;
@@ -2402,24 +2370,6 @@ Value *LLParser::PerFunctionState::GetVal(unsigned ID, Type *Ty, LocTy Loc,
// 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");
@@ -2437,21 +2387,9 @@ Value *LLParser::PerFunctionState::GetVal(unsigned ID, Type *Ty, LocTy Loc,
// Otherwise, create a new forward reference for this value and remember it.
Value *FwdVal;
if (Ty->isLabelTy()) {
- assert(!OC);
FwdVal = BasicBlock::Create(F.getContext(), "", &F);
- } 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");
- }
+ FwdVal = new Argument(Ty);
}
ForwardRefValIDs[ID] = std::make_pair(FwdVal, Loc);
@@ -2487,17 +2425,6 @@ bool LLParser::PerFunctionState::SetInstName(int NameID,
if (Sentinel->getType() != Inst->getType())
return P.Error(NameLoc, "instruction forward referenced with type '" +
getTypeString(FI->second.first->getType()) + "'");
- // 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;
@@ -2515,17 +2442,6 @@ bool LLParser::PerFunctionState::SetInstName(int NameID,
if (Sentinel->getType() != Inst->getType())
return P.Error(NameLoc, "instruction forward referenced with type '" +
getTypeString(FI->second.first->getType()) + "'");
- // 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;
@@ -4235,30 +4151,18 @@ bool LLParser::ParseMetadata(Metadata *&MD, PerFunctionState *PFS) {
//===----------------------------------------------------------------------===//
bool LLParser::ConvertValIDToValue(Type *Ty, ValID &ID, Value *&V,
- PerFunctionState *PFS,
- OperatorConstraint OC) {
+ PerFunctionState *PFS) {
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, OC);
+ V = PFS->GetVal(ID.UIntVal, Ty, ID.Loc);
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, OC);
+ V = PFS->GetVal(ID.StrVal, Ty, ID.Loc);
return V == nullptr;
case ValID::t_InlineAsm: {
if (!ID.FTy || !InlineAsm::Verify(ID.FTy, ID.StrVal2))
@@ -4385,11 +4289,10 @@ bool LLParser::parseConstantValue(Type *Ty, Constant *&C) {
}
}
-bool LLParser::ParseValue(Type *Ty, Value *&V, PerFunctionState *PFS,
- OperatorConstraint OC) {
+bool LLParser::ParseValue(Type *Ty, Value *&V, PerFunctionState *PFS) {
V = nullptr;
ValID ID;
- return ParseValID(ID, PFS) || ConvertValIDToValue(Ty, ID, V, PFS, OC);
+ return ParseValID(ID, PFS) || ConvertValIDToValue(Ty, ID, V, PFS);
}
bool LLParser::ParseTypeAndValue(Value *&V, PerFunctionState *PFS) {
@@ -4818,11 +4721,10 @@ int LLParser::ParseInstruction(Instruction *&Inst, BasicBlock *BB,
case lltok::kw_resume: return ParseResume(Inst, PFS);
case lltok::kw_cleanupret: return ParseCleanupRet(Inst, PFS);
case lltok::kw_catchret: return ParseCatchRet(Inst, PFS);
- case lltok::kw_catchpad: return ParseCatchPad(Inst, PFS);
- case lltok::kw_terminatepad: return ParseTerminatePad(Inst, PFS);
- case lltok::kw_cleanuppad: return ParseCleanupPad(Inst, PFS);
- case lltok::kw_catchendpad: return ParseCatchEndPad(Inst, PFS);
- case lltok::kw_cleanupendpad: return ParseCleanupEndPad(Inst, PFS);
+ case lltok::kw_catchswitch: return ParseCatchSwitch(Inst, PFS);
+ case lltok::kw_catchpad: return ParseCatchPad(Inst, PFS);
+ case lltok::kw_terminatepad:return ParseTerminatePad(Inst, PFS);
+ case lltok::kw_cleanuppad: return ParseCleanupPad(Inst, PFS);
// Binary Operators.
case lltok::kw_add:
case lltok::kw_sub:
@@ -5262,11 +5164,14 @@ bool LLParser::ParseExceptionArgs(SmallVectorImpl<Value *> &Args,
}
/// ParseCleanupRet
-/// ::= 'cleanupret' Value unwind ('to' 'caller' | TypeAndValue)
+/// ::= 'cleanupret' from Value unwind ('to' 'caller' | TypeAndValue)
bool LLParser::ParseCleanupRet(Instruction *&Inst, PerFunctionState &PFS) {
Value *CleanupPad = nullptr;
- if (ParseValue(Type::getTokenTy(Context), CleanupPad, PFS, OC_CleanupPad))
+ if (ParseToken(lltok::kw_from, "expected 'from' after cleanupret"))
+ return true;
+
+ if (ParseValue(Type::getTokenTy(Context), CleanupPad, PFS))
return true;
if (ParseToken(lltok::kw_unwind, "expected 'unwind' in cleanupret"))
@@ -5283,16 +5188,19 @@ bool LLParser::ParseCleanupRet(Instruction *&Inst, PerFunctionState &PFS) {
}
}
- Inst = CleanupReturnInst::Create(cast<CleanupPadInst>(CleanupPad), UnwindBB);
+ Inst = CleanupReturnInst::Create(CleanupPad, UnwindBB);
return false;
}
/// ParseCatchRet
-/// ::= 'catchret' Value 'to' TypeAndValue
+/// ::= 'catchret' from Parent Value 'to' TypeAndValue
bool LLParser::ParseCatchRet(Instruction *&Inst, PerFunctionState &PFS) {
Value *CatchPad = nullptr;
- if (ParseValue(Type::getTokenTy(Context), CatchPad, PFS, OC_CatchPad))
+ if (ParseToken(lltok::kw_from, "expected 'from' after catchret"))
+ return true;
+
+ if (ParseValue(Type::getTokenTy(Context), CatchPad, PFS))
return true;
BasicBlock *BB;
@@ -5300,114 +5208,140 @@ bool LLParser::ParseCatchRet(Instruction *&Inst, PerFunctionState &PFS) {
ParseTypeAndBasicBlock(BB, PFS))
return true;
- Inst = CatchReturnInst::Create(cast<CatchPadInst>(CatchPad), BB);
+ Inst = CatchReturnInst::Create(CatchPad, BB);
return false;
}
-/// ParseCatchPad
-/// ::= 'catchpad' ParamList 'to' TypeAndValue 'unwind' TypeAndValue
-bool LLParser::ParseCatchPad(Instruction *&Inst, PerFunctionState &PFS) {
- SmallVector<Value *, 8> Args;
- if (ParseExceptionArgs(Args, PFS))
+/// ParseCatchSwitch
+/// ::= 'catchswitch' within Parent
+bool LLParser::ParseCatchSwitch(Instruction *&Inst, PerFunctionState &PFS) {
+ Value *ParentPad;
+ LocTy BBLoc;
+
+ if (ParseToken(lltok::kw_within, "expected 'within' after catchswitch"))
return true;
- BasicBlock *NormalBB, *UnwindBB;
- if (ParseToken(lltok::kw_to, "expected 'to' in catchpad") ||
- ParseTypeAndBasicBlock(NormalBB, PFS) ||
- ParseToken(lltok::kw_unwind, "expected 'unwind' in catchpad") ||
- ParseTypeAndBasicBlock(UnwindBB, PFS))
+ if (Lex.getKind() != lltok::kw_none && Lex.getKind() != lltok::LocalVar &&
+ Lex.getKind() != lltok::LocalVarID)
+ return TokError("expected scope value for catchswitch");
+
+ if (ParseValue(Type::getTokenTy(Context), ParentPad, PFS))
return true;
- Inst = CatchPadInst::Create(NormalBB, UnwindBB, Args);
- return false;
-}
+ if (ParseToken(lltok::lsquare, "expected '[' with catchswitch labels"))
+ return true;
-/// ParseTerminatePad
-/// ::= 'terminatepad' ParamList 'to' TypeAndValue
-bool LLParser::ParseTerminatePad(Instruction *&Inst, PerFunctionState &PFS) {
- SmallVector<Value *, 8> Args;
- if (ParseExceptionArgs(Args, PFS))
+ SmallVector<BasicBlock *, 32> Table;
+ do {
+ BasicBlock *DestBB;
+ if (ParseTypeAndBasicBlock(DestBB, PFS))
+ return true;
+ Table.push_back(DestBB);
+ } while (EatIfPresent(lltok::comma));
+
+ if (ParseToken(lltok::rsquare, "expected ']' after catchswitch labels"))
return true;
- if (ParseToken(lltok::kw_unwind, "expected 'unwind' in terminatepad"))
+ if (ParseToken(lltok::kw_unwind,
+ "expected 'unwind' after catchswitch scope"))
return true;
BasicBlock *UnwindBB = nullptr;
- if (Lex.getKind() == lltok::kw_to) {
- Lex.Lex();
- if (ParseToken(lltok::kw_caller, "expected 'caller' in terminatepad"))
+ if (EatIfPresent(lltok::kw_to)) {
+ if (ParseToken(lltok::kw_caller, "expected 'caller' in catchswitch"))
return true;
} else {
- if (ParseTypeAndBasicBlock(UnwindBB, PFS)) {
+ if (ParseTypeAndBasicBlock(UnwindBB, PFS))
return true;
- }
}
- Inst = TerminatePadInst::Create(Context, UnwindBB, Args);
+ auto *CatchSwitch =
+ CatchSwitchInst::Create(ParentPad, UnwindBB, Table.size());
+ for (BasicBlock *DestBB : Table)
+ CatchSwitch->addHandler(DestBB);
+ Inst = CatchSwitch;
return false;
}
-/// ParseCleanupPad
-/// ::= 'cleanuppad' ParamList
-bool LLParser::ParseCleanupPad(Instruction *&Inst, PerFunctionState &PFS) {
+/// ParseCatchPad
+/// ::= 'catchpad' ParamList 'to' TypeAndValue 'unwind' TypeAndValue
+bool LLParser::ParseCatchPad(Instruction *&Inst, PerFunctionState &PFS) {
+ Value *CatchSwitch = nullptr;
+
+ if (ParseToken(lltok::kw_within, "expected 'within' after catchpad"))
+ return true;
+
+ if (Lex.getKind() != lltok::LocalVar && Lex.getKind() != lltok::LocalVarID)
+ return TokError("expected scope value for catchpad");
+
+ if (ParseValue(Type::getTokenTy(Context), CatchSwitch, PFS))
+ return true;
+
SmallVector<Value *, 8> Args;
if (ParseExceptionArgs(Args, PFS))
return true;
- Inst = CleanupPadInst::Create(Context, Args);
+ Inst = CatchPadInst::Create(CatchSwitch, Args);
return false;
}
-/// ParseCatchEndPad
-/// ::= 'catchendpad' unwind ('to' 'caller' | TypeAndValue)
-bool LLParser::ParseCatchEndPad(Instruction *&Inst, PerFunctionState &PFS) {
- if (ParseToken(lltok::kw_unwind, "expected 'unwind' in catchendpad"))
+/// ParseTerminatePad
+/// ::= 'terminatepad' within Parent ParamList 'to' TypeAndValue
+bool LLParser::ParseTerminatePad(Instruction *&Inst, PerFunctionState &PFS) {
+ Value *ParentPad = nullptr;
+
+ if (ParseToken(lltok::kw_within, "expected 'within' after terminatepad"))
+ return true;
+
+ if (Lex.getKind() != lltok::kw_none && Lex.getKind() != lltok::LocalVar &&
+ Lex.getKind() != lltok::LocalVarID)
+ return TokError("expected scope value for terminatepad");
+
+ if (ParseValue(Type::getTokenTy(Context), ParentPad, PFS))
+ return true;
+
+ SmallVector<Value *, 8> Args;
+ if (ParseExceptionArgs(Args, PFS))
+ return true;
+
+ if (ParseToken(lltok::kw_unwind, "expected 'unwind' in terminatepad"))
return true;
BasicBlock *UnwindBB = nullptr;
if (Lex.getKind() == lltok::kw_to) {
Lex.Lex();
- if (Lex.getKind() == lltok::kw_caller) {
- Lex.Lex();
- } else {
+ if (ParseToken(lltok::kw_caller, "expected 'caller' in terminatepad"))
return true;
- }
} else {
if (ParseTypeAndBasicBlock(UnwindBB, PFS)) {
return true;
}
}
- Inst = CatchEndPadInst::Create(Context, UnwindBB);
+ Inst = TerminatePadInst::Create(ParentPad, UnwindBB, Args);
return false;
}
-/// ParseCatchEndPad
-/// ::= 'cleanupendpad' Value unwind ('to' 'caller' | TypeAndValue)
-bool LLParser::ParseCleanupEndPad(Instruction *&Inst, PerFunctionState &PFS) {
- Value *CleanupPad = nullptr;
+/// ParseCleanupPad
+/// ::= 'cleanuppad' within Parent ParamList
+bool LLParser::ParseCleanupPad(Instruction *&Inst, PerFunctionState &PFS) {
+ Value *ParentPad = nullptr;
- if (ParseValue(Type::getTokenTy(Context), CleanupPad, PFS, OC_CleanupPad))
+ if (ParseToken(lltok::kw_within, "expected 'within' after cleanuppad"))
return true;
- if (ParseToken(lltok::kw_unwind, "expected 'unwind' in catchendpad"))
+ if (Lex.getKind() != lltok::kw_none && Lex.getKind() != lltok::LocalVar &&
+ Lex.getKind() != lltok::LocalVarID)
+ return TokError("expected scope value for cleanuppad");
+
+ if (ParseValue(Type::getTokenTy(Context), ParentPad, PFS))
return true;
- BasicBlock *UnwindBB = nullptr;
- if (Lex.getKind() == lltok::kw_to) {
- Lex.Lex();
- if (Lex.getKind() == lltok::kw_caller) {
- Lex.Lex();
- } else {
- return true;
- }
- } else {
- if (ParseTypeAndBasicBlock(UnwindBB, PFS)) {
- return true;
- }
- }
+ SmallVector<Value *, 8> Args;
+ if (ParseExceptionArgs(Args, PFS))
+ return true;
- Inst = CleanupEndPadInst::Create(cast<CleanupPadInst>(CleanupPad), UnwindBB);
+ Inst = CleanupPadInst::Create(ParentPad, Args);
return false;
}