diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp
index b254732..e535e62 100644
--- a/lib/Basic/Targets.cpp
+++ b/lib/Basic/Targets.cpp
@@ -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.
 
 //===----------------------------------------------------------------------===//
@@ -4135,15 +4172,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 {
@@ -4216,6 +4245,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);
     }
@@ -4286,7 +4317,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;
     }
@@ -4391,6 +4422,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);
     }
@@ -4420,6 +4453,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);
     }
diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp
index fb29b06..04828ce 100644
--- a/lib/CodeGen/TargetInfo.cpp
+++ b/lib/CodeGen/TargetInfo.cpp
@@ -1330,7 +1330,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;
@@ -1416,7 +1419,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;
diff --git a/test/CodeGen/arm-aapcs-vfp.c b/test/CodeGen/arm-aapcs-vfp.c
index 614b52d..23b9c30 100644
--- a/test/CodeGen/arm-aapcs-vfp.c
+++ b/test/CodeGen/arm-aapcs-vfp.c
@@ -6,6 +6,10 @@
 // RUN:   -ffreestanding \
 // RUN:   -emit-llvm -w -o - %s | FileCheck %s
 
+// RUN: %clang_cc1 -triple armv7-unknown-nacl-gnueabihf \
+// RUN:   -ffreestanding \
+// RUN:   -emit-llvm -w -o - %s | FileCheck %s
+
 #include <arm_neon.h>
 
 struct homogeneous_struct {
diff --git a/test/CodeGen/long-double-x86-nacl.c b/test/CodeGen/long-double-x86-nacl.c
new file mode 100644
index 0000000..175129c
--- /dev/null
+++ b/test/CodeGen/long-double-x86-nacl.c
@@ -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/test/CodeGen/x86_64-arguments-nacl.c b/test/CodeGen/x86_64-arguments-nacl.c
new file mode 100644
index 0000000..314524e
--- /dev/null
+++ b/test/CodeGen/x86_64-arguments-nacl.c
@@ -0,0 +1,347 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-nacl -emit-llvm -o - %s| FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-unknown-nacl -emit-llvm -o - %s -target-feature +avx | FileCheck %s -check-prefix=AVX
+#include <stdarg.h>
+
+// CHECK: define signext i8 @f0()
+char f0(void) {
+  return 0;
+}
+
+// CHECK: define signext i16 @f1()
+short f1(void) {
+  return 0;
+}
+
+// CHECK: define i32 @f2()
+int f2(void) {
+  return 0;
+}
+
+// CHECK: define float @f3()
+float f3(void) {
+  return 0;
+}
+
+// CHECK: define double @f4()
+double f4(void) {
+  return 0;
+}
+
+// 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 void @f7(i32 %a0)
+typedef enum { A, B, C } e7;
+void f7(e7 a0) {
+}
+
+
+// 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 @f14({{.*}}, i8 signext %X)
+void f14(int a, int b, int c, int d, int e, int f, char X) {}
+
+// CHECK: define void @f15({{.*}}, i8* %X)
+void f15(int a, int b, int c, int d, int e, int f, void *X) {}
+
+// CHECK: define void @f16({{.*}}, float %X)
+void f16(float a, float b, float c, float d, float e, float f, float g, float h,
+         float X) {}
+
+// CHECK: define void @f17({{.*}}, double %X)
+void f17(float a, float b, float c, float d, float e, float f, float g, float h,
+         long double X) {}
+
+// Check for valid coercion.  The struct should be passed/returned as i32, not
+// as i64 for better code quality.
+// rdar://8135035
+// CHECK: define void @f18(i32 %a, i32 %f18_arg1.coerce) 
+struct f18_s0 { int f0; };
+void f18(int a, struct f18_s0 f18_arg1) { while (1) {} }
+
+// Check byval alignment.
+
+// CHECK: define void @f19(double %x.coerce)
+struct s19 {
+  long double a;
+};
+void f19(struct s19 x) {}
+
+// CHECK: define void @f20(%struct.s20* byval align 32 %x)
+struct __attribute__((aligned(32))) s20 {
+  int x;
+  int y;
+};
+void f20(struct s20 x) {}
+
+struct StringRef {
+  long x;
+  const char *Ptr;
+};
+
+// CHECK: define i8* @f21(i64 %S.coerce)
+const char *f21(struct StringRef S) { return S.x+S.Ptr; }
+
+// PR7567
+typedef __attribute__ ((aligned(16))) struct f22s { unsigned long long x[2]; } L;
+void f22(L x, L y) { }
+// CHECK: @f22
+// CHECK: %x = alloca{{.*}}, align 16
+// CHECK: %y = alloca{{.*}}, align 16
+
+
+
+// PR7714
+struct f23S {
+  short f0;
+  unsigned f1;
+  int f2;
+};
+
+
+void f23(int A, struct f23S B) {
+  // CHECK: define void @f23(i32 %A, i64 %B.coerce0, i32 %B.coerce1)
+}
+
+struct f24s { long a; int b; };
+
+struct f23S f24(struct f23S *X, struct f24s *P2) {
+  return *X;
+  
+  // CHECK: define { i64, i32 } @f24(%struct.f23S* %X, %struct.f24s* %P2)
+}
+
+// rdar://8248065
+typedef float v4f32 __attribute__((__vector_size__(16)));
+v4f32 f25(v4f32 X) {
+  // CHECK: define <4 x float> @f25(<4 x float> %X)
+  // CHECK-NOT: alloca
+  // CHECK: alloca <4 x float>
+  // CHECK-NOT: alloca
+  // CHECK: store <4 x float> %X, <4 x float>*
+  // CHECK-NOT: store
+  // CHECK: ret <4 x float>
+  return X+X;
+}
+
+struct foo26 {
+  int *X;
+  float *Y;
+};
+
+struct foo26 f26(struct foo26 *P) {
+  // CHECK: define i64 @f26(%struct.foo26* %P)
+  return *P;
+}
+
+
+struct v4f32wrapper {
+  v4f32 v;
+};
+
+struct v4f32wrapper f27(struct v4f32wrapper X) {
+  // CHECK: define <4 x float> @f27(<4 x float> %X.coerce)
+  return X;
+}
+
+// rdar://5711709
+struct f28c {
+  double x;
+  int y;
+};
+void f28(struct f28c C) {
+  // CHECK: define void @f28(double %C.coerce0, i32 %C.coerce1)
+}
+
+struct f29a {
+  struct c {
+    double x;
+    int y;
+  } x[1];
+};
+
+void f29a(struct f29a A) {
+  // CHECK: define void @f29a(double %A.coerce0, i32 %A.coerce1)
+}
+
+// rdar://8249586
+struct S0 { char f0[8]; char f2; char f3; char f4; };
+void f30(struct S0 p_4) {
+  // CHECK: define void @f30(i64 %p_4.coerce0, i24 %p_4.coerce1)
+}
+
+// Pass the third element as a float when followed by tail padding.
+// rdar://8251384
+struct f31foo { float a, b, c; };
+float f31(struct f31foo X) {
+  // CHECK: define float @f31(<2 x float> %X.coerce0, float %X.coerce1)
+  return X.c;
+}
+
+_Complex float f32(_Complex float A, _Complex float B) {
+  // rdar://6379669
+  // CHECK: define <2 x float> @f32(<2 x float> %A.coerce, <2 x float> %B.coerce)
+  return A+B;
+}
+
+
+// rdar://8357396
+struct f33s { long x; float c,d; };
+
+void f33(va_list X) {
+  va_arg(X, struct f33s);
+}
+
+typedef unsigned long long v1i64 __attribute__((__vector_size__(8)));
+
+// rdar://8359248
+// CHECK: define i64 @f34(i64 %arg.coerce)
+v1i64 f34(v1i64 arg) { return arg; }
+
+
+// rdar://8358475
+// CHECK: define i64 @f35(i64 %arg.coerce)
+typedef unsigned long v1i64_2 __attribute__((__vector_size__(8)));
+v1i64_2 f35(v1i64_2 arg) { return arg+arg; }
+
+
+// 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);
+}
+
+// CHECK: define double @f36(double %arg.coerce)
+typedef unsigned v2i32 __attribute((__vector_size__(8)));
+v2i32 f36(v2i32 arg) { return arg; }
+
+// AVX: declare void @f38(<8 x float>)
+// AVX: declare void @f37(<8 x float>)
+// CHECK: declare void @f38(%struct.s256* byval align 32)
+// CHECK: declare void @f37(<8 x float>* byval align 32)
+typedef float __m256 __attribute__ ((__vector_size__ (32)));
+typedef struct {
+  __m256 m;
+} s256;
+
+s256 x38;
+__m256 x37;
+
+void f38(s256 x);
+void f37(__m256 x);
+void f39() { f38(x38); f37(x37); }
+
+// The two next tests make sure that the struct below is passed
+// in the same way regardless of avx being used
+
+// CHECK: declare void @func40(%struct.t128* byval align 16)
+typedef float __m128 __attribute__ ((__vector_size__ (16)));
+typedef struct t128 {
+  __m128 m;
+  __m128 n;
+} two128;
+
+extern void func40(two128 s);
+void func41(two128 s) {
+  func40(s);
+}
+
+// CHECK: declare void @func42(%struct.t128_2* byval align 16)
+typedef struct xxx {
+  __m128 array[2];
+} Atwo128;
+typedef struct t128_2 {
+  Atwo128 x;
+} SA;
+
+extern void func42(SA s);
+void func43(SA s) {
+  func42(s);
+}
+
+// CHECK: define i32 @f44
+// CHECK: ptrtoint
+// CHECK-NEXT: and {{.*}}, -32
+// CHECK-NEXT: inttoptr
+typedef int T44 __attribute((vector_size(32)));
+struct s44 { T44 x; int y; };
+int f44(int i, ...) {
+  __builtin_va_list ap;
+  __builtin_va_start(ap, i);
+  struct s44 s = __builtin_va_arg(ap, struct s44);
+  __builtin_va_end(ap);
+  return s.y;
+}
+
+// Make sure we don't use a varargs convention for a function without a
+// prototype where AVX types are involved.
+// AVX: @test45
+// AVX: call i32 bitcast (i32 (...)* @f45 to i32 (<8 x float>)*)
+int f45();
+__m256 x45;
+void test45() { f45(x45); }
+
+// Make sure we use byval to pass 64-bit vectors in memory; the LLVM call
+// lowering can't handle this case correctly because it runs after legalization.
+// CHECK: @test46
+// CHECK: call void @f46({{.*}}<2 x float>* byval align 8 {{.*}}, <2 x float>* byval align 8 {{.*}})
+typedef float v46 __attribute((vector_size(8)));
+void f46(v46,v46,v46,v46,v46,v46,v46,v46,v46,v46);
+void test46() { v46 x = {1,2}; f46(x,x,x,x,x,x,x,x,x,x); }
+
+// Check that we pass the struct below without using byval, which helps out
+// codegen.
+//
+// CHECK: @test47
+// CHECK: call void @f47(i32 {{.*}}, i32 {{.*}}, i32 {{.*}}, i32 {{.*}}, i32 {{.*}}, i32 {{.*}}, i32 {{.*}})
+struct s47 { unsigned a; };
+void f47(int,int,int,int,int,int,struct s47);
+void test47(int a, struct s47 b) { f47(a, a, a, a, a, a, b); }
diff --git a/test/Driver/x86_64-unknown-nacl.cpp b/test/Driver/x86_64-unknown-nacl.cpp
new file mode 100644
index 0000000..f923f09
--- /dev/null
+++ b/test/Driver/x86_64-unknown-nacl.cpp
@@ -0,0 +1,141 @@
+// RUN: %clang -target x86_64-unknown-nacl -ccc-clang-archs x86_64 -ccc-echo %s -emit-llvm-only -c 2>&1 | FileCheck %s -check-prefix=ECHO
+// RUN: %clang -target x86_64-unknown-nacl -ccc-clang-archs x86_64 %s -emit-llvm -S -c -o - | FileCheck %s
+// RUN: %clang -target x86_64-unknown-nacl -ccc-clang-archs x86_64 %s -emit-llvm -S -c -pthread -o - | FileCheck %s -check-prefix=THREADS
+
+// ECHO: {{.*}} -cc1 {{.*}}x86_64-unknown-nacl.c
+
+// Check platform defines
+#include <stdarg.h>
+#include <stddef.h>
+
+extern "C" {
+
+// CHECK: @align_c = global i32 1
+int align_c = __alignof(char);
+
+// CHECK: @align_s = global i32 2
+int align_s = __alignof(short);
+
+// CHECK: @align_i = global i32 4
+int align_i = __alignof(int);
+
+// CHECK: @align_l = global i32 4
+int align_l = __alignof(long);
+
+// CHECK: @align_ll = global i32 8
+int align_ll = __alignof(long long);
+
+// CHECK: @align_p = global i32 4
+int align_p = __alignof(void*);
+
+// CHECK: @align_f = global i32 4
+int align_f = __alignof(float);
+
+// CHECK: @align_d = global i32 8
+int align_d = __alignof(double);
+
+// CHECK: @align_ld = global i32 8
+int align_ld = __alignof(long double);
+
+// CHECK: @align_vl = global i32 4
+int align_vl = __alignof(va_list);
+
+// 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
+
+// Check types
+
+// CHECK: signext i8 @check_char()
+char check_char() { return 0; }
+
+// CHECK: signext i16 @check_short()
+short check_short() { return 0; }
+
+// CHECK: i32 @check_int()
+int check_int() { return 0; }
+
+// CHECK: i32 @check_long()
+long check_long() { return 0; }
+
+// CHECK: i64 @check_longlong()
+long long check_longlong() { return 0; }
+
+// CHECK: zeroext i8 @check_uchar()
+unsigned char check_uchar() { return 0; }
+
+// CHECK: zeroext i16 @check_ushort()
+unsigned short check_ushort() { return 0; }
+
+// CHECK: i32 @check_uint()
+unsigned int check_uint() { return 0; }
+
+// CHECK: i32 @check_ulong()
+unsigned long check_ulong() { return 0; }
+
+// CHECK: i64 @check_ulonglong()
+unsigned long long check_ulonglong() { return 0; }
+
+// CHECK: i32 @check_size_t()
+size_t check_size_t() { return 0; }
+
+// CHECK: float @check_float()
+float check_float() { return 0; }
+
+// CHECK: double @check_double()
+double check_double() { return 0; }
+
+// CHECK: double @check_longdouble()
+long double check_longdouble() { return 0; }
+
+}
+
+template<int> void Switch();
+template<> void Switch<4>();
+template<> void Switch<8>();
+template<> void Switch<16>();
+
+void check_pointer_size() {
+  // CHECK: SwitchILi4
+  Switch<sizeof(void*)>();
+
+  // CHECK: SwitchILi8
+  Switch<sizeof(long long)>();
+
+  // CHECK: SwitchILi16
+  Switch<sizeof(va_list)>();
+}
