[IR] Reformulate LLVM's EH funclet IR
[oota-llvm.git] / lib / AsmParser / LLParser.cpp
index b5cbee5085bd732aead6c5da4e568f22d1369863..2e411733e27168fb1b70446af32f3ab1a7e80bcf 100644 (file)
@@ -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;
 }