Properly factor Native Client defines to support NaCl as an OS
authorDerek Schuff <dschuff@google.com>
Thu, 11 Oct 2012 16:55:58 +0000 (16:55 +0000)
committerDerek Schuff <dschuff@google.com>
Thu, 11 Oct 2012 16:55:58 +0000 (16:55 +0000)
with x86/ARM architecture

llvm-svn: 165722

clang/lib/Basic/Targets.cpp
clang/lib/CodeGen/TargetInfo.cpp
clang/test/CodeGen/arm-aapcs-vfp.c
clang/test/CodeGen/long-double-x86-nacl.c [new file with mode: 0644]
clang/test/CodeGen/x86_64-arguments-nacl.c [new file with mode: 0644]
clang/test/Driver/x86_64-nacl-defines.cpp [new file with mode: 0644]
clang/test/Driver/x86_64-nacl-types.cpp [new file with mode: 0644]

index 4948ba4..d421b05 100644 (file)
@@ -590,6 +590,43 @@ public:
     : OSTargetInfo<Target>(triple) {}
 };
 
+template <typename Target>
+class NaClTargetInfo : public OSTargetInfo<Target> {
+ protected:
+  virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+                            MacroBuilder &Builder) const {
+    if (Opts.POSIXThreads)
+      Builder.defineMacro("_REENTRANT");
+    if (Opts.CPlusPlus)
+      Builder.defineMacro("_GNU_SOURCE");
+
+    DefineStd(Builder, "unix", Opts);
+    Builder.defineMacro("__ELF__");
+    Builder.defineMacro("__native_client__");
+  }
+ public:
+  NaClTargetInfo(const std::string &triple)
+    : OSTargetInfo<Target>(triple) {
+    this->UserLabelPrefix = "";
+    this->LongAlign = 32;
+    this->LongWidth = 32;
+    this->PointerAlign = 32;
+    this->PointerWidth = 32;
+    this->IntMaxType = TargetInfo::SignedLongLong;
+    this->UIntMaxType = TargetInfo::UnsignedLongLong;
+    this->Int64Type = TargetInfo::SignedLongLong;
+    this->DoubleAlign = 64;
+    this->LongDoubleWidth = 64;
+    this->LongDoubleAlign = 64;
+    this->SizeType = TargetInfo::UnsignedInt;
+    this->PtrDiffType = TargetInfo::SignedInt;
+    this->IntPtrType = TargetInfo::SignedInt;
+    this->RegParmMax = 2;
+    this->LongDoubleFormat = &llvm::APFloat::IEEEdouble;
+    this->DescriptionString = "e-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-"
+                              "f32:32:32-f64:64:64-p:32:32:32-v128:32:32";
+  }
+};
 } // end anonymous namespace.
 
 //===----------------------------------------------------------------------===//
@@ -4197,15 +4234,7 @@ public:
   }
   virtual void getTargetDefines(const LangOptions &Opts,
                                 MacroBuilder &Builder) const {
-    DefineStd(Builder, "unix", Opts);
-    Builder.defineMacro("__ELF__");
-    if (Opts.POSIXThreads)
-      Builder.defineMacro("_REENTRANT");
-    if (Opts.CPlusPlus)
-      Builder.defineMacro("_GNU_SOURCE");
-
     Builder.defineMacro("__LITTLE_ENDIAN__");
-    Builder.defineMacro("__native_client__");
     getArchDefines(Opts, Builder);
   }
   virtual bool hasFeature(StringRef Feature) const {
@@ -4278,6 +4307,8 @@ static TargetInfo *AllocateTarget(const std::string &T) {
       return new BitrigTargetInfo<ARMTargetInfo>(T);
     case llvm::Triple::RTEMS:
       return new RTEMSTargetInfo<ARMTargetInfo>(T);
+    case llvm::Triple::NativeClient:
+      return new NaClTargetInfo<ARMTargetInfo>(T);
     default:
       return new ARMTargetInfo(T);
     }
@@ -4348,7 +4379,7 @@ static TargetInfo *AllocateTarget(const std::string &T) {
   case llvm::Triple::le32:
     switch (os) {
       case llvm::Triple::NativeClient:
-        return new PNaClTargetInfo(T);
+        return new NaClTargetInfo<PNaClTargetInfo>(T);
       default:
         return NULL;
     }
@@ -4453,6 +4484,8 @@ static TargetInfo *AllocateTarget(const std::string &T) {
       return new HaikuX86_32TargetInfo(T);
     case llvm::Triple::RTEMS:
       return new RTEMSX86_32TargetInfo(T);
+    case llvm::Triple::NativeClient:
+      return new NaClTargetInfo<X86_32TargetInfo>(T);
     default:
       return new X86_32TargetInfo(T);
     }
@@ -4482,6 +4515,8 @@ static TargetInfo *AllocateTarget(const std::string &T) {
       return new MinGWX86_64TargetInfo(T);
     case llvm::Triple::Win32:   // This is what Triple.h supports now.
       return new VisualStudioWindowsX86_64TargetInfo(T);
+    case llvm::Triple::NativeClient:
+      return new NaClTargetInfo<X86_64TargetInfo>(T);
     default:
       return new X86_64TargetInfo(T);
     }
index 3136245..887ca89 100644 (file)
@@ -1333,7 +1333,10 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase,
       Hi = Integer;
     } else if (k >= BuiltinType::Bool && k <= BuiltinType::LongLong) {
       Current = Integer;
-    } else if (k == BuiltinType::Float || k == BuiltinType::Double) {
+    } else if ((k == BuiltinType::Float || k == BuiltinType::Double) ||
+               (k == BuiltinType::LongDouble &&
+                getContext().getTargetInfo().getTriple().getOS() ==
+                llvm::Triple::NativeClient)) {
       Current = SSE;
     } else if (k == BuiltinType::LongDouble) {
       Lo = X87;
@@ -1419,7 +1422,10 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase,
         Lo = Hi = Integer;
     } else if (ET == getContext().FloatTy)
       Current = SSE;
-    else if (ET == getContext().DoubleTy)
+    else if (ET == getContext().DoubleTy ||
+             (ET == getContext().LongDoubleTy &&
+              getContext().getTargetInfo().getTriple().getOS() ==
+              llvm::Triple::NativeClient))
       Lo = Hi = SSE;
     else if (ET == getContext().LongDoubleTy)
       Current = ComplexX87;
index 614b52d..7210229 100644 (file)
@@ -6,6 +6,12 @@
 // RUN:   -ffreestanding \
 // RUN:   -emit-llvm -w -o - %s | FileCheck %s
 
+// RUN: %clang_cc1 -triple armv7-unknown-nacl-gnueabi \
+// RUN:  -target-cpu cortex-a8 \
+// RUN:  -mfloat-abi hard \
+// RUN:  -ffreestanding \
+// RUN:  -emit-llvm -w -o - %s | FileCheck %s
+
 #include <arm_neon.h>
 
 struct homogeneous_struct {
diff --git a/clang/test/CodeGen/long-double-x86-nacl.c b/clang/test/CodeGen/long-double-x86-nacl.c
new file mode 100644 (file)
index 0000000..175129c
--- /dev/null
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 %s -emit-llvm -o - -triple=i686-unknown-nacl | FileCheck %s
+
+long double x = 0;
+int checksize[sizeof(x) == 8 ? 1 : -1];
+
+// CHECK: define void @s1(double %a)
+void s1(long double a) {}
diff --git a/clang/test/CodeGen/x86_64-arguments-nacl.c b/clang/test/CodeGen/x86_64-arguments-nacl.c
new file mode 100644 (file)
index 0000000..d864a75
--- /dev/null
@@ -0,0 +1,92 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-nacl -emit-llvm -o - %s| FileCheck %s
+#include <stdarg.h>
+// Test for x86-64 structure representation (instead of pnacl representation),
+// in particular for unions. Also crib a few tests from x86 Linux.
+
+union PP_VarValue {
+  int as_int;
+  double as_double;
+  long long as_i64;
+};
+
+struct PP_Var {
+  int type;
+  int padding;
+  union PP_VarValue value;
+};
+
+// CHECK: define { i64, i64 } @f0()
+struct PP_Var f0() {
+  struct PP_Var result = { 0, 0, 0 };
+  return result;
+}
+
+// CHECK: define void @f1(i64 %p1.coerce0, i64 %p1.coerce1)
+void f1(struct PP_Var p1) { while(1) {} }
+
+// long doubles are 64 bits on NaCl
+// CHECK: define double @f5()
+long double f5(void) {
+  return 0;
+}
+
+// CHECK: define void @f6(i8 signext %a0, i16 signext %a1, i32 %a2, i64 %a3, i8* %a4)
+void f6(char a0, short a1, int a2, long long a3, void *a4) {
+}
+
+// CHECK: define i64 @f8_1()
+// CHECK: define void @f8_2(i64 %a0.coerce)
+union u8 {
+  long double a;
+  int b;
+};
+union u8 f8_1() { while (1) {} }
+void f8_2(union u8 a0) {}
+
+// CHECK: define i64 @f9()
+struct s9 { int a; int b; int : 0; } f9(void) { while (1) {} }
+
+// CHECK: define void @f10(i64 %a0.coerce)
+struct s10 { int a; int b; int : 0; };
+void f10(struct s10 a0) {}
+
+// CHECK: define double @f11()
+union { long double a; float b; } f11() { while (1) {} }
+
+// CHECK: define i32 @f12_0()
+// CHECK: define void @f12_1(i32 %a0.coerce)
+struct s12 { int a __attribute__((aligned(16))); };
+struct s12 f12_0(void) { while (1) {} }
+void f12_1(struct s12 a0) {}
+
+// Check that sret parameter is accounted for when checking available integer
+// registers.
+// CHECK: define void @f13(%struct.s13_0* noalias sret %agg.result, i32 %a, i32 %b, i32 %c, i32 %d, {{.*}}* byval align 8 %e, i32 %f)
+
+struct s13_0 { long long f0[3]; };
+struct s13_1 { long long f0[2]; };
+struct s13_0 f13(int a, int b, int c, int d,
+                 struct s13_1 e, int f) { while (1) {} }
+
+// CHECK: define void @f20(%struct.s20* byval align 32 %x)
+struct __attribute__((aligned(32))) s20 {
+  int x;
+  int y;
+};
+void f20(struct s20 x) {}
+
+
+// CHECK: declare void @func(i64)
+typedef struct _str {
+  union {
+    long double a;
+    long c;
+  };
+} str;
+
+void func(str s);
+str ss;
+void f9122143()
+{
+  func(ss);
+}
diff --git a/clang/test/Driver/x86_64-nacl-defines.cpp b/clang/test/Driver/x86_64-nacl-defines.cpp
new file mode 100644 (file)
index 0000000..caa9a74
--- /dev/null
@@ -0,0 +1,45 @@
+// RUN: %clang -target x86_64-unknown-nacl -ccc-echo %s -emit-llvm-only -c 2>&1 | FileCheck %s -check-prefix=ECHO
+// RUN: %clang -target x86_64-unknown-nacl %s -emit-llvm -S -c -o - | FileCheck %s
+// RUN: %clang -target x86_64-unknown-nacl %s -emit-llvm -S -c -pthread -o - | FileCheck %s -check-prefix=THREADS
+
+// ECHO: {{.*}} -cc1 {{.*}}x86_64-nacl-defines.c
+
+// Check platform defines
+
+// CHECK: __LITTLE_ENDIAN__defined
+#ifdef __LITTLE_ENDIAN__
+void __LITTLE_ENDIAN__defined() {}
+#endif
+
+// CHECK: __native_client__defined
+#ifdef __native_client__
+void __native_client__defined() {}
+#endif
+
+// CHECK: __x86_64__defined
+#ifdef __x86_64__
+void __x86_64__defined() {}
+#endif
+
+// CHECK: unixdefined
+#ifdef unix
+void unixdefined() {}
+#endif
+
+// CHECK: __ELF__defined
+#ifdef __ELF__
+void __ELF__defined() {}
+#endif
+
+// CHECK: _GNU_SOURCEdefined
+#ifdef _GNU_SOURCE
+void _GNU_SOURCEdefined() {}
+#endif
+
+// THREADS: _REENTRANTdefined
+// CHECK: _REENTRANTundefined
+#ifdef _REENTRANT
+void _REENTRANTdefined() {}
+#else
+void _REENTRANTundefined() {}
+#endif
diff --git a/clang/test/Driver/x86_64-nacl-types.cpp b/clang/test/Driver/x86_64-nacl-types.cpp
new file mode 100644 (file)
index 0000000..2cdc26d
--- /dev/null
@@ -0,0 +1,36 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-nacl -std=c++11 -verify %s
+
+#include <stddef.h>
+#include <stdarg.h>
+
+static_assert(alignof(char) == 1, "alignof char is wrong");
+
+static_assert(alignof(short) == 2, "sizeof short is wrong");
+static_assert(alignof(short) == 2, "alignof short is wrong");
+
+static_assert(alignof(int) == 4, "sizeof int is wrong");
+static_assert(alignof(int) == 4, "alignof int is wrong");
+
+static_assert(sizeof(long) == 4, "sizeof long is wrong");
+static_assert(sizeof(long) == 4, "alignof long is wrong");
+
+static_assert(sizeof(long long) == 8, "sizeof long long is wrong wrong");
+static_assert(alignof(long long) == 8, "alignof long long is wrong wrong");
+
+static_assert(sizeof(void*) == 4, "sizeof void * is wrong");
+static_assert(alignof(void*) == 4, "alignof void * is wrong");
+
+static_assert(sizeof(float) == 4, "sizeof float is wrong");
+static_assert(alignof(float) == 4, "alignof float is wrong");
+
+static_assert(sizeof(double) == 8, "sizeof double is wrong");
+static_assert(alignof(double) == 8, "alignof double is wrong");
+
+static_assert(sizeof(long double) == 8, "sizeof long double is wrong");
+static_assert(alignof(long double) == 8, "alignof long double is wrong");
+
+static_assert(sizeof(va_list) == 16, "sizeof va_list is wrong");
+static_assert(alignof(va_list) == 4, "alignof va_list is wrong");
+
+static_assert(sizeof(size_t) == 4, "sizeof size_t is wrong");
+static_assert(alignof(size_t) == 4, "alignof size_t is wrong");