diff --git a/parser_library/src/context/ordinary_assembly/address.cpp b/parser_library/src/context/ordinary_assembly/address.cpp index 3d11faf5c..abc7a332c 100644 --- a/parser_library/src/context/ordinary_assembly/address.cpp +++ b/parser_library/src/context/ordinary_assembly/address.cpp @@ -183,12 +183,10 @@ address::address(base address_base, int offset, const space_storage& spaces) if (spaces.empty()) return; - auto new_spaces = std::make_shared>(); // libc++14 space_entry[] - new_spaces->reserve(spaces.size()); - for (auto& space : spaces) - new_spaces->emplace_back(space, 1); + auto new_spaces = std::make_shared(spaces.size()); + std::ranges::transform(spaces, new_spaces.get(), [](const auto& space) { return std::pair(space, 1); }); - spaces_.spaces = *new_spaces; + spaces_.spaces = std::span(new_spaces.get(), spaces.size()); spaces_.owner = std::move(new_spaces); } @@ -199,12 +197,10 @@ address::address(base address_base, int offset, space_storage&& spaces) if (spaces.empty()) return; - auto new_spaces = std::make_shared>(); - new_spaces->reserve(spaces.size()); - for (auto& space : spaces) - new_spaces->emplace_back(std::move(space), 1); + auto new_spaces = std::make_shared(spaces.size()); + std::ranges::transform(spaces, new_spaces.get(), [](auto& space) { return std::pair(std::move(space), 1); }); - spaces_.spaces = *new_spaces; + spaces_.spaces = std::span(new_spaces.get(), spaces.size()); spaces_.owner = std::move(new_spaces); } @@ -223,16 +219,22 @@ address::base_list merge_bases(const address::base_list& l, const address::base_ { if (l.empty()) { - auto result = std::make_shared>(r.bases.begin(), r.bases.end()); - for (auto& [_, cnt] : *result) - cnt *= -1; - return address::base_list(std::move(result)); + const auto total = std::ranges::size(r.bases); + auto result_owner = std::make_shared(total); + std::span result(result_owner.get(), total); + + std::ranges::transform(r.bases, result.begin(), [](auto e) { + e.second *= -1; + return e; + }); + + return address::base_list(result, std::move(result_owner)); } if (std::ranges::equal(l.bases, r.bases)) return {}; } - auto result = std::make_shared>(); // libc++14 base_entry[] + auto result = std::make_shared>(); result->reserve(l.bases.size() + r.bases.size()); @@ -334,13 +336,18 @@ address address::operator-(int offs) const { return address(bases_, offset_ - of address address::operator-() const { auto [spaces, off] = normalized_spaces(); - auto inv_bases = std::make_shared>( - bases_.bases.begin(), bases_.bases.end()); // libc++14 base_entry[] - for (auto& [_, cnt] : *inv_bases) - cnt = -cnt; + const auto total = std::ranges::size(bases_.bases); + auto inv_bases_owner = std::make_shared(total); + std::span inv_bases(inv_bases_owner.get(), total); + + std::ranges::transform(bases_.bases, inv_bases.begin(), [](auto b) { + b.second = -b.second; + return b; + }); + for (auto& s : spaces) s.second = -s.second; - return address(address::base_list(std::move(inv_bases)), + return address(address::base_list(inv_bases, std::move(inv_bases_owner)), -offset_ - off, space_list(std::make_shared>(std::move(spaces)))); } diff --git a/parser_library/test/context/address_test.cpp b/parser_library/test/context/address_test.cpp index ea4f7165f..0a88c7476 100644 --- a/parser_library/test/context/address_test.cpp +++ b/parser_library/test/context/address_test.cpp @@ -20,6 +20,8 @@ #include "context/ordinary_assembly/section.h" #include "library_info_transitional.h" +using namespace ::testing; + // test for // address class @@ -66,3 +68,37 @@ TEST(address, has_unresolved_spaces) ASSERT_FALSE(addr.has_unresolved_space()); } + +TEST(address, constructors) +{ + hlasm_context ctx; + auto sect = ctx.ord_ctx.set_section(id_index("TEST"), section_kind::COMMON, {}, library_info_transitional::empty); + + auto sp1 = ctx.ord_ctx.current_section()->current_location_counter().set_value_undefined(0, 0); + auto sp2 = ctx.ord_ctx.current_section()->current_location_counter().register_ordinary_space(halfword); + + space_storage spaces { sp2 }; + + address addr1({ sect, id_index() }, 12345, spaces); + address addr2({ sect, id_index() }, 12345, std::move(spaces)); + + auto diff = addr1 - addr2; + + EXPECT_TRUE(diff.bases().empty()); + EXPECT_FALSE(diff.has_spaces()); + EXPECT_EQ(diff.offset(), 0); +} + +TEST(address, subtract_optimization) +{ + hlasm_context ctx; + auto sect = ctx.ord_ctx.set_section(id_index("TEST"), section_kind::COMMON, {}, library_info_transitional::empty); + + address addr2({ sect, id_index() }, 12345, {}); + + auto diff = address() - addr2; + + std::array expected_bases { address::base_entry { sect, -1 } }; + + EXPECT_THAT(diff.bases(), Pointwise(Eq(), expected_bases)); +}