Skip to content

Commit d30dfa8

Browse files
author
Melanie Blower
committed
[clang][patch] Add support for option -fextend-arguments={32,64}: widen integer arguments to int64 in unprototyped function calls
Reviewed By: Aaron Ballman Differential Revision: https://reviews.llvm.org/D101640
1 parent 9d09d20 commit d30dfa8

File tree

9 files changed

+173
-0
lines changed

9 files changed

+173
-0
lines changed

clang/include/clang/Basic/LangOptions.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,10 @@ LANGOPT(RelativeCXXABIVTables, 1, 0,
415415

416416
LANGOPT(ArmSveVectorBits, 32, 0, "SVE vector size in bits")
417417

418+
ENUM_LANGOPT(ExtendIntArgs, ExtendArgsKind, 1, ExtendArgsKind::ExtendTo32,
419+
"Controls how scalar integer arguments are extended in calls "
420+
"to unprototyped and varargs functions")
421+
418422
#undef LANGOPT
419423
#undef COMPATIBLE_LANGOPT
420424
#undef BENIGN_LANGOPT

clang/include/clang/Basic/LangOptions.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,13 @@ class LangOptions : public LangOptionsBase {
267267
Single
268268
};
269269

270+
enum class ExtendArgsKind {
271+
/// Integer arguments are sign or zero extended to 32/64 bits
272+
/// during default argument promotions.
273+
ExtendTo32,
274+
ExtendTo64
275+
};
276+
270277
public:
271278
/// The used language standard.
272279
LangStandard::Kind LangStd;

clang/include/clang/Basic/TargetInfo.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1415,6 +1415,9 @@ class TargetInfo : public virtual TransferrableTargetInfo,
14151415
bool isBigEndian() const { return BigEndian; }
14161416
bool isLittleEndian() const { return !BigEndian; }
14171417

1418+
/// Whether the option -fextend-arguments={32,64} is supported on the target.
1419+
virtual bool supportsExtendIntArgs() const { return false; }
1420+
14181421
/// Gets the default calling convention for the given target and
14191422
/// declaration context.
14201423
virtual CallingConv getDefaultCallingConv() const {

clang/include/clang/Driver/Options.td

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1451,6 +1451,14 @@ defm math_errno : BoolFOption<"math-errno",
14511451
PosFlag<SetTrue, [CC1Option], "Require math functions to indicate errors by setting errno">,
14521452
NegFlag<SetFalse>>,
14531453
ShouldParseIf<!strconcat("!", open_cl.KeyPath)>;
1454+
def fextend_args_EQ : Joined<["-"], "fextend-arguments=">, Group<f_Group>,
1455+
Flags<[CC1Option, NoArgumentUnused]>,
1456+
HelpText<"Controls how scalar integer arguments are extended in calls "
1457+
"to unprototyped and varargs functions">,
1458+
Values<"32,64">,
1459+
NormalizedValues<["ExtendTo32", "ExtendTo64"]>,
1460+
NormalizedValuesScope<"LangOptions::ExtendArgsKind">,
1461+
MarshallingInfoEnum<LangOpts<"ExtendIntArgs">,"ExtendTo32">;
14541462
def fbracket_depth_EQ : Joined<["-"], "fbracket-depth=">, Group<f_Group>, Flags<[CoreOption]>;
14551463
def fsignaling_math : Flag<["-"], "fsignaling-math">, Group<f_Group>;
14561464
def fno_signaling_math : Flag<["-"], "fno-signaling-math">, Group<f_Group>;

clang/lib/Basic/Targets/X86.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,10 @@ class LLVM_LIBRARY_VISIBILITY X86TargetInfo : public TargetInfo {
338338

339339
bool setFPMath(StringRef Name) override;
340340

341+
bool supportsExtendIntArgs() const override {
342+
return getTriple().getArch() != llvm::Triple::x86;
343+
}
344+
341345
CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
342346
// Most of the non-ARM calling conventions are i386 conventions.
343347
switch (CC) {

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4903,6 +4903,20 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
49034903

49044904
RenderFloatingPointOptions(TC, D, OFastEnabled, Args, CmdArgs, JA);
49054905

4906+
if (Arg *A = Args.getLastArg(options::OPT_fextend_args_EQ)) {
4907+
const llvm::Triple::ArchType Arch = TC.getArch();
4908+
if (Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64) {
4909+
StringRef V = A->getValue();
4910+
if (V == "64")
4911+
CmdArgs.push_back("-fextend-arguments=64");
4912+
else if (V != "32")
4913+
D.Diag(diag::err_drv_invalid_argument_to_option)
4914+
<< A->getValue() << A->getOption().getName();
4915+
} else
4916+
D.Diag(diag::err_drv_unsupported_opt_for_target)
4917+
<< A->getOption().getName() << TripleStr;
4918+
}
4919+
49064920
if (Arg *A = Args.getLastArg(options::OPT_mdouble_EQ)) {
49074921
if (TC.getArch() == llvm::Triple::avr)
49084922
A->render(Args, CmdArgs);

clang/lib/Sema/SemaExpr.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -821,6 +821,19 @@ ExprResult Sema::DefaultArgumentPromotion(Expr *E) {
821821
E = ImpCastExprToType(E, Context.DoubleTy, CK_FloatingCast).get();
822822
}
823823
}
824+
if (BTy &&
825+
getLangOpts().getExtendIntArgs() ==
826+
LangOptions::ExtendArgsKind::ExtendTo64 &&
827+
Context.getTargetInfo().supportsExtendIntArgs() && Ty->isIntegerType() &&
828+
Context.getTypeSizeInChars(BTy) <
829+
Context.getTypeSizeInChars(Context.LongLongTy)) {
830+
E = (Ty->isUnsignedIntegerType())
831+
? ImpCastExprToType(E, Context.UnsignedLongLongTy, CK_IntegralCast)
832+
.get()
833+
: ImpCastExprToType(E, Context.LongLongTy, CK_IntegralCast).get();
834+
assert(8 == Context.getTypeSizeInChars(Context.LongLongTy).getQuantity() &&
835+
"Unexpected typesize for LongLongTy");
836+
}
824837

825838
// C++ performs lvalue-to-rvalue conversion as a default argument
826839
// promotion, even on class types, but note:

clang/test/CodeGen/extend-arg-64.c

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
// RUN: %clang_cc1 -DD128 -triple x86_64-apple-darwin -fextend-arguments=64 \
2+
// RUN: %s -emit-llvm -o - | FileCheck %s -check-prefix=CHECKEXT
3+
4+
// When the option isn't selected, no effect
5+
// RUN: %clang_cc1 -DD128 -triple x86_64-apple-darwin \
6+
// RUN: %s -emit-llvm -o - | FileCheck %s \
7+
// RUN: --implicit-check-not "ext {{.*}}to i64"
8+
9+
// The option isn't supported on x86, no effect
10+
// RUN: %clang_cc1 -triple i386-pc-linux-gnu -fextend-arguments=64 \
11+
// RUN: %s -emit-llvm -o - | FileCheck %s \
12+
// RUN: --implicit-check-not "ext {{.*}}to i64"
13+
14+
// The option isn't supported on ppc, no effect
15+
// RUN: %clang_cc1 -triple ppc64le -fextend-arguments=64 \
16+
// RUN: %s -emit-llvm -o - | FileCheck %s \
17+
// RUN: --implicit-check-not "ext {{.*}}to i64"
18+
19+
int vararg(int, ...);
20+
void knr();
21+
22+
unsigned int u32;
23+
int s32;
24+
unsigned short u16;
25+
short s16;
26+
unsigned char u8;
27+
signed char s8;
28+
long long ll;
29+
_ExtInt(23) ei23;
30+
float ff;
31+
double dd;
32+
#ifdef D128
33+
__int128 i128;
34+
#endif
35+
36+
int test() {
37+
// CHECK: define{{.*}} i32 @test{{.*}}
38+
39+
// CHECKEXT: [[TAG_u32:%.*]] = load i32, i32* @u32{{.*}}
40+
// CHECKEXT: [[CONV_u32:%.*]] = zext i32 [[TAG_u32]] to i64
41+
42+
// CHECKEXT: [[TAG_s32:%.*]] = load i32, i32* @s32
43+
// CHECKEXT: [[CONV_s32:%.*]] = sext i32 [[TAG_s32]] to i64
44+
45+
// CHECKEXT: [[TAG_u16:%.*]] = load i16, i16* @u16
46+
// CHECKEXT: [[CONV_u16:%.*]] = zext i16 [[TAG_u16]] to i64
47+
48+
// CHECKEXT: [[TAG_s16:%.*]] = load i16, i16* @s16
49+
// CHECKEXT: [[CONV_s16:%.*]] = sext i16 [[TAG_s16]] to i64
50+
51+
// CHECKEXT: [[TAG_u8:%.*]] = load i8, i8* @u8
52+
// CHECKEXT: [[CONV_u8:%.*]] = zext i8 [[TAG_u8]] to i64
53+
54+
// CHECKEXT: [[TAG_s8:%.*]] = load i8, i8* @s8
55+
// CHECKEXT: [[CONV_s8:%.*]] = sext i8 [[TAG_s8]] to i64
56+
// CHECKEXT: call{{.*}} @vararg(i32 %0, i64 [[CONV_u32]], i64 [[CONV_s32]], i64 [[CONV_u16]], i64 [[CONV_s16]], i64 [[CONV_u8]], i64 [[CONV_s8]]
57+
58+
int sum = 0;
59+
sum = vararg(sum, u32, s32, u16, s16, u8, s8);
60+
knr(ll);
61+
// CHECKEXT: load i64, i64* @ll
62+
// CHECKEXT-NEXT: call void (i64, ...) bitcast {{.*}} @knr
63+
64+
knr(ei23);
65+
// CHECKEXT: load i23, i23* @ei23
66+
// CHECKEXT-NEXT: call void (i23, ...) bitcast{{.*}} @knr
67+
68+
knr(ff);
69+
// CHECKEXT: load float
70+
// CHECKEXT-NEXT: fpext float {{.*}} to double
71+
// CHECKEXT-NEXT: call{{.*}} void (double, ...) bitcast{{.*}} @knr
72+
73+
knr(dd);
74+
// CHECKEXT: load double
75+
// CHECKEXT-NEXT: call{{.*}} void (double, ...) bitcast{{.*}} @knr
76+
77+
#ifdef D128
78+
knr(i128);
79+
// CHECKEXT: load i128
80+
// CHECKEXT: call{{.*}} void (i64, i64, ...) bitcast{{.*}} @knr
81+
#endif
82+
83+
knr(u32, s32, u16, s16, u8, s8);
84+
// CHECKEXT: [[TAg_u32:%.*]] = load i32, i32* @u32{{.*}}
85+
// CHECKEXT: [[CONv_u32:%.*]] = zext i32 [[TAg_u32]] to i64
86+
87+
// CHECKEXT: [[TAg_s32:%.*]] = load i32, i32* @s32
88+
// CHECKEXT: [[CONv_s32:%.*]] = sext i32 [[TAg_s32]] to i64
89+
90+
// CHECKEXT: [[TAg_u16:%.*]] = load i16, i16* @u16
91+
// CHECKEXT: [[CONv_u16:%.*]] = zext i16 [[TAg_u16]] to i64
92+
93+
// CHECKEXT: [[TAg_s16:%.*]] = load i16, i16* @s16
94+
// CHECKEXT: [[CONv_s16:%.*]] = sext i16 [[TAg_s16]] to i64
95+
96+
// CHECKEXT: [[TAg_u8:%.*]] = load i8, i8* @u8
97+
// CHECKEXT: [[CONv_u8:%.*]] = zext i8 [[TAg_u8]] to i64
98+
99+
// CHECKEXT: [[TAg_s8:%.*]] = load i8, i8* @s8
100+
// CHECKEXT: [[CONv_s8:%.*]] = sext i8 [[TAg_s8]] to i64
101+
// CHECKEXT: call{{.*}} void (i64, i64, i64, i64, i64, i64, ...) bitcast{{.*}} @knr
102+
return sum;
103+
}

clang/test/Driver/fextend-args.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Options for intel arch
2+
// RUN: %clang -### -target x86_64-apple-darwin -fextend-arguments=32 %s 2>&1 \
3+
// RUN: | FileCheck --implicit-check-not "-fextend-arguments=32" %s
4+
// RUN: %clang -### -target x86_64-apple-darwin -fextend-arguments=64 %s 2>&1 \
5+
// RUN: | FileCheck -check-prefix=CHECK-64 %s
6+
7+
// Unsupported target
8+
// RUN: not %clang -target aarch64-unknown-windows-msvc -fextend-arguments=32 %s 2>&1 \
9+
// RUN: | FileCheck -check-prefix=UNSUPPORTED-TARGET %s
10+
11+
// Invalid option value
12+
// RUN: not %clang -target x86_64-apple-darwin -fextend-arguments=0 %s 2>&1 \
13+
// RUN: | FileCheck -check-prefix=INVALID-VALUE %s
14+
15+
// CHECK-64: "-cc1" {{.*}}"-fextend-arguments=64"
16+
// UNSUPPORTED-TARGET: error: unsupported option
17+
// INVALID-VALUE: error: invalid argument '0' to -fextend-arguments

0 commit comments

Comments
 (0)