Properly factor Native Client defines to support NaCl as an OS

with x86/ARM architecture

llvm-svn: 165722
This commit is contained in:
Derek Schuff 2012-10-11 16:55:58 +00:00
parent d0d7860f40
commit 57b7e8f63f
7 changed files with 238 additions and 11 deletions

View 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);
}

View 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;

View 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 {

View File

@ -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) {}

View File

@ -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);
}

View File

@ -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

View File

@ -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");