Skip to content

Commit 706cfab

Browse files
gitoleglanza
authored andcommitted
[CIR][ABI][AArch64][Lowering] Initial support for return of struct types (#1004)
This PR adds a support for return values of a struct type. There are two cases that are not covered by this PR and will be added later.
1 parent c394ef0 commit 706cfab

File tree

3 files changed

+96
-1
lines changed

3 files changed

+96
-1
lines changed

clang/include/clang/CIR/MissingFeatures.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ struct MissingFeatures {
230230
static bool shouldInstrumentFunction() { return false; }
231231
static bool xray() { return false; }
232232
static bool buildConstrainedFPCall() { return false; }
233+
static bool emitEmptyRecordCheck() { return false; }
233234

234235
// Inline assembly
235236
static bool asmGoto() { return false; }

clang/lib/CIR/Dialect/Transforms/TargetLowering/Targets/AArch64.cpp

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66
//
77
//===----------------------------------------------------------------------===//
8-
98
#include "clang/CIR/Target/AArch64.h"
109
#include "ABIInfoImpl.h"
1110
#include "LowerFunctionInfo.h"
@@ -105,6 +104,39 @@ ABIArgInfo AArch64ABIInfo::classifyReturnType(Type RetTy,
105104
: ABIArgInfo::getDirect());
106105
}
107106

107+
uint64_t Size = getContext().getTypeSize(RetTy);
108+
cir_cconv_assert(!::cir::MissingFeatures::emitEmptyRecordCheck());
109+
cir_cconv_assert(
110+
!::cir::MissingFeatures::supportisHomogeneousAggregateQueryForAArch64());
111+
112+
// Aggregates <= 16 bytes are returned directly in registers or on the stack.
113+
if (Size <= 128) {
114+
if (Size <= 64 && !getDataLayout().isBigEndian()) {
115+
// Composite types are returned in lower bits of a 64-bit register for LE,
116+
// and in higher bits for BE. However, integer types are always returned
117+
// in lower bits for both LE and BE, and they are not rounded up to
118+
// 64-bits. We can skip rounding up of composite types for LE, but not for
119+
// BE, otherwise composite types will be indistinguishable from integer
120+
// types.
121+
return ABIArgInfo::getDirect(
122+
mlir::cir::IntType::get(LT.getMLIRContext(), Size, false));
123+
}
124+
125+
unsigned Alignment = getContext().getTypeAlign(RetTy);
126+
Size = llvm::alignTo(Size, 64); // round up to multiple of 8 bytes
127+
128+
// We use a pair of i64 for 16-byte aggregate with 8-byte alignment.
129+
// For aggregates with 16-byte alignment, we use i128.
130+
if (Alignment < 128 && Size == 128) {
131+
mlir::Type baseTy =
132+
mlir::cir::IntType::get(LT.getMLIRContext(), 64, false);
133+
return ABIArgInfo::getDirect(
134+
mlir::cir::ArrayType::get(LT.getMLIRContext(), baseTy, Size / 64));
135+
}
136+
137+
cir_cconv_unreachable("NYI");
138+
}
139+
108140
cir_cconv_unreachable("NYI");
109141
}
110142

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// RUN: %clang_cc1 -triple aarch64-unknown-linux-gnu -fclangir -fclangir-call-conv-lowering -emit-cir-flat -mmlir --mlir-print-ir-after=cir-call-conv-lowering %s -o %t.cir
2+
// RUN: FileCheck --input-file=%t.cir %s
3+
4+
#include <stdint.h>
5+
6+
typedef struct {
7+
short a;
8+
} LT_64;
9+
10+
typedef struct {
11+
int64_t a;
12+
} EQ_64;
13+
14+
typedef struct {
15+
int64_t a;
16+
int b;
17+
} LT_128;
18+
19+
typedef struct {
20+
int64_t a;
21+
int64_t b;
22+
} EQ_128;
23+
24+
// CHECK: cir.func {{.*@ret_lt_64}}() -> !u16i
25+
// CHECK: %[[#V0:]] = cir.alloca !ty_LT_64_, !cir.ptr<!ty_LT_64_>, ["__retval"]
26+
// CHECK: %[[#V1:]] = cir.cast(bitcast, %[[#V0]] : !cir.ptr<!ty_LT_64_>), !cir.ptr<!u16i>
27+
// CHECK: %[[#V2:]] = cir.load %[[#V1]] : !cir.ptr<!u16i>, !u16i
28+
// CHECK: cir.return %[[#V2]] : !u16i
29+
LT_64 ret_lt_64() {
30+
LT_64 x;
31+
return x;
32+
}
33+
34+
// CHECK: cir.func {{.*@ret_eq_64}}() -> !u64i
35+
// CHECK: %[[#V0:]] = cir.alloca !ty_EQ_64_, !cir.ptr<!ty_EQ_64_>, ["__retval"]
36+
// CHECK: %[[#V1:]] = cir.cast(bitcast, %[[#V0]] : !cir.ptr<!ty_EQ_64_>), !cir.ptr<!u64i>
37+
// CHECK: %[[#V2:]] = cir.load %[[#V1]] : !cir.ptr<!u64i>, !u64i
38+
// CHECK: cir.return %[[#V2]] : !u64i
39+
EQ_64 ret_eq_64() {
40+
EQ_64 x;
41+
return x;
42+
}
43+
44+
// CHECK: cir.func {{.*@ret_lt_128}}() -> !cir.array<!u64i x 2>
45+
// CHECK: %[[#V0:]] = cir.alloca !ty_LT_128_, !cir.ptr<!ty_LT_128_>, ["__retval"]
46+
// CHECK: %[[#V1:]] = cir.cast(bitcast, %[[#V0]] : !cir.ptr<!ty_LT_128_>), !cir.ptr<!cir.array<!u64i x 2>>
47+
// CHECK: %[[#V2:]] = cir.load %[[#V1]] : !cir.ptr<!cir.array<!u64i x 2>>, !cir.array<!u64i x 2>
48+
// CHECK: cir.return %[[#V2]] : !cir.array<!u64i x 2>
49+
LT_128 ret_lt_128() {
50+
LT_128 x;
51+
return x;
52+
}
53+
54+
// CHECK: cir.func {{.*@ret_eq_128}}() -> !cir.array<!u64i x 2>
55+
// CHECK: %[[#V0:]] = cir.alloca !ty_EQ_128_, !cir.ptr<!ty_EQ_128_>, ["__retval"]
56+
// CHECK: %[[#V1:]] = cir.cast(bitcast, %[[#V0]] : !cir.ptr<!ty_EQ_128_>), !cir.ptr<!cir.array<!u64i x 2>>
57+
// CHECK: %[[#V2:]] = cir.load %[[#V1]] : !cir.ptr<!cir.array<!u64i x 2>>, !cir.array<!u64i x 2>
58+
// CHECK: cir.return %[[#V2]] : !cir.array<!u64i x 2>
59+
EQ_128 ret_eq_128() {
60+
EQ_128 x;
61+
return x;
62+
}

0 commit comments

Comments
 (0)