mibintc created this revision.
mibintc added reviewers: kbsmith1, erichkeane.
mibintc added a project: clang-c.
Herald added subscribers: dexonsmith, dang, Anastasia.
mibintc requested review of this revision.
Herald added a project: clang.

The Intel C++ and Fortran compilers support the option 
-fextend-arguments={32,64}. One of our customers has requested that this 
support be added clang.  This option controls how scalar integral arguments are 
extended in calls to unprototyped and varargs functions. When we investigated 
the support for the ICL option, we discovered that "-fextend-arguments=32" had 
no effect in the generated code, so this patch proposes to support only 64 bit 
extension.  This patch is only meaningful for targets that pass int arguments 
in 64 bits.

For supported targets, signed int values are sign extended to 64 bits in the 
parameter list, and unsigned int values are zero extended to 64 bits.

@kbsmith1 tells me that this option is primarily useful for porting 32-bit 
programs to the 64-bit environment, and although that architecture shift 
happened years ago, the customer is still interested in this support.

It turns out that there is currently similar logic in clang support for the 
OpenCL option "cl_khr_fp64" which causes certain float arguments, in 
unprototyped context, to be expanded to float or double.

Will this change be acceptable?


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D101640

Files:
  clang/include/clang/Basic/LangOptions.def
  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
  clang/test/CodeGen/extend-arg-64.c

Index: clang/test/CodeGen/extend-arg-64.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/extend-arg-64.c
@@ -0,0 +1,53 @@
+// RUN: %clang_cc1 -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 -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, ...);
+
+unsigned int u32;
+int s32;
+unsigned short u16;
+short s16;
+unsigned char u8;
+signed char s8;
+
+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);
+  return sum;
+}
Index: clang/lib/Sema/SemaExpr.cpp
===================================================================
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -821,6 +821,15 @@
       E = ImpCastExprToType(E, Context.DoubleTy, CK_FloatingCast).get();
     }
   }
+  if (BTy && getLangOpts().ExtendArgs64 &&
+      Context.getTargetInfo().supportsExtendArgs64() && Ty->isIntegerType()) {
+    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:
Index: clang/lib/Driver/ToolChains/Clang.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -4908,6 +4908,9 @@
 
   RenderFloatingPointOptions(TC, D, OFastEnabled, Args, CmdArgs, JA);
 
+  if (Args.getLastArg(options::OPT_fextend_args_64))
+    CmdArgs.push_back("-fextend-arguments-64");
+
   if (Arg *A = Args.getLastArg(options::OPT_mdouble_EQ)) {
     if (TC.getArch() == llvm::Triple::avr)
       A->render(Args, CmdArgs);
Index: clang/lib/Basic/Targets/X86.h
===================================================================
--- clang/lib/Basic/Targets/X86.h
+++ clang/lib/Basic/Targets/X86.h
@@ -336,6 +336,10 @@
 
   bool setFPMath(StringRef Name) override;
 
+  bool supportsExtendArgs64() 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) {
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -1427,6 +1427,11 @@
   PosFlag<SetTrue, [CC1Option], "Require math functions to indicate errors by setting errno">,
   NegFlag<SetFalse>>,
   ShouldParseIf<!strconcat("!", open_cl.KeyPath)>;
+def fextend_args_64 : Flag<["-"], "fextend-arguments-64">, Group<f_Group>,
+  Flags<[CC1Option, NoArgumentUnused]>,
+  HelpText<"Controls how scalar integer arguments are extended in calls"
+           " to unprototyped and varargs functions">,
+  MarshallingInfoFlag<LangOpts<"ExtendArgs64">>;
 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>;
Index: clang/include/clang/Basic/TargetInfo.h
===================================================================
--- clang/include/clang/Basic/TargetInfo.h
+++ clang/include/clang/Basic/TargetInfo.h
@@ -1412,6 +1412,8 @@
   bool isBigEndian() const { return BigEndian; }
   bool isLittleEndian() const { return !BigEndian; }
 
+  virtual bool supportsExtendArgs64() const { return false; }
+
   /// Gets the default calling convention for the given target and
   /// declaration context.
   virtual CallingConv getDefaultCallingConv() const {
Index: clang/include/clang/Basic/LangOptions.def
===================================================================
--- clang/include/clang/Basic/LangOptions.def
+++ clang/include/clang/Basic/LangOptions.def
@@ -414,6 +414,10 @@
 
 LANGOPT(ArmSveVectorBits, 32, 0, "SVE vector size in bits")
 
+COMPATIBLE_LANGOPT(ExtendArgs64, 1, 0, 
+                   "Controls how scalar integer arguments are extended in calls"
+                   " to unprototyped and varargs functions")
+
 #undef LANGOPT
 #undef COMPATIBLE_LANGOPT
 #undef BENIGN_LANGOPT
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to