-
Notifications
You must be signed in to change notification settings - Fork 13.4k
[CIR] Upstream support for switch statements case kinds #138003
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
ff564e6
ee0b0aa
3142924
b032de7
39861dd
c772736
906e697
f470023
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -253,6 +253,7 @@ mlir::LogicalResult CIRGenFunction::emitSimpleStmt(const Stmt *s, | |
case Stmt::NullStmtClass: | ||
break; | ||
case Stmt::CaseStmtClass: | ||
case Stmt::DefaultStmtClass: | ||
// If we reached here, we must not handling a switch case in the top level. | ||
return emitSwitchCase(cast<SwitchCase>(*s), | ||
/*buildingTopLevelCase=*/false); | ||
|
@@ -455,7 +456,7 @@ CIRGenFunction::emitCaseDefaultCascade(const T *stmt, mlir::Type condType, | |
if (isa<DefaultStmt>(sub) && isa<CaseStmt>(stmt)) { | ||
subStmtKind = SubStmtKind::Default; | ||
builder.createYield(loc); | ||
} else if (isa<CaseStmt>(sub) && isa<DefaultStmt>(stmt)) { | ||
} else if (isa<CaseStmt>(sub) && isa<DefaultStmt, CaseStmt>(stmt)) { | ||
subStmtKind = SubStmtKind::Case; | ||
builder.createYield(loc); | ||
} else { | ||
|
@@ -500,8 +501,8 @@ CIRGenFunction::emitCaseDefaultCascade(const T *stmt, mlir::Type condType, | |
if (subStmtKind == SubStmtKind::Case) { | ||
result = emitCaseStmt(*cast<CaseStmt>(sub), condType, buildingTopLevelCase); | ||
} else if (subStmtKind == SubStmtKind::Default) { | ||
getCIRGenModule().errorNYI(sub->getSourceRange(), "Default case"); | ||
return mlir::failure(); | ||
result = emitDefaultStmt(*cast<DefaultStmt>(sub), condType, | ||
buildingTopLevelCase); | ||
} else if (buildingTopLevelCase) { | ||
// If we're building a top level case, try to restore the insert point to | ||
// the case we're building, then we can attach more random stmts to the | ||
|
@@ -515,19 +516,40 @@ CIRGenFunction::emitCaseDefaultCascade(const T *stmt, mlir::Type condType, | |
mlir::LogicalResult CIRGenFunction::emitCaseStmt(const CaseStmt &s, | ||
mlir::Type condType, | ||
bool buildingTopLevelCase) { | ||
cir::CaseOpKind kind; | ||
mlir::ArrayAttr value; | ||
llvm::APSInt intVal = s.getLHS()->EvaluateKnownConstInt(getContext()); | ||
SmallVector<mlir::Attribute, 1> caseEltValueListAttr; | ||
caseEltValueListAttr.push_back(cir::IntAttr::get(condType, intVal)); | ||
mlir::ArrayAttr value = builder.getArrayAttr(caseEltValueListAttr); | ||
if (s.getRHS()) { | ||
getCIRGenModule().errorNYI(s.getSourceRange(), "SwitchOp range kind"); | ||
return mlir::failure(); | ||
|
||
// If the case statement has an RHS value, it is representing a GNU | ||
// case range statement, where LHS is the beginning of the range | ||
// and RHS is the end of the range. | ||
if (const Expr *rhs = s.getRHS()) { | ||
llvm::APSInt endVal = rhs->EvaluateKnownConstInt(getContext()); | ||
value = builder.getArrayAttr({cir::IntAttr::get(condType, intVal), | ||
cir::IntAttr::get(condType, endVal)}); | ||
kind = cir::CaseOpKind::Range; | ||
|
||
// We don't currently fold case range statements with other case statements. | ||
// TODO(cir): Add this capability. Folding these cases is going to be | ||
// implemented in CIRSimplify when it is upstreamed. | ||
assert(!cir::MissingFeatures::foldRangeCase()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need this? I thought we were going to move all of this to an opt pass instead? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I left it there as a reminder to fold the ranges in the future, but you're right it's not appropriate in this spot. Is there a better place to leave the comment instead? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't have a good idea? perhaps in the pass manager or whatever pass we expect to do this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I updated the comment to mention implementing this in CIRSimplify. |
||
assert(!cir::MissingFeatures::foldCascadingCases()); | ||
} else { | ||
value = builder.getArrayAttr({cir::IntAttr::get(condType, intVal)}); | ||
kind = cir::CaseOpKind::Equal; | ||
} | ||
assert(!cir::MissingFeatures::foldCaseStmt()); | ||
return emitCaseDefaultCascade(&s, condType, value, cir::CaseOpKind::Equal, | ||
|
||
return emitCaseDefaultCascade(&s, condType, value, kind, | ||
buildingTopLevelCase); | ||
} | ||
|
||
mlir::LogicalResult CIRGenFunction::emitDefaultStmt(const clang::DefaultStmt &s, | ||
mlir::Type condType, | ||
bool buildingTopLevelCase) { | ||
return emitCaseDefaultCascade(&s, condType, builder.getArrayAttr({}), | ||
cir::CaseOpKind::Default, buildingTopLevelCase); | ||
} | ||
|
||
mlir::LogicalResult CIRGenFunction::emitSwitchCase(const SwitchCase &s, | ||
bool buildingTopLevelCase) { | ||
assert(!condTypeStack.empty() && | ||
|
@@ -537,10 +559,9 @@ mlir::LogicalResult CIRGenFunction::emitSwitchCase(const SwitchCase &s, | |
return emitCaseStmt(cast<CaseStmt>(s), condTypeStack.back(), | ||
buildingTopLevelCase); | ||
|
||
if (s.getStmtClass() == Stmt::DefaultStmtClass) { | ||
getCIRGenModule().errorNYI(s.getSourceRange(), "Default case"); | ||
return mlir::failure(); | ||
} | ||
if (s.getStmtClass() == Stmt::DefaultStmtClass) | ||
return emitDefaultStmt(cast<DefaultStmt>(s), condTypeStack.back(), | ||
buildingTopLevelCase); | ||
|
||
llvm_unreachable("expect case or default stmt"); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does 'top level' switch case mean here? I realize it is pre-existing, but trying to grok what is going on here