[clang] [CIR] Upstream basic alloca and load support (PR #128792)

via cfe-commits cfe-commits at lists.llvm.org
Tue Feb 25 16:14:15 PST 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clangir

Author: Andy Kaylor (andykaylor)

<details>
<summary>Changes</summary>

This change implements basic support in ClangIR for local variables using the cir.alloca and cir.load operations.

---

Patch is 42.22 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/128792.diff


18 Files Affected:

- (modified) clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h (+44) 
- (modified) clang/include/clang/CIR/Dialect/IR/CIRAttrs.td (+15) 
- (modified) clang/include/clang/CIR/Dialect/IR/CIROps.td (+143) 
- (modified) clang/include/clang/CIR/MissingFeatures.h (+18) 
- (added) clang/lib/CIR/CodeGen/Address.h (+76) 
- (added) clang/lib/CIR/CodeGen/CIRGenDecl.cpp (+82) 
- (added) clang/lib/CIR/CodeGen/CIRGenExpr.cpp (+128) 
- (modified) clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp (+66) 
- (modified) clang/lib/CIR/CodeGen/CIRGenFunction.cpp (+17) 
- (modified) clang/lib/CIR/CodeGen/CIRGenFunction.h (+61-1) 
- (modified) clang/lib/CIR/CodeGen/CIRGenModule.h (+5) 
- (modified) clang/lib/CIR/CodeGen/CIRGenStmt.cpp (+12) 
- (added) clang/lib/CIR/CodeGen/CIRGenValue.h (+125) 
- (modified) clang/lib/CIR/CodeGen/CMakeLists.txt (+2) 
- (modified) clang/lib/CIR/Dialect/IR/CIRDialect.cpp (+18) 
- (added) clang/lib/CIR/Dialect/IR/CIRMemorySlot.cpp (+77) 
- (modified) clang/lib/CIR/Dialect/IR/CMakeLists.txt (+1) 
- (added) clang/test/CIR/CodeGen/basic.cpp (+13) 


``````````diff
diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index f03241a875845..a62b00cc8ed33 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -9,6 +9,7 @@
 #ifndef LLVM_CLANG_CIR_DIALECT_BUILDER_CIRBASEBUILDER_H
 #define LLVM_CLANG_CIR_DIALECT_BUILDER_CIRBASEBUILDER_H
 
+#include "clang/AST/CharUnits.h"
 #include "clang/CIR/Dialect/IR/CIRAttrs.h"
 #include "clang/CIR/Dialect/IR/CIRDialect.h"
 #include "clang/CIR/Dialect/IR/CIRTypes.h"
@@ -51,6 +52,49 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
     return cir::ConstPtrAttr::get(
         getContext(), mlir::cast<cir::PointerType>(type), valueAttr);
   }
+
+  mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType,
+                           mlir::Type type, llvm::StringRef name,
+                           mlir::IntegerAttr alignment,
+                           mlir::Value dynAllocSize) {
+    return create<cir::AllocaOp>(loc, addrType, type, name, alignment,
+                                 dynAllocSize);
+  }
+
+  cir::LoadOp createLoad(mlir::Location loc, mlir::Value ptr,
+                         bool isVolatile = false, uint64_t alignment = 0) {
+    mlir::IntegerAttr intAttr;
+    if (alignment)
+      intAttr = mlir::IntegerAttr::get(
+          mlir::IntegerType::get(ptr.getContext(), 64), alignment);
+
+    return create<cir::LoadOp>(loc, ptr);
+  }
+
+  //
+  // Block handling helpers
+  // ----------------------
+  //
+  static OpBuilder::InsertPoint getBestAllocaInsertPoint(mlir::Block *block) {
+    auto last =
+        std::find_if(block->rbegin(), block->rend(), [](mlir::Operation &op) {
+          // TODO: Add LabelOp missing feature here
+          return mlir::isa<cir::AllocaOp>(&op);
+        });
+
+    if (last != block->rend())
+      return OpBuilder::InsertPoint(block, ++mlir::Block::iterator(&*last));
+    return OpBuilder::InsertPoint(block, block->begin());
+  };
+
+  mlir::IntegerAttr getSizeFromCharUnits(mlir::MLIRContext *ctx,
+                                         clang::CharUnits size) {
+    // Note that mlir::IntegerType is used instead of cir::IntType here
+    // because we don't need sign information for this to be useful, so keep
+    // it simple.
+    return mlir::IntegerAttr::get(mlir::IntegerType::get(ctx, 64),
+                                  size.getQuantity());
+  }
 };
 
 } // namespace cir
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
index 097616ba06749..ece04c225e322 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
@@ -54,6 +54,21 @@ def CIR_BoolAttr : CIR_Attr<"Bool", "bool", [TypedAttrInterface]> {
   }];
 }
 
+//===----------------------------------------------------------------------===//
+// UndefAttr
+//===----------------------------------------------------------------------===//
+
+def UndefAttr : CIR_Attr<"Undef", "undef", [TypedAttrInterface]> {
+  let summary = "Represent an undef constant";
+  let description = [{
+    The UndefAttr represents an undef constant, corresponding to LLVM's notion
+    of undef.
+  }];
+
+  let parameters = (ins AttributeSelfTypeParameter<"">:$type);
+  let assemblyFormat = [{}];
+}
+
 //===----------------------------------------------------------------------===//
 // IntegerAttr
 //===----------------------------------------------------------------------===//
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 45d39807b35c8..1ff5e215c10a0 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -115,6 +115,149 @@ def ConstantOp : CIR_Op<"const",
   let hasFolder = 1;
 }
 
+//===----------------------------------------------------------------------===//
+// AllocaOp
+//===----------------------------------------------------------------------===//
+
+class AllocaTypesMatchWith<string summary, string lhsArg, string rhsArg,
+                     string transform, string comparator = "std::equal_to<>()">
+  : PredOpTrait<summary, CPred<
+      comparator # "(" #
+      !subst("$_self", "$" # lhsArg # ".getType()", transform) #
+             ", $" # rhsArg # ")">> {
+  string lhs = lhsArg;
+  string rhs = rhsArg;
+  string transformer = transform;
+}
+
+def AllocaOp : CIR_Op<"alloca", [
+  AllocaTypesMatchWith<"'allocaType' matches pointee type of 'addr'",
+                 "addr", "allocaType",
+                 "cast<PointerType>($_self).getPointee()">,
+                 DeclareOpInterfaceMethods<PromotableAllocationOpInterface>]> {
+  let summary = "Defines a scope-local variable";
+  let description = [{
+    The `cir.alloca` operation defines a scope-local variable.
+
+    The presence `init` attribute indicates that the local variable represented
+    by this alloca was originally initialized in C/C++ source code. In such
+    cases, the first use contains the initialization (a cir.store, a cir.call
+    to a ctor, etc).
+
+    The presence of the `const` attribute indicates that the local variable is
+    declared with C/C++ `const` keyword.
+
+    The `dynAllocSize` specifies the size to dynamically allocate on the stack
+    and ignores the allocation size based on the original type. This is useful
+    when handling VLAs and is omitted when declaring regular local variables.
+
+    The result type is a pointer to the input's type.
+
+    Example:
+
+    ```mlir
+    // int count = 3;
+    %0 = cir.alloca i32, !cir.ptr<i32>, ["count", init] {alignment = 4 : i64}
+
+    // int *ptr;
+    %1 = cir.alloca !cir.ptr<i32>, !cir.ptr<!cir.ptr<i32>>, ["ptr"] {alignment = 8 : i64}
+    ...
+    ```
+  }];
+
+  let arguments = (ins
+    Optional<PrimitiveInt>:$dynAllocSize,
+    TypeAttr:$allocaType,
+    StrAttr:$name,
+    UnitAttr:$init,
+    UnitAttr:$constant,
+    ConfinedAttr<OptionalAttr<I64Attr>, [IntMinValue<0>]>:$alignment,
+    OptionalAttr<ArrayAttr>:$annotations
+  );
+
+  let results = (outs Res<CIR_PointerType, "",
+                      [MemAlloc<AutomaticAllocationScopeResource>]>:$addr);
+
+  let skipDefaultBuilders = 1;
+  let builders = [
+    OpBuilder<(ins "mlir::Type":$addr, "mlir::Type":$allocaType,
+                   "llvm::StringRef":$name,
+                   "mlir::IntegerAttr":$alignment)>,
+
+    OpBuilder<(ins "mlir::Type":$addr,
+                   "mlir::Type":$allocaType,
+                   "llvm::StringRef":$name,
+                   "mlir::IntegerAttr":$alignment,
+                   "mlir::Value":$dynAllocSize),
+    [{
+      if (dynAllocSize)
+        $_state.addOperands(dynAllocSize);
+      build($_builder, $_state, addr, allocaType, name, alignment);
+    }]>
+  ];
+
+  let extraClassDeclaration = [{
+    // Whether the alloca input type is a pointer.
+    bool isPointerType() { return ::mlir::isa<::cir::PointerType>(getAllocaType()); }
+
+    bool isDynamic() { return (bool)getDynAllocSize(); }
+  }];
+
+  let assemblyFormat = [{
+    $allocaType `,` qualified(type($addr)) `,`
+    ($dynAllocSize^ `:` type($dynAllocSize) `,`)?
+    `[` $name
+       (`,` `init` $init^)?
+       (`,` `const` $constant^)?
+    `]`
+    ($annotations^)? attr-dict
+  }];
+
+  let hasVerifier = 0;
+}
+
+//===----------------------------------------------------------------------===//
+// LoadOp
+//===----------------------------------------------------------------------===//
+
+def LoadOp : CIR_Op<"load", [
+  TypesMatchWith<"type of 'result' matches pointee type of 'addr'",
+                 "addr", "result",
+                 "cast<PointerType>($_self).getPointee()">,
+                 DeclareOpInterfaceMethods<PromotableMemOpInterface>]> {
+
+  let summary = "Load value from memory adddress";
+  let description = [{
+    `cir.load` reads a value (lvalue to rvalue conversion) given an address
+    backed up by a `cir.ptr` type. A unit attribute `deref` can be used to
+    mark the resulting value as used by another operation to dereference
+    a pointer. A unit attribute `volatile` can be used to indicate a volatile
+    loading. Load can be marked atomic by using `atomic(<mem_order>)`.
+
+    `align` can be used to specify an alignment that's different from the
+    default, which is computed from `result`'s type ABI data layout.
+
+    Example:
+
+    ```mlir
+
+    // Read from local variable, address in %0.
+    %1 = cir.load %0 : !cir.ptr<i32>, i32
+    ```
+  }];
+
+  let arguments = (ins Arg<CIR_PointerType, "the address to load from",
+                           [MemRead]>:$addr
+                       );
+  let results = (outs CIR_AnyType:$result);
+
+  let assemblyFormat = [{
+    $addr `:` qualified(type($addr)) `,` type($result) attr-dict
+  }];
+
+  // FIXME: add verifier.
+}
+
 //===----------------------------------------------------------------------===//
 // ReturnOp
 //===----------------------------------------------------------------------===//
diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h
index d4fcd52e7e6e3..97e919b5c2d74 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -36,6 +36,24 @@ struct MissingFeatures {
   static bool opGlobalConstant() { return false; }
   static bool opGlobalAlignment() { return false; }
   static bool opGlobalLinkage() { return false; }
+
+  // Load attributes
+  static bool opLoadThreadLocal() { return false; }
+  static bool opLoadEmitScalarRangeCheck() { return false; }
+  static bool opLoadBooleanRepresentation() { return false; }
+
+  // AllocaOp handling
+  static bool opAllocaVarDeclContext() { return false; }
+  static bool opAllocaStaticLocal() { return false; }
+  static bool opAllocaNonGC() { return false; }
+  static bool opAllocaImpreciseLifetime() { return false; }
+  static bool opAllocaTLS() { return false; }
+  static bool opAllocaOpenMPThreadPrivate() { return false; }
+  static bool opAllocaEscapeByReference() { return false; }
+  static bool opAllocaReference() { return false; }
+
+  // Options for casts
+  static bool scalarConversionOpts() { return false; }
 };
 
 } // namespace cir
diff --git a/clang/lib/CIR/CodeGen/Address.h b/clang/lib/CIR/CodeGen/Address.h
new file mode 100644
index 0000000000000..c68facde9a18c
--- /dev/null
+++ b/clang/lib/CIR/CodeGen/Address.h
@@ -0,0 +1,76 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This class provides a simple wrapper for a pair of a pointer and an
+// alignment.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_CIR_ADDRESS_H
+#define LLVM_CLANG_LIB_CIR_ADDRESS_H
+
+#include "mlir/IR/Value.h"
+#include "clang/AST/CharUnits.h"
+#include "clang/CIR/Dialect/IR/CIRTypes.h"
+#include "llvm/ADT/PointerIntPair.h"
+
+namespace clang::CIRGen {
+
+class Address {
+
+  // The boolean flag indicates whether the pointer is known to be non-null.
+  llvm::PointerIntPair<mlir::Value, 1, bool> pointerAndKnownNonNull;
+
+  /// The expected CIR type of the pointer. Carrying accurate element type
+  /// information in Address makes it more convenient to work with Address
+  /// values and allows frontend assertions to catch simple mistakes.
+  mlir::Type elementType;
+
+  clang::CharUnits alignment;
+
+protected:
+  Address(std::nullptr_t) : elementType(nullptr) {}
+
+public:
+  Address(mlir::Value pointer, mlir::Type elementType,
+          clang::CharUnits alignment)
+      : pointerAndKnownNonNull(pointer, false), elementType(elementType),
+        alignment(alignment) {
+    assert(mlir::isa<cir::PointerType>(pointer.getType()) &&
+           "Expected cir.ptr type");
+
+    assert(pointer && "Pointer cannot be null");
+    assert(elementType && "Element type cannot be null");
+    assert(!alignment.isZero() && "Alignment cannot be zero");
+
+    assert(mlir::cast<cir::PointerType>(pointer.getType()).getPointee() ==
+           elementType);
+  }
+
+  static Address invalid() { return Address(nullptr); }
+  bool isValid() const {
+    return pointerAndKnownNonNull.getPointer() != nullptr;
+  }
+
+  mlir::Value getPointer() const {
+    assert(isValid());
+    return pointerAndKnownNonNull.getPointer();
+  }
+
+  mlir::Type getElementType() const {
+    assert(isValid());
+    assert(mlir::cast<cir::PointerType>(
+               pointerAndKnownNonNull.getPointer().getType())
+               .getPointee() == elementType);
+    return elementType;
+  }
+};
+
+} // namespace clang::CIRGen
+
+#endif // LLVM_CLANG_LIB_CIR_ADDRESS_H
diff --git a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
new file mode 100644
index 0000000000000..34e0b18594efe
--- /dev/null
+++ b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
@@ -0,0 +1,82 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This contains code to emit Decl nodes as CIR code.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CIRGenFunction.h"
+#include "clang/AST/Expr.h"
+#include "clang/CIR/MissingFeatures.h"
+
+using namespace clang;
+using namespace clang::CIRGen;
+
+/// Emit code and set up symbol table for a variable declaration with auto,
+/// register, or no storage class specifier. These turn into simple stack
+/// objects, globals depending on target.
+void CIRGenFunction::emitAutoVarDecl(const VarDecl &d) {
+  QualType ty = d.getType();
+  assert(ty.getAddressSpace() == LangAS::Default);
+
+  auto loc = getLoc(d.getSourceRange());
+
+  if (d.isEscapingByref())
+    cgm.errorNYI(d.getSourceRange(),
+                 "emitAutoVarDecl: decl escaping by reference");
+
+  CharUnits alignment = getContext().getDeclAlign(&d);
+
+  // If the type is variably-modified, emit all the VLA sizes for it.
+  if (ty->isVariablyModifiedType())
+    cgm.errorNYI(d.getSourceRange(), "emitAutoVarDecl: variably modified type");
+
+  Address address = Address::invalid();
+  if (!ty->isConstantSizeType())
+    cgm.errorNYI(d.getSourceRange(), "emitAutoVarDecl: non-constant size type");
+
+  // A normal fixed sized variable becomes an alloca in the entry block,
+  mlir::Type allocaTy = convertTypeForMem(ty);
+  // Create the temp alloca and declare variable using it.
+  mlir::Value addrVal;
+  address = createTempAlloca(allocaTy, alignment, loc, d.getName(),
+                             /*ArraySize=*/nullptr);
+  setAddrOfLocalVar(&d, address);
+  // TODO: emit var init and cleanup
+}
+
+void CIRGenFunction::emitVarDecl(const VarDecl &d) {
+  if (d.hasExternalStorage()) {
+    // Don't emit it now, allow it to be emitted lazily on its first use.
+    return;
+  }
+
+  if (d.getStorageDuration() != SD_Automatic)
+    cgm.errorNYI(d.getSourceRange(), "emitVarDecl automatic storage duration");
+  if (d.getType().getAddressSpace() == LangAS::opencl_local)
+    cgm.errorNYI(d.getSourceRange(), "emitVarDecl openCL address space");
+
+  assert(d.hasLocalStorage());
+
+  assert(!cir::MissingFeatures::opAllocaVarDeclContext());
+  return emitAutoVarDecl(d);
+}
+
+void CIRGenFunction::emitDecl(const Decl &d) {
+  switch (d.getKind()) {
+  case Decl::Var: {
+    const VarDecl &vd = cast<VarDecl>(d);
+    assert(vd.isLocalVarDecl() &&
+           "Should not see file-scope variables inside a function!");
+    emitVarDecl(vd);
+    return;
+  }
+  default:
+    cgm.errorNYI(d.getSourceRange(), "emitDecl: unhandled decl type");
+  }
+}
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
new file mode 100644
index 0000000000000..8bb670d0d5bae
--- /dev/null
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -0,0 +1,128 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This contains code to emit Expr nodes as CIR code.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Address.h"
+#include "CIRGenFunction.h"
+#include "CIRGenValue.h"
+#include "clang/AST/Attr.h"
+#include "clang/AST/CharUnits.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/CIR/Dialect/IR/CIRDialect.h"
+#include "clang/CIR/MissingFeatures.h"
+
+using namespace clang;
+using namespace clang::CIRGen;
+using namespace cir;
+
+mlir::Value CIRGenFunction::emitLoadOfScalar(LValue lvalue,
+                                             SourceLocation loc) {
+  assert(!cir::MissingFeatures::opLoadThreadLocal());
+  assert(!cir::MissingFeatures::opLoadEmitScalarRangeCheck());
+  assert(!cir::MissingFeatures::opLoadBooleanRepresentation());
+
+  Address addr = lvalue.getAddress();
+  mlir::Type eltTy = addr.getElementType();
+
+  auto ptr = addr.getPointer();
+  if (mlir::isa<cir::VoidType>(eltTy))
+    cgm.errorNYI(loc, "emitLoadOfScalar: void type");
+
+  auto loadOp = builder.CIRBaseBuilderTy::createLoad(getLoc(loc), ptr,
+                                                     false /*isVolatile*/);
+
+  return loadOp;
+}
+
+/// Given an expression that represents a value lvalue, this
+/// method emits the address of the lvalue, then loads the result as an rvalue,
+/// returning the rvalue.
+RValue CIRGenFunction::emitLoadOfLValue(LValue lv, SourceLocation loc) {
+  assert(!lv.getType()->isFunctionType());
+  assert(!(lv.getType()->isConstantMatrixType()) && "not implemented");
+
+  if (lv.isSimple())
+    return RValue::get(emitLoadOfScalar(lv, loc));
+
+  cgm.errorNYI(loc, "emitLoadOfLValue");
+}
+
+LValue CIRGenFunction::emitDeclRefLValue(const DeclRefExpr *e) {
+  const NamedDecl *nd = e->getDecl();
+  QualType ty = e->getType();
+
+  assert(e->isNonOdrUse() != NOUR_Unevaluated &&
+         "should not emit an unevaluated operand");
+
+  if (const auto *vd = dyn_cast<VarDecl>(nd)) {
+    // Checks for omitted feature handling
+    assert(!cir::MissingFeatures::opAllocaStaticLocal());
+    assert(!cir::MissingFeatures::opAllocaNonGC());
+    assert(!cir::MissingFeatures::opAllocaImpreciseLifetime());
+    assert(!cir::MissingFeatures::opAllocaTLS());
+    assert(!cir::MissingFeatures::opAllocaOpenMPThreadPrivate());
+    assert(!cir::MissingFeatures::opAllocaEscapeByReference());
+
+    // Check if this is a global variable
+    if (vd->hasLinkage() || vd->isStaticDataMember())
+      cgm.errorNYI(vd->getSourceRange(), "emitDeclRefLValue: global variable");
+
+    Address addr = Address::invalid();
+
+    // The variable should generally be present in the local decl map.
+    auto iter = LocalDeclMap.find(vd);
+    if (iter != LocalDeclMap.end()) {
+      addr = iter->second;
+    } else {
+      // Otherwise, it might be static local we haven't emitted yet for some
+      // reason; most likely, because it's in an outer function.
+      cgm.errorNYI(vd->getSourceRange(), "emitDeclRefLValue: static local");
+    }
+
+    return LValue::makeAddr(addr, ty);
+  }
+
+  cgm.errorNYI(e->getSourceRange(), "emitDeclRefLValue: unhandled decl type");
+}
+
+mlir::Value CIRGenFunction::emitAlloca(StringRef name, mlir::Type ty,
+                                       mlir::Location loc, CharUnits alignment,
+                                       mlir::Value arraySize) {
+  mlir::Block *entryBlock = getCurFunctionEntryBlock();
+
+  // CIR uses its own alloca AS rather than follow the target data layout like
+  // original CodeGen. The data layout awareness should be done in the lowering
+  // pass instead.
+  a...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/128792


More information about the cfe-commits mailing list