Skip to content

Commit 30d13e3

Browse files
authored
[CIR] Upstream ArraySubscriptExpr from function parameter with pointer base (#135493)
This change adds an ArraySubscriptExpr from the function parameter with base type as Pointer Issue #130197
1 parent 3b91030 commit 30d13e3

File tree

2 files changed

+148
-17
lines changed

2 files changed

+148
-17
lines changed

clang/lib/CIR/CodeGen/CIRGenExpr.cpp

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -552,7 +552,19 @@ CIRGenFunction::emitArraySubscriptExpr(const clang::ArraySubscriptExpr *e) {
552552
// in lexical order (this complexity is, sadly, required by C++17).
553553
assert((e->getIdx() == e->getLHS() || e->getIdx() == e->getRHS()) &&
554554
"index was neither LHS nor RHS");
555-
const mlir::Value idx = emitScalarExpr(e->getIdx());
555+
556+
auto emitIdxAfterBase = [&]() -> mlir::Value {
557+
const mlir::Value idx = emitScalarExpr(e->getIdx());
558+
559+
// Extend or truncate the index type to 32 or 64-bits.
560+
auto ptrTy = mlir::dyn_cast<cir::PointerType>(idx.getType());
561+
if (ptrTy && mlir::isa<cir::IntType>(ptrTy.getPointee()))
562+
cgm.errorNYI(e->getSourceRange(),
563+
"emitArraySubscriptExpr: index type cast");
564+
return idx;
565+
};
566+
567+
const mlir::Value idx = emitIdxAfterBase();
556568
if (const Expr *array = getSimpleArrayDecayOperand(e->getBase())) {
557569
LValue arrayLV;
558570
if (const auto *ase = dyn_cast<ArraySubscriptExpr>(array))
@@ -566,13 +578,34 @@ CIRGenFunction::emitArraySubscriptExpr(const clang::ArraySubscriptExpr *e) {
566578
arrayLV.getAddress(), e->getType(), idx, cgm.getLoc(e->getExprLoc()),
567579
/*shouldDecay=*/true);
568580

569-
return LValue::makeAddr(addr, e->getType(), LValueBaseInfo());
581+
const LValue lv = LValue::makeAddr(addr, e->getType(), LValueBaseInfo());
582+
583+
if (getLangOpts().ObjC && getLangOpts().getGC() != LangOptions::NonGC) {
584+
cgm.errorNYI(e->getSourceRange(), "emitArraySubscriptExpr: ObjC with GC");
585+
}
586+
587+
return lv;
570588
}
571589

572590
// The base must be a pointer; emit it with an estimate of its alignment.
573-
cgm.errorNYI(e->getSourceRange(),
574-
"emitArraySubscriptExpr: The base must be a pointer");
575-
return {};
591+
assert(e->getBase()->getType()->isPointerType() &&
592+
"The base must be a pointer");
593+
594+
LValueBaseInfo eltBaseInfo;
595+
const Address ptrAddr = emitPointerWithAlignment(e->getBase(), &eltBaseInfo);
596+
// Propagate the alignment from the array itself to the result.
597+
const Address addxr = emitArraySubscriptPtr(
598+
*this, cgm.getLoc(e->getBeginLoc()), cgm.getLoc(e->getEndLoc()), ptrAddr,
599+
e->getType(), idx, cgm.getLoc(e->getExprLoc()),
600+
/*shouldDecay=*/false);
601+
602+
const LValue lv = LValue::makeAddr(addxr, e->getType(), eltBaseInfo);
603+
604+
if (getLangOpts().ObjC && getLangOpts().getGC() != LangOptions::NonGC) {
605+
cgm.errorNYI(e->getSourceRange(), "emitArraySubscriptExpr: ObjC with GC");
606+
}
607+
608+
return lv;
576609
}
577610

578611
LValue CIRGenFunction::emitBinaryOperatorLValue(const BinaryOperator *e) {

clang/test/CIR/CodeGen/array.cpp

Lines changed: 110 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -350,20 +350,118 @@ void func7() {
350350
// OGCG: %[[ARR:.*]] = alloca [1 x ptr], align 8
351351
// OGCG: call void @llvm.memset.p0.i64(ptr align 8 %[[ARR]], i8 0, i64 8, i1 false)
352352

353-
void func8(int p[10]) {}
354-
// CIR: cir.func @func8(%arg0: !cir.ptr<!s32i>
355-
// CIR: cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["p", init]
353+
void func8(int arr[10]) {
354+
int e = arr[0];
355+
int e2 = arr[1];
356+
}
356357

357-
// LLVM: define void @func8(ptr {{%.*}})
358-
// LLVM-NEXT: alloca ptr, i64 1, align 8
358+
// CIR: cir.func @func8(%[[ARG:.*]]: !cir.ptr<!s32i>
359+
// CIR: %[[ARR:.*]] = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["arr", init]
360+
// CIR: %[[INIT:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["e", init]
361+
// CIR: %[[INIT_2:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["e2", init]
362+
// CIR: cir.store %[[ARG]], %[[ARR]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>
363+
// CIR: %[[IDX:.*]] = cir.const #cir.int<0> : !s32i
364+
// CIR: %[[TMP_1:.*]] = cir.load %[[ARR]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i>
365+
// CIR: %[[ELE_0:.*]] = cir.ptr_stride(%[[TMP_1]] : !cir.ptr<!s32i>, %[[IDX]] : !s32i), !cir.ptr<!s32i>
366+
// CIR: %[[TMP_2:.*]] = cir.load %[[ELE_0]] : !cir.ptr<!s32i>, !s32i
367+
// CIR: cir.store %[[TMP_2]], %[[INIT]] : !s32i, !cir.ptr<!s32i>
368+
// CIR: %[[IDX_1:.*]] = cir.const #cir.int<1> : !s32i
369+
// CIR: %[[TMP_3:.*]] = cir.load %[[ARR]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i>
370+
// CIR: %[[ELE_1:.*]] = cir.ptr_stride(%[[TMP_3]] : !cir.ptr<!s32i>, %[[IDX_1]] : !s32i), !cir.ptr<!s32i>
371+
// CIR: %[[TMP_4:.*]] = cir.load %[[ELE_1]] : !cir.ptr<!s32i>, !s32i
372+
// CIR: cir.store %[[TMP_4]], %[[INIT_2]] : !s32i, !cir.ptr<!s32i>
373+
374+
// LLVM: define void @func8(ptr %[[ARG:.*]])
375+
// LLVM: %[[ARR:.*]] = alloca ptr, i64 1, align 8
376+
// LLVM: %[[INIT:.*]] = alloca i32, i64 1, align 4
377+
// LLVM: %[[INIT_2:.*]] = alloca i32, i64 1, align 4
378+
// LLVM: store ptr %[[ARG]], ptr %[[ARR]], align 8
379+
// LLVM: %[[TMP_1:.*]] = load ptr, ptr %[[ARR]], align 8
380+
// LLVM: %[[ELE_0:.*]] = getelementptr i32, ptr %[[TMP_1]], i64 0
381+
// LLVM: %[[TMP_2:.*]] = load i32, ptr %[[ELE_0]], align 4
382+
// LLVM: store i32 %[[TMP_2]], ptr %[[INIT]], align 4
383+
// LLVM: %[[TMP_3:.*]] = load ptr, ptr %[[ARR]], align 8
384+
// LLVM: %[[ELE_1:.*]] = getelementptr i32, ptr %[[TMP_3]], i64 1
385+
// LLVM: %[[TMP_4:.*]] = load i32, ptr %[[ELE_1]], align 4
386+
// LLVM: store i32 %[[TMP_4]], ptr %[[INIT_2]], align 4
387+
388+
// OGCG: %[[ARR:.*]] = alloca ptr, align 8
389+
// OGCG: %[[INIT:.*]] = alloca i32, align 4
390+
// OGCG: %[[INIT_2:.*]] = alloca i32, align 4
391+
// OGCG: store ptr {{%.*}}, ptr %[[ARR]], align 8
392+
// OGCG: %[[TMP_1:.*]] = load ptr, ptr %[[ARR]], align 8
393+
// OGCG: %[[ELE_0:.*]] = getelementptr inbounds i32, ptr %[[TMP_1]], i64 0
394+
// OGCG: %[[TMP_2:.*]] = load i32, ptr %[[ELE_0]], align 4
395+
// OGCG: store i32 %[[TMP_2]], ptr %[[INIT]], align 4
396+
// OGCG: %[[TMP_3:.*]] = load ptr, ptr %[[ARR]], align 8
397+
// OGCG: %[[ELE_1:.*]] = getelementptr inbounds i32, ptr %[[TMP_3]], i64 1
398+
// OGCG: %[[TMP_2:.*]] = load i32, ptr %[[ELE_1]], align 4
399+
// OGCG: store i32 %[[TMP_2]], ptr %[[INIT_2]], align 4
359400

360-
// OGCG: alloca ptr, align 8
401+
void func9(int arr[10][5]) {
402+
int e = arr[1][2];
403+
}
361404

362-
void func9(int pp[10][5]) {}
363-
// CIR: cir.func @func9(%arg0: !cir.ptr<!cir.array<!s32i x 5>>
364-
// CIR: cir.alloca !cir.ptr<!cir.array<!s32i x 5>>, !cir.ptr<!cir.ptr<!cir.array<!s32i x 5>>>
405+
// CIR: cir.func @func9(%[[ARG:.*]]: !cir.ptr<!cir.array<!s32i x 5>>
406+
// CIR: %[[ARR:.*]] = cir.alloca !cir.ptr<!cir.array<!s32i x 5>>, !cir.ptr<!cir.ptr<!cir.array<!s32i x 5>>>, ["arr", init]
407+
// CIR: %[[INIT:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["e", init]
408+
// CIR: cir.store %[[ARG]], %[[ARR]] : !cir.ptr<!cir.array<!s32i x 5>>, !cir.ptr<!cir.ptr<!cir.array<!s32i x 5>>>
409+
// CIR: %[[IDX:.*]] = cir.const #cir.int<2> : !s32i
410+
// CIR: %[[IDX_1:.*]] = cir.const #cir.int<1> : !s32i
411+
// CIR: %[[TMP_1:.*]] = cir.load %[[ARR]] : !cir.ptr<!cir.ptr<!cir.array<!s32i x 5>>>, !cir.ptr<!cir.array<!s32i x 5>>
412+
// CIR: %[[ARR_1:.*]] = cir.ptr_stride(%[[TMP_1]] : !cir.ptr<!cir.array<!s32i x 5>>, %[[IDX_1]] : !s32i), !cir.ptr<!cir.array<!s32i x 5>>
413+
// CIR: %[[ARR_1_PTR:.*]] = cir.cast(array_to_ptrdecay, %[[ARR_1]] : !cir.ptr<!cir.array<!s32i x 5>>), !cir.ptr<!s32i>
414+
// CIR: %[[ARR_1_2:.*]] = cir.ptr_stride(%[[ARR_1_PTR]] : !cir.ptr<!s32i>, %[[IDX]] : !s32i), !cir.ptr<!s32i>
415+
// CIR: %[[TMP_2:.*]] = cir.load %[[ARR_1_2]] : !cir.ptr<!s32i>, !s32i
416+
// CIR: cir.store %[[TMP_2]], %[[INIT]] : !s32i, !cir.ptr<!s32i>
417+
418+
// LLVM: define void @func9(ptr %[[ARG:.*]])
419+
// LLVM: %[[ARR:.*]] = alloca ptr, i64 1, align 8
420+
// LLVM: %[[INIT:.*]] = alloca i32, i64 1, align 4
421+
// LLVM: store ptr %[[ARG]], ptr %[[ARR]], align 8
422+
// LLVM: %[[TMP_1:.*]] = load ptr, ptr %[[ARR]], align 8
423+
// LLVM: %[[ARR_1:.*]] = getelementptr [5 x i32], ptr %[[TMP_1]], i64 1
424+
// LLVM: %[[ARR_1_PTR:.*]] = getelementptr i32, ptr %[[ARR_1]], i32 0
425+
// LLVM: %[[ARR_1_2:.*]] = getelementptr i32, ptr %[[ARR_1_PTR]], i64 2
426+
// LLVM: %[[TMP_2:.*]] = load i32, ptr %[[ARR_1_2]], align 4
427+
// LLVM: store i32 %[[TMP_2]], ptr %[[INIT]], align 4
428+
429+
// OGCG: %[[ARR:.*]] = alloca ptr, align 8
430+
// OGCG: %[[INIT:.*]] = alloca i32, align 4
431+
// OGCG: store ptr {{%.*}}, ptr %[[ARR]], align 8
432+
// OGCG: %[[TMP_1:.*]] = load ptr, ptr %[[ARR]], align 8
433+
// OGCG: %[[ARR_1:.*]] = getelementptr inbounds [5 x i32], ptr %[[TMP_1]], i64 1
434+
// OGCG: %[[ARR_1_2:.*]] = getelementptr inbounds [5 x i32], ptr %[[ARR_1]], i64 0, i64 2
435+
// OGCG: %[[TMP_2:.*]] = load i32, ptr %[[ARR_1_2]], align 4
436+
// OGCG: store i32 %[[TMP_2]], ptr %[[INIT]], align 4
437+
438+
void func10(int *a) {
439+
int e = a[5];
440+
}
365441

366-
// LLVM: define void @func9(ptr {{%.*}})
367-
// LLVM-NEXT: alloca ptr, i64 1, align 8
442+
// CIR: cir.func @func10(%[[ARG:.*]]: !cir.ptr<!s32i>
443+
// CIR: %[[ARR:.*]] = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["a", init]
444+
// CIR: %[[INIT:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["e", init]
445+
// CIR: cir.store %[[ARG]], %[[ARR]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>
446+
// CIR: %[[IDX:.*]] = cir.const #cir.int<5> : !s32i
447+
// CIR: %[[TMP_1:.*]] = cir.load %[[ARR]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i>
448+
// CIR: %[[ELE:.*]] = cir.ptr_stride(%[[TMP_1]] : !cir.ptr<!s32i>, %[[IDX]] : !s32i), !cir.ptr<!s32i>
449+
// CIR: %[[TMP_2:.*]] = cir.load %[[ELE]] : !cir.ptr<!s32i>, !s32i
450+
// CIR: cir.store %[[TMP_2]], %[[INIT]] : !s32i, !cir.ptr<!s32i>
451+
452+
// LLVM: define void @func10(ptr %[[ARG:.*]]) {
453+
// LLVM: %[[ARR:.*]] = alloca ptr, i64 1, align 8
454+
// LLVM: %[[INIT:.*]] = alloca i32, i64 1, align 4
455+
// LLVM: store ptr %[[ARG]], ptr %[[ARR]], align 8
456+
// LLVM: %[[TMP_1:.*]] = load ptr, ptr %[[ARR]], align 8
457+
// LLVM: %[[ELE:.*]] = getelementptr i32, ptr %[[TMP_1]], i64 5
458+
// LLVM: %[[TMP_2:.*]] = load i32, ptr %[[ELE]], align 4
459+
// LLVM: store i32 %[[TMP_2]], ptr %[[INIT]], align 4
368460

369-
// OGCG: alloca ptr, align 8
461+
// OGCG: %[[ARR:.*]] = alloca ptr, align 8
462+
// OGCG: %[[INIT:.*]] = alloca i32, align 4
463+
// OGCG: store ptr {{%.*}}, ptr %[[ARR]], align 8
464+
// OGCG: %[[TMP_1:.*]] = load ptr, ptr %[[ARR]], align 8
465+
// OGCG: %[[ELE:.*]] = getelementptr inbounds i32, ptr %[[TMP_1]], i64 5
466+
// OGCG: %[[TMP_2:.*]] = load i32, ptr %[[ELE]], align 4
467+
// OGCG: store i32 %[[TMP_2]], ptr %[[INIT]], align 4

0 commit comments

Comments
 (0)