[cfe-commits] r163333 - in /cfe/trunk: lib/CodeGen/TargetInfo.cpp test/CodeGen/le32-arguments.c test/CodeGen/le32-regparm.c

Derek Schuff dschuff at google.com
Thu Sep 6 10:37:28 PDT 2012


Author: dschuff
Date: Thu Sep  6 12:37:28 2012
New Revision: 163333

URL: http://llvm.org/viewvc/llvm-project?rev=163333&view=rev
Log:
Use custom ABIInfo for le32/PNaCl argument codegen

This patch uses a new ABIInfo implementation specific to the le32
target, rather than falling back to DefaultABIInfo. Its behavior is
basically the same, but it also allows the regparm argument attribute.
It also includes basic tests for argument codegen and attributes.

Added:
    cfe/trunk/test/CodeGen/le32-arguments.c
    cfe/trunk/test/CodeGen/le32-regparm.c
Modified:
    cfe/trunk/lib/CodeGen/TargetInfo.cpp

Modified: cfe/trunk/lib/CodeGen/TargetInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/TargetInfo.cpp?rev=163333&r1=163332&r2=163333&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/TargetInfo.cpp (original)
+++ cfe/trunk/lib/CodeGen/TargetInfo.cpp Thu Sep  6 12:37:28 2012
@@ -389,6 +389,90 @@
           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) {
@@ -3768,6 +3852,8 @@
   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));

Added: cfe/trunk/test/CodeGen/le32-arguments.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/le32-arguments.c?rev=163333&view=auto
==============================================================================
--- cfe/trunk/test/CodeGen/le32-arguments.c (added)
+++ cfe/trunk/test/CodeGen/le32-arguments.c Thu Sep  6 12:37:28 2012
@@ -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.s2* 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) {}

Added: cfe/trunk/test/CodeGen/le32-regparm.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/le32-regparm.c?rev=163333&view=auto
==============================================================================
--- cfe/trunk/test/CodeGen/le32-regparm.c (added)
+++ cfe/trunk/test/CodeGen/le32-regparm.c Thu Sep  6 12:37:28 2012
@@ -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);
+}





More information about the cfe-commits mailing list