diff options
3 files changed, 59 insertions, 14 deletions
diff --git a/runtime/arch/riscv64/instruction_set_features_riscv64.cc b/runtime/arch/riscv64/instruction_set_features_riscv64.cc index 7e5299dce4..947ea54ddb 100644 --- a/runtime/arch/riscv64/instruction_set_features_riscv64.cc +++ b/runtime/arch/riscv64/instruction_set_features_riscv64.cc @@ -19,11 +19,14 @@ #include <fstream> #include <sstream> +#include "android-base/stringprintf.h" #include "android-base/strings.h" #include "base/logging.h" namespace art { +using android::base::StringPrintf; + // Basic feature set is rv64gcv, aka rv64imafdcv. constexpr uint32_t BasicFeatures() { return Riscv64InstructionSetFeatures::kExtGeneric | @@ -83,26 +86,44 @@ bool Riscv64InstructionSetFeatures::Equals(const InstructionSetFeatures* other) uint32_t Riscv64InstructionSetFeatures::AsBitmap() const { return bits_; } +static const std::pair<uint32_t, std::string> kExtensionList[] = { + {Riscv64InstructionSetFeatures::kExtGeneric, "rv64g"}, + {Riscv64InstructionSetFeatures::kExtCompressed, "c"}, + {Riscv64InstructionSetFeatures::kExtVector, "v"}, +}; + std::string Riscv64InstructionSetFeatures::GetFeatureString() const { - std::string result = "rv64"; - if (bits_ & kExtGeneric) { - result += "g"; - } - if (bits_ & kExtCompressed) { - result += "c"; - } - if (bits_ & kExtVector) { - result += "v"; + std::string result = ""; + for (auto&& [ext_bit, ext_string] : kExtensionList) { + if (bits_ & ext_bit) { + result += ext_string; + } } return result; } std::unique_ptr<const InstructionSetFeatures> -Riscv64InstructionSetFeatures::AddFeaturesFromSplitString( - [[maybe_unused]] const std::vector<std::string>& features, - [[maybe_unused]] std::string* error_msg) const { - UNIMPLEMENTED(WARNING); - return std::unique_ptr<const InstructionSetFeatures>(new Riscv64InstructionSetFeatures(bits_)); +Riscv64InstructionSetFeatures::AddFeaturesFromSplitString(const std::vector<std::string>& features, + std::string* error_msg) const { + uint32_t bits = bits_; + if (!features.empty()) { + // There should be only one feature, the ISA string. + DCHECK_EQ(features.size(), 1U); + std::string_view isa_string = features.front(); + bits = 0; + for (auto&& [ext_bit, ext_string] : kExtensionList) { + if (isa_string.substr(0, ext_string.length()) == ext_string) { + isa_string.remove_prefix(ext_string.length()); + bits |= ext_bit; + } + } + if (!isa_string.empty()) { + *error_msg = StringPrintf("Unknown extension in ISA string: '%s'", features.front().c_str()); + return nullptr; + } + DCHECK(bits & kExtGeneric); + } + return FromBitmap(bits); } } // namespace art diff --git a/runtime/arch/riscv64/instruction_set_features_riscv64.h b/runtime/arch/riscv64/instruction_set_features_riscv64.h index 1ad2ffd830..56c41f085b 100644 --- a/runtime/arch/riscv64/instruction_set_features_riscv64.h +++ b/runtime/arch/riscv64/instruction_set_features_riscv64.h @@ -67,6 +67,13 @@ class Riscv64InstructionSetFeatures final : public InstructionSetFeatures { virtual ~Riscv64InstructionSetFeatures() {} protected: + // If `features` is empty, this method doesn't add/remove anything from the + // existing set of features. + // If `features` is not empty, this method expects it to have exactly one value + // which is assumed to be a complete and valid features string. In this case, the + // new features will override the old ones. For example, if the existing set of + // features were `rv64gcv_zba_zbb_zbs` but `features` is `{"rv64gcv"}`, then the + // new features will not have the bits set for Zba, Zbb, or Zbs. std::unique_ptr<const InstructionSetFeatures> AddFeaturesFromSplitString( const std::vector<std::string>& features, std::string* error_msg) const override; diff --git a/runtime/arch/riscv64/instruction_set_features_riscv64_test.cc b/runtime/arch/riscv64/instruction_set_features_riscv64_test.cc index 0f0cbda8b7..fd9e83b81a 100644 --- a/runtime/arch/riscv64/instruction_set_features_riscv64_test.cc +++ b/runtime/arch/riscv64/instruction_set_features_riscv64_test.cc @@ -37,4 +37,21 @@ TEST(Riscv64InstructionSetFeaturesTest, Riscv64FeaturesFromDefaultVariant) { EXPECT_EQ(riscv64_features->AsBitmap(), expected_extensions); } +TEST(Riscv64InstructionSetFeaturesTest, Riscv64FeaturesFromString) { + std::string error_msg; + std::unique_ptr<const InstructionSetFeatures> generic_features( + InstructionSetFeatures::FromVariant(InstructionSet::kRiscv64, "generic", &error_msg)); + ASSERT_TRUE(generic_features.get() != nullptr) << error_msg; + + std::unique_ptr<const InstructionSetFeatures> rv64gv_features( + generic_features->AddFeaturesFromString("rv64gv", &error_msg)); + ASSERT_TRUE(rv64gv_features.get() != nullptr) << error_msg; + + EXPECT_FALSE(generic_features->Equals(rv64gv_features.get())); + + uint32_t expected_extensions = Riscv64InstructionSetFeatures::kExtGeneric | + Riscv64InstructionSetFeatures::kExtVector; + EXPECT_EQ(rv64gv_features->AsBitmap(), expected_extensions); +} + } // namespace art |