diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 761af3ced802..a8726f492620 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -5336,38 +5336,4 @@ def SignBitOp : CIR_Op<"signbit", [Pure]> { }]; } -//===----------------------------------------------------------------------===// -// StdInitializerListOp -//===----------------------------------------------------------------------===// - -def StdInitializerListOp : CIR_Op<"std.initializer_list"> { - let summary = "Initialize std::initializer_list"; - let description = [{ - The `std.initializer_list` operation will initialize - `std::initializer_list<T>` with given arguments list. - - ```cpp - initializer_list<int> v{1,2,3}; // initialize v with 1, 2, 3 - ``` - - The code above will generate CIR similar as: - - ```mlir - %0 = cir.alloca INITLIST_TYPE, !cir.ptr<INITLIST_TYPE> - %1 = cir.const #cir.int<1> - ... - cir.std.initializer_list %0 (%1 %2 %3) - ``` - - The type of each argument should be the same as template parameter of - `std::initializer_list` (aka `T` in `std::initializer_list<T>`). - }]; - let arguments = (ins StructPtr:$initList, Variadic<CIR_AnyType>:$args); - let assemblyFormat = [{ - $initList ` ` `(` ($args^ `:` type($args))? `)` `:` type($initList) attr-dict - }]; - - let hasVerifier = 1; -} - #endif // LLVM_CLANG_CIR_DIALECT_IR_CIROPS diff --git a/clang/lib/CIR/CodeGen/CIRGenExprAgg.cpp b/clang/lib/CIR/CodeGen/CIRGenExprAgg.cpp index d436822bf9ec..32f343ffd605 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprAgg.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprAgg.cpp @@ -18,15 +18,11 @@ #include "clang/AST/Decl.h" #include "clang/AST/Expr.h" -#include "clang/AST/ExprCXX.h" #include "clang/AST/OperationKinds.h" #include "clang/AST/RecordLayout.h" #include "clang/AST/StmtVisitor.h" #include "clang/CIR/Dialect/IR/CIRAttrs.h" -#include "clang/CIR/Dialect/IR/CIRDialect.h" #include "clang/CIR/MissingFeatures.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" @@ -301,25 +297,62 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> { void VisitCXXInheritedCtorInitExpr(const CXXInheritedCtorInitExpr *E); void VisitLambdaExpr(LambdaExpr *E); void VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E) { + ASTContext &Ctx = CGF.getContext(); + CIRGenFunction::SourceLocRAIIObject locRAIIObject{ + CGF, CGF.getLoc(E->getSourceRange())}; + // Emit an array containing the elements. The array is externally + // destructed if the std::initializer_list object is. + LValue Array = CGF.emitLValue(E->getSubExpr()); + assert(Array.isSimple() && "initializer_list array not a simple lvalue"); + Address ArrayPtr = Array.getAddress(); + + const ConstantArrayType *ArrayType = + Ctx.getAsConstantArrayType(E->getSubExpr()->getType()); + assert(ArrayType && "std::initializer_list constructed from non-array"); + + RecordDecl *Record = E->getType()->castAs<RecordType>()->getDecl(); + RecordDecl::field_iterator Field = Record->field_begin(); + assert(Field != Record->field_end() && + Ctx.hasSameType(Field->getType()->getPointeeType(), + ArrayType->getElementType()) && + "Expected std::initializer_list first field to be const E *"); + // Start pointer. auto loc = CGF.getLoc(E->getSourceRange()); - auto builder = CGF.getBuilder(); - auto *subExpr = - llvm::cast<MaterializeTemporaryExpr>(E->getSubExpr())->getSubExpr(); - llvm::SmallVector<mlir::Value> inits{}; - for (auto *init : llvm::cast<InitListExpr>(subExpr)->inits()) { - RValue tmpInit = CGF.emitAnyExprToTemp(init); - if (tmpInit.isScalar()) { - inits.push_back(tmpInit.getScalarVal()); - } else if (tmpInit.isComplex()) { - inits.push_back(tmpInit.getComplexVal()); - } else if (tmpInit.isAggregate()) { - inits.push_back(tmpInit.getAggregatePointer()); - } else { - llvm_unreachable("invalid temp expr type"); - } + AggValueSlot Dest = EnsureSlot(loc, E->getType()); + LValue DestLV = CGF.makeAddrLValue(Dest.getAddress(), E->getType()); + LValue Start = + CGF.emitLValueForFieldInitialization(DestLV, *Field, Field->getName()); + mlir::Value ArrayStart = ArrayPtr.emitRawPointer(); + CGF.emitStoreThroughLValue(RValue::get(ArrayStart), Start); + ++Field; + assert(Field != Record->field_end() && + "Expected std::initializer_list to have two fields"); + + auto Builder = CGF.getBuilder(); + + auto sizeOp = Builder.getConstInt(loc, ArrayType->getSize()); + + mlir::Value Size = sizeOp.getRes(); + Builder.getUIntNTy(ArrayType->getSizeBitWidth()); + LValue EndOrLength = + CGF.emitLValueForFieldInitialization(DestLV, *Field, Field->getName()); + if (Ctx.hasSameType(Field->getType(), Ctx.getSizeType())) { + // Length. + CGF.emitStoreThroughLValue(RValue::get(Size), EndOrLength); + } else { + // End pointer. + assert(Field->getType()->isPointerType() && + Ctx.hasSameType(Field->getType()->getPointeeType(), + ArrayType->getElementType()) && + "Expected std::initializer_list second field to be const E *"); + + auto ArrayEnd = + Builder.getArrayElement(loc, loc, ArrayPtr.getPointer(), + ArrayPtr.getElementType(), Size, false); + CGF.emitStoreThroughLValue(RValue::get(ArrayEnd), EndOrLength); } - mlir::Value dest = EnsureSlot(loc, E->getType()).getPointer(); - builder.create<cir::StdInitializerListOp>(loc, dest, inits); + assert(++Field == Record->field_end() && + "Expected std::initializer_list to only have two fields"); } void VisitExprWithCleanups(ExprWithCleanups *E); diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index dcd993582971..b219a50d1391 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -3865,29 +3865,6 @@ LogicalResult cir::CatchParamOp::verify() { return success(); } -//===----------------------------------------------------------------------===// -// StdInitializerListOp Definitions -//===----------------------------------------------------------------------===// - -LogicalResult cir::StdInitializerListOp::verify() { - auto resultType = mlir::cast<cir::StructType>( - mlir::cast<cir::PointerType>(getInitList().getType()).getPointee()); - if (resultType.getMembers().size() != 2) - return emitOpError( - "std::initializer_list must be '!cir.struct' with two fields"); - auto memberPtr = mlir::dyn_cast<cir::PointerType>(resultType.getMembers()[0]); - if (memberPtr == nullptr) - return emitOpError("first member type of std::initializer_list must be " - "'!cir.ptr', but provided ") - << resultType.getMembers()[0]; - auto expectedType = memberPtr.getPointee(); - for (const mlir::Value &arg : getArgs()) - if (expectedType != arg.getType()) - return emitOpError("arg type must be ") - << expectedType << ", but provided " << arg.getType(); - return mlir::success(); -} - //===----------------------------------------------------------------------===// // TableGen'd op method definitions //===----------------------------------------------------------------------===// diff --git a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp index a949d78eaf80..b0709e9638ff 100644 --- a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp +++ b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp @@ -12,19 +12,15 @@ #include "mlir/IR/Region.h" #include "clang/AST/ASTContext.h" #include "clang/AST/CharUnits.h" -#include "clang/AST/Decl.h" #include "clang/AST/Mangle.h" #include "clang/Basic/Module.h" #include "clang/Basic/TargetInfo.h" #include "clang/CIR/Dialect/Builder/CIRBaseBuilder.h" #include "clang/CIR/Dialect/IR/CIRDataLayout.h" #include "clang/CIR/Dialect/IR/CIRDialect.h" -#include "clang/CIR/Dialect/IR/CIROpsEnums.h" -#include "clang/CIR/Dialect/IR/CIRTypes.h" #include "clang/CIR/Dialect/Passes.h" #include "clang/CIR/Interfaces/ASTAttrInterfaces.h" #include "llvm/ADT/APFloat.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" @@ -89,7 +85,6 @@ struct LoweringPreparePass : public LoweringPrepareBase<LoweringPreparePass> { void lowerToMemCpy(StoreOp op); void lowerArrayDtor(ArrayDtor op); void lowerArrayCtor(ArrayCtor op); - void lowerStdInitializerListOp(StdInitializerListOp op); /// Collect annotations of global values in the module void addGlobalAnnotations(mlir::Operation *op, mlir::ArrayAttr annotations); @@ -1125,79 +1120,6 @@ void LoweringPreparePass::lowerIterEndOp(IterEndOp op) { op.erase(); } -/// lowering construction of std::initializer_list. -/// 1. alloca array for arg list. -/// 2. copy arg list to array. -/// 3. construct std::initializer_list from array. -void LoweringPreparePass::lowerStdInitializerListOp(StdInitializerListOp op) { - auto loc = op.getLoc(); - cir::CIRDataLayout dataLayout(theModule); - auto args = op.getArgs(); - - auto stdInitializerListType = mlir::cast<cir::StructType>( - mlir::cast<cir::PointerType>(op.getInitList().getType()).getPointee()); - clang::RecordDecl::field_range stdInitializerListFields = - stdInitializerListType.getAst().getRawDecl()->fields(); - - mlir::Type elementType = - mlir::cast<cir::PointerType>(stdInitializerListType.getMembers()[0]) - .getPointee(); - auto tempArrayType = - cir::ArrayType::get(&getContext(), elementType, args.size()); - - CIRBaseBuilderTy builder(getContext()); - builder.setInsertionPointAfter(op); - - IntegerAttr alignment = builder.getI64IntegerAttr( - dataLayout.getPrefTypeAlign(tempArrayType).value()); - assert(!cir::MissingFeatures::addressSpace()); - mlir::Value arrayPtr = builder.createAlloca( - loc, cir::PointerType::get(tempArrayType), tempArrayType, "", alignment); - mlir::Value arrayStartPtr = - builder.createCast(cir::CastKind::array_to_ptrdecay, arrayPtr, - cir::PointerType::get(elementType)); - for (unsigned i = 0; i < args.size(); i++) { - if (i == 0) { - builder.createStore(loc, args[i], arrayStartPtr); - } else { - mlir::Value offset = builder.getUnsignedInt(loc, i, 64); - mlir::Value dest = builder.create<cir::PtrStrideOp>( - loc, arrayStartPtr.getType(), arrayStartPtr, offset); - builder.createStore(loc, args[i], dest); - } - } - - // FIXME(cir): better handling according to different field type. [ptr ptr], - // [ptr size], [size ptr]. - - clang::RecordDecl::field_iterator it = stdInitializerListFields.begin(); - const clang::RecordDecl::field_iterator startField = it; - const unsigned startIdx = 0U; - const clang::RecordDecl::field_iterator endOrSizeField = ++it; - const unsigned endOrSizeIdx = 1U; - assert(llvm::range_size(stdInitializerListFields) == 2U); - - mlir::Value startMemberPtr = builder.createGetMemberOp( - loc, op.getInitList(), startField->getName().data(), startIdx); - builder.createStore(loc, arrayStartPtr, startMemberPtr); - - mlir::Value size = builder.getUnsignedInt(loc, args.size(), 64); - if (endOrSizeField->getType()->isPointerType()) { - mlir::Value arrayEndPtr = builder.create<cir::PtrStrideOp>( - loc, arrayStartPtr.getType(), arrayStartPtr, size); - mlir::Value endMemberPtr = builder.createGetMemberOp( - loc, op.getInitList(), endOrSizeField->getName().data(), endOrSizeIdx); - builder.createStore(loc, arrayEndPtr, endMemberPtr); - } else { - assert(endOrSizeField->getType()->isIntegerType()); - mlir::Value sizeMemberPtr = builder.createGetMemberOp( - loc, op.getInitList(), endOrSizeField->getName().data(), endOrSizeIdx); - builder.createStore(loc, size, sizeMemberPtr); - } - - op.erase(); -} - void LoweringPreparePass::addGlobalAnnotations(mlir::Operation *op, mlir::ArrayAttr annotations) { auto globalValue = cast<mlir::SymbolOpInterface>(op); @@ -1258,8 +1180,6 @@ void LoweringPreparePass::runOnOp(Operation *op) { } if (std::optional<mlir::ArrayAttr> annotations = fnOp.getAnnotations()) addGlobalAnnotations(fnOp, annotations.value()); - } else if (auto stdInitializerListOp = dyn_cast<StdInitializerListOp>(op)) { - lowerStdInitializerListOp(stdInitializerListOp); } } @@ -1275,8 +1195,7 @@ void LoweringPreparePass::runOnOperation() { op->walk([&](Operation *op) { if (isa<UnaryOp, BinOp, CastOp, ComplexBinOp, CmpThreeWayOp, VAArgOp, GlobalOp, DynamicCastOp, StdFindOp, IterEndOp, IterBeginOp, - ArrayCtor, ArrayDtor, cir::FuncOp, StoreOp, StdInitializerListOp>( - op)) + ArrayCtor, ArrayDtor, cir::FuncOp, StoreOp>(op)) opsToTransform.push_back(op); }); diff --git a/clang/test/CIR/CodeGen/initlist-ptr-ptr.cpp b/clang/test/CIR/CodeGen/initlist-ptr-ptr.cpp index 8a0e2ac7aaab..25873623d6e8 100644 --- a/clang/test/CIR/CodeGen/initlist-ptr-ptr.cpp +++ b/clang/test/CIR/CodeGen/initlist-ptr-ptr.cpp @@ -1,5 +1,3 @@ -// RUN: %clang_cc1 -triple aarch64-none-linux-android21 -fclangir -emit-cir %s -o %t.cir -clangir-disable-passes -// RUN: FileCheck --check-prefix=BEFORE --input-file=%t.cir %s // RUN: %clang_cc1 -triple aarch64-none-linux-android21 -fclangir -emit-cir %s -o %t.cir // RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s // RUN: %clang_cc1 -triple aarch64-none-linux-android21 -fclangir -emit-llvm -fno-clangir-call-conv-lowering %s -o %t.ll @@ -17,16 +15,6 @@ void test() { } } // namespace std -// BEFORE: [[INITLIST_TYPE:!.*]] = !cir.struct<class "std::initializer_list<const char *>" {!cir.ptr<!cir.ptr<!s8i>>, !cir.ptr<!cir.ptr<!s8i>>} #cir.record.decl.ast> -// BEFORE: %0 = cir.alloca [[INITLIST_TYPE]], !cir.ptr<[[INITLIST_TYPE]]>, -// BEFORE: %1 = cir.get_global @".str" : !cir.ptr<!cir.array<!s8i x 3>> -// BEFORE: %2 = cir.cast(array_to_ptrdecay, %1 : !cir.ptr<!cir.array<!s8i x 3>>), !cir.ptr<!s8i> -// BEFORE: %3 = cir.get_global @".str.1" : !cir.ptr<!cir.array<!s8i x 3>> -// BEFORE: %4 = cir.cast(array_to_ptrdecay, %3 : !cir.ptr<!cir.array<!s8i x 3>>), !cir.ptr<!s8i> -// BEFORE: cir.std.initializer_list %0 (%2, %4 : !cir.ptr<!s8i>, !cir.ptr<!s8i>) : !cir.ptr<[[INITLIST_TYPE]]> -// BEFORE: %5 = cir.load %0 : !cir.ptr<[[INITLIST_TYPE]]>, [[INITLIST_TYPE]] -// BEFORE: cir.call @_ZSt1fIPKcEvSt16initializer_listIT_E(%5) : ([[INITLIST_TYPE]]) -> () - // CIR: [[INITLIST_TYPE:!.*]] = !cir.struct<class "std::initializer_list<const char *>" {!cir.ptr<!cir.ptr<!s8i>>, !cir.ptr<!cir.ptr<!s8i>>}> // CIR: cir.func linkonce_odr @_ZSt1fIPKcEvSt16initializer_listIT_E(%arg0: [[INITLIST_TYPE]] // CIR: [[LOCAL:%.*]] = cir.alloca [[INITLIST_TYPE]], !cir.ptr<[[INITLIST_TYPE]]>, @@ -39,22 +27,24 @@ void test() { // CIR: cir.func @_ZSt4testv() // CIR: cir.scope { // CIR: [[INITLIST_LOCAL:%.*]] = cir.alloca [[INITLIST_TYPE]], !cir.ptr<[[INITLIST_TYPE]]>, +// CIR: [[LOCAL_ELEM_ARRAY:%.*]] = cir.alloca !cir.array<!cir.ptr<!s8i> x 2>, !cir.ptr<!cir.array<!cir.ptr<!s8i> x 2>>, +// CIR: [[FIRST_ELEM_PTR:%.*]] = cir.cast(array_to_ptrdecay, [[LOCAL_ELEM_ARRAY]] : !cir.ptr<!cir.array<!cir.ptr<!s8i> x 2>>), !cir.ptr<!cir.ptr<!s8i>> // CIR: [[XY_CHAR_ARRAY:%.*]] = cir.get_global [[STR_XY]] : !cir.ptr<!cir.array<!s8i x 3>> // CIR: [[STR_XY_PTR:%.*]] = cir.cast(array_to_ptrdecay, [[XY_CHAR_ARRAY]] : !cir.ptr<!cir.array<!s8i x 3>>), !cir.ptr<!s8i> +// CIR: cir.store [[STR_XY_PTR]], [[FIRST_ELEM_PTR]] : !cir.ptr<!s8i>, !cir.ptr<!cir.ptr<!s8i>> +// CIR: [[ONE:%.*]] = cir.const #cir.int<1> +// CIR: [[NEXT_ELEM_PTR:%.*]] = cir.ptr_stride([[FIRST_ELEM_PTR]] : !cir.ptr<!cir.ptr<!s8i>>, [[ONE]] : !s64i), !cir.ptr<!cir.ptr<!s8i>> // CIR: [[UV_CHAR_ARRAY:%.*]] = cir.get_global [[STR_UV]] : !cir.ptr<!cir.array<!s8i x 3>> // CIR: [[STR_UV_PTR:%.*]] = cir.cast(array_to_ptrdecay, [[UV_CHAR_ARRAY]] : !cir.ptr<!cir.array<!s8i x 3>>), !cir.ptr<!s8i> -// CIR: [[LOCAL_ELEM_ARRAY:%.*]] = cir.alloca !cir.array<!cir.ptr<!s8i> x 2>, !cir.ptr<!cir.array<!cir.ptr<!s8i> x 2>>, -// CIR: [[ELEM_BEGIN:%.*]] = cir.cast(array_to_ptrdecay, [[LOCAL_ELEM_ARRAY]] : !cir.ptr<!cir.array<!cir.ptr<!s8i> x 2>>), !cir.ptr<!cir.ptr<!s8i>> -// CIR: cir.store [[STR_XY_PTR]], [[ELEM_BEGIN]] : !cir.ptr<!s8i>, !cir.ptr<!cir.ptr<!s8i>> -// CIR: [[ONE:%.*]] = cir.const #cir.int<1> -// CIR: [[NEXT_ELEM_PTR:%.*]] = cir.ptr_stride([[ELEM_BEGIN]] : !cir.ptr<!cir.ptr<!s8i>>, [[ONE]] : !u64i), !cir.ptr<!cir.ptr<!s8i>> // CIR: cir.store [[STR_UV_PTR]], [[NEXT_ELEM_PTR]] : !cir.ptr<!s8i>, !cir.ptr<!cir.ptr<!s8i>> // CIR: [[START_FLD_PTR:%.*]] = cir.get_member [[INITLIST_LOCAL]][0] {name = "array_start"} : !cir.ptr<[[INITLIST_TYPE]]> -> !cir.ptr<!cir.ptr<!cir.ptr<!s8i>>> -// CIR: cir.store [[ELEM_BEGIN]], [[START_FLD_PTR]] : !cir.ptr<!cir.ptr<!s8i>>, !cir.ptr<!cir.ptr<!cir.ptr<!s8i>>> +// CIR: [[START_FLD_PTR_AS_PTR_2_CHAR_ARRAY:%.*]] = cir.cast(bitcast, [[START_FLD_PTR]] : !cir.ptr<!cir.ptr<!cir.ptr<!s8i>>>), !cir.ptr<!cir.ptr<!cir.array<!cir.ptr<!s8i> x 2>>> +// CIR: cir.store [[LOCAL_ELEM_ARRAY]], [[START_FLD_PTR_AS_PTR_2_CHAR_ARRAY]] : !cir.ptr<!cir.array<!cir.ptr<!s8i> x 2>>, !cir.ptr<!cir.ptr<!cir.array<!cir.ptr<!s8i> x 2>>> // CIR: [[ELEM_ARRAY_LEN:%.*]] = cir.const #cir.int<2> -// CIR: [[ELEM_END:%.*]] = cir.ptr_stride([[ELEM_BEGIN]] : !cir.ptr<!cir.ptr<!s8i>>, [[ELEM_ARRAY_LEN]] : !u64i), !cir.ptr<!cir.ptr<!s8i>> // CIR: [[END_FLD_PTR:%.*]] = cir.get_member [[INITLIST_LOCAL]][1] {name = "array_end"} : !cir.ptr<[[INITLIST_TYPE]]> -> !cir.ptr<!cir.ptr<!cir.ptr<!s8i>>> -// CIR: cir.store [[ELEM_END]], [[END_FLD_PTR]] : !cir.ptr<!cir.ptr<!s8i>>, !cir.ptr<!cir.ptr<!cir.ptr<!s8i>>> +// CIR: [[LOCAL_ELEM_ARRAY_END:%.*]] = cir.ptr_stride([[LOCAL_ELEM_ARRAY]] : !cir.ptr<!cir.array<!cir.ptr<!s8i> x 2>>, [[ELEM_ARRAY_LEN]] : !u64i), !cir.ptr<!cir.array<!cir.ptr<!s8i> x 2>> +// CIR: [[END_FLD_PTR_AS_PTR_2_CHAR_ARRAY:%.*]] = cir.cast(bitcast, [[END_FLD_PTR]] : !cir.ptr<!cir.ptr<!cir.ptr<!s8i>>>), !cir.ptr<!cir.ptr<!cir.array<!cir.ptr<!s8i> x 2>>> +// CIR: cir.store [[LOCAL_ELEM_ARRAY_END]], [[END_FLD_PTR_AS_PTR_2_CHAR_ARRAY]] : !cir.ptr<!cir.array<!cir.ptr<!s8i> x 2>>, !cir.ptr<!cir.ptr<!cir.array<!cir.ptr<!s8i> x 2>>> // CIR: [[ARG:%.*]] = cir.load [[INITLIST_LOCAL]] : !cir.ptr<[[INITLIST_TYPE]]>, [[INITLIST_TYPE]] // CIR: cir.call @_ZSt1fIPKcEvSt16initializer_listIT_E([[ARG]]) : ([[INITLIST_TYPE]]) -> () // CIR: } @@ -82,9 +72,9 @@ void test() { // LLVM: [[PTR_SECOND_ELEM:%.*]] = getelementptr ptr, ptr [[PTR_FIRST_ELEM]], i64 1 // LLVM: store ptr @.str.1, ptr [[PTR_SECOND_ELEM]], align 8 // LLVM: [[INIT_START_FLD_PTR:%.*]] = getelementptr %"class.std::initializer_list<const char *>", ptr [[INIT_STRUCT]], i32 0, i32 0 -// LLVM: store ptr [[PTR_FIRST_ELEM]], ptr [[INIT_START_FLD_PTR]], align 8 -// LLVM: [[ELEM_ARRAY_END:%.*]] = getelementptr ptr, ptr [[PTR_FIRST_ELEM]], i64 2 +// LLVM: store ptr [[ELEM_ARRAY_PTR]], ptr [[INIT_START_FLD_PTR]], align 8 // LLVM: [[INIT_END_FLD_PTR:%.*]] = getelementptr %"class.std::initializer_list<const char *>", ptr [[INIT_STRUCT]], i32 0, i32 1 +// LLVM: [[ELEM_ARRAY_END:%.*]] = getelementptr [2 x ptr], ptr [[ELEM_ARRAY_PTR]], i64 2 // LLVM: store ptr [[ELEM_ARRAY_END]], ptr [[INIT_END_FLD_PTR]], align 8 // LLVM: [[ARG2PASS:%.*]] = load %"class.std::initializer_list<const char *>", ptr [[INIT_STRUCT]], align 8 // LLVM: call void @_ZSt1fIPKcEvSt16initializer_listIT_E(%"class.std::initializer_list<const char *>" [[ARG2PASS]]) diff --git a/clang/test/CIR/CodeGen/initlist-ptr-unsigned.cpp b/clang/test/CIR/CodeGen/initlist-ptr-unsigned.cpp index 08ed514ca707..cc90d0ac1d84 100644 --- a/clang/test/CIR/CodeGen/initlist-ptr-unsigned.cpp +++ b/clang/test/CIR/CodeGen/initlist-ptr-unsigned.cpp @@ -1,5 +1,3 @@ -// RUN: %clang_cc1 -triple aarch64-none-linux-android21 -fclangir -emit-cir %s -o %t.cir -clangir-disable-passes -// RUN: FileCheck --check-prefix=BEFORE --input-file=%t.cir %s // RUN: %clang_cc1 -triple aarch64-none-linux-android21 -fclangir -emit-cir %s -o %t.cir // RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s // RUN: %clang_cc1 -triple aarch64-none-linux-android21 -fclangir -emit-llvm -fno-clangir-call-conv-lowering %s -o %t.ll @@ -17,13 +15,6 @@ void test() { } } // namespace std -// BEFORE: [[INITLIST_TYPE:!.*]] = !cir.struct<class "std::initializer_list<int>" {!cir.ptr<!s32i>, !u64i} #cir.record.decl.ast> -// BEFORE: %0 = cir.alloca [[INITLIST_TYPE]], !cir.ptr<[[INITLIST_TYPE]]>, -// BEFORE: %1 = cir.const #cir.int<7> : !s32i -// BEFORE: cir.std.initializer_list %0 (%1 : !s32i) : !cir.ptr<[[INITLIST_TYPE]]> -// BEFORE: %2 = cir.load %0 : !cir.ptr<[[INITLIST_TYPE]]>, [[INITLIST_TYPE]] -// BEFORE: cir.call @_ZSt1fIiEvSt16initializer_listIT_E(%2) : ([[INITLIST_TYPE]]) -> () - // CIR: [[INITLIST_TYPE:!.*]] = !cir.struct<class "std::initializer_list<int>" {!cir.ptr<!s32i>, !u64i}> // CIR: cir.func linkonce_odr @_ZSt1fIiEvSt16initializer_listIT_E(%arg0: [[INITLIST_TYPE]] @@ -34,12 +25,13 @@ void test() { // CIR: cir.func @_ZSt4testv() // CIR: cir.scope { // CIR: [[LIST_PTR:%.*]] = cir.alloca [[INITLIST_TYPE]], !cir.ptr<[[INITLIST_TYPE]]>, -// CIR: [[SEVEN:%.*]] = cir.const #cir.int<7> : !s32i // CIR: [[ARRAY:%.*]] = cir.alloca !cir.array<!s32i x 1>, !cir.ptr<!cir.array<!s32i x 1>>, // CIR: [[DECAY_PTR:%.*]] = cir.cast(array_to_ptrdecay, [[ARRAY]] : !cir.ptr<!cir.array<!s32i x 1>>), !cir.ptr<!s32i> +// CIR: [[SEVEN:%.*]] = cir.const #cir.int<7> : !s32i // CIR: cir.store [[SEVEN]], [[DECAY_PTR]] : !s32i, !cir.ptr<!s32i> // CIR: [[FLD_C:%.*]] = cir.get_member [[LIST_PTR]][0] {name = "c"} : !cir.ptr<[[INITLIST_TYPE]]> -> !cir.ptr<!cir.ptr<!s32i>> -// CIR: cir.store [[DECAY_PTR]], [[FLD_C]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>> +// CIR: [[ARRAY_PTR:%.*]] = cir.cast(bitcast, [[FLD_C]] : !cir.ptr<!cir.ptr<!s32i>>), !cir.ptr<!cir.ptr<!cir.array<!s32i x 1>>> +// CIR: cir.store [[ARRAY]], [[ARRAY_PTR]] : !cir.ptr<!cir.array<!s32i x 1>>, !cir.ptr<!cir.ptr<!cir.array<!s32i x 1>>> // CIR: [[LENGTH_ONE:%.*]] = cir.const #cir.int<1> // CIR: [[FLD_LEN:%.*]] = cir.get_member [[LIST_PTR]][1] {name = "len"} : !cir.ptr<[[INITLIST_TYPE]]> -> !cir.ptr<!u64i> // CIR: cir.store [[LENGTH_ONE]], [[FLD_LEN]] : !u64i, !cir.ptr<!u64i> @@ -62,7 +54,7 @@ void test() { // LLVM: [[PTR_FIRST_ELEM:%.*]] = getelementptr i32, ptr [[ELEM_ARRAY]], i32 0 // LLVM: store i32 7, ptr [[PTR_FIRST_ELEM]], align 4 // LLVM: [[ELEM_ARRAY_PTR:%.*]] = getelementptr %"class.std::initializer_list<int>", ptr [[INIT_STRUCT]], i32 0, i32 0 -// LLVM: store ptr [[PTR_FIRST_ELEM]], ptr [[ELEM_ARRAY_PTR]], align 8 +// LLVM: store ptr [[ELEM_ARRAY]], ptr [[ELEM_ARRAY_PTR]], align 8 // LLVM: [[INIT_LEN_FLD:%.*]] = getelementptr %"class.std::initializer_list<int>", ptr [[INIT_STRUCT]], i32 0, i32 1 // LLVM: store i64 1, ptr [[INIT_LEN_FLD]], align 8 // LLVM: [[ARG2PASS:%.*]] = load %"class.std::initializer_list<int>", ptr [[INIT_STRUCT]], align 8 diff --git a/clang/test/CIR/IR/invalid.cir b/clang/test/CIR/IR/invalid.cir index bbe61a0502b0..80fe6e114127 100644 --- a/clang/test/CIR/IR/invalid.cir +++ b/clang/test/CIR/IR/invalid.cir @@ -1450,84 +1450,6 @@ cir.global external @f = #cir.fp<42> : !cir.float // ----- -!s32i = !cir.int<s, 32> -!u32i = !cir.int<u, 32> -!initializer_list_s32i = !cir.struct<class {!cir.ptr<!s32i>, !cir.ptr<!s32i>}> -cir.func @std_initializer_list_wrong_arg_type() { - %0 = cir.alloca !initializer_list_s32i, !cir.ptr<!initializer_list_s32i>, ["v"] - %1 = cir.const #cir.int<1> : !s32i - %2 = cir.const #cir.int<1> : !u32i - // expected-error @below {{'cir.std.initializer_list' op arg type must be '!cir.int<s, 32>', but provided '!cir.int<u, 32>'}} - cir.std.initializer_list %0 (%2, %1, %1 : !u32i, !s32i, !s32i) : !cir.ptr<!initializer_list_s32i> -} - -// ----- - -!s32i = !cir.int<s, 32> -!u32i = !cir.int<u, 32> -!initializer_list_s32i = !cir.struct<class {!cir.ptr<!s32i>, !cir.ptr<!s32i>}> -cir.func @std_initializer_list_wrong_arg_type() { - %0 = cir.alloca !initializer_list_s32i, !cir.ptr<!initializer_list_s32i>, ["v"] - %1 = cir.const #cir.int<1> : !s32i - %2 = cir.const #cir.int<1> : !u32i - // expected-error @below {{'cir.std.initializer_list' op arg type must be '!cir.int<s, 32>', but provided '!cir.int<u, 32>'}} - cir.std.initializer_list %0 (%1, %2, %1 : !s32i, !u32i, !s32i) : !cir.ptr<!initializer_list_s32i> - cir.return -} - -// ----- - -!s32i = !cir.int<s, 32> -!u32i = !cir.int<u, 32> -!initializer_list_s32i = !cir.struct<class {!cir.ptr<!s32i>, !cir.ptr<!s32i>}> -cir.func @std_initializer_list_wrong_arg_type() { - %0 = cir.alloca !initializer_list_s32i, !cir.ptr<!initializer_list_s32i>, ["v"] - %1 = cir.const #cir.int<1> : !s32i - %2 = cir.const #cir.int<1> : !u32i - // expected-error @below {{'cir.std.initializer_list' op arg type must be '!cir.int<s, 32>', but provided '!cir.int<u, 32>'}} - cir.std.initializer_list %0 (%1, %1, %2 : !s32i, !s32i, !u32i) : !cir.ptr<!initializer_list_s32i> - cir.return -} - -// ----- - -!s32i = !cir.int<s, 32> -!u32i = !cir.int<u, 32> -!initializer_list_s32i = !cir.struct<class {!cir.ptr<!s32i>, !cir.ptr<!s32i>}> -cir.func @std_initializer_list_wrong_arg_type() { - %0 = cir.alloca !initializer_list_s32i, !cir.ptr<!initializer_list_s32i>, ["v"] - %1 = cir.const #cir.int<1> : !s32i - %2 = cir.const #cir.int<1> : !u32i - // expected-error @below {{'cir.std.initializer_list' op arg type must be '!cir.int<s, 32>', but provided '!cir.int<u, 32>'}} - cir.std.initializer_list %0 (%2, %2, %2 : !u32i, !u32i, !u32i) : !cir.ptr<!initializer_list_s32i> - cir.return -} - -// ----- - -!s32i = !cir.int<s, 32> -!initializer_list_s32i = !cir.struct<class {!cir.ptr<!s32i>, !cir.ptr<!s32i>, !cir.ptr<!s32i>}> -cir.func @std_initializer_list_wrong_struct() { - %0 = cir.alloca !initializer_list_s32i, !cir.ptr<!initializer_list_s32i>, ["v"] - %1 = cir.const #cir.int<1> : !s32i - // expected-error @below {{'cir.std.initializer_list' op std::initializer_list must be '!cir.struct' with two fields}} - cir.std.initializer_list %0 (%1, %1, %1 : !s32i, !s32i, !s32i) : !cir.ptr<!initializer_list_s32i> - cir.return -} - -// ----- - -!s32i = !cir.int<s, 32> -!initializer_list_s32i = !cir.struct<class {!s32i, !cir.ptr<!s32i>}> -cir.func @std_initializer_list_wrong_struct() { - %0 = cir.alloca !initializer_list_s32i, !cir.ptr<!initializer_list_s32i>, ["v"] - %1 = cir.const #cir.int<1> : !s32i - // expected-error @below {{'cir.std.initializer_list' op first member type of std::initializer_list must be '!cir.ptr', but provided '!cir.int<s, 32>'}} - cir.std.initializer_list %0 (%1, %1, %1 : !s32i, !s32i, !s32i) : !cir.ptr<!initializer_list_s32i> - cir.return -} - -// ----- // Verify !s32i = !cir.int<s, 32> cir.func @cast0(%arg0: !s32i, %arg1: !s32i) {