Skip to content

Commit

Permalink
[CIR] revert StdInitializerListOp (#1216)
Browse files Browse the repository at this point in the history
Revert "[CIR][Dialect] Introduce StdInitializerListOp to represent
high-level semantics of C++ initializer list (#1121)".

This reverts commit 7532e05.

First step for #1215.
  • Loading branch information
HerrCai0907 authored Dec 7, 2024
1 parent 8d507b1 commit 3189c0d
Show file tree
Hide file tree
Showing 7 changed files with 71 additions and 272 deletions.
34 changes: 0 additions & 34 deletions clang/include/clang/CIR/Dialect/IR/CIROps.td
Original file line number Diff line number Diff line change
Expand Up @@ -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
75 changes: 54 additions & 21 deletions clang/lib/CIR/CodeGen/CIRGenExprAgg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -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);
Expand Down
23 changes: 0 additions & 23 deletions clang/lib/CIR/Dialect/IR/CIRDialect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
//===----------------------------------------------------------------------===//
Expand Down
83 changes: 1 addition & 82 deletions clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}
}

Expand All @@ -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);
});

Expand Down
34 changes: 12 additions & 22 deletions clang/test/CIR/CodeGen/initlist-ptr-ptr.cpp
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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]]>,
Expand All @@ -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: }
Expand Down Expand Up @@ -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]])
Expand Down
Loading

0 comments on commit 3189c0d

Please sign in to comment.