arch: Convert the static constexpr SIZE in vec_reg to a function.
authorGabe Black <gabeblack@google.com>
Sat, 1 Feb 2020 00:57:36 +0000 (16:57 -0800)
committerGabe Black <gabeblack@google.com>
Thu, 20 Feb 2020 23:13:00 +0000 (23:13 +0000)
When defining a static constexpr variable in C++11, it is still
required to have a separate definition someplace, something that can
be particularly problematic in template classes. C++17 fixes this
problem by adding inline variables which don't, but in the mean time
having a static constexpr value with no backing store will, if the
compiler decides to not fold away the storage location, cause linking
errors.

This happened to me when trying to build the debug build of ARM just
now.

By turning these expressions into static inline functions, then they
no longer need definitions elsewhere, still fold away to nothing, and
are compliant with C++11 which is currently the standard gem5 expects
to be using.

Change-Id: I647d7cf4a1e8de98251ee9ef116f007e08eac1f3
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/24964
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Chun-Chen TK Hsu <chunchenhsu@google.com>
Maintainer: Giacomo Travaglini <giacomo.travaglini@arm.com>

src/arch/arm/fastmodel/iris/thread_context.cc
src/arch/generic/vec_reg.hh

index 98fc09eb3ae070820c084059a557a138456fec64..85171fcf8c8ae6d81f9186dc87352649f37c4358 100644 (file)
@@ -589,7 +589,7 @@ ThreadContext::readVecReg(const RegId &reg_id) const
     iris::ResourceReadResult result;
     call().resource_read(_instId, result, vecRegIds.at(idx));
     size_t data_size = result.data.size() * (sizeof(*result.data.data()));
-    size_t size = std::min(data_size, reg.SIZE);
+    size_t size = std::min(data_size, reg.size());
     memcpy(reg.raw_ptr<void>(), (void *)result.data.data(), size);
 
     return reg;
index 8b9bea108410be404f915912adc2987dd213579c..4156ac5efdfdafd0b59536d127487412ce645385 100644 (file)
@@ -170,12 +170,16 @@ template <typename VecElem, size_t NumElems, bool Const>
 class VecRegT
 {
     /** Size of the register in bytes. */
-    static constexpr size_t SIZE = sizeof(VecElem) * NumElems;
+    static constexpr inline size_t
+    size()
+    {
+        return sizeof(VecElem) * NumElems;
+    }
   public:
     /** Container type alias. */
     using Container = typename std::conditional<Const,
-                                              const VecRegContainer<SIZE>,
-                                              VecRegContainer<SIZE>>::type;
+                                              const VecRegContainer<size()>,
+                                              VecRegContainer<size()>>::type;
   private:
     /** My type alias. */
     using MyClass = VecRegT<VecElem, NumElems, Const>;
@@ -238,7 +242,7 @@ class VecRegT
     {
         /* 0-sized is not allowed */
         os << "[" << std::hex << (uint32_t)vr[0];
-        for (uint32_t e = 1; e < vr.SIZE; e++)
+        for (uint32_t e = 1; e < vr.size(); e++)
             os << " " << std::hex << (uint32_t)vr[e];
         os << ']';
         return os;
@@ -264,16 +268,16 @@ class VecLaneT;
  * portion through the method 'as
  * @tparam Sz Size of the container in bytes.
  */
-template <size_t Sz>
+template <size_t SIZE>
 class VecRegContainer
 {
-  static_assert(Sz > 0,
+  static_assert(SIZE > 0,
           "Cannot create Vector Register Container of zero size");
-  static_assert(Sz <= MaxVecRegLenInBytes,
+  static_assert(SIZE <= MaxVecRegLenInBytes,
           "Vector Register size limit exceeded");
   public:
-    static constexpr size_t SIZE = Sz;
-    using Container = std::array<uint8_t,Sz>;
+    static constexpr inline size_t size() { return SIZE; };
+    using Container = std::array<uint8_t, SIZE>;
   private:
     Container container;
     using MyClass = VecRegContainer<SIZE>;
@@ -377,7 +381,7 @@ class VecRegContainer
      * @tparam NumElem Amount of elements in the view.
      */
     /** @{ */
-    template <typename VecElem, size_t NumElems = SIZE/sizeof(VecElem)>
+    template <typename VecElem, size_t NumElems=(SIZE / sizeof(VecElem))>
     VecRegT<VecElem, NumElems, true> as() const
     {
         static_assert(SIZE % sizeof(VecElem) == 0,
@@ -387,7 +391,7 @@ class VecRegContainer
         return VecRegT<VecElem, NumElems, true>(*this);
     }
 
-    template <typename VecElem, size_t NumElems = SIZE/sizeof(VecElem)>
+    template <typename VecElem, size_t NumElems=(SIZE / sizeof(VecElem))>
     VecRegT<VecElem, NumElems, false> as()
     {
         static_assert(SIZE % sizeof(VecElem) == 0,
@@ -638,10 +642,10 @@ template <size_t Sz>
 inline bool
 to_number(const std::string& value, VecRegContainer<Sz>& v)
 {
-    fatal_if(value.size() > 2 * VecRegContainer<Sz>::SIZE,
+    fatal_if(value.size() > 2 * VecRegContainer<Sz>::size(),
              "Vector register value overflow at unserialize");
 
-    for (int i = 0; i < VecRegContainer<Sz>::SIZE; i++) {
+    for (int i = 0; i < VecRegContainer<Sz>::size(); i++) {
         uint8_t b = 0;
         if (2 * i < value.size())
             b = stoul(value.substr(i * 2, 2), nullptr, 16);