[CIR] Add Aggregate Expression LValue Visitors (#163410)
This patch implements visitors for MemberExpr, UnaryDeref, StringLiteral and CompoundLiteralExpr inside aggregate expressions.
This commit is contained in:
parent
61ba312f5d
commit
cd05383a46
4 changed files with 169 additions and 13 deletions
|
|
@ -170,19 +170,10 @@ public:
|
|||
void VisitConstantExpr(ConstantExpr *e) {
|
||||
cgf.cgm.errorNYI(e->getSourceRange(), "AggExprEmitter: VisitConstantExpr");
|
||||
}
|
||||
void VisitMemberExpr(MemberExpr *e) {
|
||||
cgf.cgm.errorNYI(e->getSourceRange(), "AggExprEmitter: VisitMemberExpr");
|
||||
}
|
||||
void VisitUnaryDeref(UnaryOperator *e) {
|
||||
cgf.cgm.errorNYI(e->getSourceRange(), "AggExprEmitter: VisitUnaryDeref");
|
||||
}
|
||||
void VisitStringLiteral(StringLiteral *e) {
|
||||
cgf.cgm.errorNYI(e->getSourceRange(), "AggExprEmitter: VisitStringLiteral");
|
||||
}
|
||||
void VisitCompoundLiteralExpr(CompoundLiteralExpr *e) {
|
||||
cgf.cgm.errorNYI(e->getSourceRange(),
|
||||
"AggExprEmitter: VisitCompoundLiteralExpr");
|
||||
}
|
||||
void VisitMemberExpr(MemberExpr *e) { emitAggLoadOfLValue(e); }
|
||||
void VisitUnaryDeref(UnaryOperator *e) { emitAggLoadOfLValue(e); }
|
||||
void VisitStringLiteral(StringLiteral *e) { emitAggLoadOfLValue(e); }
|
||||
void VisitCompoundLiteralExpr(CompoundLiteralExpr *e);
|
||||
void VisitPredefinedExpr(const PredefinedExpr *e) {
|
||||
cgf.cgm.errorNYI(e->getSourceRange(),
|
||||
"AggExprEmitter: VisitPredefinedExpr");
|
||||
|
|
@ -325,6 +316,31 @@ void AggExprEmitter::emitAggLoadOfLValue(const Expr *e) {
|
|||
emitFinalDestCopy(e->getType(), lv);
|
||||
}
|
||||
|
||||
void AggExprEmitter::VisitCompoundLiteralExpr(CompoundLiteralExpr *e) {
|
||||
if (dest.isPotentiallyAliased() && e->getType().isPODType(cgf.getContext())) {
|
||||
// For a POD type, just emit a load of the lvalue + a copy, because our
|
||||
// compound literal might alias the destination.
|
||||
emitAggLoadOfLValue(e);
|
||||
return;
|
||||
}
|
||||
|
||||
AggValueSlot slot = ensureSlot(cgf.getLoc(e->getSourceRange()), e->getType());
|
||||
|
||||
// Block-scope compound literals are destroyed at the end of the enclosing
|
||||
// scope in C.
|
||||
bool destruct =
|
||||
!cgf.getLangOpts().CPlusPlus && !slot.isExternallyDestructed();
|
||||
if (destruct)
|
||||
slot.setExternallyDestructed();
|
||||
|
||||
cgf.emitAggExpr(e->getInitializer(), slot);
|
||||
|
||||
if (destruct)
|
||||
if ([[maybe_unused]] QualType::DestructionKind dtorKind =
|
||||
e->getType().isDestructedType())
|
||||
cgf.cgm.errorNYI(e->getSourceRange(), "compound literal with destructor");
|
||||
}
|
||||
|
||||
void AggExprEmitter::emitArrayInit(Address destPtr, cir::ArrayType arrayTy,
|
||||
QualType arrayQTy, Expr *e,
|
||||
ArrayRef<Expr *> args, Expr *arrayFiller) {
|
||||
|
|
|
|||
|
|
@ -390,6 +390,8 @@ public:
|
|||
|
||||
IsZeroed_t isZeroed() const { return IsZeroed_t(zeroedFlag); }
|
||||
|
||||
IsAliased_t isPotentiallyAliased() const { return IsAliased_t(aliasedFlag); }
|
||||
|
||||
RValue asRValue() const {
|
||||
if (isIgnored())
|
||||
return RValue::getIgnored();
|
||||
|
|
|
|||
111
clang/test/CIR/CodeGen/agg-expr-lvalue.c
Normal file
111
clang/test/CIR/CodeGen/agg-expr-lvalue.c
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir
|
||||
// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
|
||||
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-cir.ll
|
||||
// RUN: FileCheck --check-prefix=LLVM --input-file=%t-cir.ll %s
|
||||
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll
|
||||
// RUN: FileCheck --check-prefix=OGCG --input-file=%t.ll %s
|
||||
|
||||
struct Point {
|
||||
int x, y;
|
||||
};
|
||||
|
||||
struct Line {
|
||||
struct Point start;
|
||||
struct Point end;
|
||||
};
|
||||
|
||||
// AggExprEmitter::VisitMemberExpr
|
||||
void test_member_in_array(void) {
|
||||
struct Line line = {{1, 2}, {3, 4}};
|
||||
struct Point arr[1] = {line.start};
|
||||
}
|
||||
|
||||
// CIR-LABEL: cir.func{{.*}} @test_member_in_array
|
||||
// CIR: %[[LINE:.*]] = cir.alloca !rec_Line{{.*}}, ["line", init]
|
||||
// CIR: %[[ARR:.*]] = cir.alloca !cir.array<!rec_Point x 1>{{.*}}, ["arr", init]
|
||||
// CIR: %[[MEMBER:.*]] = cir.get_member %[[LINE]][0] {name = "start"}
|
||||
// CIR: cir.copy
|
||||
|
||||
// LLVM-LABEL: define{{.*}} @test_member_in_array
|
||||
// LLVM: %[[LINE:.*]] = alloca %struct.Line
|
||||
// LLVM: %[[ARR:.*]] = alloca [1 x %struct.Point]
|
||||
// LLVM: %[[MEMBER:.*]] = getelementptr{{.*}}%struct.Line{{.*}}%[[LINE]]{{.*}}i32 0, i32 0
|
||||
// LLVM: call void @llvm.memcpy
|
||||
|
||||
// OGCG-LABEL: define{{.*}} @test_member_in_array
|
||||
// OGCG: %[[LINE:.*]] = alloca %struct.Line
|
||||
// OGCG: %[[ARR:.*]] = alloca [1 x %struct.Point]
|
||||
// OGCG: %[[MEMBER:.*]] = getelementptr{{.*}}%struct.Line{{.*}}%[[LINE]]{{.*}}i32 0, i32 0
|
||||
// OGCG: call void @llvm.memcpy
|
||||
|
||||
// AggExprEmitter::VisitMemberExpr
|
||||
void test_member_arrow_in_array(void) {
|
||||
struct Line *line_ptr;
|
||||
struct Point arr[1] = {line_ptr->start};
|
||||
}
|
||||
|
||||
// CIR-LABEL: cir.func{{.*}} @test_member_arrow_in_array
|
||||
// CIR: %[[PTR:.*]] = cir.alloca !cir.ptr<!rec_Line>{{.*}}, ["line_ptr"]
|
||||
// CIR: %[[ARR:.*]] = cir.alloca !cir.array<!rec_Point x 1>{{.*}}, ["arr", init]
|
||||
// CIR: %[[LOADED:.*]] = cir.load{{.*}}%[[PTR]]
|
||||
// CIR: %[[MEMBER:.*]] = cir.get_member %[[LOADED]][0] {name = "start"}
|
||||
// CIR: cir.copy
|
||||
|
||||
// LLVM-LABEL: define{{.*}} @test_member_arrow_in_array
|
||||
// LLVM: %[[PTR:.*]] = alloca ptr
|
||||
// LLVM: %[[ARR:.*]] = alloca [1 x %struct.Point]
|
||||
// LLVM: %[[LOADED:.*]] = load ptr{{.*}}%[[PTR]]
|
||||
// LLVM: %[[MEMBER:.*]] = getelementptr{{.*}}%struct.Line{{.*}}%[[LOADED]]{{.*}}i32 0, i32 0
|
||||
// LLVM: call void @llvm.memcpy
|
||||
|
||||
// OGCG-LABEL: define{{.*}} @test_member_arrow_in_array
|
||||
// OGCG: %[[PTR:.*]] = alloca ptr
|
||||
// OGCG: %[[ARR:.*]] = alloca [1 x %struct.Point]
|
||||
// OGCG: %[[LOADED:.*]] = load ptr{{.*}}%[[PTR]]
|
||||
// OGCG: %[[MEMBER:.*]] = getelementptr{{.*}}%struct.Line{{.*}}%[[LOADED]]{{.*}}i32 0, i32 0
|
||||
// OGCG: call void @llvm.memcpy
|
||||
|
||||
// AggExprEmitter::VisitUnaryDeref
|
||||
void test_deref_in_array(void) {
|
||||
struct Point *ptr;
|
||||
struct Point arr[1] = {*ptr};
|
||||
}
|
||||
|
||||
// CIR-LABEL: cir.func{{.*}} @test_deref_in_array
|
||||
// CIR: %[[PTR:.*]] = cir.alloca !cir.ptr<!rec_Point>{{.*}}, ["ptr"]
|
||||
// CIR: %[[ARR:.*]] = cir.alloca !cir.array<!rec_Point x 1>{{.*}}, ["arr", init]
|
||||
// CIR: %[[LOADED:.*]] = cir.load{{.*}}%[[PTR]]
|
||||
// CIR: cir.copy
|
||||
|
||||
// LLVM-LABEL: define{{.*}} @test_deref_in_array
|
||||
// LLVM: %[[PTR:.*]] = alloca ptr
|
||||
// LLVM: %[[ARR:.*]] = alloca [1 x %struct.Point]
|
||||
// LLVM: %[[LOADED:.*]] = load ptr{{.*}}%[[PTR]]
|
||||
// LLVM: call void @llvm.memcpy
|
||||
|
||||
// OGCG-LABEL: define{{.*}} @test_deref_in_array
|
||||
// OGCG: %[[PTR:.*]] = alloca ptr
|
||||
// OGCG: %[[ARR:.*]] = alloca [1 x %struct.Point]
|
||||
// OGCG: %[[LOADED:.*]] = load ptr{{.*}}%[[PTR]]
|
||||
// OGCG: call void @llvm.memcpy
|
||||
|
||||
// AggExprEmitter::VisitStringLiteral
|
||||
void test_string_array_in_array(void) {
|
||||
char matrix[2][6] = {"hello", "world"};
|
||||
}
|
||||
|
||||
// CIR-LABEL: cir.func{{.*}} @test_string_array_in_array
|
||||
// CIR: cir.alloca !cir.array<!cir.array<!s8i x 6> x 2>, {{.*}}, ["matrix", init]
|
||||
// CIR: cir.get_global
|
||||
// CIR: cir.copy
|
||||
// CIR: cir.get_global
|
||||
// CIR: cir.copy
|
||||
|
||||
// LLVM-LABEL: define{{.*}} @test_string_array_in_array
|
||||
// LLVM: alloca [2 x [6 x i8]]
|
||||
// LLVM: call void @llvm.memcpy
|
||||
// LLVM: call void @llvm.memcpy
|
||||
|
||||
// OGCG-LABEL: define{{.*}} @test_string_array_in_array
|
||||
// OGCG: alloca [2 x [6 x i8]]
|
||||
// OGCG: call void @llvm.memcpy{{.*}}@__const.test_string_array_in_array
|
||||
|
|
@ -97,3 +97,30 @@ void foo3() {
|
|||
// OGCG: %[[TMP:.*]] = load <4 x i32>, ptr %[[CL_ADDR]], align 16
|
||||
// OGCG: store <4 x i32> %[[TMP]], ptr %[[A_ADDR]], align 16
|
||||
|
||||
struct Point {
|
||||
int x, y;
|
||||
};
|
||||
|
||||
void foo4() {
|
||||
Point p = (Point){5, 10};
|
||||
}
|
||||
|
||||
// CIR-LABEL: @_Z4foo4v
|
||||
// CIR: %[[P:.*]] = cir.alloca !rec_Point, !cir.ptr<!rec_Point>, ["p", init]
|
||||
// CIR: %[[P_X:.*]] = cir.get_member %[[P]][0] {name = "x"}
|
||||
// CIR: %[[FIVE:.*]] = cir.const #cir.int<5> : !s32i
|
||||
// CIR: cir.store{{.*}} %[[FIVE]], %[[P_X]]
|
||||
// CIR: %[[P_Y:.*]] = cir.get_member %[[P]][1] {name = "y"}
|
||||
// CIR: %[[TEN:.*]] = cir.const #cir.int<10> : !s32i
|
||||
// CIR: cir.store{{.*}} %[[TEN]], %[[P_Y]]
|
||||
|
||||
// LLVM-LABEL: @_Z4foo4v
|
||||
// LLVM: %[[P:.*]] = alloca %struct.Point
|
||||
// LLVM: %[[P_X:.*]] = getelementptr %struct.Point, ptr %[[P]], i32 0, i32 0
|
||||
// LLVM: store i32 5, ptr %[[P_X]]
|
||||
// LLVM: %[[P_Y:.*]] = getelementptr %struct.Point, ptr %[[P]], i32 0, i32 1
|
||||
// LLVM: store i32 10, ptr %[[P_Y]]
|
||||
|
||||
// OGCG-LABEL: @_Z4foo4v
|
||||
// OGCG: %[[P:.*]] = alloca %struct.Point
|
||||
// OGCG: call void @llvm.memcpy{{.*}}(ptr{{.*}} %[[P]], ptr{{.*}} @__const._Z4foo4v.p
|
||||
|
|
|
|||
Loading…
Reference in a new issue