Skip to content

Commit 53fac69

Browse files
committed
ABI/x86-32 & x86-64: Alignment on 'byval' must be set when when the alignment
exceeds the minimum ABI alignment. llvm-svn: 102019
1 parent f5dbc07 commit 53fac69

File tree

3 files changed

+67
-20
lines changed

3 files changed

+67
-20
lines changed

clang/lib/CodeGen/TargetInfo.cpp

Lines changed: 40 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -292,9 +292,6 @@ class X86_32ABIInfo : public ABIInfo {
292292

293293
static bool shouldReturnTypeInRegister(QualType Ty, ASTContext &Context);
294294

295-
static unsigned getIndirectArgumentAlignment(QualType Ty,
296-
ASTContext &Context);
297-
298295
/// getIndirectResult - Give a source type \arg Ty, return a suitable result
299296
/// such that the argument will be passed in memory.
300297
ABIArgInfo getIndirectResult(QualType Ty, ASTContext &Context,
@@ -496,21 +493,19 @@ ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy,
496493
}
497494
}
498495

499-
unsigned X86_32ABIInfo::getIndirectArgumentAlignment(QualType Ty,
500-
ASTContext &Context) {
501-
unsigned Align = Context.getTypeAlign(Ty);
502-
if (Align < 128) return 0;
503-
if (const RecordType* RT = Ty->getAs<RecordType>())
504-
if (typeContainsSSEVector(RT->getDecl(), Context))
505-
return 16;
506-
return 0;
507-
}
508-
509496
ABIArgInfo X86_32ABIInfo::getIndirectResult(QualType Ty,
510497
ASTContext &Context,
511498
bool ByVal) const {
512-
return ABIArgInfo::getIndirect(getIndirectArgumentAlignment(Ty, Context),
513-
ByVal);
499+
if (!ByVal)
500+
return ABIArgInfo::getIndirect(0, false);
501+
502+
// Compute the byval alignment. We trust the back-end to honor the
503+
// minimum ABI alignment for byval, to make cleaner IR.
504+
const unsigned MinABIAlign = 4;
505+
unsigned Align = Context.getTypeAlign(Ty) / 8;
506+
if (Align > MinABIAlign)
507+
return ABIArgInfo::getIndirect(Align);
508+
return ABIArgInfo::getIndirect(0);
514509
}
515510

516511
ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
@@ -696,6 +691,10 @@ class X86_64ABIInfo : public ABIInfo {
696691
const llvm::Type *CoerceTo,
697692
ASTContext &Context) const;
698693

694+
/// getIndirectResult - Give a source type \arg Ty, return a suitable result
695+
/// such that the argument will be returned in memory.
696+
ABIArgInfo getIndirectReturnResult(QualType Ty, ASTContext &Context) const;
697+
699698
/// getIndirectResult - Give a source type \arg Ty, return a suitable result
700699
/// such that the argument will be passed in memory.
701700
ABIArgInfo getIndirectResult(QualType Ty, ASTContext &Context) const;
@@ -1071,6 +1070,22 @@ ABIArgInfo X86_64ABIInfo::getCoerceResult(QualType Ty,
10711070
return ABIArgInfo::getCoerce(CoerceTo);
10721071
}
10731072

1073+
ABIArgInfo X86_64ABIInfo::getIndirectReturnResult(QualType Ty,
1074+
ASTContext &Context) const {
1075+
// If this is a scalar LLVM value then assume LLVM will pass it in the right
1076+
// place naturally.
1077+
if (!CodeGenFunction::hasAggregateLLVMType(Ty)) {
1078+
// Treat an enum type as its underlying type.
1079+
if (const EnumType *EnumTy = Ty->getAs<EnumType>())
1080+
Ty = EnumTy->getDecl()->getIntegerType();
1081+
1082+
return (Ty->isPromotableIntegerType() ?
1083+
ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
1084+
}
1085+
1086+
return ABIArgInfo::getIndirect(0);
1087+
}
1088+
10741089
ABIArgInfo X86_64ABIInfo::getIndirectResult(QualType Ty,
10751090
ASTContext &Context) const {
10761091
// If this is a scalar LLVM value then assume LLVM will pass it in the right
@@ -1084,10 +1099,16 @@ ABIArgInfo X86_64ABIInfo::getIndirectResult(QualType Ty,
10841099
ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
10851100
}
10861101

1087-
bool ByVal = !isRecordWithNonTrivialDestructorOrCopyConstructor(Ty);
1102+
if (isRecordWithNonTrivialDestructorOrCopyConstructor(Ty))
1103+
return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
10881104

1089-
// FIXME: Set alignment correctly.
1090-
return ABIArgInfo::getIndirect(0, ByVal);
1105+
// Compute the byval alignment. We trust the back-end to honor the
1106+
// minimum ABI alignment for byval, to make cleaner IR.
1107+
const unsigned MinABIAlign = 8;
1108+
unsigned Align = Context.getTypeAlign(Ty) / 8;
1109+
if (Align > MinABIAlign)
1110+
return ABIArgInfo::getIndirect(Align);
1111+
return ABIArgInfo::getIndirect(0);
10911112
}
10921113

10931114
ABIArgInfo X86_64ABIInfo::classifyReturnType(QualType RetTy,
@@ -1115,7 +1136,7 @@ ABIArgInfo X86_64ABIInfo::classifyReturnType(QualType RetTy,
11151136
// AMD64-ABI 3.2.3p4: Rule 2. Types of class memory are returned via
11161137
// hidden argument.
11171138
case Memory:
1118-
return getIndirectResult(RetTy, Context);
1139+
return getIndirectReturnResult(RetTy, Context);
11191140

11201141
// AMD64-ABI 3.2.3p4: Rule 3. If the class is INTEGER, the next
11211142
// available register of the sequence %rax, %rdx is used.

clang/test/CodeGen/x86_32-arguments.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,3 +202,15 @@ void f50(struct s50 a0) { }
202202
struct s51 { vvbp f0; int f1; };
203203
void f51(struct s51 a0) { }
204204

205+
// CHECK: define void @f52(%struct.s52* byval align 16 %x)
206+
struct s52 {
207+
long double a;
208+
};
209+
void f52(struct s52 x) {}
210+
211+
// CHECK: define void @f53(%struct.s53* byval align 32 %x)
212+
struct __attribute__((aligned(32))) s53 {
213+
int x;
214+
int y;
215+
};
216+
void f53(struct s53 x) {}

clang/test/CodeGen/x86_64-arguments.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ struct s9 { int a; int b; int : 0; } f9(void) { while (1) {} }
6060
struct s10 { int a; int b; int : 0; };
6161
void f10(struct s10 a0) {}
6262

63-
// CHECK: define void @f11(%union.anon* sret %agg.result)
63+
// CHECK: define void @f11(%struct.s19* sret %agg.result)
6464
union { long double a; float b; } f11() { while (1) {} }
6565

6666
// CHECK: define i64 @f12_0()
@@ -99,3 +99,17 @@ void f17(float a, float b, float c, float d, float e, float f, float g, float h,
9999
struct f18_s0 { int f0; };
100100
void f18(int a, struct f18_s0 f18_arg1) { while (1) {} }
101101

102+
// Check byval alignment.
103+
104+
// CHECK: define void @f19(%struct.s19* byval align 16 %x)
105+
struct s19 {
106+
long double a;
107+
};
108+
void f19(struct s19 x) {}
109+
110+
// CHECK: define void @f20(%struct.s20* byval align 32 %x)
111+
struct __attribute__((aligned(32))) s20 {
112+
int x;
113+
int y;
114+
};
115+
void f20(struct s20 x) {}

0 commit comments

Comments
 (0)