[clang] [CIR] [Upstream local initialization for ArrayType (PR #132974)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Mar 25 12:10:29 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clangir
Author: Amr Hesham (AmrDeveloper)
<details>
<summary>Changes</summary>
This change adds local initialization for ArrayType
Issue #<!-- -->130197
---
Patch is 59.03 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/132974.diff
25 Files Affected:
- (modified) clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h (+35)
- (modified) clang/include/clang/CIR/Dialect/IR/CIRDialect.h (+25)
- (modified) clang/include/clang/CIR/Dialect/IR/CIROps.td (+44)
- (added) clang/include/clang/CIR/LoweringHelpers.h (+40)
- (modified) clang/lib/CIR/CodeGen/Address.h (+10)
- (modified) clang/lib/CIR/CodeGen/CIRGenBuilder.h (+4)
- (modified) clang/lib/CIR/CodeGen/CIRGenDecl.cpp (+1-1)
- (added) clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp (+277)
- (modified) clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp (+23)
- (modified) clang/lib/CIR/CodeGen/CIRGenFunction.cpp (+46)
- (modified) clang/lib/CIR/CodeGen/CIRGenFunction.h (+8-4)
- (modified) clang/lib/CIR/CodeGen/CIRGenModule.cpp (+12)
- (modified) clang/lib/CIR/CodeGen/CIRGenModule.h (+5)
- (modified) clang/lib/CIR/CodeGen/CIRGenTypeCache.h (+13)
- (modified) clang/lib/CIR/CodeGen/CIRGenTypes.cpp (+24)
- (modified) clang/lib/CIR/CodeGen/CIRGenTypes.h (+4)
- (modified) clang/lib/CIR/CodeGen/CIRGenValue.h (+42-2)
- (modified) clang/lib/CIR/CodeGen/CMakeLists.txt (+1)
- (modified) clang/lib/CIR/Dialect/IR/CIRDialect.cpp (+35-7)
- (modified) clang/lib/CIR/Lowering/CMakeLists.txt (+1)
- (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp (+109)
- (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h (+15)
- (added) clang/lib/CIR/Lowering/LoweringHelpers.cpp (+150)
- (modified) clang/test/CIR/CodeGen/array.cpp (+91-6)
- (modified) clang/test/CIR/Lowering/array.cpp (+72-5)
``````````diff
diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index c6aea10d46b63..4c7e6ec061d46 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -32,6 +32,11 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
return create<cir::ConstantOp>(loc, attr.getType(), attr);
}
+ // Creates constant null value for integral type ty.
+ cir::ConstantOp getNullValue(mlir::Type ty, mlir::Location loc) {
+ return create<cir::ConstantOp>(loc, ty, getZeroInitAttr(ty));
+ }
+
cir::ConstantOp getBool(bool state, mlir::Location loc) {
return create<cir::ConstantOp>(loc, getBoolTy(), getCIRBoolAttr(state));
}
@@ -68,6 +73,36 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
getContext(), mlir::cast<cir::PointerType>(type), valueAttr);
}
+ mlir::TypedAttr getConstNullPtrAttr(mlir::Type t) {
+ assert(mlir::isa<cir::PointerType>(t) && "expected cir.ptr");
+ return getConstPtrAttr(t, 0);
+ }
+
+ mlir::TypedAttr getZeroAttr(mlir::Type t) {
+ return cir::ZeroAttr::get(getContext(), t);
+ }
+
+ mlir::TypedAttr getZeroInitAttr(mlir::Type ty) {
+ if (mlir::isa<cir::IntType>(ty))
+ return cir::IntAttr::get(ty, 0);
+ if (auto fltType = mlir::dyn_cast<cir::SingleType>(ty))
+ return cir::FPAttr::getZero(fltType);
+ if (auto fltType = mlir::dyn_cast<cir::DoubleType>(ty))
+ return cir::FPAttr::getZero(fltType);
+ if (auto fltType = mlir::dyn_cast<cir::FP16Type>(ty))
+ return cir::FPAttr::getZero(fltType);
+ if (auto fltType = mlir::dyn_cast<cir::BF16Type>(ty))
+ return cir::FPAttr::getZero(fltType);
+ if (auto arrTy = mlir::dyn_cast<cir::ArrayType>(ty))
+ return getZeroAttr(arrTy);
+ if (auto ptrTy = mlir::dyn_cast<cir::PointerType>(ty))
+ return getConstNullPtrAttr(ptrTy);
+ if (mlir::isa<cir::BoolType>(ty)) {
+ return getCIRBoolAttr(false);
+ }
+ llvm_unreachable("Zero initializer for given type is NYI");
+ }
+
mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType,
mlir::Type type, llvm::StringRef name,
mlir::IntegerAttr alignment) {
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRDialect.h b/clang/include/clang/CIR/Dialect/IR/CIRDialect.h
index da3b41371b9ab..ba7bbedf4714e 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRDialect.h
+++ b/clang/include/clang/CIR/Dialect/IR/CIRDialect.h
@@ -32,6 +32,31 @@
#include "clang/CIR/Interfaces/CIRLoopOpInterface.h"
#include "clang/CIR/Interfaces/CIROpInterfaces.h"
+namespace mlir {
+namespace OpTrait {
+
+namespace impl {
+// These functions are out-of-line implementations of the methods in the
+// corresponding trait classes. This avoids them being template
+// instantiated/duplicated.
+LogicalResult verifySameFirstOperandAndResultType(Operation *op);
+} // namespace impl
+
+/// This class provides verification for ops that are known to have the same
+/// first operand and result type.
+///
+template <typename ConcreteType>
+class SameFirstOperandAndResultType
+ : public TraitBase<ConcreteType, SameFirstOperandAndResultType> {
+public:
+ static llvm::LogicalResult verifyTrait(Operation *op) {
+ return impl::verifySameFirstOperandAndResultType(op);
+ }
+};
+
+} // namespace OpTrait
+} // namespace mlir
+
// TableGen'erated files for MLIR dialects require that a macro be defined when
// they are included. GET_OP_CLASSES tells the file to define the classes for
// the operations of that dialect.
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index d7d63e040a2ba..7784c8a51fdf3 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -79,6 +79,13 @@ class LLVMLoweringInfo {
class CIR_Op<string mnemonic, list<Trait> traits = []> :
Op<CIR_Dialect, mnemonic, traits>, LLVMLoweringInfo;
+//===----------------------------------------------------------------------===//
+// CIR Op Traits
+//===----------------------------------------------------------------------===//
+
+def SameFirstOperandAndResultType :
+ NativeOpTrait<"SameFirstOperandAndResultType">;
+
//===----------------------------------------------------------------------===//
// CastOp
//===----------------------------------------------------------------------===//
@@ -229,6 +236,43 @@ def CastOp : CIR_Op<"cast",
let hasFolder = 1;
}
+
+//===----------------------------------------------------------------------===//
+// PtrStrideOp
+//===----------------------------------------------------------------------===//
+
+def PtrStrideOp : CIR_Op<"ptr_stride",
+ [Pure, SameFirstOperandAndResultType]> {
+ let summary = "Pointer access with stride";
+ let description = [{
+ Given a base pointer as first operand, provides a new pointer after applying
+ a stride (second operand).
+
+ ```mlir
+ %3 = cir.const 0 : i32
+ %4 = cir.ptr_stride(%2 : !cir.ptr<i32>, %3 : i32), !cir.ptr<i32>
+ ```
+ }];
+
+ let arguments = (ins CIR_PointerType:$base, PrimitiveInt:$stride);
+ let results = (outs CIR_PointerType:$result);
+
+ let assemblyFormat = [{
+ `(` $base `:` qualified(type($base)) `,` $stride `:` qualified(type($stride)) `)`
+ `,` qualified(type($result)) attr-dict
+ }];
+
+ let extraClassDeclaration = [{
+ // Get type pointed by the base pointer.
+ mlir::Type getElementTy() {
+ return mlir::cast<cir::PointerType>(getBase().getType()).getPointee();
+ }
+ }];
+
+ // SameFirstOperandAndResultType already checks all we need.
+ let hasVerifier = 0;
+}
+
//===----------------------------------------------------------------------===//
// ConstantOp
//===----------------------------------------------------------------------===//
diff --git a/clang/include/clang/CIR/LoweringHelpers.h b/clang/include/clang/CIR/LoweringHelpers.h
new file mode 100644
index 0000000000000..3077010ee5ffe
--- /dev/null
+++ b/clang/include/clang/CIR/LoweringHelpers.h
@@ -0,0 +1,40 @@
+//====- LoweringHelpers.h - Lowering helper functions ---------------------===//
+//
+// 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 file declares helper functions for lowering from CIR to LLVM or MLIR.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_CIR_LOWERINGHELPERS_H
+#define LLVM_CLANG_CIR_LOWERINGHELPERS_H
+
+#include "mlir/IR/BuiltinAttributes.h"
+#include "mlir/Transforms/DialectConversion.h"
+#include "clang/CIR/Dialect/IR/CIRDialect.h"
+
+mlir::DenseElementsAttr
+convertStringAttrToDenseElementsAttr(cir::ConstArrayAttr attr, mlir::Type type);
+
+template <typename StorageTy> StorageTy getZeroInitFromType(mlir::Type ty);
+template <> mlir::APInt getZeroInitFromType(mlir::Type ty);
+template <> mlir::APFloat getZeroInitFromType(mlir::Type ty);
+
+template <typename AttrTy, typename StorageTy>
+void convertToDenseElementsAttrImpl(cir::ConstArrayAttr attr,
+ llvm::SmallVectorImpl<StorageTy> &values);
+
+template <typename AttrTy, typename StorageTy>
+mlir::DenseElementsAttr
+convertToDenseElementsAttr(cir::ConstArrayAttr attr,
+ const llvm::SmallVectorImpl<int64_t> &dims,
+ mlir::Type type);
+
+std::optional<mlir::Attribute>
+lowerConstArrayAttr(cir::ConstArrayAttr constArr,
+ const mlir::TypeConverter *converter);
+
+#endif
diff --git a/clang/lib/CIR/CodeGen/Address.h b/clang/lib/CIR/CodeGen/Address.h
index fba1ffd90877b..2cc8ada783197 100644
--- a/clang/lib/CIR/CodeGen/Address.h
+++ b/clang/lib/CIR/CodeGen/Address.h
@@ -70,6 +70,14 @@ class Address {
return pointerAndKnownNonNull.getPointer();
}
+ mlir::Type getType() const {
+ assert(mlir::cast<cir::PointerType>(
+ pointerAndKnownNonNull.getPointer().getType())
+ .getPointee() == elementType);
+
+ return mlir::cast<cir::PointerType>(getPointer().getType());
+ }
+
mlir::Type getElementType() const {
assert(isValid());
assert(mlir::cast<cir::PointerType>(
@@ -77,6 +85,8 @@ class Address {
.getPointee() == elementType);
return elementType;
}
+
+ clang::CharUnits getAlignment() const { return alignment; }
};
} // namespace clang::CIRGen
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
index fef290612149a..d1a81f85b66fc 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h
+++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
@@ -83,6 +83,10 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
bool isInt(mlir::Type i) { return mlir::isa<cir::IntType>(i); }
+ bool isInt8Ty(mlir::Type i) {
+ return i == typeCache.UInt8Ty || i == typeCache.SInt8Ty;
+ }
+
// Creates constant nullptr for pointer type ty.
cir::ConstantOp getNullPtr(mlir::Type ty, mlir::Location loc) {
assert(!cir::MissingFeatures::targetCodeGenInfoGetNullPointer());
diff --git a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
index a93e8dbcb42de..a0c6b832faa24 100644
--- a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
@@ -250,7 +250,7 @@ void CIRGenFunction::emitExprAsInit(const Expr *init, const ValueDecl *d,
return;
}
case cir::TEK_Aggregate:
- cgm.errorNYI(init->getSourceRange(), "emitExprAsInit: aggregate type");
+ emitAggExpr(init, AggValueSlot::forLValue(lvalue));
return;
}
llvm_unreachable("bad evaluation kind");
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
new file mode 100644
index 0000000000000..3bd898422f4d6
--- /dev/null
+++ b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
@@ -0,0 +1,277 @@
+//===--- CIRGenExprAgg.cpp - Emit CIR Code from Aggregate Expressions -----===//
+//
+// 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 Aggregate Expr nodes as CIR code.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CIRGenBuilder.h"
+#include "CIRGenFunction.h"
+#include "CIRGenValue.h"
+#include "clang/CIR/Dialect/IR/CIRAttrs.h"
+
+#include "clang/AST/Expr.h"
+#include "clang/AST/StmtVisitor.h"
+#include <cstdint>
+
+using namespace clang;
+using namespace clang::CIRGen;
+
+namespace {
+class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
+
+ CIRGenFunction &cgf;
+ AggValueSlot dest;
+
+ AggValueSlot ensureSlot(mlir::Location loc, QualType t) {
+ if (!dest.isIgnored())
+ return dest;
+ llvm_unreachable("Slot for ignored address NTI");
+ }
+
+public:
+ AggExprEmitter(CIRGenFunction &cgf, AggValueSlot dest)
+ : cgf(cgf), dest(dest) {}
+
+ void emitArrayInit(Address destPtr, cir::ArrayType arrayTy, QualType arrayQTy,
+ Expr *exprToVisit, ArrayRef<Expr *> args,
+ Expr *arrayFiller);
+
+ void emitInitializationToLValue(Expr *e, LValue lv);
+
+ void emitNullInitializationToLValue(mlir::Location loc, LValue lv);
+
+ void Visit(Expr *e) { StmtVisitor<AggExprEmitter>::Visit(e); }
+
+ void VisitInitListExpr(InitListExpr *e);
+
+ void visitCXXParenListOrInitListExpr(Expr *e, ArrayRef<Expr *> args,
+ FieldDecl *initializedFieldInUnion,
+ Expr *arrayFiller);
+};
+
+} // namespace
+
+static bool isTrivialFiller(Expr *e) {
+ if (!e)
+ return true;
+
+ if (isa<ImplicitValueInitExpr>(e))
+ return true;
+
+ if (auto *ile = dyn_cast<InitListExpr>(e)) {
+ if (ile->getNumInits())
+ return false;
+ return isTrivialFiller(ile->getArrayFiller());
+ }
+
+ if (const auto *cons = dyn_cast_or_null<CXXConstructExpr>(e))
+ return cons->getConstructor()->isDefaultConstructor() &&
+ cons->getConstructor()->isTrivial();
+
+ return false;
+}
+
+void AggExprEmitter::emitArrayInit(Address destPtr, cir::ArrayType arrayTy,
+ QualType arrayQTy, Expr *e,
+ ArrayRef<Expr *> args, Expr *arrayFiller) {
+ CIRGenBuilderTy &builder = cgf.getBuilder();
+ const mlir::Location loc = cgf.getLoc(e->getSourceRange());
+
+ const uint64_t numInitElements = args.size();
+
+ const QualType elementType =
+ cgf.getContext().getAsArrayType(arrayQTy)->getElementType();
+
+ if (elementType.isDestructedType()) {
+ llvm_unreachable("dtorKind NYI");
+ }
+
+ const QualType elementPtrType = cgf.getContext().getPointerType(elementType);
+
+ const mlir::Type cirElementType = cgf.convertType(elementType);
+ const cir::PointerType cirElementPtrType =
+ builder.getPointerTo(cirElementType);
+
+ auto begin = builder.create<cir::CastOp>(loc, cirElementPtrType,
+ cir::CastKind::array_to_ptrdecay,
+ destPtr.getPointer());
+
+ const CharUnits elementSize =
+ cgf.getContext().getTypeSizeInChars(elementType);
+ const CharUnits elementAlign =
+ destPtr.getAlignment().alignmentOfArrayElement(elementSize);
+
+ // The 'current element to initialize'. The invariants on this
+ // variable are complicated. Essentially, after each iteration of
+ // the loop, it points to the last initialized element, except
+ // that it points to the beginning of the array before any
+ // elements have been initialized.
+ mlir::Value element = begin;
+
+ // Don't build the 'one' before the cycle to avoid
+ // emmiting the redundant `cir.const 1` instrs.
+ mlir::Value one;
+
+ // Emit the explicit initializers.
+ for (uint64_t i = 0; i != numInitElements; ++i) {
+ // Advance to the next element.
+ if (i > 0) {
+ one = builder.create<cir::ConstantOp>(
+ loc, cgf.PtrDiffTy, cir::IntAttr::get(cgf.PtrDiffTy, i));
+ element =
+ builder.create<cir::PtrStrideOp>(loc, cirElementPtrType, begin, one);
+ }
+
+ const Address address = Address(element, cirElementType, elementAlign);
+ const LValue elementLV = LValue::makeAddr(address, elementType);
+ emitInitializationToLValue(args[i], elementLV);
+ }
+
+ const uint64_t numArrayElements = arrayTy.getSize();
+
+ // Check whether there's a non-trivial array-fill expression.
+ const bool hasTrivialFiller = isTrivialFiller(arrayFiller);
+
+ // Any remaining elements need to be zero-initialized, possibly
+ // using the filler expression. We can skip this if the we're
+ // emitting to zeroed memory.
+ if (numInitElements != numArrayElements &&
+ !(dest.isZeroed() && hasTrivialFiller &&
+ cgf.getTypes().isZeroInitializable(elementType))) {
+ // Advance to the start of the rest of the array.
+ if (numInitElements) {
+ one = builder.create<cir::ConstantOp>(
+ loc, cgf.PtrDiffTy, cir::IntAttr::get(cgf.PtrDiffTy, 1));
+ element = builder.create<cir::PtrStrideOp>(loc, cirElementPtrType,
+ element, one);
+ }
+
+ // Allocate the temporary variable
+ // to store the pointer to first unitialized element
+ auto tmpAddr = cgf.createTempAlloca(
+ cirElementPtrType, cgf.getPointerAlign(), loc, "arrayinit.temp");
+ LValue tmpLV = LValue::makeAddr(tmpAddr, elementPtrType);
+ cgf.emitStoreThroughLValue(RValue::get(element), tmpLV);
+
+ // TODO:Replace this part later with cir::DoWhileOp
+ for (unsigned i = numInitElements; i != numArrayElements; ++i) {
+ auto currentElement = builder.createLoad(loc, tmpAddr.getPointer());
+
+ // Emit the actual filler expression.
+ const LValue elementLV = LValue::makeAddr(
+ Address(currentElement, cirElementType, elementAlign), elementType);
+
+ if (arrayFiller)
+ emitInitializationToLValue(arrayFiller, elementLV);
+ else
+ emitNullInitializationToLValue(loc, elementLV);
+
+ // Advance pointer and store them to temporary variable
+ one = builder.create<cir::ConstantOp>(
+ loc, cgf.PtrDiffTy, cir::IntAttr::get(cgf.PtrDiffTy, 1));
+
+ auto nextElement = builder.create<cir::PtrStrideOp>(
+ loc, cirElementPtrType, currentElement, one);
+ cgf.emitStoreThroughLValue(RValue::get(nextElement), tmpLV);
+ }
+ }
+}
+
+void AggExprEmitter::emitInitializationToLValue(Expr *e, LValue lv) {
+ const QualType type = lv.getType();
+
+ if (isa<ImplicitValueInitExpr, CXXScalarValueInitExpr>(e)) {
+ const auto loc = e->getSourceRange().isValid()
+ ? cgf.getLoc(e->getSourceRange())
+ : *cgf.currSrcLoc;
+ return emitNullInitializationToLValue(loc, lv);
+ }
+
+ if (isa<NoInitExpr>(e))
+ return;
+
+ if (type->isReferenceType()) {
+ llvm_unreachable("NTI");
+ }
+
+ switch (cgf.getEvaluationKind(type)) {
+ case cir::TEK_Complex:
+ llvm_unreachable("TEK_Complex NYI");
+ break;
+ case cir::TEK_Aggregate:
+ cgf.emitAggExpr(e, AggValueSlot::forLValue(lv));
+ return;
+ case cir::TEK_Scalar:
+ if (lv.isSimple())
+ cgf.emitScalarInit(e, cgf.getLoc(e->getSourceRange()), lv);
+ else
+ cgf.emitStoreThroughLValue(RValue::get(cgf.emitScalarExpr(e)), lv);
+ return;
+ }
+}
+
+void AggExprEmitter::emitNullInitializationToLValue(mlir::Location loc,
+ LValue lv) {
+ const QualType type = lv.getType();
+
+ // If the destination slot is already zeroed out before the aggregate is
+ // copied into it, we don't have to emit any zeros here.
+ if (dest.isZeroed() && cgf.getTypes().isZeroInitializable(type))
+ return;
+
+ if (cgf.hasScalarEvaluationKind(type)) {
+ // For non-aggregates, we can store the appropriate null constant.
+ auto null = cgf.cgm.emitNullConstant(type, loc);
+ if (lv.isSimple()) {
+ cgf.emitStoreOfScalar(null, lv, /* isInitialization */ true);
+ return;
+ }
+
+ llvm_unreachable("emitStoreThroughBitfieldLValue NYI");
+ return;
+ }
+
+ // There's a potential optimization opportunity in combining
+ // memsets; that would be easy for arrays, but relatively
+ // difficult for structures with the current code.
+ cgf.emitNullInitialization(loc, lv.getAddress(), lv.getType());
+}
+
+void AggExprEmitter::VisitInitListExpr(InitListExpr *e) {
+ if (e->hadArrayRangeDesignator())
+ llvm_unreachable("GNU array range designator extension");
+
+ if (e->isTransparent())
+ return Visit(e->getInit(0));
+
+ visitCXXParenListOrInitListExpr(
+ e, e->inits(), e->getInitializedFieldInUnion(), e->getArrayFiller());
+}
+
+void AggExprEmitter::visitCXXParenListOrInitListExpr(
+ Expr *e, ArrayRef<Expr *> args, FieldDecl *initializedFieldInUnion,
+ Expr *arrayFiller) {
+
+ const AggValueSlot dest =
+ ensureSlot(cgf.getLoc(e->getSourceRange()), e->getType());
+
+ if (e->getType()->isConstantArrayType()) {
+ cir::ArrayType arrayTy =
+ cast<cir::ArrayType>(dest.getAddress().getElementType());
+ emitArrayInit(dest.getAddress(), arrayTy, e->getType(), e, args,
+ arrayFiller);
+ return;
+ }
+
+ llvm_unreachable("NYI");
+}
+
+void CIRGenFunction::emitAggExpr(const Expr *e, AggValueSlot slot) {
+ AggExprEmitter(*this, slot).Visit(const_cast<Expr *>(e));
+}
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
index fc49d6da97206..06fcc0e2c040a 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
@@ -412,3 +412,26 @@ mlir::Attribute ConstantEmitter::tryEmitPrivate(const APValue &value,
}
llvm_unreachable("Unknown APValue kind");
}
+
+mlir::Value CIRGenModule::emitNullConstant(QualType t, mlir::Location loc) {
+ if (t->getAs<PointerType>()) {
+ return builder.getNullPtr(getTypes().convertTypeForM...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/132974
More information about the cfe-commits
mailing list