[clang] [CIR] Upstream initial for-loop support (PR #132266)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Mar 20 11:15:42 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Andy Kaylor (andykaylor)
<details>
<summary>Changes</summary>
This change adds support for empty for-loops. This will be the infrastructre needed for complete for loops, but that depends on compare operations, which have not been upstreamed yet.
---
Patch is 46.30 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/132266.diff
21 Files Affected:
- (modified) clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h (+19)
- (modified) clang/include/clang/CIR/Dialect/IR/CIRDialect.h (+1)
- (modified) clang/include/clang/CIR/Dialect/IR/CIROps.td (+162-2)
- (added) clang/include/clang/CIR/Interfaces/CIRLoopOpInterface.h (+34)
- (added) clang/include/clang/CIR/Interfaces/CIRLoopOpInterface.td (+99)
- (modified) clang/include/clang/CIR/Interfaces/CMakeLists.txt (+1)
- (modified) clang/include/clang/CIR/MissingFeatures.h (+19-7)
- (modified) clang/lib/CIR/CodeGen/CIRGenExpr.cpp (+19)
- (modified) clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp (+10)
- (modified) clang/lib/CIR/CodeGen/CIRGenFunction.h (+15)
- (modified) clang/lib/CIR/CodeGen/CIRGenStmt.cpp (+108-1)
- (modified) clang/lib/CIR/Dialect/IR/CIRDialect.cpp (+78)
- (modified) clang/lib/CIR/Dialect/IR/CMakeLists.txt (+2)
- (modified) clang/lib/CIR/Dialect/Transforms/CIRCanonicalize.cpp (+1-2)
- (modified) clang/lib/CIR/Dialect/Transforms/FlattenCFG.cpp (+111-2)
- (added) clang/lib/CIR/Interfaces/CIRLoopOpInterface.cpp (+63)
- (modified) clang/lib/CIR/Interfaces/CMakeLists.txt (+2)
- (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp (+17)
- (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h (+10)
- (added) clang/test/CIR/CodeGen/loop.cpp (+46)
- (added) clang/test/CIR/Transforms/loop.cir (+29)
``````````diff
diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index 32d1af677c62b..c6aea10d46b63 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -52,6 +52,15 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
return cir::BoolAttr::get(getContext(), getBoolTy(), state);
}
+ /// Create a for operation.
+ cir::ForOp createFor(
+ mlir::Location loc,
+ llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> condBuilder,
+ llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> bodyBuilder,
+ llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> stepBuilder) {
+ return create<cir::ForOp>(loc, condBuilder, bodyBuilder, stepBuilder);
+ }
+
mlir::TypedAttr getConstPtrAttr(mlir::Type type, int64_t value) {
auto valueAttr = mlir::IntegerAttr::get(
mlir::IntegerType::get(type.getContext(), 64), value);
@@ -158,6 +167,16 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
return mlir::IntegerAttr::get(mlir::IntegerType::get(ctx, 64),
size.getQuantity());
}
+
+ /// Create a loop condition.
+ cir::ConditionOp createCondition(mlir::Value condition) {
+ return create<cir::ConditionOp>(condition.getLoc(), condition);
+ }
+
+ /// Create a yield operation.
+ cir::YieldOp createYield(mlir::Location loc, mlir::ValueRange value = {}) {
+ return create<cir::YieldOp>(loc, value);
+ }
};
} // namespace cir
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRDialect.h b/clang/include/clang/CIR/Dialect/IR/CIRDialect.h
index 0684cf5034f5d..da3b41371b9ab 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRDialect.h
+++ b/clang/include/clang/CIR/Dialect/IR/CIRDialect.h
@@ -29,6 +29,7 @@
#include "clang/CIR/Dialect/IR/CIRAttrs.h"
#include "clang/CIR/Dialect/IR/CIROpsDialect.h.inc"
#include "clang/CIR/Dialect/IR/CIROpsEnums.h"
+#include "clang/CIR/Interfaces/CIRLoopOpInterface.h"
#include "clang/CIR/Interfaces/CIROpInterfaces.h"
// TableGen'erated files for MLIR dialects require that a macro be defined when
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 352d72ff31a8a..d7d63e040a2ba 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -19,6 +19,7 @@ include "clang/CIR/Dialect/IR/CIRTypes.td"
include "clang/CIR/Dialect/IR/CIRAttrs.td"
include "clang/CIR/Interfaces/CIROpInterfaces.td"
+include "clang/CIR/Interfaces/CIRLoopOpInterface.td"
include "mlir/IR/BuiltinAttributeInterfaces.td"
include "mlir/IR/EnumAttr.td"
@@ -423,7 +424,7 @@ def StoreOp : CIR_Op<"store", [
// ReturnOp
//===----------------------------------------------------------------------===//
-def ReturnOp : CIR_Op<"return", [ParentOneOf<["FuncOp", "ScopeOp"]>,
+def ReturnOp : CIR_Op<"return", [ParentOneOf<["FuncOp", "ScopeOp", "ForOp"]>,
Terminator]> {
let summary = "Return from function";
let description = [{
@@ -460,12 +461,57 @@ def ReturnOp : CIR_Op<"return", [ParentOneOf<["FuncOp", "ScopeOp"]>,
let hasVerifier = 1;
}
+//===----------------------------------------------------------------------===//
+// ConditionOp
+//===----------------------------------------------------------------------===//
+
+def ConditionOp : CIR_Op<"condition", [
+ Terminator,
+ DeclareOpInterfaceMethods<RegionBranchTerminatorOpInterface,
+ ["getSuccessorRegions"]>
+]> {
+ let summary = "Loop continuation condition.";
+ let description = [{
+ The `cir.condition` terminates conditional regions. It takes a single
+ `cir.bool` operand and, depending on its value, may branch to different
+ regions:
+
+ - When in the `cond` region of a `cir.loop`, it continues the loop
+ if true, or exits it if false.
+ - When in the `ready` region of a `cir.await`, it branches to the `resume`
+ region when true, and to the `suspend` region when false.
+
+ Example:
+
+ ```mlir
+ cir.loop for(cond : {
+ cir.condition(%arg0) // Branches to `step` region or exits.
+ }, step : {
+ [...]
+ }) {
+ [...]
+ }
+
+ cir.await(user, ready : {
+ cir.condition(%arg0) // Branches to `resume` or `suspend` region.
+ }, suspend : {
+ [...]
+ }, resume : {
+ [...]
+ },)
+ ```
+ }];
+ let arguments = (ins CIR_BoolType:$condition);
+ let assemblyFormat = " `(` $condition `)` attr-dict ";
+ let hasVerifier = 1;
+}
+
//===----------------------------------------------------------------------===//
// YieldOp
//===----------------------------------------------------------------------===//
def YieldOp : CIR_Op<"yield", [ReturnLike, Terminator,
- ParentOneOf<["ScopeOp"]>]> {
+ ParentOneOf<["ScopeOp", "ForOp"]>]> {
let summary = "Represents the default branching behaviour of a region";
let description = [{
The `cir.yield` operation terminates regions on different CIR operations,
@@ -666,6 +712,120 @@ def UnaryOp : CIR_Op<"unary", [Pure, SameOperandsAndResultType]> {
let hasFolder = 1;
}
+//===----------------------------------------------------------------------===//
+// BrCondOp
+//===----------------------------------------------------------------------===//
+
+def BrCondOp : CIR_Op<"brcond",
+ [DeclareOpInterfaceMethods<BranchOpInterface, ["getSuccessorForOperands"]>,
+ Pure, Terminator, AttrSizedOperandSegments]> {
+ let summary = "Conditional branch";
+ let description = [{
+ The `cir.brcond %cond, ^bb0, ^bb1` branches to 'bb0' block in case
+ %cond (which must be a !cir.bool type) evaluates to true, otherwise
+ it branches to 'bb1'.
+
+ Example:
+
+ ```mlir
+ ...
+ cir.brcond %a, ^bb3, ^bb4
+ ^bb3:
+ cir.return
+ ^bb4:
+ cir.yield
+ ```
+ }];
+
+ let builders = [
+ OpBuilder<(ins "mlir::Value":$cond, "mlir::Block *":$destTrue, "mlir::Block *":$destFalse,
+ CArg<"mlir::ValueRange", "{}">:$destOperandsTrue,
+ CArg<"mlir::ValueRange", "{}">:$destOperandsFalse), [{
+ build($_builder, $_state, cond, destOperandsTrue,
+ destOperandsFalse, destTrue, destFalse);
+ }]>
+ ];
+
+ let arguments = (ins CIR_BoolType:$cond,
+ Variadic<CIR_AnyType>:$destOperandsTrue,
+ Variadic<CIR_AnyType>:$destOperandsFalse);
+ let successors = (successor AnySuccessor:$destTrue, AnySuccessor:$destFalse);
+ let assemblyFormat = [{
+ $cond
+ $destTrue (`(` $destOperandsTrue^ `:` type($destOperandsTrue) `)`)?
+ `,`
+ $destFalse (`(` $destOperandsFalse^ `:` type($destOperandsFalse) `)`)?
+ attr-dict
+ }];
+}
+
+//===----------------------------------------------------------------------===//
+// ForOp
+//===----------------------------------------------------------------------===//
+
+def ForOp : CIR_Op<"for", [LoopOpInterface, NoRegionArguments]> {
+ let summary = "C/C++ for loop counterpart";
+ let description = [{
+ Represents a C/C++ for loop. It consists of three regions:
+
+ - `cond`: single block region with the loop's condition. Should be
+ terminated with a `cir.condition` operation.
+ - `body`: contains the loop body and an arbitrary number of blocks.
+ - `step`: single block region with the loop's step.
+
+ Example:
+
+ ```mlir
+ cir.for cond {
+ cir.condition(%val)
+ } body {
+ cir.break
+ ^bb2:
+ cir.yield
+ } step {
+ cir.yield
+ }
+ ```
+ }];
+
+ let regions = (region SizedRegion<1>:$cond,
+ MinSizedRegion<1>:$body,
+ SizedRegion<1>:$step);
+ let assemblyFormat = [{
+ `:` `cond` $cond
+ `body` $body
+ `step` $step
+ attr-dict
+ }];
+
+ let builders = [
+ OpBuilder<(ins "llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)>":$condBuilder,
+ "llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)>":$bodyBuilder,
+ "llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)>":$stepBuilder), [{
+ mlir::OpBuilder::InsertionGuard guard($_builder);
+
+ // Build condition region.
+ $_builder.createBlock($_state.addRegion());
+ condBuilder($_builder, $_state.location);
+
+ // Build body region.
+ $_builder.createBlock($_state.addRegion());
+ bodyBuilder($_builder, $_state.location);
+
+ // Build step region.
+ $_builder.createBlock($_state.addRegion());
+ stepBuilder($_builder, $_state.location);
+ }]>
+ ];
+
+ let extraClassDeclaration = [{
+ mlir::Region *maybeGetStep() { return &getStep(); }
+ llvm::SmallVector<mlir::Region *> getRegionsInExecutionOrder() {
+ return llvm::SmallVector<mlir::Region *, 3>{&getCond(), &getBody(), &getStep()};
+ }
+ }];
+}
+
//===----------------------------------------------------------------------===//
// GlobalOp
//===----------------------------------------------------------------------===//
diff --git a/clang/include/clang/CIR/Interfaces/CIRLoopOpInterface.h b/clang/include/clang/CIR/Interfaces/CIRLoopOpInterface.h
new file mode 100644
index 0000000000000..3722c5e4a195c
--- /dev/null
+++ b/clang/include/clang/CIR/Interfaces/CIRLoopOpInterface.h
@@ -0,0 +1,34 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===---------------------------------------------------------------------===//
+//
+// Defines the interface to generically handle CIR loop operations.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_CIR_INTERFACES_CIRLOOPOPINTERFACE_H
+#define CLANG_CIR_INTERFACES_CIRLOOPOPINTERFACE_H
+
+#include "mlir/IR/BuiltinTypes.h"
+#include "mlir/IR/OpDefinition.h"
+#include "mlir/IR/Operation.h"
+#include "mlir/Interfaces/ControlFlowInterfaces.h"
+#include "mlir/Interfaces/LoopLikeInterface.h"
+
+namespace cir {
+namespace detail {
+
+/// Verify invariants of the LoopOpInterface.
+mlir::LogicalResult verifyLoopOpInterface(::mlir::Operation *op);
+
+} // namespace detail
+} // namespace cir
+
+/// Include the tablegen'd interface declarations.
+#include "clang/CIR/Interfaces/CIRLoopOpInterface.h.inc"
+
+#endif // CLANG_CIR_INTERFACES_CIRLOOPOPINTERFACE_H
diff --git a/clang/include/clang/CIR/Interfaces/CIRLoopOpInterface.td b/clang/include/clang/CIR/Interfaces/CIRLoopOpInterface.td
new file mode 100644
index 0000000000000..cbe8adba5e9f6
--- /dev/null
+++ b/clang/include/clang/CIR/Interfaces/CIRLoopOpInterface.td
@@ -0,0 +1,99 @@
+//===---------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===---------------------------------------------------------------------===//
+
+#ifndef CLANG_CIR_INTERFACES_CIRLOOPOPINTERFACE
+#define CLANG_CIR_INTERFACES_CIRLOOPOPINTERFACE
+
+include "mlir/IR/OpBase.td"
+include "mlir/Interfaces/ControlFlowInterfaces.td"
+include "mlir/Interfaces/LoopLikeInterface.td"
+
+def LoopOpInterface : OpInterface<"LoopOpInterface", [
+ DeclareOpInterfaceMethods<RegionBranchOpInterface>,
+ DeclareOpInterfaceMethods<LoopLikeOpInterface>
+]> {
+ let description = [{
+ Contains helper functions to query properties and perform transformations
+ on a loop.
+ }];
+ let cppNamespace = "::cir";
+
+ let methods = [
+ InterfaceMethod<[{
+ Returns the loop's conditional region.
+ }],
+ /*retTy=*/"mlir::Region &",
+ /*methodName=*/"getCond"
+ >,
+ InterfaceMethod<[{
+ Returns the loop's body region.
+ }],
+ /*retTy=*/"mlir::Region &",
+ /*methodName=*/"getBody"
+ >,
+ InterfaceMethod<[{
+ Returns a pointer to the loop's step region or nullptr.
+ }],
+ /*retTy=*/"mlir::Region *",
+ /*methodName=*/"maybeGetStep",
+ /*args=*/(ins),
+ /*methodBody=*/"",
+ /*defaultImplementation=*/"return nullptr;"
+ >,
+ InterfaceMethod<[{
+ Returns the first region to be executed in the loop.
+ }],
+ /*retTy=*/"mlir::Region &",
+ /*methodName=*/"getEntry",
+ /*args=*/(ins),
+ /*methodBody=*/"",
+ /*defaultImplementation=*/"return $_op.getCond();"
+ >,
+ InterfaceMethod<[{
+ Returns a list of regions in order of execution.
+ }],
+ /*retTy=*/"llvm::SmallVector<mlir::Region *>",
+ /*methodName=*/"getRegionsInExecutionOrder",
+ /*args=*/(ins),
+ /*methodBody=*/"",
+ /*defaultImplementation=*/[{
+ return llvm::SmallVector<mlir::Region *, 2>{&$_op.getRegion(0), &$_op.getRegion(1)};
+ }]
+ >,
+ InterfaceMethod<[{
+ Recursively walks the body of the loop in pre-order while skipping
+ nested loops and executing a callback on every other operation.
+ }],
+ /*retTy=*/"mlir::WalkResult",
+ /*methodName=*/"walkBodySkippingNestedLoops",
+ /*args=*/(ins "::llvm::function_ref<mlir::WalkResult (mlir::Operation *)>":$callback),
+ /*methodBody=*/"",
+ /*defaultImplementation=*/[{
+ return $_op.getBody().template walk<mlir::WalkOrder::PreOrder>([&](mlir::Operation *op) {
+ if (mlir::isa<LoopOpInterface>(op))
+ return mlir::WalkResult::skip();
+ return callback(op);
+ });
+ }]
+ >
+ ];
+
+ let extraClassDeclaration = [{
+ /// Generic method to retrieve the successors of a LoopOpInterface operation.
+ static void getLoopOpSuccessorRegions(
+ ::cir::LoopOpInterface op, ::mlir::RegionBranchPoint point,
+ ::mlir::SmallVectorImpl<::mlir::RegionSuccessor> ®ions);
+ }];
+
+ let verify = [{
+ /// Verify invariants of the LoopOpInterface.
+ return detail::verifyLoopOpInterface($_op);
+ }];
+}
+
+#endif // CLANG_CIR_INTERFACES_CIRLOOPOPINTERFACE
diff --git a/clang/include/clang/CIR/Interfaces/CMakeLists.txt b/clang/include/clang/CIR/Interfaces/CMakeLists.txt
index e9929f6964605..3c155193235d7 100644
--- a/clang/include/clang/CIR/Interfaces/CMakeLists.txt
+++ b/clang/include/clang/CIR/Interfaces/CMakeLists.txt
@@ -20,4 +20,5 @@ function(add_clang_mlir_type_interface interface)
endfunction()
add_clang_mlir_op_interface(CIROpInterfaces)
+add_clang_mlir_op_interface(CIRLoopOpInterface)
add_clang_mlir_type_interface(CIRFPTypeInterface)
diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h
index d276af5686995..144d7d0f853d1 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -72,6 +72,9 @@ struct MissingFeatures {
static bool opFuncLinkage() { return false; }
static bool opFuncVisibility() { return false; }
+ // ScopeOp handling
+ static bool opScopeCleanupRegion() { return false; }
+
// Unary operator handling
static bool opUnarySignedOverflow() { return false; }
static bool opUnaryPromotionType() { return false; }
@@ -90,12 +93,16 @@ struct MissingFeatures {
static bool stackSaveOp() { return false; }
static bool aggValueSlot() { return false; }
static bool generateDebugInfo() { return false; }
-
static bool fpConstraints() { return false; }
static bool sanitizers() { return false; }
static bool addHeapAllocSiteMetadata() { return false; }
static bool targetCodeGenInfoGetNullPointer() { return false; }
static bool CGFPOptionsRAII() { return false; }
+ static bool loopInfoStack() { return false; }
+ static bool requiresCleanups() { return false; }
+ static bool createProfileWeightsForLoop() { return false; }
+ static bool emitCondLikelihoodViaExpectIntrinsic() { return false; }
+ static bool pgoUse() { return false; }
// Missing types
static bool dataMemberType() { return false; }
@@ -106,16 +113,21 @@ struct MissingFeatures {
static bool vectorType() { return false; }
// Future CIR operations
+ static bool awaitOp() { return false; }
+ static bool breakOp() { return false; }
+ static bool callOp() { return false; }
+ static bool complexCreateOp() { return false; }
+ static bool complexImagOp() { return false; }
+ static bool complexRealOp() { return false; }
+ static bool continueOp() { return false; }
+ static bool ifOp() { return false; }
static bool labelOp() { return false; }
- static bool brCondOp() { return false; }
+ static bool selectOp() { return false; }
static bool switchOp() { return false; }
+ static bool ternaryOp() { return false; }
static bool tryOp() { return false; }
static bool unaryOp() { return false; }
- static bool selectOp() { return false; }
- static bool complexCreateOp() { return false; }
- static bool complexRealOp() { return false; }
- static bool complexImagOp() { return false; }
- static bool callOp() { return false; }
+ static bool zextOp() { return false; }
};
} // namespace cir
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index 1c529b9efc84b..306130b80d457 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -165,6 +165,25 @@ LValue CIRGenFunction::emitDeclRefLValue(const DeclRefExpr *e) {
return LValue();
}
+mlir::Value CIRGenFunction::evaluateExprAsBool(const Expr *e) {
+ QualType boolTy = getContext().BoolTy;
+ SourceLocation loc = e->getExprLoc();
+
+ assert(!cir::MissingFeatures::pgoUse());
+ if (const MemberPointerType *MPT = e->getType()->getAs<MemberPointerType>()) {
+ cgm.errorNYI(e->getSourceRange(),
+ "evaluateExprAsBool: member pointer type");
+ return createDummyValue(getLoc(loc), boolTy);
+ }
+
+ assert(!cir::MissingFeatures::CGFPOptionsRAII());
+ if (!e->getType()->isAnyComplexType())
+ return emitScalarConversion(emitScalarExpr(e), e->getType(), boolTy, loc);
+
+ cgm.errorNYI(e->getSourceRange(), "evaluateExprAsBool: complex type");
+ return createDummyValue(getLoc(loc), boolTy);
+}
+
LValue CIRGenFunction::emitUnaryOpLValue(const UnaryOperator *e) {
UnaryOperatorKind op = e->getOpcode();
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index 726062b805775..ca0090f8d35b3 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -742,6 +742,16 @@ mlir::Value ScalarExprEmitter::VisitCastExpr(CastExpr *ce) {
return {};
}
+mlir::Value CIRGenFunction::emitScalarConversion(mlir::Value src,
+ QualType srcTy, QualType dstTy,
+ SourceLocation loc) {
+ assert(CIRGenFunction::hasScalarEvaluationKind(srcTy) &&
+ CIRGenFunction::hasScalarEvaluationKind(dstTy) &&
+ "Invalid scalar expression to emit");
+ return ScalarExprEmitter(*this, builder)
+ .emitScalarConversion(src, srcTy, dstTy, loc);
+}
+
/// Return the size or alignment of the type of argument of the sizeof
/// expression as an integer.
mlir::Value ScalarExprEmitter::VisitUnaryExprOrTypeTraitExpr(
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index ba05fb46a3c46..631217cf67762 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -175,6 +175,9 @@ class CIRGenFunction : public CIRGenTypeCache {
void finishFunction(SourceLocation endLoc);
mlir::LogicalResult emitFunctionBody(const clang::Stmt *body);
+ /// Build a debug stoppoint if we are emitting debug info.
+ void emitStopPoint(const Stmt *s);
+
// Build CIR for a statement. useCurrentScope should be true if no
// new scopes need be created when finding a compound statement.
mlir::LogicalResult
@@ -184,6 +187,8 @@ class CIRGenFunction : public CIRGenTypeCache {
mlir::LogicalResult emitSimpleStmt(const clang::Stmt *s,
bool useCurrentScope);
+ m...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/132266
More information about the cfe-commits
mailing list