diff options
Diffstat (limited to 'clang/lib/CIR/Dialect/IR')
-rw-r--r-- | clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 186 |
1 files changed, 173 insertions, 13 deletions
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index 5f88590..0712de2 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -15,6 +15,7 @@ #include "clang/CIR/Dialect/IR/CIROpsEnums.h" #include "clang/CIR/Dialect/IR/CIRTypes.h" +#include "mlir/IR/DialectImplementation.h" #include "mlir/Interfaces/ControlFlowInterfaces.h" #include "mlir/Interfaces/FunctionImplementation.h" #include "mlir/Support/LLVM.h" @@ -1720,6 +1721,43 @@ ParseResult cir::FuncOp::parse(OpAsmParser &parser, OperationState &state) { hasAlias = true; } + auto parseGlobalDtorCtor = + [&](StringRef keyword, + llvm::function_ref<void(std::optional<int> prio)> createAttr) + -> mlir::LogicalResult { + if (mlir::succeeded(parser.parseOptionalKeyword(keyword))) { + std::optional<int> priority; + if (mlir::succeeded(parser.parseOptionalLParen())) { + auto parsedPriority = mlir::FieldParser<int>::parse(parser); + if (mlir::failed(parsedPriority)) + return parser.emitError(parser.getCurrentLocation(), + "failed to parse 'priority', of type 'int'"); + priority = parsedPriority.value_or(int()); + // Parse literal ')' + if (parser.parseRParen()) + return failure(); + } + createAttr(priority); + } + return success(); + }; + + if (parseGlobalDtorCtor("global_ctor", [&](std::optional<int> priority) { + mlir::IntegerAttr globalCtorPriorityAttr = + builder.getI32IntegerAttr(priority.value_or(65535)); + state.addAttribute(getGlobalCtorPriorityAttrName(state.name), + globalCtorPriorityAttr); + }).failed()) + return failure(); + + if (parseGlobalDtorCtor("global_dtor", [&](std::optional<int> priority) { + mlir::IntegerAttr globalDtorPriorityAttr = + builder.getI32IntegerAttr(priority.value_or(65535)); + state.addAttribute(getGlobalDtorPriorityAttrName(state.name), + globalDtorPriorityAttr); + }).failed()) + return failure(); + // Parse the optional function body. auto *body = state.addRegion(); OptionalParseResult parseResult = parser.parseOptionalRegion( @@ -1801,6 +1839,18 @@ void cir::FuncOp::print(OpAsmPrinter &p) { p << ")"; } + if (auto globalCtorPriority = getGlobalCtorPriority()) { + p << " global_ctor"; + if (globalCtorPriority.value() != 65535) + p << "(" << globalCtorPriority.value() << ")"; + } + + if (auto globalDtorPriority = getGlobalDtorPriority()) { + p << " global_dtor"; + if (globalDtorPriority.value() != 65535) + p << "(" << globalDtorPriority.value() << ")"; + } + // Print the body if this is not an external function. Region &body = getOperation()->getRegion(0); if (!body.empty()) { @@ -2851,31 +2901,141 @@ mlir::LogicalResult cir::ThrowOp::verify() { } //===----------------------------------------------------------------------===// -// AtomicCmpXchg +// TypeInfoAttr //===----------------------------------------------------------------------===// -LogicalResult cir::AtomicCmpXchg::verify() { - mlir::Type pointeeType = getPtr().getType().getPointee(); +LogicalResult cir::TypeInfoAttr::verify( + ::llvm::function_ref<::mlir::InFlightDiagnostic()> emitError, + ::mlir::Type type, ::mlir::ArrayAttr typeInfoData) { - if (pointeeType != getExpected().getType() || - pointeeType != getDesired().getType()) - return emitOpError("ptr, expected and desired types must match"); + if (cir::ConstRecordAttr::verify(emitError, type, typeInfoData).failed()) + return failure(); return success(); } //===----------------------------------------------------------------------===// -// TypeInfoAttr +// TryOp //===----------------------------------------------------------------------===// -LogicalResult cir::TypeInfoAttr::verify( - ::llvm::function_ref<::mlir::InFlightDiagnostic()> emitError, - ::mlir::Type type, ::mlir::ArrayAttr typeInfoData) { +void cir::TryOp::getSuccessorRegions( + mlir::RegionBranchPoint point, + llvm::SmallVectorImpl<mlir::RegionSuccessor> ®ions) { + // The `try` and the `catchers` region branch back to the parent operation. + if (!point.isParent()) { + regions.push_back(mlir::RegionSuccessor()); + return; + } - if (cir::ConstRecordAttr::verify(emitError, type, typeInfoData).failed()) - return failure(); + regions.push_back(mlir::RegionSuccessor(&getTryRegion())); - return success(); + // TODO(CIR): If we know a target function never throws a specific type, we + // can remove the catch handler. + for (mlir::Region &handlerRegion : this->getHandlerRegions()) + regions.push_back(mlir::RegionSuccessor(&handlerRegion)); +} + +static void +printTryHandlerRegions(mlir::OpAsmPrinter &printer, cir::TryOp op, + mlir::MutableArrayRef<mlir::Region> handlerRegions, + mlir::ArrayAttr handlerTypes) { + if (!handlerTypes) + return; + + for (const auto [typeIdx, typeAttr] : llvm::enumerate(handlerTypes)) { + if (typeIdx) + printer << " "; + + if (mlir::isa<cir::CatchAllAttr>(typeAttr)) { + printer << "catch all "; + } else if (mlir::isa<cir::UnwindAttr>(typeAttr)) { + printer << "unwind "; + } else { + printer << "catch [type "; + printer.printAttribute(typeAttr); + printer << "] "; + } + + printer.printRegion(handlerRegions[typeIdx], + /*printEntryBLockArgs=*/false, + /*printBlockTerminators=*/true); + } +} + +static mlir::ParseResult parseTryHandlerRegions( + mlir::OpAsmParser &parser, + llvm::SmallVectorImpl<std::unique_ptr<mlir::Region>> &handlerRegions, + mlir::ArrayAttr &handlerTypes) { + + auto parseCheckedCatcherRegion = [&]() -> mlir::ParseResult { + handlerRegions.emplace_back(new mlir::Region); + + mlir::Region &currRegion = *handlerRegions.back(); + mlir::SMLoc regionLoc = parser.getCurrentLocation(); + if (parser.parseRegion(currRegion)) { + handlerRegions.clear(); + return failure(); + } + + if (!currRegion.empty() && !(currRegion.back().mightHaveTerminator() && + currRegion.back().getTerminator())) + return parser.emitError( + regionLoc, "blocks are expected to be explicitly terminated"); + + return success(); + }; + + bool hasCatchAll = false; + llvm::SmallVector<mlir::Attribute, 4> catcherAttrs; + while (parser.parseOptionalKeyword("catch").succeeded()) { + bool hasLSquare = parser.parseOptionalLSquare().succeeded(); + + llvm::StringRef attrStr; + if (parser.parseOptionalKeyword(&attrStr, {"all", "type"}).failed()) + return parser.emitError(parser.getCurrentLocation(), + "expected 'all' or 'type' keyword"); + + bool isCatchAll = attrStr == "all"; + if (isCatchAll) { + if (hasCatchAll) + return parser.emitError(parser.getCurrentLocation(), + "can't have more than one catch all"); + hasCatchAll = true; + } + + mlir::Attribute exceptionRTTIAttr; + if (!isCatchAll && parser.parseAttribute(exceptionRTTIAttr).failed()) + return parser.emitError(parser.getCurrentLocation(), + "expected valid RTTI info attribute"); + + catcherAttrs.push_back(isCatchAll + ? cir::CatchAllAttr::get(parser.getContext()) + : exceptionRTTIAttr); + + if (hasLSquare && isCatchAll) + return parser.emitError(parser.getCurrentLocation(), + "catch all dosen't need RTTI info attribute"); + + if (hasLSquare && parser.parseRSquare().failed()) + return parser.emitError(parser.getCurrentLocation(), + "expected `]` after RTTI info attribute"); + + if (parseCheckedCatcherRegion().failed()) + return mlir::failure(); + } + + if (parser.parseOptionalKeyword("unwind").succeeded()) { + if (hasCatchAll) + return parser.emitError(parser.getCurrentLocation(), + "unwind can't be used with catch all"); + + catcherAttrs.push_back(cir::UnwindAttr::get(parser.getContext())); + if (parseCheckedCatcherRegion().failed()) + return mlir::failure(); + } + + handlerTypes = parser.getBuilder().getArrayAttr(catcherAttrs); + return mlir::success(); } //===----------------------------------------------------------------------===// |