r347699 - [clang][ARC] Add ARCTargetInfo

Tatyana Krasnukha via cfe-commits cfe-commits at lists.llvm.org
Tue Nov 27 11:52:11 PST 2018


Author: tkrasnukha
Date: Tue Nov 27 11:52:10 2018
New Revision: 347699

URL: http://llvm.org/viewvc/llvm-project?rev=347699&view=rev
Log:
[clang][ARC] Add ARCTargetInfo

Based-on-patch-by: Pete Couperus <petecoup at synopsys.com>

Differential Revision: https://reviews.llvm.org/D53100

Added:
    cfe/trunk/lib/Basic/Targets/ARC.cpp
    cfe/trunk/lib/Basic/Targets/ARC.h
    cfe/trunk/test/CodeGen/arc/
    cfe/trunk/test/CodeGen/arc/arguments.c
    cfe/trunk/test/CodeGen/arc/struct-align.c
Modified:
    cfe/trunk/lib/Basic/CMakeLists.txt
    cfe/trunk/lib/Basic/Targets.cpp
    cfe/trunk/lib/CodeGen/TargetInfo.cpp
    cfe/trunk/test/CodeGen/target-data.c

Modified: cfe/trunk/lib/Basic/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/CMakeLists.txt?rev=347699&r1=347698&r2=347699&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/CMakeLists.txt (original)
+++ cfe/trunk/lib/Basic/CMakeLists.txt Tue Nov 27 11:52:10 2018
@@ -71,6 +71,7 @@ add_clang_library(clangBasic
   Targets.cpp
   Targets/AArch64.cpp
   Targets/AMDGPU.cpp
+  Targets/ARC.cpp
   Targets/ARM.cpp
   Targets/AVR.cpp
   Targets/BPF.cpp

Modified: cfe/trunk/lib/Basic/Targets.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Targets.cpp?rev=347699&r1=347698&r2=347699&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/Targets.cpp (original)
+++ cfe/trunk/lib/Basic/Targets.cpp Tue Nov 27 11:52:10 2018
@@ -16,6 +16,7 @@
 
 #include "Targets/AArch64.h"
 #include "Targets/AMDGPU.h"
+#include "Targets/ARC.h"
 #include "Targets/ARM.h"
 #include "Targets/AVR.h"
 #include "Targets/BPF.h"
@@ -124,6 +125,9 @@ TargetInfo *AllocateTarget(const llvm::T
   default:
     return nullptr;
 
+  case llvm::Triple::arc:
+    return new ARCTargetInfo(Triple, Opts);
+
   case llvm::Triple::xcore:
     return new XCoreTargetInfo(Triple, Opts);
 

Added: cfe/trunk/lib/Basic/Targets/ARC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Targets/ARC.cpp?rev=347699&view=auto
==============================================================================
--- cfe/trunk/lib/Basic/Targets/ARC.cpp (added)
+++ cfe/trunk/lib/Basic/Targets/ARC.cpp Tue Nov 27 11:52:10 2018
@@ -0,0 +1,25 @@
+//===--- ARC.cpp - Implement ARC target feature support -------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements ARC TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ARC.h"
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/MacroBuilder.h"
+#include "clang/Basic/TargetBuiltins.h"
+
+using namespace clang;
+using namespace clang::targets;
+
+void ARCTargetInfo::getTargetDefines(const LangOptions &Opts,
+                                     MacroBuilder &Builder) const {
+  Builder.defineMacro("__arc__");
+}

Added: cfe/trunk/lib/Basic/Targets/ARC.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Targets/ARC.h?rev=347699&view=auto
==============================================================================
--- cfe/trunk/lib/Basic/Targets/ARC.h (added)
+++ cfe/trunk/lib/Basic/Targets/ARC.h Tue Nov 27 11:52:10 2018
@@ -0,0 +1,74 @@
+//===--- ARC.h - Declare ARC target feature support -------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares ARC TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_ARC_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_ARC_H
+
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Compiler.h"
+
+namespace clang {
+namespace targets {
+
+class LLVM_LIBRARY_VISIBILITY ARCTargetInfo : public TargetInfo {
+public:
+  ARCTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
+      : TargetInfo(Triple) {
+    NoAsmVariants = true;
+    LongLongAlign = 32;
+    SuitableAlign = 32;
+    DoubleAlign = LongDoubleAlign = 32;
+    SizeType = UnsignedInt;
+    PtrDiffType = SignedInt;
+    IntPtrType = SignedInt;
+    UseZeroLengthBitfieldAlignment = true;
+    resetDataLayout("e-m:e-p:32:32-i1:8:32-i8:8:32-i16:16:32-"
+                    "i32:32:32-f32:32:32-i64:32-f64:32-a:0:32-n32");
+  }
+
+  void getTargetDefines(const LangOptions &Opts,
+                        MacroBuilder &Builder) const override;
+
+  ArrayRef<Builtin::Info> getTargetBuiltins() const override { return None; }
+
+  BuiltinVaListKind getBuiltinVaListKind() const override {
+    return TargetInfo::VoidPtrBuiltinVaList;
+  }
+
+  const char *getClobbers() const override { return ""; }
+
+  ArrayRef<const char *> getGCCRegNames() const override {
+    static const char *const GCCRegNames[] = {
+        "r0",  "r1",  "r2",  "r3",  "r4",  "r5",     "r6",  "r7",
+        "r8",  "r9",  "r10", "r11", "r12", "r13",    "r14", "r15",
+        "r16", "r17", "r18", "r19", "r20", "r21",    "r22", "r23",
+        "r24", "r25", "gp",  "sp",  "fp",  "ilink1", "r30", "blink"};
+    return llvm::makeArrayRef(GCCRegNames);
+  }
+
+  ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
+    return None;
+  }
+
+  bool validateAsmConstraint(const char *&Name,
+                             TargetInfo::ConstraintInfo &Info) const override {
+    return false;
+  }
+};
+
+} // namespace targets
+} // namespace clang
+
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_ARC_H

Modified: cfe/trunk/lib/CodeGen/TargetInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/TargetInfo.cpp?rev=347699&r1=347698&r2=347699&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/TargetInfo.cpp (original)
+++ cfe/trunk/lib/CodeGen/TargetInfo.cpp Tue Nov 27 11:52:10 2018
@@ -8249,6 +8249,137 @@ SparcV9TargetCodeGenInfo::initDwarfEHReg
   return false;
 }
 
+// ARC ABI implementation.
+namespace {
+
+class ARCABIInfo : public DefaultABIInfo {
+public:
+  using DefaultABIInfo::DefaultABIInfo;
+
+private:
+  Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+                    QualType Ty) const override;
+
+  void updateState(const ABIArgInfo &Info, QualType Ty, CCState &State) const {
+    if (!State.FreeRegs)
+      return;
+    if (Info.isIndirect() && Info.getInReg())
+      State.FreeRegs--;
+    else if (Info.isDirect() && Info.getInReg()) {
+      unsigned sz = (getContext().getTypeSize(Ty) + 31) / 32;
+      if (sz < State.FreeRegs)
+        State.FreeRegs -= sz;
+      else
+        State.FreeRegs = 0;
+    }
+  }
+
+  void computeInfo(CGFunctionInfo &FI) const override {
+    CCState State(FI.getCallingConvention());
+    // ARC uses 8 registers to pass arguments.
+    State.FreeRegs = 8;
+
+    if (!getCXXABI().classifyReturnType(FI))
+      FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
+    updateState(FI.getReturnInfo(), FI.getReturnType(), State);
+    for (auto &I : FI.arguments()) {
+      I.info = classifyArgumentType(I.type, State.FreeRegs);
+      updateState(I.info, I.type, State);
+    }
+  }
+
+  ABIArgInfo getIndirectByRef(QualType Ty, bool HasFreeRegs) const;
+  ABIArgInfo getIndirectByValue(QualType Ty) const;
+  ABIArgInfo classifyArgumentType(QualType Ty, uint8_t FreeRegs) const;
+  ABIArgInfo classifyReturnType(QualType RetTy) const;
+};
+
+class ARCTargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+  ARCTargetCodeGenInfo(CodeGenTypes &CGT)
+      : TargetCodeGenInfo(new ARCABIInfo(CGT)) {}
+};
+
+
+ABIArgInfo ARCABIInfo::getIndirectByRef(QualType Ty, bool HasFreeRegs) const {
+  return HasFreeRegs ? getNaturalAlignIndirectInReg(Ty) :
+                       getNaturalAlignIndirect(Ty, false);
+}
+
+ABIArgInfo ARCABIInfo::getIndirectByValue(QualType Ty) const {
+  // Compute the byval alignment. 
+  const unsigned MinABIStackAlignInBytes = 4;
+  unsigned TypeAlign = getContext().getTypeAlign(Ty) / 8;
+  return ABIArgInfo::getIndirect(CharUnits::fromQuantity(4), /*ByVal=*/true,
+                                 TypeAlign > MinABIStackAlignInBytes);
+}
+
+Address ARCABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+                              QualType Ty) const {
+  return emitVoidPtrVAArg(CGF, VAListAddr, Ty, /*indirect*/ false,
+                          getContext().getTypeInfoInChars(Ty),
+                          CharUnits::fromQuantity(4), true);
+}
+
+ABIArgInfo ARCABIInfo::classifyArgumentType(QualType Ty,
+                                            uint8_t FreeRegs) const {
+  // Handle the generic C++ ABI.
+  const RecordType *RT = Ty->getAs<RecordType>();
+  if (RT) {
+    CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI());
+    if (RAA == CGCXXABI::RAA_Indirect)
+      return getIndirectByRef(Ty, FreeRegs > 0);
+
+    if (RAA == CGCXXABI::RAA_DirectInMemory)
+      return getIndirectByValue(Ty);
+  }
+
+  // Treat an enum type as its underlying type.
+  if (const EnumType *EnumTy = Ty->getAs<EnumType>())
+    Ty = EnumTy->getDecl()->getIntegerType();
+
+  auto SizeInRegs = llvm::alignTo(getContext().getTypeSize(Ty), 32) / 32;
+
+  if (isAggregateTypeForABI(Ty)) {
+    // Structures with flexible arrays are always indirect.
+    if (RT && RT->getDecl()->hasFlexibleArrayMember())
+      return getIndirectByValue(Ty);
+
+    // Ignore empty structs/unions.
+    if (isEmptyRecord(getContext(), Ty, true))
+      return ABIArgInfo::getIgnore();
+
+    llvm::LLVMContext &LLVMContext = getVMContext();
+
+    llvm::IntegerType *Int32 = llvm::Type::getInt32Ty(LLVMContext);
+    SmallVector<llvm::Type *, 3> Elements(SizeInRegs, Int32);
+    llvm::Type *Result = llvm::StructType::get(LLVMContext, Elements);
+
+    return FreeRegs >= SizeInRegs ?
+        ABIArgInfo::getDirectInReg(Result) :
+        ABIArgInfo::getDirect(Result, 0, nullptr, false);
+  }
+
+  return Ty->isPromotableIntegerType() ?
+      (FreeRegs >= SizeInRegs ? ABIArgInfo::getExtendInReg(Ty) :
+                                ABIArgInfo::getExtend(Ty)) :
+      (FreeRegs >= SizeInRegs ? ABIArgInfo::getDirectInReg() :
+                                ABIArgInfo::getDirect());
+}
+
+ABIArgInfo ARCABIInfo::classifyReturnType(QualType RetTy) const {
+  if (RetTy->isAnyComplexType())
+    return ABIArgInfo::getDirectInReg();
+
+  // Arguments of size > 4 registers are indirect.  
+  auto RetSize = llvm::alignTo(getContext().getTypeSize(RetTy), 32) / 32;
+  if (RetSize > 4)
+    return getIndirectByRef(RetTy, /*HasFreeRegs*/ true);
+
+  return DefaultABIInfo::classifyReturnType(RetTy);
+}
+
+} // End anonymous namespace.
 
 //===----------------------------------------------------------------------===//
 // XCore ABI Implementation
@@ -9270,6 +9401,8 @@ const TargetCodeGenInfo &CodeGenModule::
     return SetCGInfo(new SparcV9TargetCodeGenInfo(Types));
   case llvm::Triple::xcore:
     return SetCGInfo(new XCoreTargetCodeGenInfo(Types));
+  case llvm::Triple::arc:
+    return SetCGInfo(new ARCTargetCodeGenInfo(Types));
   case llvm::Triple::spir:
   case llvm::Triple::spir64:
     return SetCGInfo(new SPIRTargetCodeGenInfo(Types));

Added: cfe/trunk/test/CodeGen/arc/arguments.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/arc/arguments.c?rev=347699&view=auto
==============================================================================
--- cfe/trunk/test/CodeGen/arc/arguments.c (added)
+++ cfe/trunk/test/CodeGen/arc/arguments.c Tue Nov 27 11:52:10 2018
@@ -0,0 +1,135 @@
+// RUN: %clang_cc1 -triple arc-unknown-unknown %s -emit-llvm -o - \
+// RUN:   | FileCheck %s
+
+// Basic argument tests for ARC.
+
+// CHECK: define void @f0(i32 inreg %i, i32 inreg %j, i64 inreg %k)
+void f0(int i, long j, long long k) {}
+
+typedef struct {
+  int aa;
+  int bb;
+} s1;
+// CHECK: define void @f1(i32 inreg %i.coerce0, i32 inreg %i.coerce1)
+void f1(s1 i) {}
+
+typedef struct {
+  char aa; char bb; char cc; char dd;
+} cs1;
+// CHECK: define void @cf1(i32 inreg %i.coerce)
+void cf1(cs1 i) {}
+
+typedef struct {
+  int cc;
+} s2;
+// CHECK: define void @f2(%struct.s2* noalias sret %agg.result)
+s2 f2() {
+  s2 foo;
+  return foo;
+}
+
+typedef struct {
+  int cc;
+  int dd;
+} s3;
+// CHECK: define void @f3(%struct.s3* noalias sret %agg.result)
+s3 f3() {
+  s3 foo;
+  return foo;
+}
+
+// CHECK: define void @f4(i64 inreg %i)
+void f4(long long i) {}
+
+// CHECK: define void @f5(i8 inreg signext %a, i16 inreg signext %b)
+void f5(signed char a, short b) {}
+
+// CHECK: define void @f6(i8 inreg zeroext %a, i16 inreg zeroext %b)
+void f6(unsigned char a, unsigned short b) {}
+
+enum my_enum {
+  ENUM1,
+  ENUM2,
+  ENUM3,
+};
+// Enums should be treated as the underlying i32.
+// CHECK: define void @f7(i32 inreg %a)
+void f7(enum my_enum a) {}
+
+enum my_big_enum {
+  ENUM4 = 0xFFFFFFFFFFFFFFFF,
+};
+// Big enums should be treated as the underlying i64.
+// CHECK: define void @f8(i64 inreg %a)
+void f8(enum my_big_enum a) {}
+
+union simple_union {
+  int a;
+  char b;
+};
+// Unions should be passed inreg.
+// CHECK: define void @f9(i32 inreg %s.coerce)
+void f9(union simple_union s) {}
+
+typedef struct {
+  int b4 : 4;
+  int b3 : 3;
+  int b8 : 8;
+} bitfield1;
+// Bitfields should be passed inreg.
+// CHECK: define void @f10(i32 inreg %bf1.coerce)
+void f10(bitfield1 bf1) {}
+
+// CHECK: define inreg { float, float } @cplx1(float inreg %r)
+_Complex float cplx1(float r) {
+  return r + 2.0fi;
+}
+
+// CHECK: define inreg { double, double } @cplx2(double inreg %r)
+_Complex double cplx2(double r) {
+  return r + 2.0i;
+}
+
+// CHECK: define inreg { i32, i32 } @cplx3(i32 inreg %r)
+_Complex int cplx3(int r) {
+  return r + 2i;
+}
+
+// CHECK: define inreg { i64, i64 } @cplx4(i64 inreg %r)
+_Complex long long cplx4(long long r) {
+  return r + 2i;
+}
+
+// CHECK: define inreg { i8, i8 } @cplx6(i8 inreg signext %r)
+_Complex signed char cplx6(signed char r) {
+  return r + 2i;
+}
+
+// CHECK: define inreg { i16, i16 } @cplx7(i16 inreg signext %r)
+_Complex short cplx7(short r) {
+  return r + 2i;
+}
+
+typedef struct {
+  int aa; int bb;
+} s8;
+
+typedef struct {
+  int aa; int bb; int cc; int dd;
+} s16;
+
+// Use 16-byte struct 2 times, gets 8 registers.
+void st2(s16 a, s16 b) {}
+// CHECK: define void @st2(i32 inreg %a.coerce0, i32 inreg %a.coerce1, i32 inreg %a.coerce2, i32 inreg %a.coerce3, i32 inreg %b.coerce0, i32 inreg %b.coerce1, i32 inreg %b.coerce2, i32 inreg %b.coerce3)
+
+// Use 8-byte struct 3 times, gets 8 registers, 1 byval struct argument.
+void st3(s16 a, s16 b, s16 c) {}
+// CHECK: define void @st3(i32 inreg %a.coerce0, i32 inreg %a.coerce1, i32 inreg %a.coerce2, i32 inreg %a.coerce3, i32 inreg %b.coerce0, i32 inreg %b.coerce1, i32 inreg %b.coerce2, i32 inreg %b.coerce3, i32 %c.coerce0, i32 %c.coerce1, i32 %c.coerce2, i32 %c.coerce3)
+
+// 1 sret + 1 i32 + 2*(i32 coerce) + 4*(i32 coerce) + 1 byval
+s16 st4(int x, s8 a, s16 b, s16 c) { return b; }
+// CHECK: define void @st4(%struct.s16* noalias sret %agg.result, i32 inreg %x, i32 inreg %a.coerce0, i32 inreg %a.coerce1, i32 inreg %b.coerce0, i32 inreg %b.coerce1, i32 inreg %b.coerce2, i32 inreg %b.coerce3, i32 %c.coerce0, i32 %c.coerce1, i32 %c.coerce2, i32 %c.coerce3)
+
+// 1 sret + 2*(i32 coerce) + 4*(i32 coerce) + 4*(i32 coerce)
+s16 st5(s8 a, s16 b, s16 c) { return b; }
+// CHECK: define void @st5(%struct.s16* noalias sret %agg.result, i32 inreg %a.coerce0, i32 inreg %a.coerce1, i32 inreg %b.coerce0, i32 inreg %b.coerce1, i32 inreg %b.coerce2, i32 inreg %b.coerce3, i32 %c.coerce0, i32 %c.coerce1, i32 %c.coerce2, i32 %c.coerce3)

Added: cfe/trunk/test/CodeGen/arc/struct-align.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/arc/struct-align.c?rev=347699&view=auto
==============================================================================
--- cfe/trunk/test/CodeGen/arc/struct-align.c (added)
+++ cfe/trunk/test/CodeGen/arc/struct-align.c Tue Nov 27 11:52:10 2018
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -triple arc-unknown-unknown %s -emit-llvm -o - \
+// RUN:   | FileCheck %s
+
+// 64-bit fields need only be 32-bit aligned for arc.
+
+typedef struct {
+  int aa;
+  double bb;
+} s1;
+
+// CHECK: define i32 @f1
+// CHECK: ret i32 12
+int f1() {
+  return sizeof(s1);
+}
+
+typedef struct {
+  int aa;
+  long long bb;
+} s2;
+// CHECK: define i32 @f2
+// CHECK: ret i32 12
+int f2() {
+  return sizeof(s2);
+}
+

Modified: cfe/trunk/test/CodeGen/target-data.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/target-data.c?rev=347699&r1=347698&r2=347699&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/target-data.c (original)
+++ cfe/trunk/test/CodeGen/target-data.c Tue Nov 27 11:52:10 2018
@@ -179,6 +179,10 @@
 // RUN: %s | FileCheck %s -check-prefix=ARM-GNU
 // ARM-GNU: target datalayout = "e-m:e-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"
 
+// RUN: %clang_cc1 -triple arc-unknown-unknown -o - -emit-llvm %s | \
+// RUN: FileCheck %s -check-prefix=ARC
+// ARC: target datalayout = "e-m:e-p:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-f32:32:32-i64:32-f64:32-a:0:32-n32"
+
 // RUN: %clang_cc1 -triple hexagon-unknown -o - -emit-llvm %s | \
 // RUN: FileCheck %s -check-prefix=HEXAGON
 // HEXAGON: target datalayout = "e-m:e-p:32:32:32-a:0-n16:32-i64:64:64-i32:32:32-i16:16:16-i1:8:8-f32:32:32-f64:64:64-v32:32:32-v64:64:64-v512:512:512-v1024:1024:1024-v2048:2048:2048"




More information about the cfe-commits mailing list