[clang] 96d4ccf - [VE] Clang toolchain for VE

Simon Moll via cfe-commits cfe-commits at lists.llvm.org
Wed Jun 24 01:12:54 PDT 2020


Author: Kazushi (Jam) Marukawa
Date: 2020-06-24T10:12:09+02:00
New Revision: 96d4ccf00c8f746aebb549288fac33dcbb15bc4b

URL: https://github.com/llvm/llvm-project/commit/96d4ccf00c8f746aebb549288fac33dcbb15bc4b
DIFF: https://github.com/llvm/llvm-project/commit/96d4ccf00c8f746aebb549288fac33dcbb15bc4b.diff

LOG: [VE] Clang toolchain for VE

Summary:
This patch enables compilation of C code for the VE target with Clang.

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

Added: 
    clang/lib/Basic/Targets/VE.cpp
    clang/lib/Basic/Targets/VE.h
    clang/lib/Driver/ToolChains/Arch/VE.cpp
    clang/lib/Driver/ToolChains/Arch/VE.h
    clang/lib/Driver/ToolChains/VE.cpp
    clang/lib/Driver/ToolChains/VE.h
    clang/test/CodeGen/ve-abi.c

Modified: 
    clang/include/clang/Basic/TargetBuiltins.h
    clang/lib/Basic/CMakeLists.txt
    clang/lib/Basic/Targets.cpp
    clang/lib/CodeGen/TargetInfo.cpp
    clang/lib/Driver/CMakeLists.txt
    clang/lib/Driver/Driver.cpp
    clang/lib/Driver/ToolChains/Clang.cpp
    clang/lib/Driver/ToolChains/Clang.h
    clang/lib/Driver/ToolChains/CommonArgs.cpp
    clang/lib/Driver/ToolChains/Gnu.cpp
    clang/lib/Driver/ToolChains/Linux.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/TargetBuiltins.h b/clang/include/clang/Basic/TargetBuiltins.h
index eba055c302a7..b472547012f0 100644
--- a/clang/include/clang/Basic/TargetBuiltins.h
+++ b/clang/include/clang/Basic/TargetBuiltins.h
@@ -119,6 +119,11 @@ namespace clang {
   };
   }
 
+  /// VE builtins
+  namespace VE {
+  enum { LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1, LastTSBuiltin };
+  }
+
   /// Flags to identify the types for overloaded Neon builtins.
   ///
   /// These must be kept in sync with the flags in utils/TableGen/NeonEmitter.h.

diff  --git a/clang/lib/Basic/CMakeLists.txt b/clang/lib/Basic/CMakeLists.txt
index cd310ec811b4..1b55d8417377 100644
--- a/clang/lib/Basic/CMakeLists.txt
+++ b/clang/lib/Basic/CMakeLists.txt
@@ -84,6 +84,7 @@ add_clang_library(clangBasic
   Targets/Sparc.cpp
   Targets/SystemZ.cpp
   Targets/TCE.cpp
+  Targets/VE.cpp
   Targets/WebAssembly.cpp
   Targets/X86.cpp
   Targets/XCore.cpp

diff  --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp
index 69133ca31fec..6bbcafa27dfe 100644
--- a/clang/lib/Basic/Targets.cpp
+++ b/clang/lib/Basic/Targets.cpp
@@ -33,6 +33,7 @@
 #include "Targets/Sparc.h"
 #include "Targets/SystemZ.h"
 #include "Targets/TCE.h"
+#include "Targets/VE.h"
 #include "Targets/WebAssembly.h"
 #include "Targets/X86.h"
 #include "Targets/XCore.h"
@@ -613,6 +614,9 @@ TargetInfo *AllocateTarget(const llvm::Triple &Triple,
     return new LinuxTargetInfo<RenderScript32TargetInfo>(Triple, Opts);
   case llvm::Triple::renderscript64:
     return new LinuxTargetInfo<RenderScript64TargetInfo>(Triple, Opts);
+
+  case llvm::Triple::ve:
+    return new LinuxTargetInfo<VETargetInfo>(Triple, Opts);
   }
 }
 } // namespace targets

diff  --git a/clang/lib/Basic/Targets/VE.cpp b/clang/lib/Basic/Targets/VE.cpp
new file mode 100644
index 000000000000..22223654e8ad
--- /dev/null
+++ b/clang/lib/Basic/Targets/VE.cpp
@@ -0,0 +1,39 @@
+//===--- VE.cpp - Implement VE target feature support ---------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements VE TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "VE.h"
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/MacroBuilder.h"
+#include "clang/Basic/TargetBuiltins.h"
+
+using namespace clang;
+using namespace clang::targets;
+
+void VETargetInfo::getTargetDefines(const LangOptions &Opts,
+                                    MacroBuilder &Builder) const {
+  Builder.defineMacro("_LP64", "1");
+  Builder.defineMacro("unix", "1");
+  Builder.defineMacro("__unix__", "1");
+  Builder.defineMacro("__linux__", "1");
+  Builder.defineMacro("__ve", "1");
+  Builder.defineMacro("__ve__", "1");
+  Builder.defineMacro("__STDC_HOSTED__", "1");
+  Builder.defineMacro("__STDC__", "1");
+  Builder.defineMacro("__NEC__", "1");
+  // FIXME: define __FAST_MATH__ 1 if -ffast-math is enabled
+  // FIXME: define __OPTIMIZE__ n if -On is enabled
+  // FIXME: define __VECTOR__ n 1 if automatic vectorization is enabled
+}
+
+ArrayRef<Builtin::Info> VETargetInfo::getTargetBuiltins() const {
+  return ArrayRef<Builtin::Info>();
+}

diff  --git a/clang/lib/Basic/Targets/VE.h b/clang/lib/Basic/Targets/VE.h
new file mode 100644
index 000000000000..7e50e7daeb90
--- /dev/null
+++ b/clang/lib/Basic/Targets/VE.h
@@ -0,0 +1,170 @@
+//===--- VE.h - Declare VE target feature support ---------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares VE TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_VE_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_VE_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 VETargetInfo : public TargetInfo {
+  static const Builtin::Info BuiltinInfo[];
+
+public:
+  VETargetInfo(const llvm::Triple &Triple, const TargetOptions &)
+      : TargetInfo(Triple) {
+    NoAsmVariants = true;
+    LongDoubleWidth = 128;
+    LongDoubleAlign = 128;
+    LongDoubleFormat = &llvm::APFloat::IEEEquad();
+    DoubleAlign = LongLongAlign = 64;
+    SuitableAlign = 64;
+    LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
+    SizeType = UnsignedLong;
+    PtrDiffType = SignedLong;
+    IntPtrType = SignedLong;
+    IntMaxType = SignedLong;
+    Int64Type = SignedLong;
+    RegParmMax = 8;
+    MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
+
+    WCharType = UnsignedInt;
+    WIntType = UnsignedInt;
+    UseZeroLengthBitfieldAlignment = true;
+    resetDataLayout("e-m:e-i64:64-n32:64-S64");
+  }
+
+  void getTargetDefines(const LangOptions &Opts,
+                        MacroBuilder &Builder) const override;
+
+  bool hasSjLjLowering() const override {
+    // TODO
+    return false;
+  }
+
+  ArrayRef<Builtin::Info> getTargetBuiltins() const override;
+
+  BuiltinVaListKind getBuiltinVaListKind() const override {
+    return TargetInfo::VoidPtrBuiltinVaList;
+  }
+
+  CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
+    switch (CC) {
+    default:
+      return CCCR_Warning;
+    case CC_C:
+      return CCCR_OK;
+    }
+  }
+
+  const char *getClobbers() const override { return ""; }
+
+  ArrayRef<const char *> getGCCRegNames() const override {
+    static const char *const GCCRegNames[] = {
+        // Regular registers
+        "sx0",  "sx1",  "sx2",  "sx3",  "sx4",  "sx5",  "sx6",  "sx7",
+        "sx8",  "sx9",  "sx10", "sx11", "sx12", "sx13", "sx14", "sx15",
+        "sx16", "sx17", "sx18", "sx19", "sx20", "sx21", "sx22", "sx23",
+        "sx24", "sx25", "sx26", "sx27", "sx28", "sx29", "sx30", "sx31",
+        "sx32", "sx33", "sx34", "sx35", "sx36", "sx37", "sx38", "sx39",
+        "sx40", "sx41", "sx42", "sx43", "sx44", "sx45", "sx46", "sx47",
+        "sx48", "sx49", "sx50", "sx51", "sx52", "sx53", "sx54", "sx55",
+        "sx56", "sx57", "sx58", "sx59", "sx60", "sx61", "sx62", "sx63",
+    };
+    return llvm::makeArrayRef(GCCRegNames);
+  }
+
+  ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
+    static const TargetInfo::GCCRegAlias GCCRegAliases[] = {
+        {{"s0"}, "sx0"},
+        {{"s1"}, "sx1"},
+        {{"s2"}, "sx2"},
+        {{"s3"}, "sx3"},
+        {{"s4"}, "sx4"},
+        {{"s5"}, "sx5"},
+        {{"s6"}, "sx6"},
+        {{"s7"}, "sx7"},
+        {{"s8", "sl"}, "sx8"},
+        {{"s9", "fp"}, "sx9"},
+        {{"s10", "lr"}, "sx10"},
+        {{"s11", "sp"}, "sx11"},
+        {{"s12", "outer"}, "sx12"},
+        {{"s13"}, "sx13"},
+        {{"s14", "tp"}, "sx14"},
+        {{"s15", "got"}, "sx15"},
+        {{"s16", "plt"}, "sx16"},
+        {{"s17", "info"}, "sx17"},
+        {{"s18"}, "sx18"},
+        {{"s19"}, "sx19"},
+        {{"s20"}, "sx20"},
+        {{"s21"}, "sx21"},
+        {{"s22"}, "sx22"},
+        {{"s23"}, "sx23"},
+        {{"s24"}, "sx24"},
+        {{"s25"}, "sx25"},
+        {{"s26"}, "sx26"},
+        {{"s27"}, "sx27"},
+        {{"s28"}, "sx28"},
+        {{"s29"}, "sx29"},
+        {{"s30"}, "sx30"},
+        {{"s31"}, "sx31"},
+        {{"s32"}, "sx32"},
+        {{"s33"}, "sx33"},
+        {{"s34"}, "sx34"},
+        {{"s35"}, "sx35"},
+        {{"s36"}, "sx36"},
+        {{"s37"}, "sx37"},
+        {{"s38"}, "sx38"},
+        {{"s39"}, "sx39"},
+        {{"s40"}, "sx40"},
+        {{"s41"}, "sx41"},
+        {{"s42"}, "sx42"},
+        {{"s43"}, "sx43"},
+        {{"s44"}, "sx44"},
+        {{"s45"}, "sx45"},
+        {{"s46"}, "sx46"},
+        {{"s47"}, "sx47"},
+        {{"s48"}, "sx48"},
+        {{"s49"}, "sx49"},
+        {{"s50"}, "sx50"},
+        {{"s51"}, "sx51"},
+        {{"s52"}, "sx52"},
+        {{"s53"}, "sx53"},
+        {{"s54"}, "sx54"},
+        {{"s55"}, "sx55"},
+        {{"s56"}, "sx56"},
+        {{"s57"}, "sx57"},
+        {{"s58"}, "sx58"},
+        {{"s59"}, "sx59"},
+        {{"s60"}, "sx60"},
+        {{"s61"}, "sx61"},
+        {{"s62"}, "sx62"},
+        {{"s63"}, "sx63"},
+    };
+    return llvm::makeArrayRef(GCCRegAliases);
+  }
+
+  bool validateAsmConstraint(const char *&Name,
+                             TargetInfo::ConstraintInfo &Info) const override {
+    return false;
+  }
+
+  bool allowsLargerPreferedTypeAlignment() const override { return false; }
+};
+} // namespace targets
+} // namespace clang
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_VE_H

diff  --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp
index 9710e676e58f..d28326f9f2f8 100644
--- a/clang/lib/CodeGen/TargetInfo.cpp
+++ b/clang/lib/CodeGen/TargetInfo.cpp
@@ -10548,6 +10548,56 @@ class RISCVTargetCodeGenInfo : public TargetCodeGenInfo {
 };
 } // namespace
 
+//===----------------------------------------------------------------------===//
+// VE ABI Implementation.
+//
+namespace {
+class VEABIInfo : public DefaultABIInfo {
+public:
+  VEABIInfo(CodeGenTypes &CGT) : DefaultABIInfo(CGT) {}
+
+private:
+  ABIArgInfo classifyReturnType(QualType RetTy) const;
+  ABIArgInfo classifyArgumentType(QualType RetTy) const;
+  void computeInfo(CGFunctionInfo &FI) const override;
+};
+} // end anonymous namespace
+
+ABIArgInfo VEABIInfo::classifyReturnType(QualType Ty) const {
+  if (Ty->isAnyComplexType()) {
+    return ABIArgInfo::getDirect();
+  }
+  return DefaultABIInfo::classifyReturnType(Ty);
+}
+
+ABIArgInfo VEABIInfo::classifyArgumentType(QualType Ty) const {
+  if (Ty->isAnyComplexType()) {
+    return ABIArgInfo::getDirect();
+  }
+  return DefaultABIInfo::classifyArgumentType(Ty);
+}
+
+void VEABIInfo::computeInfo(CGFunctionInfo &FI) const {
+
+  FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
+  for (auto &Arg : FI.arguments())
+    Arg.info = classifyArgumentType(Arg.type);
+}
+
+namespace {
+class VETargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+  VETargetCodeGenInfo(CodeGenTypes &CGT)
+      : TargetCodeGenInfo(std::make_unique<VEABIInfo>(CGT)) {}
+  // VE ABI requires the arguments of variadic and prototype-less functions
+  // are passed in both registers and memory.
+  bool isNoProtoCallVariadic(const CallArgList &args,
+                             const FunctionNoProtoType *fnType) const override {
+    return true;
+  }
+};
+} // end anonymous namespace
+
 //===----------------------------------------------------------------------===//
 // Driver code
 //===----------------------------------------------------------------------===//
@@ -10750,6 +10800,8 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() {
   case llvm::Triple::spir:
   case llvm::Triple::spir64:
     return SetCGInfo(new SPIRTargetCodeGenInfo(Types));
+  case llvm::Triple::ve:
+    return SetCGInfo(new VETargetCodeGenInfo(Types));
   }
 }
 

diff  --git a/clang/lib/Driver/CMakeLists.txt b/clang/lib/Driver/CMakeLists.txt
index 6f25d3588ebb..b13789f8b2a8 100644
--- a/clang/lib/Driver/CMakeLists.txt
+++ b/clang/lib/Driver/CMakeLists.txt
@@ -31,6 +31,7 @@ add_clang_library(clangDriver
   ToolChains/Arch/RISCV.cpp
   ToolChains/Arch/Sparc.cpp
   ToolChains/Arch/SystemZ.cpp
+  ToolChains/Arch/VE.cpp
   ToolChains/Arch/X86.cpp
   ToolChains/AIX.cpp
   ToolChains/Ananas.cpp
@@ -67,6 +68,7 @@ add_clang_library(clangDriver
   ToolChains/RISCVToolchain.cpp
   ToolChains/Solaris.cpp
   ToolChains/TCE.cpp
+  ToolChains/VE.cpp
   ToolChains/WebAssembly.cpp
   ToolChains/XCore.cpp
   ToolChains/PPCLinux.cpp

diff  --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 0cf99377f2b5..24436ec4e8d7 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -43,6 +43,7 @@
 #include "ToolChains/RISCVToolchain.h"
 #include "ToolChains/Solaris.h"
 #include "ToolChains/TCE.h"
+#include "ToolChains/VE.h"
 #include "ToolChains/WebAssembly.h"
 #include "ToolChains/XCore.h"
 #include "clang/Basic/Version.h"
@@ -4907,6 +4908,9 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
                Target.getArch() == llvm::Triple::ppc64le)
         TC = std::make_unique<toolchains::PPCLinuxToolChain>(*this, Target,
                                                               Args);
+      else if (Target.getArch() == llvm::Triple::ve)
+        TC = std::make_unique<toolchains::VEToolChain>(*this, Target, Args);
+
       else
         TC = std::make_unique<toolchains::Linux>(*this, Target, Args);
       break;
@@ -4999,6 +5003,9 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
       case llvm::Triple::riscv64:
         TC = std::make_unique<toolchains::RISCVToolChain>(*this, Target, Args);
         break;
+      case llvm::Triple::ve:
+        TC = std::make_unique<toolchains::VEToolChain>(*this, Target, Args);
+        break;
       default:
         if (Target.getVendor() == llvm::Triple::Myriad)
           TC = std::make_unique<toolchains::MyriadToolChain>(*this, Target,

diff  --git a/clang/lib/Driver/ToolChains/Arch/VE.cpp b/clang/lib/Driver/ToolChains/Arch/VE.cpp
new file mode 100644
index 000000000000..fa10e4810f1c
--- /dev/null
+++ b/clang/lib/Driver/ToolChains/Arch/VE.cpp
@@ -0,0 +1,26 @@
+//===--- VE.cpp - Tools Implementations -------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "VE.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/Options.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Option/ArgList.h"
+
+using namespace clang::driver;
+using namespace clang::driver::tools;
+using namespace clang;
+using namespace llvm::opt;
+
+const char *ve::getVEAsmModeForCPU(StringRef Name, const llvm::Triple &Triple) {
+  return "";
+}
+
+void ve::getVETargetFeatures(const Driver &D, const ArgList &Args,
+                             std::vector<StringRef> &Features) {}

diff  --git a/clang/lib/Driver/ToolChains/Arch/VE.h b/clang/lib/Driver/ToolChains/Arch/VE.h
new file mode 100644
index 000000000000..713e3e7d042f
--- /dev/null
+++ b/clang/lib/Driver/ToolChains/Arch/VE.h
@@ -0,0 +1,33 @@
+//===--- VE.h - VE-specific Tool Helpers ------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ARCH_VE_H
+#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ARCH_VE_H
+
+#include "clang/Driver/Driver.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Option/Option.h"
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace driver {
+namespace tools {
+namespace ve {
+
+void getVETargetFeatures(const Driver &D, const llvm::opt::ArgList &Args,
+                         std::vector<llvm::StringRef> &Features);
+const char *getVEAsmModeForCPU(llvm::StringRef Name,
+                               const llvm::Triple &Triple);
+
+} // end namespace ve
+} // namespace tools
+} // end namespace driver
+} // end namespace clang
+
+#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ARCH_VE_H

diff  --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index aa18727671be..54c79032545c 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -15,6 +15,7 @@
 #include "Arch/RISCV.h"
 #include "Arch/Sparc.h"
 #include "Arch/SystemZ.h"
+#include "Arch/VE.h"
 #include "Arch/X86.h"
 #include "CommonArgs.h"
 #include "Hexagon.h"
@@ -368,6 +369,9 @@ static void getTargetFeatures(const Driver &D, const llvm::Triple &Triple,
     break;
   case llvm::Triple::msp430:
     msp430::getMSP430TargetFeatures(D, Args, Features);
+    break;
+  case llvm::Triple::ve:
+    ve::getVETargetFeatures(D, Args, Features);
   }
 
   // Find the last of each feature.
@@ -1663,6 +1667,10 @@ void Clang::RenderTargetOptions(const llvm::Triple &EffectiveTriple,
   case llvm::Triple::wasm64:
     AddWebAssemblyTargetArgs(Args, CmdArgs);
     break;
+
+  case llvm::Triple::ve:
+    AddVETargetArgs(Args, CmdArgs);
+    break;
   }
 }
 
@@ -2160,6 +2168,12 @@ void Clang::AddWebAssemblyTargetArgs(const ArgList &Args,
   }
 }
 
+void Clang::AddVETargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const {
+  // Floating point operations and argument passing are hard.
+  CmdArgs.push_back("-mfloat-abi");
+  CmdArgs.push_back("hard");
+}
+
 void Clang::DumpCompilationDatabase(Compilation &C, StringRef Filename,
                                     StringRef Target, const InputInfo &Output,
                                     const InputInfo &Input, const ArgList &Args) const {

diff  --git a/clang/lib/Driver/ToolChains/Clang.h b/clang/lib/Driver/ToolChains/Clang.h
index 48100c2fc6ec..180bf9f321ab 100644
--- a/clang/lib/Driver/ToolChains/Clang.h
+++ b/clang/lib/Driver/ToolChains/Clang.h
@@ -73,6 +73,8 @@ class LLVM_LIBRARY_VISIBILITY Clang : public Tool {
                           llvm::opt::ArgStringList &CmdArgs) const;
   void AddWebAssemblyTargetArgs(const llvm::opt::ArgList &Args,
                                 llvm::opt::ArgStringList &CmdArgs) const;
+  void AddVETargetArgs(const llvm::opt::ArgList &Args,
+                       llvm::opt::ArgStringList &CmdArgs) const;
 
   enum RewriteKind { RK_None, RK_Fragile, RK_NonFragile };
 

diff  --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 542fb67db7ef..2a9d7e30a461 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -12,6 +12,7 @@
 #include "Arch/Mips.h"
 #include "Arch/PPC.h"
 #include "Arch/SystemZ.h"
+#include "Arch/VE.h"
 #include "Arch/X86.h"
 #include "HIP.h"
 #include "Hexagon.h"
@@ -504,8 +505,11 @@ void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args,
 
 void tools::addArchSpecificRPath(const ToolChain &TC, const ArgList &Args,
                                  ArgStringList &CmdArgs) {
+  // Enable -frtlib-add-rpath by default for the case of VE.
+  const bool IsVE = TC.getTriple().isVE();
+  bool DefaultValue = IsVE;
   if (!Args.hasFlag(options::OPT_frtlib_add_rpath,
-                    options::OPT_fno_rtlib_add_rpath, false))
+                    options::OPT_fno_rtlib_add_rpath, DefaultValue))
     return;
 
   std::string CandidateRPath = TC.getArchSpecificLibPath();

diff  --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp
index 4e577ee163df..ede84c2e3dc4 100644
--- a/clang/lib/Driver/ToolChains/Gnu.cpp
+++ b/clang/lib/Driver/ToolChains/Gnu.cpp
@@ -305,6 +305,8 @@ static const char *getLDMOption(const llvm::Triple &T, const ArgList &Args) {
     if (T.getEnvironment() == llvm::Triple::GNUX32)
       return "elf32_x86_64";
     return "elf_x86_64";
+  case llvm::Triple::ve:
+    return "elf64ve";
   default:
     return nullptr;
   }
@@ -396,6 +398,7 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
   const llvm::Triple::ArchType Arch = ToolChain.getArch();
   const bool isAndroid = ToolChain.getTriple().isAndroid();
   const bool IsIAMCU = ToolChain.getTriple().isOSIAMCU();
+  const bool IsVE = ToolChain.getTriple().isVE();
   const bool IsPIE = getPIE(Args, ToolChain);
   const bool IsStaticPIE = getStaticPIE(Args, ToolChain);
   const bool IsStatic = getStatic(Args);
@@ -514,6 +517,11 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
       CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o")));
     }
 
+    if (IsVE) {
+      CmdArgs.push_back("-z");
+      CmdArgs.push_back("max-page-size=0x4000000");
+    }
+
     if (IsIAMCU)
       CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt0.o")));
     else if (HasCRTBeginEndFiles) {
@@ -683,6 +691,7 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C,
   llvm::Reloc::Model RelocationModel;
   unsigned PICLevel;
   bool IsPIE;
+  const char *DefaultAssembler = "as";
   std::tie(RelocationModel, PICLevel, IsPIE) =
       ParsePICArgs(getToolChain(), Args);
 
@@ -903,6 +912,8 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C,
     CmdArgs.push_back(Args.MakeArgString("-march=" + CPUName));
     break;
   }
+  case llvm::Triple::ve:
+    DefaultAssembler = "nas";
   }
 
   for (const Arg *A : Args.filtered(options::OPT_ffile_prefix_map_EQ,
@@ -927,7 +938,8 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C,
   for (const auto &II : Inputs)
     CmdArgs.push_back(II.getFilename());
 
-  const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
+  const char *Exec =
+      Args.MakeArgString(getToolChain().GetProgramPath(DefaultAssembler));
   C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
 
   // Handle the debug info splitting at object creation time if we're

diff  --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp
index 5e74a2b3c5ff..180350476c38 100644
--- a/clang/lib/Driver/ToolChains/Linux.cpp
+++ b/clang/lib/Driver/ToolChains/Linux.cpp
@@ -541,6 +541,8 @@ std::string Linux::getDynamicLinker(const ArgList &Args) const {
     Loader = X32 ? "ld-linux-x32.so.2" : "ld-linux-x86-64.so.2";
     break;
   }
+  case llvm::Triple::ve:
+    return "/opt/nec/ve/lib/ld-linux-ve.so.1";
   }
 
   if (Distro == Distro::Exherbo &&

diff  --git a/clang/lib/Driver/ToolChains/VE.cpp b/clang/lib/Driver/ToolChains/VE.cpp
new file mode 100644
index 000000000000..ae4e5fedf6b4
--- /dev/null
+++ b/clang/lib/Driver/ToolChains/VE.cpp
@@ -0,0 +1,119 @@
+//===--- VE.cpp - VE ToolChain Implementations ------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "VE.h"
+#include "CommonArgs.h"
+#include "clang/Driver/Compilation.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/Options.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include <cstdlib> // ::getenv
+
+using namespace clang::driver;
+using namespace clang::driver::toolchains;
+using namespace clang;
+using namespace llvm::opt;
+
+/// VE tool chain
+VEToolChain::VEToolChain(const Driver &D, const llvm::Triple &Triple,
+                         const ArgList &Args)
+    : Linux(D, Triple, Args) {
+  getProgramPaths().push_back("/opt/nec/ve/bin");
+  // ProgramPaths are found via 'PATH' environment variable.
+
+  // default file paths are:
+  //   ${RESOURCEDIR}/lib/linux/ve (== getArchSpecificLibPath)
+  //   /lib/../lib64
+  //   /usr/lib/../lib64
+  //   ${BINPATH}/../lib
+  //   /lib
+  //   /usr/lib
+  //
+  // These are OK for host, but no go for VE.  So, defines them all
+  // from scratch here.
+  getFilePaths().clear();
+  getFilePaths().push_back(getArchSpecificLibPath());
+  getFilePaths().push_back(computeSysRoot() + "/opt/nec/ve/lib");
+}
+
+Tool *VEToolChain::buildAssembler() const {
+  return new tools::gnutools::Assembler(*this);
+}
+
+Tool *VEToolChain::buildLinker() const {
+  return new tools::gnutools::Linker(*this);
+}
+
+bool VEToolChain::isPICDefault() const { return false; }
+
+bool VEToolChain::isPIEDefault() const { return false; }
+
+bool VEToolChain::isPICDefaultForced() const { return false; }
+
+bool VEToolChain::SupportsProfiling() const { return false; }
+
+bool VEToolChain::hasBlocksRuntime() const { return false; }
+
+void VEToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
+                                            ArgStringList &CC1Args) const {
+  if (DriverArgs.hasArg(clang::driver::options::OPT_nostdinc))
+    return;
+
+  if (DriverArgs.hasArg(options::OPT_nobuiltininc) &&
+      DriverArgs.hasArg(options::OPT_nostdlibinc))
+    return;
+
+  if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
+    SmallString<128> P(getDriver().ResourceDir);
+    llvm::sys::path::append(P, "include");
+    addSystemInclude(DriverArgs, CC1Args, P);
+  }
+
+  if (!DriverArgs.hasArg(options::OPT_nostdlibinc)) {
+    if (const char *cl_include_dir = getenv("NCC_C_INCLUDE_PATH")) {
+      SmallVector<StringRef, 4> Dirs;
+      const char EnvPathSeparatorStr[] = {llvm::sys::EnvPathSeparator, '\0'};
+      StringRef(cl_include_dir).split(Dirs, StringRef(EnvPathSeparatorStr));
+      ArrayRef<StringRef> DirVec(Dirs);
+      addSystemIncludes(DriverArgs, CC1Args, DirVec);
+    } else {
+      addSystemInclude(DriverArgs, CC1Args,
+                       getDriver().SysRoot + "/opt/nec/ve/include");
+    }
+  }
+}
+
+void VEToolChain::addClangTargetOptions(const ArgList &DriverArgs,
+                                        ArgStringList &CC1Args,
+                                        Action::OffloadKind) const {
+  CC1Args.push_back("-nostdsysteminc");
+  bool UseInitArrayDefault = true;
+  if (!DriverArgs.hasFlag(options::OPT_fuse_init_array,
+                          options::OPT_fno_use_init_array, UseInitArrayDefault))
+    CC1Args.push_back("-fno-use-init-array");
+}
+
+void VEToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
+                                               ArgStringList &CC1Args) const {
+  // TODO upstream VE libc++ patches
+  llvm_unreachable("The VE target has no C++ stdlib for Clang yet");
+}
+
+void VEToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
+                                      ArgStringList &CmdArgs) const {
+  // TODO upstream VE libc++ patches
+  llvm_unreachable("The VE target has no C++ stdlib for Clang yet");
+}
+
+llvm::ExceptionHandling
+VEToolChain::GetExceptionModel(const ArgList &Args) const {
+  // VE uses SjLj exceptions.
+  return llvm::ExceptionHandling::SjLj;
+}

diff  --git a/clang/lib/Driver/ToolChains/VE.h b/clang/lib/Driver/ToolChains/VE.h
new file mode 100644
index 000000000000..59069c0a7595
--- /dev/null
+++ b/clang/lib/Driver/ToolChains/VE.h
@@ -0,0 +1,66 @@
+//===--- VE.h - VE ToolChain Implementations --------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_VE_H
+#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_VE_H
+
+#include "Linux.h"
+#include "clang/Driver/ToolChain.h"
+
+namespace clang {
+namespace driver {
+namespace toolchains {
+
+class LLVM_LIBRARY_VISIBILITY VEToolChain : public Linux {
+public:
+  VEToolChain(const Driver &D, const llvm::Triple &Triple,
+              const llvm::opt::ArgList &Args);
+
+protected:
+  Tool *buildAssembler() const override;
+  Tool *buildLinker() const override;
+
+public:
+  bool isPICDefault() const override;
+  bool isPIEDefault() const override;
+  bool isPICDefaultForced() const override;
+  bool SupportsProfiling() const override;
+  bool hasBlocksRuntime() const override;
+  void
+  AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+                            llvm::opt::ArgStringList &CC1Args) const override;
+  void
+  addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
+                        llvm::opt::ArgStringList &CC1Args,
+                        Action::OffloadKind DeviceOffloadKind) const override;
+  void AddClangCXXStdlibIncludeArgs(
+      const llvm::opt::ArgList &DriverArgs,
+      llvm::opt::ArgStringList &CC1Args) const override;
+  void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
+                           llvm::opt::ArgStringList &CmdArgs) const override;
+
+  llvm::ExceptionHandling
+  GetExceptionModel(const llvm::opt::ArgList &Args) const override;
+
+  CXXStdlibType
+  GetCXXStdlibType(const llvm::opt::ArgList &Args) const override {
+    return ToolChain::CST_Libcxx;
+  }
+
+  RuntimeLibType GetDefaultRuntimeLibType() const override {
+    return ToolChain::RLT_CompilerRT;
+  }
+
+  const char *getDefaultLinker() const override { return "nld"; }
+};
+
+} // end namespace toolchains
+} // end namespace driver
+} // end namespace clang
+
+#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_VE_H

diff  --git a/clang/test/CodeGen/ve-abi.c b/clang/test/CodeGen/ve-abi.c
new file mode 100644
index 000000000000..aa35095d5dea
--- /dev/null
+++ b/clang/test/CodeGen/ve-abi.c
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -triple ve-linux-gnu -emit-llvm %s -o - | FileCheck %s
+
+// CHECK-LABEL: define { float, float } @p(float %a.coerce0, float %a.coerce1, float %b.coerce0, float %b.coerce1) #0 {
+float __complex__ p(float __complex__ a, float __complex__ b) {
+}
+
+// CHECK-LABEL: define { double, double } @q(double %a.coerce0, double %a.coerce1, double %b.coerce0, double %b.coerce1) #0 {
+double __complex__ q(double __complex__ a, double __complex__ b) {
+}
+
+void func() {
+  // CHECK-LABEL: %call = call i32 (i32, i32, i32, i32, i32, i32, i32, ...) bitcast (i32 (...)* @hoge to i32 (i32, i32, i32, i32, i32, i32, i32, ...)*)(i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7)
+  hoge(1, 2, 3, 4, 5, 6, 7);
+}


        


More information about the cfe-commits mailing list