+bool LLParser::ParseExceptionArgs(SmallVectorImpl<Value *> &Args,
+ PerFunctionState &PFS) {
+ if (ParseToken(lltok::lsquare, "expected '[' in catchpad/cleanuppad"))
+ return true;
+
+ while (Lex.getKind() != lltok::rsquare) {
+ // If this isn't the first argument, we need a comma.
+ if (!Args.empty() &&
+ ParseToken(lltok::comma, "expected ',' in argument list"))
+ return true;
+
+ // Parse the argument.
+ LocTy ArgLoc;
+ Type *ArgTy = nullptr;
+ if (ParseType(ArgTy, ArgLoc))
+ return true;
+
+ Value *V;
+ if (ArgTy->isMetadataTy()) {
+ if (ParseMetadataAsValue(V, PFS))
+ return true;
+ } else {
+ if (ParseValue(ArgTy, V, PFS))
+ return true;
+ }
+ Args.push_back(V);
+ }
+
+ Lex.Lex(); // Lex the ']'.
+ return false;
+}
+
+/// ParseCleanupRet
+/// ::= 'cleanupret' from Value unwind ('to' 'caller' | TypeAndValue)
+bool LLParser::ParseCleanupRet(Instruction *&Inst, PerFunctionState &PFS) {
+ Value *CleanupPad = nullptr;
+
+ 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"))
+ return true;
+
+ BasicBlock *UnwindBB = nullptr;
+ if (Lex.getKind() == lltok::kw_to) {
+ Lex.Lex();
+ if (ParseToken(lltok::kw_caller, "expected 'caller' in cleanupret"))
+ return true;
+ } else {
+ if (ParseTypeAndBasicBlock(UnwindBB, PFS)) {
+ return true;
+ }
+ }
+
+ Inst = CleanupReturnInst::Create(CleanupPad, UnwindBB);
+ return false;
+}
+
+/// ParseCatchRet
+/// ::= 'catchret' from Parent Value 'to' TypeAndValue
+bool LLParser::ParseCatchRet(Instruction *&Inst, PerFunctionState &PFS) {
+ Value *CatchPad = nullptr;
+
+ if (ParseToken(lltok::kw_from, "expected 'from' after catchret"))
+ return true;
+
+ if (ParseValue(Type::getTokenTy(Context), CatchPad, PFS))
+ return true;
+
+ BasicBlock *BB;
+ if (ParseToken(lltok::kw_to, "expected 'to' in catchret") ||
+ ParseTypeAndBasicBlock(BB, PFS))
+ return true;
+
+ Inst = CatchReturnInst::Create(CatchPad, BB);
+ return false;
+}
+
+/// 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;
+
+ 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;
+
+ if (ParseToken(lltok::lsquare, "expected '[' with catchswitch labels"))
+ return true;
+
+ 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' after catchswitch scope"))
+ return true;
+
+ BasicBlock *UnwindBB = nullptr;
+ if (EatIfPresent(lltok::kw_to)) {
+ if (ParseToken(lltok::kw_caller, "expected 'caller' in catchswitch"))
+ return true;
+ } else {
+ if (ParseTypeAndBasicBlock(UnwindBB, PFS))
+ return true;
+ }
+
+ auto *CatchSwitch =
+ CatchSwitchInst::Create(ParentPad, UnwindBB, Table.size());
+ for (BasicBlock *DestBB : Table)
+ CatchSwitch->addHandler(DestBB);
+ Inst = CatchSwitch;
+ return false;
+}
+
+/// 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 = CatchPadInst::Create(CatchSwitch, Args);
+ return false;
+}
+
+/// ParseCleanupPad
+/// ::= 'cleanuppad' within Parent ParamList
+bool LLParser::ParseCleanupPad(Instruction *&Inst, PerFunctionState &PFS) {
+ Value *ParentPad = nullptr;
+
+ if (ParseToken(lltok::kw_within, "expected 'within' after cleanuppad"))
+ return true;
+
+ 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;
+
+ SmallVector<Value *, 8> Args;
+ if (ParseExceptionArgs(Args, PFS))
+ return true;
+
+ Inst = CleanupPadInst::Create(ParentPad, Args);
+ return false;
+}
+