tatyana-krasnukha created this revision.
tatyana-krasnukha added a reviewer: petecoup.
tatyana-krasnukha added a project: clang.
Herald added subscribers: cfe-commits, mgorny.
tatyana-krasnukha added a dependency: D53100: clang: Add ARCTargetInfo.

This option affects registers count for passing arguments.


Repository:
  rC Clang

https://reviews.llvm.org/D53101

Files:
  include/clang/Driver/Options.td
  lib/Basic/CMakeLists.txt
  lib/Basic/Targets.cpp
  lib/Basic/Targets/ARC.cpp
  lib/Basic/Targets/ARC.h
  lib/CodeGen/TargetInfo.cpp
  lib/Driver/CMakeLists.txt
  lib/Driver/ToolChains/Arch/ARC.cpp
  lib/Driver/ToolChains/Arch/ARC.h
  lib/Driver/ToolChains/Clang.cpp
  test/CodeGen/arc/arguments.c
  test/CodeGen/arc/struct-align.c
  test/CodeGen/target-data.c
  test/Driver/arc-target-features.c

Index: test/Driver/arc-target-features.c
===================================================================
--- test/Driver/arc-target-features.c
+++ test/Driver/arc-target-features.c
@@ -0,0 +1,5 @@
+// REQUIRES: arc-registered-target
+
+// RUN: %clang -target arc-unknown-unknown -### -S %s -mrf16 2>&1 | FileCheck %s -check-prefix=CHECK-RF16
+// CHECK-RF16: "-target-feature" "+rf16"
+// CHECK: #define __ARC_RF16__
Index: test/CodeGen/target-data.c
===================================================================
--- test/CodeGen/target-data.c
+++ test/CodeGen/target-data.c
@@ -151,6 +151,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"
Index: test/CodeGen/arc/struct-align.c
===================================================================
--- test/CodeGen/arc/struct-align.c
+++ test/CodeGen/arc/struct-align.c
@@ -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);
+}
+
Index: test/CodeGen/arc/arguments.c
===================================================================
--- test/CodeGen/arc/arguments.c
+++ test/CodeGen/arc/arguments.c
@@ -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, i32 inreg %k.coerce0, i32 inreg %k.coerce1)
+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(i32 inreg %i.coerce0, i32 inreg %i.coerce1)
+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(i32 inreg %a.coerce0, i32 inreg %a.coerce1)
+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(i32 inreg %r.coerce0, i32 inreg %r.coerce1)
+_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(i32 inreg %r.coerce0, i32 inreg %r.coerce1)
+_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)
Index: lib/Driver/ToolChains/Clang.cpp
===================================================================
--- lib/Driver/ToolChains/Clang.cpp
+++ lib/Driver/ToolChains/Clang.cpp
@@ -9,6 +9,7 @@
 
 #include "Clang.h"
 #include "Arch/AArch64.h"
+#include "Arch/ARC.h"
 #include "Arch/ARM.h"
 #include "Arch/Mips.h"
 #include "Arch/PPC.h"
@@ -363,6 +364,10 @@
   case llvm::Triple::amdgcn:
     amdgpu::getAMDGPUTargetFeatures(D, Args, Features);
     break;
+
+  case llvm::Triple::arc:
+    arc::getARCTargetFeatures(Args, Features);
+    break;
   }
 
   // Find the last of each feature.
Index: lib/Driver/ToolChains/Arch/ARC.h
===================================================================
--- lib/Driver/ToolChains/Arch/ARC.h
+++ lib/Driver/ToolChains/Arch/ARC.h
@@ -0,0 +1,35 @@
+//===--- ARC.h - ARC ToolChain Implementations ----------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ARC_H
+#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ARC_H
+
+#include <vector>
+
+namespace llvm {
+  class StringRef;
+  namespace opt {
+    class ArgList;
+  }
+}
+
+namespace clang {
+namespace driver {
+namespace tools {
+namespace arc {
+
+void getARCTargetFeatures(const llvm::opt::ArgList &Args,
+                          std::vector<llvm::StringRef> &Features);
+
+} // end namespace arc
+} // end namespace tools
+} // end namespace driver
+} // end namespace clang
+
+#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ARC_H
Index: lib/Driver/ToolChains/Arch/ARC.cpp
===================================================================
--- lib/Driver/ToolChains/Arch/ARC.cpp
+++ lib/Driver/ToolChains/Arch/ARC.cpp
@@ -0,0 +1,25 @@
+//===----------- ARC.cpp - ARC ToolChain Implementations --------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ARC.h"
+#include "ToolChains/CommonArgs.h"
+#include "clang/Driver/Options.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Option/ArgList.h"
+
+using namespace clang::driver;
+using namespace clang::driver::tools;
+
+// ARC target features.
+void arc::getARCTargetFeatures(const llvm::opt::ArgList &Args,
+                               std::vector<llvm::StringRef> &Features) {
+  handleTargetFeaturesGroup(Args, Features,
+                            options::OPT_m_arc_Features_Group);
+}
+
Index: lib/Driver/CMakeLists.txt
===================================================================
--- lib/Driver/CMakeLists.txt
+++ lib/Driver/CMakeLists.txt
@@ -21,6 +21,7 @@
   SanitizerArgs.cpp
   Tool.cpp
   ToolChain.cpp
+  ToolChains/Arch/ARC.cpp
   ToolChains/Arch/AArch64.cpp
   ToolChains/Arch/ARM.cpp
   ToolChains/Arch/Mips.cpp
Index: lib/CodeGen/TargetInfo.cpp
===================================================================
--- lib/CodeGen/TargetInfo.cpp
+++ lib/CodeGen/TargetInfo.cpp
@@ -8209,7 +8209,139 @@
   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 (4 for reduced register set).
+    State.FreeRegs = getTarget().hasFeature("rf16") ? 4 : 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) || SizeInRegs > 1) {
+    const RecordType *RT = Ty->getAs<RecordType>();
+    // 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);
+  }
+
+  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
 //===----------------------------------------------------------------------===//
@@ -9230,6 +9362,8 @@
     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));
Index: lib/Basic/Targets/ARC.h
===================================================================
--- lib/Basic/Targets/ARC.h
+++ lib/Basic/Targets/ARC.h
@@ -0,0 +1,85 @@
+//===--- 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;
+  }
+
+  bool isValidFeatureName(StringRef Feature) const override;
+
+  bool hasFeature(StringRef Feature) const override;
+
+  bool handleTargetFeatures(std::vector<std::string> &Features,
+                            DiagnosticsEngine &Diags) override;
+
+private:
+  // Target cpu features.
+  bool IsRF16Enabled = false;
+};
+
+} // namespace targets
+} // namespace clang
+
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_ARC_H
Index: lib/Basic/Targets/ARC.cpp
===================================================================
--- lib/Basic/Targets/ARC.cpp
+++ lib/Basic/Targets/ARC.cpp
@@ -0,0 +1,65 @@
+//===--- 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/MacroBuilder.h"
+#include "llvm/ADT/StringSwitch.h"
+
+using namespace clang;
+using namespace clang::targets;
+
+namespace arc {
+namespace macro {
+  constexpr llvm::StringLiteral arch("__arc__");
+  constexpr llvm::StringLiteral rf16("__ARC_RF16__");
+} // namespace macro
+
+namespace feature {
+  constexpr llvm::StringLiteral rf16("rf16");
+} // namespace feature
+}
+
+void ARCTargetInfo::getTargetDefines(const LangOptions &Opts,
+                                     MacroBuilder &Builder) const {
+  Builder.defineMacro(arc::macro::arch);
+  if (IsRF16Enabled)
+    Builder.defineMacro(arc::macro::rf16);
+}
+
+bool ARCTargetInfo::isValidFeatureName(StringRef Feature) const {
+  return llvm::StringSwitch<bool>(Feature)
+      .Case(arc::feature::rf16, true)
+      .Default(false);
+}
+
+bool ARCTargetInfo::hasFeature(StringRef Feature) const {
+  return llvm::StringSwitch<bool>(Feature)
+      .Case(arc::feature::rf16, IsRF16Enabled)
+      .Default(false);
+}
+
+bool ARCTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
+                                         DiagnosticsEngine &Diags) {
+  for (llvm::StringRef feature : Features) {
+    bool enable = llvm::StringSwitch<bool>(feature)
+      .StartsWith("+", true)
+      .StartsWith("-", false)
+      .Default(false);
+
+    if (feature.endswith(arc::feature::rf16))
+      IsRF16Enabled = enable;
+    else
+      return false;
+  }
+  return true;
+}
\ No newline at end of file
Index: lib/Basic/Targets.cpp
===================================================================
--- lib/Basic/Targets.cpp
+++ lib/Basic/Targets.cpp
@@ -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 @@
   default:
     return nullptr;
 
+  case llvm::Triple::arc:
+    return new ARCTargetInfo(Triple, Opts);
+
   case llvm::Triple::xcore:
     return new XCoreTargetInfo(Triple, Opts);
 
Index: lib/Basic/CMakeLists.txt
===================================================================
--- lib/Basic/CMakeLists.txt
+++ lib/Basic/CMakeLists.txt
@@ -71,6 +71,7 @@
   Targets.cpp
   Targets/AArch64.cpp
   Targets/AMDGPU.cpp
+  Targets/ARC.cpp
   Targets/ARM.cpp
   Targets/AVR.cpp
   Targets/BPF.cpp
Index: include/clang/Driver/Options.td
===================================================================
--- include/clang/Driver/Options.td
+++ include/clang/Driver/Options.td
@@ -135,6 +135,8 @@
                                Group<m_Group>, DocName<"AARCH64">;
 def m_amdgpu_Features_Group : OptionGroup<"<amdgpu features group>">,
                               Group<m_Group>, DocName<"AMDGPU">;
+def m_arc_Features_Group : OptionGroup<"<arc features group>">,
+                           Group<m_Group>, DocName<"ARC">;
 def m_arm_Features_Group : OptionGroup<"<arm features group>">,
                            Group<m_Group>, DocName<"ARM">;
 def m_hexagon_Features_Group : OptionGroup<"<hexagon features group>">,
@@ -2644,6 +2646,10 @@
 def _write_user_dependencies : Flag<["--"], "write-user-dependencies">, Alias<MMD>;
 def _ : Joined<["--"], "">, Flags<[Unsupported]>;
 
+// ARC feature flags.
+def mrf16 : Flag<["-"], "mrf16">, Group<m_arc_Features_Group>,
+  HelpText<"Enable 16-entry register file (ARC only). Defines the __ARC_RF16__ preprocessor macro.">;
+
 // Hexagon feature flags.
 def mieee_rnd_near : Flag<["-"], "mieee-rnd-near">,
   Group<m_hexagon_Features_Group>;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to