[clang] d30dfa8 - [clang][patch] Add support for option -fextend-arguments={32,64}: widen integer arguments to int64 in unprototyped function calls
Melanie Blower via cfe-commits
cfe-commits at lists.llvm.org
Wed May 19 08:00:15 PDT 2021
Author: Melanie Blower
Date: 2021-05-19T10:59:56-04:00
New Revision: d30dfa86760ced9ac57f676340b34f2247898102
URL: https://github.com/llvm/llvm-project/commit/d30dfa86760ced9ac57f676340b34f2247898102
DIFF: https://github.com/llvm/llvm-project/commit/d30dfa86760ced9ac57f676340b34f2247898102.diff
LOG: [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
Added:
clang/test/CodeGen/extend-arg-64.c
clang/test/Driver/fextend-args.c
Modified:
clang/include/clang/Basic/LangOptions.def
clang/include/clang/Basic/LangOptions.h
clang/include/clang/Basic/TargetInfo.h
clang/include/clang/Driver/Options.td
clang/lib/Basic/Targets/X86.h
clang/lib/Driver/ToolChains/Clang.cpp
clang/lib/Sema/SemaExpr.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def
index 20c03987bd02..fff5fe23dc80 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -415,6 +415,10 @@ LANGOPT(RelativeCXXABIVTables, 1, 0,
LANGOPT(ArmSveVectorBits, 32, 0, "SVE vector size in bits")
+ENUM_LANGOPT(ExtendIntArgs, ExtendArgsKind, 1, ExtendArgsKind::ExtendTo32,
+ "Controls how scalar integer arguments are extended in calls "
+ "to unprototyped and varargs functions")
+
#undef LANGOPT
#undef COMPATIBLE_LANGOPT
#undef BENIGN_LANGOPT
diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h
index 454c101b2142..7fd4bf0eb206 100644
--- a/clang/include/clang/Basic/LangOptions.h
+++ b/clang/include/clang/Basic/LangOptions.h
@@ -267,6 +267,13 @@ class LangOptions : public LangOptionsBase {
Single
};
+ enum class ExtendArgsKind {
+ /// Integer arguments are sign or zero extended to 32/64 bits
+ /// during default argument promotions.
+ ExtendTo32,
+ ExtendTo64
+ };
+
public:
/// The used language standard.
LangStandard::Kind LangStd;
diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h
index b55a99051cfb..29b957607f3e 100644
--- a/clang/include/clang/Basic/TargetInfo.h
+++ b/clang/include/clang/Basic/TargetInfo.h
@@ -1415,6 +1415,9 @@ class TargetInfo : public virtual TransferrableTargetInfo,
bool isBigEndian() const { return BigEndian; }
bool isLittleEndian() const { return !BigEndian; }
+ /// Whether the option -fextend-arguments={32,64} is supported on the target.
+ virtual bool supportsExtendIntArgs() const { return false; }
+
/// Gets the default calling convention for the given target and
/// declaration context.
virtual CallingConv getDefaultCallingConv() const {
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index a876f48c5596..1b78810bf352 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -1451,6 +1451,14 @@ defm math_errno : BoolFOption<"math-errno",
PosFlag<SetTrue, [CC1Option], "Require math functions to indicate errors by setting errno">,
NegFlag<SetFalse>>,
ShouldParseIf<!strconcat("!", open_cl.KeyPath)>;
+def fextend_args_EQ : Joined<["-"], "fextend-arguments=">, Group<f_Group>,
+ Flags<[CC1Option, NoArgumentUnused]>,
+ HelpText<"Controls how scalar integer arguments are extended in calls "
+ "to unprototyped and varargs functions">,
+ Values<"32,64">,
+ NormalizedValues<["ExtendTo32", "ExtendTo64"]>,
+ NormalizedValuesScope<"LangOptions::ExtendArgsKind">,
+ MarshallingInfoEnum<LangOpts<"ExtendIntArgs">,"ExtendTo32">;
def fbracket_depth_EQ : Joined<["-"], "fbracket-depth=">, Group<f_Group>, Flags<[CoreOption]>;
def fsignaling_math : Flag<["-"], "fsignaling-math">, Group<f_Group>;
def fno_signaling_math : Flag<["-"], "fno-signaling-math">, Group<f_Group>;
diff --git a/clang/lib/Basic/Targets/X86.h b/clang/lib/Basic/Targets/X86.h
index 58b48ffd6328..0ba2fd6ba024 100644
--- a/clang/lib/Basic/Targets/X86.h
+++ b/clang/lib/Basic/Targets/X86.h
@@ -338,6 +338,10 @@ class LLVM_LIBRARY_VISIBILITY X86TargetInfo : public TargetInfo {
bool setFPMath(StringRef Name) override;
+ bool supportsExtendIntArgs() const override {
+ return getTriple().getArch() != llvm::Triple::x86;
+ }
+
CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
// Most of the non-ARM calling conventions are i386 conventions.
switch (CC) {
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 47552dcb6fdf..add62e3ab4ab 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -4903,6 +4903,20 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
RenderFloatingPointOptions(TC, D, OFastEnabled, Args, CmdArgs, JA);
+ if (Arg *A = Args.getLastArg(options::OPT_fextend_args_EQ)) {
+ const llvm::Triple::ArchType Arch = TC.getArch();
+ if (Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64) {
+ StringRef V = A->getValue();
+ if (V == "64")
+ CmdArgs.push_back("-fextend-arguments=64");
+ else if (V != "32")
+ D.Diag(diag::err_drv_invalid_argument_to_option)
+ << A->getValue() << A->getOption().getName();
+ } else
+ D.Diag(diag::err_drv_unsupported_opt_for_target)
+ << A->getOption().getName() << TripleStr;
+ }
+
if (Arg *A = Args.getLastArg(options::OPT_mdouble_EQ)) {
if (TC.getArch() == llvm::Triple::avr)
A->render(Args, CmdArgs);
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 51df75707145..16fab09a96dd 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -821,6 +821,19 @@ ExprResult Sema::DefaultArgumentPromotion(Expr *E) {
E = ImpCastExprToType(E, Context.DoubleTy, CK_FloatingCast).get();
}
}
+ if (BTy &&
+ getLangOpts().getExtendIntArgs() ==
+ LangOptions::ExtendArgsKind::ExtendTo64 &&
+ Context.getTargetInfo().supportsExtendIntArgs() && Ty->isIntegerType() &&
+ Context.getTypeSizeInChars(BTy) <
+ Context.getTypeSizeInChars(Context.LongLongTy)) {
+ E = (Ty->isUnsignedIntegerType())
+ ? ImpCastExprToType(E, Context.UnsignedLongLongTy, CK_IntegralCast)
+ .get()
+ : ImpCastExprToType(E, Context.LongLongTy, CK_IntegralCast).get();
+ assert(8 == Context.getTypeSizeInChars(Context.LongLongTy).getQuantity() &&
+ "Unexpected typesize for LongLongTy");
+ }
// C++ performs lvalue-to-rvalue conversion as a default argument
// promotion, even on class types, but note:
diff --git a/clang/test/CodeGen/extend-arg-64.c b/clang/test/CodeGen/extend-arg-64.c
new file mode 100644
index 000000000000..85b70e0238cb
--- /dev/null
+++ b/clang/test/CodeGen/extend-arg-64.c
@@ -0,0 +1,103 @@
+// RUN: %clang_cc1 -DD128 -triple x86_64-apple-darwin -fextend-arguments=64 \
+// RUN: %s -emit-llvm -o - | FileCheck %s -check-prefix=CHECKEXT
+
+// When the option isn't selected, no effect
+// RUN: %clang_cc1 -DD128 -triple x86_64-apple-darwin \
+// RUN: %s -emit-llvm -o - | FileCheck %s \
+// RUN: --implicit-check-not "ext {{.*}}to i64"
+
+// The option isn't supported on x86, no effect
+// RUN: %clang_cc1 -triple i386-pc-linux-gnu -fextend-arguments=64 \
+// RUN: %s -emit-llvm -o - | FileCheck %s \
+// RUN: --implicit-check-not "ext {{.*}}to i64"
+
+// The option isn't supported on ppc, no effect
+// RUN: %clang_cc1 -triple ppc64le -fextend-arguments=64 \
+// RUN: %s -emit-llvm -o - | FileCheck %s \
+// RUN: --implicit-check-not "ext {{.*}}to i64"
+
+int vararg(int, ...);
+void knr();
+
+unsigned int u32;
+int s32;
+unsigned short u16;
+short s16;
+unsigned char u8;
+signed char s8;
+long long ll;
+_ExtInt(23) ei23;
+float ff;
+double dd;
+#ifdef D128
+__int128 i128;
+#endif
+
+int test() {
+ // CHECK: define{{.*}} i32 @test{{.*}}
+
+ // CHECKEXT: [[TAG_u32:%.*]] = load i32, i32* @u32{{.*}}
+ // CHECKEXT: [[CONV_u32:%.*]] = zext i32 [[TAG_u32]] to i64
+
+ // CHECKEXT: [[TAG_s32:%.*]] = load i32, i32* @s32
+ // CHECKEXT: [[CONV_s32:%.*]] = sext i32 [[TAG_s32]] to i64
+
+ // CHECKEXT: [[TAG_u16:%.*]] = load i16, i16* @u16
+ // CHECKEXT: [[CONV_u16:%.*]] = zext i16 [[TAG_u16]] to i64
+
+ // CHECKEXT: [[TAG_s16:%.*]] = load i16, i16* @s16
+ // CHECKEXT: [[CONV_s16:%.*]] = sext i16 [[TAG_s16]] to i64
+
+ // CHECKEXT: [[TAG_u8:%.*]] = load i8, i8* @u8
+ // CHECKEXT: [[CONV_u8:%.*]] = zext i8 [[TAG_u8]] to i64
+
+ // CHECKEXT: [[TAG_s8:%.*]] = load i8, i8* @s8
+ // CHECKEXT: [[CONV_s8:%.*]] = sext i8 [[TAG_s8]] to i64
+ // CHECKEXT: call{{.*}} @vararg(i32 %0, i64 [[CONV_u32]], i64 [[CONV_s32]], i64 [[CONV_u16]], i64 [[CONV_s16]], i64 [[CONV_u8]], i64 [[CONV_s8]]
+
+ int sum = 0;
+ sum = vararg(sum, u32, s32, u16, s16, u8, s8);
+ knr(ll);
+ // CHECKEXT: load i64, i64* @ll
+ // CHECKEXT-NEXT: call void (i64, ...) bitcast {{.*}} @knr
+
+ knr(ei23);
+ // CHECKEXT: load i23, i23* @ei23
+ // CHECKEXT-NEXT: call void (i23, ...) bitcast{{.*}} @knr
+
+ knr(ff);
+ // CHECKEXT: load float
+ // CHECKEXT-NEXT: fpext float {{.*}} to double
+ // CHECKEXT-NEXT: call{{.*}} void (double, ...) bitcast{{.*}} @knr
+
+ knr(dd);
+ // CHECKEXT: load double
+ // CHECKEXT-NEXT: call{{.*}} void (double, ...) bitcast{{.*}} @knr
+
+#ifdef D128
+ knr(i128);
+ // CHECKEXT: load i128
+ // CHECKEXT: call{{.*}} void (i64, i64, ...) bitcast{{.*}} @knr
+#endif
+
+ knr(u32, s32, u16, s16, u8, s8);
+ // CHECKEXT: [[TAg_u32:%.*]] = load i32, i32* @u32{{.*}}
+ // CHECKEXT: [[CONv_u32:%.*]] = zext i32 [[TAg_u32]] to i64
+
+ // CHECKEXT: [[TAg_s32:%.*]] = load i32, i32* @s32
+ // CHECKEXT: [[CONv_s32:%.*]] = sext i32 [[TAg_s32]] to i64
+
+ // CHECKEXT: [[TAg_u16:%.*]] = load i16, i16* @u16
+ // CHECKEXT: [[CONv_u16:%.*]] = zext i16 [[TAg_u16]] to i64
+
+ // CHECKEXT: [[TAg_s16:%.*]] = load i16, i16* @s16
+ // CHECKEXT: [[CONv_s16:%.*]] = sext i16 [[TAg_s16]] to i64
+
+ // CHECKEXT: [[TAg_u8:%.*]] = load i8, i8* @u8
+ // CHECKEXT: [[CONv_u8:%.*]] = zext i8 [[TAg_u8]] to i64
+
+ // CHECKEXT: [[TAg_s8:%.*]] = load i8, i8* @s8
+ // CHECKEXT: [[CONv_s8:%.*]] = sext i8 [[TAg_s8]] to i64
+ // CHECKEXT: call{{.*}} void (i64, i64, i64, i64, i64, i64, ...) bitcast{{.*}} @knr
+ return sum;
+}
diff --git a/clang/test/Driver/fextend-args.c b/clang/test/Driver/fextend-args.c
new file mode 100644
index 000000000000..7f19f8c5ec48
--- /dev/null
+++ b/clang/test/Driver/fextend-args.c
@@ -0,0 +1,17 @@
+// Options for intel arch
+// RUN: %clang -### -target x86_64-apple-darwin -fextend-arguments=32 %s 2>&1 \
+// RUN: | FileCheck --implicit-check-not "-fextend-arguments=32" %s
+// RUN: %clang -### -target x86_64-apple-darwin -fextend-arguments=64 %s 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK-64 %s
+
+// Unsupported target
+// RUN: not %clang -target aarch64-unknown-windows-msvc -fextend-arguments=32 %s 2>&1 \
+// RUN: | FileCheck -check-prefix=UNSUPPORTED-TARGET %s
+
+// Invalid option value
+// RUN: not %clang -target x86_64-apple-darwin -fextend-arguments=0 %s 2>&1 \
+// RUN: | FileCheck -check-prefix=INVALID-VALUE %s
+
+// CHECK-64: "-cc1" {{.*}}"-fextend-arguments=64"
+// UNSUPPORTED-TARGET: error: unsupported option
+// INVALID-VALUE: error: invalid argument '0' to -fextend-arguments
More information about the cfe-commits
mailing list