[VE] Support VE in libunwind
authorKazushi (Jam) Marukawa <marukawa@nec.com>
Sat, 26 Dec 2020 13:50:17 +0000 (22:50 +0900)
committerKazushi (Jam) Marukawa <marukawa@nec.com>
Sun, 17 Jan 2021 06:35:02 +0000 (15:35 +0900)
Modify libunwind to support SjLj exception handling routines for VE.
In order to do that, we need to implement not only SjLj exception
handling routines but also a Registers_ve class.  This implementation
of Registers_ve is incomplete.  We will work on it later when we need
backtrace in libunwind.

Reviewed By: #libunwind, compnerd

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

libunwind/include/__libunwind_config.h
libunwind/include/libunwind.h
libunwind/src/Registers.hpp
libunwind/src/Unwind-sjlj.c
libunwind/src/libunwind.cpp

index 80be357..34ac6f7 100644 (file)
@@ -25,6 +25,7 @@
 #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC     31
 #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_HEXAGON   34
 #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV     64
+#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_VE        143
 
 #if defined(_LIBUNWIND_IS_NATIVE_ONLY)
 # if defined(__linux__)
 #    error "Unsupported RISC-V ABI"
 #  endif
 # define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV
+# elif defined(__ve__)
+#  define _LIBUNWIND_TARGET_VE 1
+#  define _LIBUNWIND_CONTEXT_SIZE 67
+#  define _LIBUNWIND_CURSOR_SIZE 79
+#  define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_VE
 # else
 #  error "Unsupported architecture."
 # endif
 # define _LIBUNWIND_TARGET_SPARC 1
 # define _LIBUNWIND_TARGET_HEXAGON 1
 # define _LIBUNWIND_TARGET_RISCV 1
+# define _LIBUNWIND_TARGET_VE 1
 # define _LIBUNWIND_CONTEXT_SIZE 167
 # define _LIBUNWIND_CURSOR_SIZE 179
 # define _LIBUNWIND_HIGHEST_DWARF_REGISTER 287
index 6ec649a..5bae8d0 100644 (file)
@@ -947,4 +947,156 @@ enum {
   UNW_RISCV_F31 = 63,
 };
 
+// VE register numbers
+enum {
+  UNW_VE_S0   = 0,
+  UNW_VE_S1   = 1,
+  UNW_VE_S2   = 2,
+  UNW_VE_S3   = 3,
+  UNW_VE_S4   = 4,
+  UNW_VE_S5   = 5,
+  UNW_VE_S6   = 6,
+  UNW_VE_S7   = 7,
+  UNW_VE_S8   = 8,
+  UNW_VE_S9   = 9,
+  UNW_VE_S10  = 10,
+  UNW_VE_S11  = 11,
+  UNW_VE_S12  = 12,
+  UNW_VE_S13  = 13,
+  UNW_VE_S14  = 14,
+  UNW_VE_S15  = 15,
+  UNW_VE_S16  = 16,
+  UNW_VE_S17  = 17,
+  UNW_VE_S18  = 18,
+  UNW_VE_S19  = 19,
+  UNW_VE_S20  = 20,
+  UNW_VE_S21  = 21,
+  UNW_VE_S22  = 22,
+  UNW_VE_S23  = 23,
+  UNW_VE_S24  = 24,
+  UNW_VE_S25  = 25,
+  UNW_VE_S26  = 26,
+  UNW_VE_S27  = 27,
+  UNW_VE_S28  = 28,
+  UNW_VE_S29  = 29,
+  UNW_VE_S30  = 30,
+  UNW_VE_S31  = 31,
+  UNW_VE_S32  = 32,
+  UNW_VE_S33  = 33,
+  UNW_VE_S34  = 34,
+  UNW_VE_S35  = 35,
+  UNW_VE_S36  = 36,
+  UNW_VE_S37  = 37,
+  UNW_VE_S38  = 38,
+  UNW_VE_S39  = 39,
+  UNW_VE_S40  = 40,
+  UNW_VE_S41  = 41,
+  UNW_VE_S42  = 42,
+  UNW_VE_S43  = 43,
+  UNW_VE_S44  = 44,
+  UNW_VE_S45  = 45,
+  UNW_VE_S46  = 46,
+  UNW_VE_S47  = 47,
+  UNW_VE_S48  = 48,
+  UNW_VE_S49  = 49,
+  UNW_VE_S50  = 50,
+  UNW_VE_S51  = 51,
+  UNW_VE_S52  = 52,
+  UNW_VE_S53  = 53,
+  UNW_VE_S54  = 54,
+  UNW_VE_S55  = 55,
+  UNW_VE_S56  = 56,
+  UNW_VE_S57  = 57,
+  UNW_VE_S58  = 58,
+  UNW_VE_S59  = 59,
+  UNW_VE_S60  = 60,
+  UNW_VE_S61  = 61,
+  UNW_VE_S62  = 62,
+  UNW_VE_S63  = 63,
+  UNW_VE_V0   = 64 + 0,
+  UNW_VE_V1   = 64 + 1,
+  UNW_VE_V2   = 64 + 2,
+  UNW_VE_V3   = 64 + 3,
+  UNW_VE_V4   = 64 + 4,
+  UNW_VE_V5   = 64 + 5,
+  UNW_VE_V6   = 64 + 6,
+  UNW_VE_V7   = 64 + 7,
+  UNW_VE_V8   = 64 + 8,
+  UNW_VE_V9   = 64 + 9,
+  UNW_VE_V10  = 64 + 10,
+  UNW_VE_V11  = 64 + 11,
+  UNW_VE_V12  = 64 + 12,
+  UNW_VE_V13  = 64 + 13,
+  UNW_VE_V14  = 64 + 14,
+  UNW_VE_V15  = 64 + 15,
+  UNW_VE_V16  = 64 + 16,
+  UNW_VE_V17  = 64 + 17,
+  UNW_VE_V18  = 64 + 18,
+  UNW_VE_V19  = 64 + 19,
+  UNW_VE_V20  = 64 + 20,
+  UNW_VE_V21  = 64 + 21,
+  UNW_VE_V22  = 64 + 22,
+  UNW_VE_V23  = 64 + 23,
+  UNW_VE_V24  = 64 + 24,
+  UNW_VE_V25  = 64 + 25,
+  UNW_VE_V26  = 64 + 26,
+  UNW_VE_V27  = 64 + 27,
+  UNW_VE_V28  = 64 + 28,
+  UNW_VE_V29  = 64 + 29,
+  UNW_VE_V30  = 64 + 30,
+  UNW_VE_V31  = 64 + 31,
+  UNW_VE_V32  = 64 + 32,
+  UNW_VE_V33  = 64 + 33,
+  UNW_VE_V34  = 64 + 34,
+  UNW_VE_V35  = 64 + 35,
+  UNW_VE_V36  = 64 + 36,
+  UNW_VE_V37  = 64 + 37,
+  UNW_VE_V38  = 64 + 38,
+  UNW_VE_V39  = 64 + 39,
+  UNW_VE_V40  = 64 + 40,
+  UNW_VE_V41  = 64 + 41,
+  UNW_VE_V42  = 64 + 42,
+  UNW_VE_V43  = 64 + 43,
+  UNW_VE_V44  = 64 + 44,
+  UNW_VE_V45  = 64 + 45,
+  UNW_VE_V46  = 64 + 46,
+  UNW_VE_V47  = 64 + 47,
+  UNW_VE_V48  = 64 + 48,
+  UNW_VE_V49  = 64 + 49,
+  UNW_VE_V50  = 64 + 50,
+  UNW_VE_V51  = 64 + 51,
+  UNW_VE_V52  = 64 + 52,
+  UNW_VE_V53  = 64 + 53,
+  UNW_VE_V54  = 64 + 54,
+  UNW_VE_V55  = 64 + 55,
+  UNW_VE_V56  = 64 + 56,
+  UNW_VE_V57  = 64 + 57,
+  UNW_VE_V58  = 64 + 58,
+  UNW_VE_V59  = 64 + 59,
+  UNW_VE_V60  = 64 + 60,
+  UNW_VE_V61  = 64 + 61,
+  UNW_VE_V62  = 64 + 62,
+  UNW_VE_V63  = 64 + 63,
+  UNW_VE_VM0  = 128 + 0,
+  UNW_VE_VM1  = 128 + 1,
+  UNW_VE_VM2  = 128 + 2,
+  UNW_VE_VM3  = 128 + 3,
+  UNW_VE_VM4  = 128 + 4,
+  UNW_VE_VM5  = 128 + 5,
+  UNW_VE_VM6  = 128 + 6,
+  UNW_VE_VM7  = 128 + 7,
+  UNW_VE_VM8  = 128 + 8,
+  UNW_VE_VM9  = 128 + 9,
+  UNW_VE_VM10 = 128 + 10,
+  UNW_VE_VM11 = 128 + 11,
+  UNW_VE_VM12 = 128 + 12,
+  UNW_VE_VM13 = 128 + 13,
+  UNW_VE_VM14 = 128 + 14,
+  UNW_VE_VM15 = 128 + 15, // = 143
+
+  // Following registers don't have DWARF register numbers.
+  UNW_VE_VIXR = 144,
+  UNW_VE_VL   = 145,
+};
+
 #endif
index e0cb84f..efeaf43 100644 (file)
@@ -36,6 +36,7 @@ enum {
   REGISTERS_SPARC,
   REGISTERS_HEXAGON,
   REGISTERS_RISCV,
+  REGISTERS_VE,
 };
 
 #if defined(_LIBUNWIND_TARGET_I386)
@@ -3983,6 +3984,447 @@ inline void Registers_riscv::setVectorRegister(int, v128) {
   _LIBUNWIND_ABORT("no riscv vector register support yet");
 }
 #endif // _LIBUNWIND_TARGET_RISCV
+
+#if defined(_LIBUNWIND_TARGET_VE)
+/// Registers_ve holds the register state of a thread in a VE process.
+class _LIBUNWIND_HIDDEN Registers_ve {
+public:
+  Registers_ve();
+  Registers_ve(const void *registers);
+
+  bool        validRegister(int num) const;
+  uint64_t    getRegister(int num) const;
+  void        setRegister(int num, uint64_t value);
+  bool        validFloatRegister(int num) const;
+  double      getFloatRegister(int num) const;
+  void        setFloatRegister(int num, double value);
+  bool        validVectorRegister(int num) const;
+  v128        getVectorRegister(int num) const;
+  void        setVectorRegister(int num, v128 value);
+  static const char *getRegisterName(int num);
+  void        jumpto();
+  static int  lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_VE; }
+  static int  getArch() { return REGISTERS_VE; }
+
+  uint64_t  getSP() const         { return _registers.__s[11]; }
+  void      setSP(uint64_t value) { _registers.__s[11] = value; }
+  uint64_t  getIP() const         { return _registers.__ic; }
+  void      setIP(uint64_t value) { _registers.__ic = value; }
+
+private:
+  // FIXME: Need to store not only scalar registers but also vector and vector
+  // mask registers.  VEOS uses mcontext_t defined in ucontext.h.  It takes
+  // 524288 bytes (65536*8 bytes), though.  Currently, we use libunwind for
+  // SjLj exception support only, so Registers_ve is not implemented completely.
+  struct ve_thread_state_t {
+    uint64_t __s[64]; // s0-s64
+    uint64_t __ic;    // Instruction counter (IC)
+    uint64_t __vixr;  // Vector Index Register
+    uint64_t __vl;    // Vector Length Register
+  };
+
+  ve_thread_state_t _registers; // total 67 registers
+
+  // Currently no vector register is preserved.
+};
+
+inline Registers_ve::Registers_ve(const void *registers) {
+  static_assert((check_fit<Registers_ve, unw_context_t>::does_fit),
+                "ve registers do not fit into unw_context_t");
+  memcpy(&_registers, static_cast<const uint8_t *>(registers),
+         sizeof(_registers));
+  static_assert(sizeof(_registers) == 536,
+                "expected vector register offset to be 536");
+}
+
+inline Registers_ve::Registers_ve() {
+  memset(&_registers, 0, sizeof(_registers));
+}
+
+inline bool Registers_ve::validRegister(int regNum) const {
+  if (regNum >= UNW_VE_S0 && regNum <= UNW_VE_S63)
+    return true;
+
+  switch (regNum) {
+  case UNW_REG_IP:
+  case UNW_REG_SP:
+  case UNW_VE_VIXR:
+  case UNW_VE_VL:
+    return true;
+  default:
+    return false;
+  }
+}
+
+inline uint64_t Registers_ve::getRegister(int regNum) const {
+  if (regNum >= UNW_VE_S0 && regNum <= UNW_VE_S63)
+    return _registers.__s[regNum - UNW_VE_S0];
+
+  switch (regNum) {
+  case UNW_REG_IP:
+    return _registers.__ic;
+  case UNW_REG_SP:
+    return _registers.__s[11];
+  case UNW_VE_VIXR:
+    return _registers.__vixr;
+  case UNW_VE_VL:
+    return _registers.__vl;
+  }
+  _LIBUNWIND_ABORT("unsupported ve register");
+}
+
+inline void Registers_ve::setRegister(int regNum, uint64_t value) {
+  if (regNum >= UNW_VE_S0 && regNum <= UNW_VE_S63) {
+    _registers.__s[regNum - UNW_VE_S0] = value;
+    return;
+  }
+
+  switch (regNum) {
+  case UNW_REG_IP:
+    _registers.__ic = value;
+    return;
+  case UNW_REG_SP:
+    _registers.__s[11] = value;
+    return;
+  case UNW_VE_VIXR:
+    _registers.__vixr = value;
+    return;
+  case UNW_VE_VL:
+    _registers.__vl = value;
+    return;
+  }
+  _LIBUNWIND_ABORT("unsupported ve register");
+}
+
+inline bool Registers_ve::validFloatRegister(int /* regNum */) const {
+  return false;
+}
+
+inline double Registers_ve::getFloatRegister(int /* regNum */) const {
+  _LIBUNWIND_ABORT("VE doesn't have float registers");
+}
+
+inline void Registers_ve::setFloatRegister(int /* regNum */,
+                                           double /* value */) {
+  _LIBUNWIND_ABORT("VE doesn't have float registers");
+}
+
+inline bool Registers_ve::validVectorRegister(int /* regNum */) const {
+  return false;
+}
+
+inline v128 Registers_ve::getVectorRegister(int /* regNum */) const {
+  _LIBUNWIND_ABORT("VE vector support not implemented");
+}
+
+inline void Registers_ve::setVectorRegister(int /* regNum */,
+                                            v128 /* value */) {
+  _LIBUNWIND_ABORT("VE vector support not implemented");
+}
+
+inline const char *Registers_ve::getRegisterName(int regNum) {
+  switch (regNum) {
+  case UNW_REG_IP:
+    return "ip";
+  case UNW_REG_SP:
+    return "sp";
+  case UNW_VE_VIXR:
+    return "vixr";
+  case UNW_VE_VL:
+    return "vl";
+  case UNW_VE_S0:
+    return "s0";
+  case UNW_VE_S1:
+    return "s1";
+  case UNW_VE_S2:
+    return "s2";
+  case UNW_VE_S3:
+    return "s3";
+  case UNW_VE_S4:
+    return "s4";
+  case UNW_VE_S5:
+    return "s5";
+  case UNW_VE_S6:
+    return "s6";
+  case UNW_VE_S7:
+    return "s7";
+  case UNW_VE_S8:
+    return "s8";
+  case UNW_VE_S9:
+    return "s9";
+  case UNW_VE_S10:
+    return "s10";
+  case UNW_VE_S11:
+    return "s11";
+  case UNW_VE_S12:
+    return "s12";
+  case UNW_VE_S13:
+    return "s13";
+  case UNW_VE_S14:
+    return "s14";
+  case UNW_VE_S15:
+    return "s15";
+  case UNW_VE_S16:
+    return "s16";
+  case UNW_VE_S17:
+    return "s17";
+  case UNW_VE_S18:
+    return "s18";
+  case UNW_VE_S19:
+    return "s19";
+  case UNW_VE_S20:
+    return "s20";
+  case UNW_VE_S21:
+    return "s21";
+  case UNW_VE_S22:
+    return "s22";
+  case UNW_VE_S23:
+    return "s23";
+  case UNW_VE_S24:
+    return "s24";
+  case UNW_VE_S25:
+    return "s25";
+  case UNW_VE_S26:
+    return "s26";
+  case UNW_VE_S27:
+    return "s27";
+  case UNW_VE_S28:
+    return "s28";
+  case UNW_VE_S29:
+    return "s29";
+  case UNW_VE_S30:
+    return "s30";
+  case UNW_VE_S31:
+    return "s31";
+  case UNW_VE_S32:
+    return "s32";
+  case UNW_VE_S33:
+    return "s33";
+  case UNW_VE_S34:
+    return "s34";
+  case UNW_VE_S35:
+    return "s35";
+  case UNW_VE_S36:
+    return "s36";
+  case UNW_VE_S37:
+    return "s37";
+  case UNW_VE_S38:
+    return "s38";
+  case UNW_VE_S39:
+    return "s39";
+  case UNW_VE_S40:
+    return "s40";
+  case UNW_VE_S41:
+    return "s41";
+  case UNW_VE_S42:
+    return "s42";
+  case UNW_VE_S43:
+    return "s43";
+  case UNW_VE_S44:
+    return "s44";
+  case UNW_VE_S45:
+    return "s45";
+  case UNW_VE_S46:
+    return "s46";
+  case UNW_VE_S47:
+    return "s47";
+  case UNW_VE_S48:
+    return "s48";
+  case UNW_VE_S49:
+    return "s49";
+  case UNW_VE_S50:
+    return "s50";
+  case UNW_VE_S51:
+    return "s51";
+  case UNW_VE_S52:
+    return "s52";
+  case UNW_VE_S53:
+    return "s53";
+  case UNW_VE_S54:
+    return "s54";
+  case UNW_VE_S55:
+    return "s55";
+  case UNW_VE_S56:
+    return "s56";
+  case UNW_VE_S57:
+    return "s57";
+  case UNW_VE_S58:
+    return "s58";
+  case UNW_VE_S59:
+    return "s59";
+  case UNW_VE_S60:
+    return "s60";
+  case UNW_VE_S61:
+    return "s61";
+  case UNW_VE_S62:
+    return "s62";
+  case UNW_VE_S63:
+    return "s63";
+  case UNW_VE_V0:
+    return "v0";
+  case UNW_VE_V1:
+    return "v1";
+  case UNW_VE_V2:
+    return "v2";
+  case UNW_VE_V3:
+    return "v3";
+  case UNW_VE_V4:
+    return "v4";
+  case UNW_VE_V5:
+    return "v5";
+  case UNW_VE_V6:
+    return "v6";
+  case UNW_VE_V7:
+    return "v7";
+  case UNW_VE_V8:
+    return "v8";
+  case UNW_VE_V9:
+    return "v9";
+  case UNW_VE_V10:
+    return "v10";
+  case UNW_VE_V11:
+    return "v11";
+  case UNW_VE_V12:
+    return "v12";
+  case UNW_VE_V13:
+    return "v13";
+  case UNW_VE_V14:
+    return "v14";
+  case UNW_VE_V15:
+    return "v15";
+  case UNW_VE_V16:
+    return "v16";
+  case UNW_VE_V17:
+    return "v17";
+  case UNW_VE_V18:
+    return "v18";
+  case UNW_VE_V19:
+    return "v19";
+  case UNW_VE_V20:
+    return "v20";
+  case UNW_VE_V21:
+    return "v21";
+  case UNW_VE_V22:
+    return "v22";
+  case UNW_VE_V23:
+    return "v23";
+  case UNW_VE_V24:
+    return "v24";
+  case UNW_VE_V25:
+    return "v25";
+  case UNW_VE_V26:
+    return "v26";
+  case UNW_VE_V27:
+    return "v27";
+  case UNW_VE_V28:
+    return "v28";
+  case UNW_VE_V29:
+    return "v29";
+  case UNW_VE_V30:
+    return "v30";
+  case UNW_VE_V31:
+    return "v31";
+  case UNW_VE_V32:
+    return "v32";
+  case UNW_VE_V33:
+    return "v33";
+  case UNW_VE_V34:
+    return "v34";
+  case UNW_VE_V35:
+    return "v35";
+  case UNW_VE_V36:
+    return "v36";
+  case UNW_VE_V37:
+    return "v37";
+  case UNW_VE_V38:
+    return "v38";
+  case UNW_VE_V39:
+    return "v39";
+  case UNW_VE_V40:
+    return "v40";
+  case UNW_VE_V41:
+    return "v41";
+  case UNW_VE_V42:
+    return "v42";
+  case UNW_VE_V43:
+    return "v43";
+  case UNW_VE_V44:
+    return "v44";
+  case UNW_VE_V45:
+    return "v45";
+  case UNW_VE_V46:
+    return "v46";
+  case UNW_VE_V47:
+    return "v47";
+  case UNW_VE_V48:
+    return "v48";
+  case UNW_VE_V49:
+    return "v49";
+  case UNW_VE_V50:
+    return "v50";
+  case UNW_VE_V51:
+    return "v51";
+  case UNW_VE_V52:
+    return "v52";
+  case UNW_VE_V53:
+    return "v53";
+  case UNW_VE_V54:
+    return "v54";
+  case UNW_VE_V55:
+    return "v55";
+  case UNW_VE_V56:
+    return "v56";
+  case UNW_VE_V57:
+    return "v57";
+  case UNW_VE_V58:
+    return "v58";
+  case UNW_VE_V59:
+    return "v59";
+  case UNW_VE_V60:
+    return "v60";
+  case UNW_VE_V61:
+    return "v61";
+  case UNW_VE_V62:
+    return "v62";
+  case UNW_VE_V63:
+    return "v63";
+  case UNW_VE_VM0:
+    return "vm0";
+  case UNW_VE_VM1:
+    return "vm1";
+  case UNW_VE_VM2:
+    return "vm2";
+  case UNW_VE_VM3:
+    return "vm3";
+  case UNW_VE_VM4:
+    return "vm4";
+  case UNW_VE_VM5:
+    return "vm5";
+  case UNW_VE_VM6:
+    return "vm6";
+  case UNW_VE_VM7:
+    return "vm7";
+  case UNW_VE_VM8:
+    return "vm8";
+  case UNW_VE_VM9:
+    return "vm9";
+  case UNW_VE_VM10:
+    return "vm10";
+  case UNW_VE_VM11:
+    return "vm11";
+  case UNW_VE_VM12:
+    return "vm12";
+  case UNW_VE_VM13:
+    return "vm13";
+  case UNW_VE_VM14:
+    return "vm14";
+  case UNW_VE_VM15:
+    return "vm15";
+  }
+  return "unknown register";
+}
+#endif // _LIBUNWIND_TARGET_VE
+
 } // namespace libunwind
 
 #endif // __REGISTERS_HPP__
index 85a4cc3..fd2a95b 100644 (file)
@@ -32,11 +32,23 @@ struct _Unwind_FunctionContext {
   // next function in stack of handlers
   struct _Unwind_FunctionContext *prev;
 
+#if defined(__ve__)
+  // VE requires to store 64 bit pointers in the buffer for SjLj execption.
+  // We expand the size of values defined here.  This size must be matched
+  // to the size returned by TargetMachine::getSjLjDataSize().
+
+  // set by calling function before registering to be the landing pad
+  uint64_t                        resumeLocation;
+
+  // set by personality handler to be parameters passed to landing pad function
+  uint64_t                        resumeParameters[4];
+#else
   // set by calling function before registering to be the landing pad
   uint32_t                        resumeLocation;
 
   // set by personality handler to be parameters passed to landing pad function
   uint32_t                        resumeParameters[4];
+#endif
 
   // set by calling function before registering
   _Unwind_Personality_Fn personality;          // arm offset=24
index fd079da..c21461b 100644 (file)
@@ -62,6 +62,8 @@ _LIBUNWIND_HIDDEN int __unw_init_local(unw_cursor_t *cursor,
 # define REGISTER_KIND Registers_sparc
 #elif defined(__riscv) && __riscv_xlen == 64
 # define REGISTER_KIND Registers_riscv
+#elif defined(__ve__)
+# define REGISTER_KIND Registers_ve
 #else
 # error Architecture not supported
 #endif