Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 29 additions & 13 deletions clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,19 +170,10 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
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");
Expand Down Expand Up @@ -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) {
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenValue.h
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,8 @@ class AggValueSlot {

IsZeroed_t isZeroed() const { return IsZeroed_t(zeroedFlag); }

IsAliased_t isPotentiallyAliased() const { return IsAliased_t(aliasedFlag); }

RValue asRValue() const {
if (isIgnored())
return RValue::getIgnored();
Expand Down
111 changes: 111 additions & 0 deletions clang/test/CIR/CodeGen/agg-expr-lvalue.c
Original file line number Diff line number Diff line change
@@ -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
27 changes: 27 additions & 0 deletions clang/test/CIR/CodeGen/compound_literal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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