diff options
Diffstat (limited to 'gdb/arch')
-rw-r--r-- | gdb/arch/riscv.c | 31 | ||||
-rw-r--r-- | gdb/arch/riscv.h | 9 |
2 files changed, 40 insertions, 0 deletions
diff --git a/gdb/arch/riscv.c b/gdb/arch/riscv.c index cb715fa..81fd2f2 100644 --- a/gdb/arch/riscv.c +++ b/gdb/arch/riscv.c @@ -18,17 +18,45 @@ #include "common-defs.h" #include "riscv.h" #include <stdlib.h> +#include <unordered_map> #include "../features/riscv/32bit-cpu.c" #include "../features/riscv/64bit-cpu.c" #include "../features/riscv/32bit-fpu.c" #include "../features/riscv/64bit-fpu.c" +/* Wrapper used by std::unordered_map to generate hash for feature set. */ +struct riscv_gdbarch_features_hasher +{ + std::size_t + operator() (const riscv_gdbarch_features &features) const noexcept + { + return features.hash (); + } +}; + +/* Cache of previously seen target descriptions, indexed by the feature set + that created them. */ +static std::unordered_map<riscv_gdbarch_features, + target_desc *, + riscv_gdbarch_features_hasher> riscv_tdesc_cache; + /* See arch/riscv.h. */ const target_desc * riscv_create_target_description (struct riscv_gdbarch_features features) { + /* Have we seen this feature set before? If we have return the same + target description. GDB expects that if two target descriptions are + the same (in content terms) then they will actually be the same + instance. This is important when trying to lookup gdbarch objects as + GDBARCH_LIST_LOOKUP_BY_INFO performs a pointer comparison on target + descriptions to find candidate gdbarch objects. */ + const auto it = riscv_tdesc_cache.find (features); + if (it != riscv_tdesc_cache.end ()) + return it->second; + + /* Now we should create a new target description. */ target_desc *tdesc = allocate_target_description (); #ifndef IN_PROCESS_AGENT @@ -65,5 +93,8 @@ riscv_create_target_description (struct riscv_gdbarch_features features) else if (features.flen == 8) regnum = create_feature_riscv_64bit_fpu (tdesc, regnum); + /* Add to the cache. */ + riscv_tdesc_cache.emplace (features, tdesc); + return tdesc; } diff --git a/gdb/arch/riscv.h b/gdb/arch/riscv.h index be41828e..79f5ec6 100644 --- a/gdb/arch/riscv.h +++ b/gdb/arch/riscv.h @@ -66,6 +66,15 @@ struct riscv_gdbarch_features { return !((*this) == rhs); } + + /* Used by std::unordered_map to hash feature sets. */ + std::size_t hash () const noexcept + { + std::size_t val = ((xlen & 0x1f) << 6 + | (flen & 0x1f) << 1 + | (hw_float_abi ? 1 : 0)); + return val; + } }; /* Create and return a target description that is compatible with |