diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp
index 9c23ed9..c94023f 100644
--- a/lib/CodeGen/TargetInfo.cpp
+++ b/lib/CodeGen/TargetInfo.cpp
@@ -389,6 +389,90 @@ ABIArgInfo DefaultABIInfo::classifyReturnType(QualType RetTy) const {
           ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
 }
 
+//===----------------------------------------------------------------------===//
+// le32/PNaCl bitcode ABI Implementation
+//===----------------------------------------------------------------------===//
+
+class PNaClABIInfo : public ABIInfo {
+ public:
+  PNaClABIInfo(CodeGen::CodeGenTypes &CGT) : ABIInfo(CGT) {}
+
+  ABIArgInfo classifyReturnType(QualType RetTy) const;
+  ABIArgInfo classifyArgumentType(QualType RetTy, unsigned &FreeRegs) const;
+
+  virtual void computeInfo(CGFunctionInfo &FI) const;
+  virtual llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
+                                 CodeGenFunction &CGF) const;
+};
+
+class PNaClTargetCodeGenInfo : public TargetCodeGenInfo {
+ public:
+  PNaClTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT)
+    : TargetCodeGenInfo(new PNaClABIInfo(CGT)) {}
+};
+
+void PNaClABIInfo::computeInfo(CGFunctionInfo &FI) const {
+    FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
+
+    unsigned FreeRegs = FI.getHasRegParm() ? FI.getRegParm() : 0;
+
+    for (CGFunctionInfo::arg_iterator it = FI.arg_begin(), ie = FI.arg_end();
+         it != ie; ++it)
+      it->info = classifyArgumentType(it->type, FreeRegs);
+  }
+
+llvm::Value *PNaClABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
+                                       CodeGenFunction &CGF) const {
+  return 0;
+}
+
+ABIArgInfo PNaClABIInfo::classifyArgumentType(QualType Ty,
+                                              unsigned &FreeRegs) const {
+  if (isAggregateTypeForABI(Ty)) {
+    // Records with non trivial destructors/constructors should not be passed
+    // by value.
+    FreeRegs = 0;
+    if (isRecordWithNonTrivialDestructorOrCopyConstructor(Ty))
+      return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
+
+    return ABIArgInfo::getIndirect(0);
+  }
+
+  // Treat an enum type as its underlying type.
+  if (const EnumType *EnumTy = Ty->getAs<EnumType>())
+    Ty = EnumTy->getDecl()->getIntegerType();
+
+  ABIArgInfo BaseInfo = (Ty->isPromotableIntegerType() ?
+          ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
+
+  // Regparm regs hold 32 bits.
+  unsigned SizeInRegs = (getContext().getTypeSize(Ty) + 31) / 32;
+  if (SizeInRegs == 0) return BaseInfo;
+  if (SizeInRegs > FreeRegs) {
+    FreeRegs = 0;
+    return BaseInfo;
+  }
+  FreeRegs -= SizeInRegs;
+  return BaseInfo.isDirect() ?
+      ABIArgInfo::getDirectInReg(BaseInfo.getCoerceToType()) :
+      ABIArgInfo::getExtendInReg(BaseInfo.getCoerceToType());
+}
+
+ABIArgInfo PNaClABIInfo::classifyReturnType(QualType RetTy) const {
+  if (RetTy->isVoidType())
+    return ABIArgInfo::getIgnore();
+
+  if (isAggregateTypeForABI(RetTy))
+    return ABIArgInfo::getIndirect(0);
+
+  // Treat an enum type as its underlying type.
+  if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
+    RetTy = EnumTy->getDecl()->getIntegerType();
+
+  return (RetTy->isPromotableIntegerType() ?
+          ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
+}
+
 /// UseX86_MMXType - Return true if this is an MMX type that should use the
 /// special x86_mmx type.
 bool UseX86_MMXType(llvm::Type *IRType) {
@@ -3767,6 +3851,8 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() {
   default:
     return *(TheTargetCodeGenInfo = new DefaultTargetCodeGenInfo(Types));
 
+  case llvm::Triple::le32:
+    return *(TheTargetCodeGenInfo = new PNaClTargetCodeGenInfo(Types));
   case llvm::Triple::mips:
   case llvm::Triple::mipsel:
     return *(TheTargetCodeGenInfo = new MIPSTargetCodeGenInfo(Types, true));
diff --git a/test/CodeGen/le32-arguments.c b/test/CodeGen/le32-arguments.c
new file mode 100644
index 0000000..c612113
--- /dev/null
+++ b/test/CodeGen/le32-arguments.c
@@ -0,0 +1,61 @@
+// RUN: %clang_cc1 -triple le32-unknown-nacl %s -emit-llvm -o - | FileCheck %s
+
+// Basic argument/attribute tests for le32/PNaCl
+
+// CHECK: define void @f0(i32 %i, i32 %j, double %k)
+void f0(int i, long j, double k) {}
+
+typedef struct {
+  int aa;
+  int bb;
+} s1;
+// Structs should be passed byval and not split up
+// CHECK: define void @f1(%struct.s1* byval %i)
+void f1(s1 i) {}
+
+typedef struct {
+  int cc;
+} s2;
+// Structs should be returned sret and not simplified by the frontend
+// CHECK: define void @f2(%struct.s1* noalias sret %agg.result)
+s2 f2() {
+  s2 foo;
+  return foo;
+}
+
+// CHECK: define void @f3(i64 %i)
+void f3(long long i) {}
+
+// i8/i16 should be signext, i32 and higher should not
+// CHECK: define void @f4(i8 signext %a, i16 signext %b)
+void f4(char a, short b) {}
+
+// CHECK: define void @f5(i8 zeroext %a, i16 zeroext %b)
+void f5(unsigned char a, unsigned short b) {}
+
+
+enum my_enum {
+  ENUM1,
+  ENUM2,
+  ENUM3,
+};
+// Enums should be treated as the underlying i32
+// CHECK: define void @f6(i32 %a)
+void f6(enum my_enum a) {}
+
+union simple_union {
+  int a;
+  char b;
+};
+// Unions should be passed as byval structs
+// CHECK: define void @f7(%union.simple_union* byval %s)
+void f7(union simple_union s) {}
+
+typedef struct {
+  int b4 : 4;
+  int b3 : 3;
+  int b8 : 8;
+} bitfield1;
+// Bitfields should be passed as byval structs
+// CHECK: define void @f8(%struct.bitfield1* byval %bf1)
+void f8(bitfield1 bf1) {}
diff --git a/test/CodeGen/le32-regparm.c b/test/CodeGen/le32-regparm.c
new file mode 100644
index 0000000..6ab5a11
--- /dev/null
+++ b/test/CodeGen/le32-regparm.c
@@ -0,0 +1,41 @@
+// RUN: %clang_cc1 -triple le32-unknown-nacl %s -emit-llvm -o - | FileCheck %s
+
+#define FASTCALL __attribute__((regparm(2)))
+
+typedef struct {
+  int aaa;
+  double bbbb;
+  int ccc[200];
+} foo;
+
+// 2 inreg arguments are supported.
+void FASTCALL f1(int i, int j, int k);
+// CHECK: define void @f1(i32 inreg %i, i32 inreg %j, i32 %k)
+void f1(int i, int j, int k) { }
+
+// inreg structs are not supported.
+// CHECK: define void @f2(%struct.foo* inreg %a)
+void __attribute__((regparm(1))) f2(foo* a) {}
+
+// Only the first 2 arguments can be passed inreg, and the first
+// non-integral type consumes remaining available registers.
+// CHECK: define void @f3(%struct.foo* byval %a, i32 %b)
+void __attribute__((regparm(2))) f3(foo a, int b) {}
+
+// Only 64 total bits are supported
+// CHECK: define void @f4(i64 inreg %g, i32 %h)
+void __attribute__((regparm(2))) f4(long long g, int h) {}
+
+typedef void (*FType)(int, int) __attribute ((regparm (2)));
+FType bar;
+extern void FASTCALL reduced(char b, double c, foo* d, double e, int f);
+
+int
+main(void) {
+  // The presence of double c means that foo* d is not passed inreg. This
+  // behavior is different from current x86-32 behavior
+  // CHECK: call void @reduced(i8 signext inreg 0, {{.*}} %struct.foo* null
+  reduced(0, 0.0, 0, 0.0, 0);
+  // CHECK: call void {{.*}}(i32 inreg 1, i32 inreg 2)
+  bar(1,2);
+}
