diff --git a/MODULE.bazel b/MODULE.bazel index c6c5d3c..40d50c9 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -1,3 +1,3 @@ -bazel_dep(name = "abseil-cpp", repo_name = "com_google_absl", version = "20230125.1") -bazel_dep(name = "bazel_skylib", repo_name = "bazel_skylib", version = "1.4.2") -bazel_dep(name = "nth-cc", repo_name = "nth_cc", version = "20240602.00") +bazel_dep(name = "abseil-cpp", repo_name = "com_google_absl", version = "20240116.2") +bazel_dep(name = "bazel_skylib", repo_name = "bazel_skylib", version = "1.5.0") +bazel_dep(name = "nth-cc", repo_name = "nth_cc", version = "20240812.00") diff --git a/examples/BUILD b/examples/BUILD index ae7f053..e729df3 100644 --- a/examples/BUILD +++ b/examples/BUILD @@ -46,25 +46,3 @@ cc_binary( "@nth_cc//nth/container:stack", ], ) - - -cc_binary( - name = "serialization", - srcs = ["serialization.cc"], - deps = [ - "//jasmin/core:instruction", - "//jasmin/core:function", - "//jasmin/core:function_registry", - "//jasmin/core:program_fragment", - "//jasmin/instructions:arithmetic", - "//jasmin/instructions:compare", - "//jasmin/instructions:common", - "@nth_cc//nth/debug", - "@nth_cc//nth/debug/log:stderr_log_sink", - "@nth_cc//nth/io/deserialize", - "@nth_cc//nth/io/serialize", - "@nth_cc//nth/io/reader:string", - "@nth_cc//nth/io/writer:string", - "@com_google_absl//absl/container:flat_hash_set", - ], -) diff --git a/examples/brainfuck/file.cc b/examples/brainfuck/file.cc index 527c39a..4e822c4 100644 --- a/examples/brainfuck/file.cc +++ b/examples/brainfuck/file.cc @@ -19,7 +19,7 @@ std::string LoadFileContentsOrDie(std::string_view path) { std::string contents(file->size(), '\0'); std::span data = file->read_into(contents); if (not file->close()) { std::abort(); } - NTH_REQUIRE((v.debug), data.size() == contents.size()); + NTH_REQUIRE((debug), data.size() == contents.size()); return contents; } diff --git a/examples/brainfuck/interpreter.cc b/examples/brainfuck/interpreter.cc index 604a15f..55b782d 100644 --- a/examples/brainfuck/interpreter.cc +++ b/examples/brainfuck/interpreter.cc @@ -6,7 +6,7 @@ #include "nth/debug/log/stderr_log_sink.h" int main(int argc, char* argv[]) { - nth::RegisterLogSink(nth::stderr_log_sink); + nth::register_log_sink(nth::stderr_log_sink); if (argc != 2) { return 1; } std::string contents = bf::LoadFileContentsOrDie(argv[1]); diff --git a/examples/serialization.cc b/examples/serialization.cc deleted file mode 100644 index 98f2f34..0000000 --- a/examples/serialization.cc +++ /dev/null @@ -1,131 +0,0 @@ -#include -#include - -#include "jasmin/core/function.h" -#include "jasmin/core/function_registry.h" -#include "jasmin/core/instruction.h" -#include "jasmin/core/program_fragment.h" -#include "jasmin/instructions/arithmetic.h" -#include "jasmin/instructions/common.h" -#include "jasmin/instructions/compare.h" -#include "nth/container/interval.h" -#include "nth/debug/debug.h" -#include "nth/debug/log/stderr_log_sink.h" -#include "nth/io/deserialize/deserialize.h" -#include "nth/io/reader/string.h" -#include "nth/io/serialize/serialize.h" -#include "nth/io/writer/string.h" - -using Instructions = jasmin::MakeInstructionSet< - jasmin::Duplicate, jasmin::Swap, jasmin::Push, - jasmin::Push*>, jasmin::LessThan, - jasmin::Add, jasmin::Subtract>; - -jasmin::ProgramFragment MakeProgram() { - jasmin::ProgramFragment p; - auto& func = p.declare("fib", 1, 1).function; - func.append(); - func.append>(2); - func.append>(); - nth::interval jump = - func.append_with_placeholders(); - func.append(); - func.append>(1); - func.append>(); - func.append*>>(&func); - func.append( - jasmin::InstructionSpecification{.parameters = 1, .returns = 1}); - func.append(); - func.append>(2); - func.append>(); - func.append*>>(&func); - func.append( - jasmin::InstructionSpecification{.parameters = 1, .returns = 1}); - func.append>(); - nth::interval ret = func.append(); - func.set_value(jump, 0, ret.lower_bound() - jump.lower_bound()); - return p; -} - -// Defines a serializer that understands how to serialize -// jasmin::ProgramFragments. We still need to teach the serializer how to -// serialize specific immediate value types. -struct Serializer : nth::io::string_writer { - explicit Serializer(std::string& s) : nth::io::string_writer(s) {} - - friend bool NthSerialize(Serializer& s, uint64_t n) { - return nth::io::write_integer(s, n); - } - - jasmin::FunctionRegistry& context( - decltype(nth::type)) { - return registry_; - } - - private: - jasmin::FunctionRegistry registry_; -}; - -// Defines a deserializer that understands how to deserialize -// jasmin::ProgramFragments. We still need to teach the deserializer how to -// deserialize specific immediate value types. -struct Deserializer : nth::io::string_reader { - explicit Deserializer(std::string_view s) : nth::io::string_reader(s) {} - - friend bool NthDeserialize(Deserializer& d, uint64_t& n) { - return nth::io::read_integer(d, n); - } - - friend bool NthDeserialize(Deserializer& d, std::integral auto& x) { - return nth::io::read_integer(d, x); - } - - friend bool NthDeserialize(Deserializer& d, std::floating_point auto& x) { - return nth::io::read_fixed(d, x); - } - - jasmin::FunctionRegistry& context( - decltype(nth::type)) { - return registry_; - } - - private: - jasmin::FunctionRegistry registry_; -}; - -int main() { - // The string which is going to hold the serialized program. - std::string content; - - { - // Construct a program and serialize it into `content`. - jasmin::ProgramFragment p = MakeProgram(); - Serializer serializer(content); - if (not nth::io::serialize(serializer, p)) { return 1; } - } - - // At this point the constructed program has been destroyed. The only remnants - // of it are this serialization. - std::puts("Serialized program:"); - for (size_t i = 0; i < content.size(); ++i) { - std::printf(" %0.2x", content[i]); - if (i % 8 == 7) { std::putchar('\n'); } - } - std::putchar('\n'); - - { - // Reconstitute the program previously serialized into `content` back into - // the program `p`. - jasmin::ProgramFragment p; - Deserializer deserializer(content); - if (not nth::io::deserialize(deserializer, p)) { return 1; } - - uint64_t n = 15; - nth::stack stack = {n}; - p.function("fib").invoke(stack); - std::printf("fib(%" PRIu64 ") = %" PRIu64 "\n", n, - stack.top().as()); - } - - return 0; -} diff --git a/jasmin/compile/BUILD b/jasmin/compile/BUILD index a4063f5..465fe90 100644 --- a/jasmin/compile/BUILD +++ b/jasmin/compile/BUILD @@ -7,5 +7,6 @@ cc_library( visibility = ["//visibility:public"], deps = [ "@nth_cc//nth/debug", + "@nth_cc//nth/memory:bytes", ], ) diff --git a/jasmin/compile/compiled_function.cc b/jasmin/compile/compiled_function.cc index 67f432a..06b41ec 100644 --- a/jasmin/compile/compiled_function.cc +++ b/jasmin/compile/compiled_function.cc @@ -5,12 +5,12 @@ #include #include "nth/debug/debug.h" +#include "nth/memory/bytes.h" namespace jasmin { CompiledFunction::operator std::span() const { - return std::span( - reinterpret_cast(content_.data()), content_.size()); + return nth::byte_range(content_); } void CompiledFunction::write(std::initializer_list instructions) { @@ -18,7 +18,7 @@ void CompiledFunction::write(std::initializer_list instructions) { } void CompiledFunction::write_at_impl(size_t offset, uint32_t n) { - NTH_REQUIRE((v.harden), n + sizeof(uint32_t) <= content_.size()); + NTH_REQUIRE((harden), n + sizeof(uint32_t) <= content_.size()); std::memcpy(content_.data() + offset, &n, sizeof(n)); } diff --git a/jasmin/core/BUILD b/jasmin/core/BUILD index 3f9f655..9bb3c61 100644 --- a/jasmin/core/BUILD +++ b/jasmin/core/BUILD @@ -28,9 +28,8 @@ cc_library( "//jasmin/core/internal:function_base", "//jasmin/core/internal:function_forward", "//jasmin/core/internal:instruction_traits", + "@nth_cc//nth/format", "@nth_cc//nth/container:interval", - "@nth_cc//nth/io/deserialize", - "@nth_cc//nth/io/serialize", ], ) @@ -51,10 +50,6 @@ cc_library( deps = [ "//jasmin/core/internal:function_forward", "@nth_cc//nth/debug", - "@nth_cc//nth/io/deserialize", - "@nth_cc//nth/io/reader", - "@nth_cc//nth/io/serialize", - "@nth_cc//nth/io/writer", ], ) @@ -139,7 +134,7 @@ cc_library( "//jasmin/core/internal:instruction_traits", "@com_google_absl//absl/container:flat_hash_map", "@nth_cc//nth/debug", - "@nth_cc//nth/utility:no_destructor", + "@nth_cc//nth/base:indestructible", ], ) @@ -182,26 +177,11 @@ cc_library( ":instruction", ":value", "@nth_cc//nth/debug", - "@nth_cc//nth/io/deserialize", - "@nth_cc//nth/io/serialize", + "@nth_cc//nth/format", "@nth_cc//nth/utility:iterator_range", ], ) -cc_test( - name = "serialization_test", - srcs = ["serialization_test.cc"], - deps = [ - ":function", - ":function_registry", - ":program_fragment", - "//jasmin/instructions:common", - "@nth_cc//nth/io/reader:string", - "@nth_cc//nth/io/writer:string", - "@nth_cc//nth/test:main", - ], -) - cc_library( name = "value", hdrs = ["value.h"], diff --git a/jasmin/core/debugger.cc b/jasmin/core/debugger.cc index 0dc123d..5adf417 100644 --- a/jasmin/core/debugger.cc +++ b/jasmin/core/debugger.cc @@ -28,7 +28,7 @@ void Debugger::set_function_breakpoint(std::string name, auto &f = program_.function(name); auto [iter, inserted] = breakpoint_functions_.try_emplace( std::move(name), nullptr, std::move(response)); - NTH_REQUIRE((v.harden), inserted); + NTH_REQUIRE((harden), inserted); iter->second.first = std::exchange(f, nullptr); auto fn = std::make_unique>(0, 0); f.raw_append(DebugImpl); diff --git a/jasmin/core/debugger.h b/jasmin/core/debugger.h index 2c9773d..832a8ee 100644 --- a/jasmin/core/debugger.h +++ b/jasmin/core/debugger.h @@ -56,7 +56,7 @@ void Debugger::set_function_breakpoint(std::string name, auto [iter, inserted] = breakpoint_functions_.try_emplace( std::move(name), Function(f.parameter_count(), f.return_count()), std::move(response)); - NTH_REQUIRE((v.harden), inserted); + NTH_REQUIRE((harden), inserted); iter->second.first = std::move(f); f = Function(0, 0); f.raw_append(internal::DebugImpl); diff --git a/jasmin/core/function.h b/jasmin/core/function.h index 10fe10b..899369f 100644 --- a/jasmin/core/function.h +++ b/jasmin/core/function.h @@ -10,6 +10,7 @@ #include "jasmin/core/internal/instruction_traits.h" #include "jasmin/core/metadata.h" #include "nth/container/interval.h" +#include "nth/format/format.h" #include "nth/io/serialize/serialize.h" #include "nth/meta/type.h" @@ -104,10 +105,10 @@ struct Function : Function<> { friend nth::io::serializer_result_type NthSerialize(S &s, Function const &fn) { using result_type = nth::io::serializer_result_type; - if (not nth::io::write_integer(s, fn.parameter_count())) { + if (not nth::format_integer(s, fn.parameter_count())) { return result_type(false); } - if (not nth::io::write_integer(s, fn.return_count())) { + if (not nth::format_integer(s, fn.return_count())) { return result_type(false); } auto const &set_metadata = Metadata(); @@ -124,7 +125,7 @@ struct Function : Function<> { while (not insts.empty()) { uint16_t index = set_metadata.opcode(insts[0]); - if (not nth::io::write_fixed(s, index)) { return result_type(false); } + if (not nth::format_fixed(s, index)) { return result_type(false); } auto immediate_value_count = set_metadata.metadata(index).immediate_value_count; result_type result = @@ -303,7 +304,7 @@ InstructionSerializer( } else if constexpr (nth::type == nth::type) { return nth::io::serialize(s, v[0].as()); } else if constexpr (nth::any_of) { - return result_type(nth::io::write_integer(s, v[0].as())); + return result_type(nth::format_integer(s, v[0].as())); } else { constexpr auto params = [] { if constexpr (requires { I::execute; }) { diff --git a/jasmin/core/function_identifier.h b/jasmin/core/function_identifier.h index 85b02f3..2a51934 100644 --- a/jasmin/core/function_identifier.h +++ b/jasmin/core/function_identifier.h @@ -5,10 +5,6 @@ #include #include "jasmin/core/internal/function_forward.h" -#include "nth/io/deserialize/deserialize.h" -#include "nth/io/reader/reader.h" -#include "nth/io/serialize/serialize.h" -#include "nth/io/writer/writer.h" namespace jasmin { @@ -19,30 +15,6 @@ struct FunctionIdentifier { constexpr FunctionIdentifier() = default; static constexpr FunctionIdentifier Invalid() { return FunctionIdentifier(); } - template - friend nth::io::serializer_result_type NthSerialize( - S& s, FunctionIdentifier id) { - using result_type = nth::io::serializer_result_type; - if (id == Invalid()) { return result_type(false); } - if (not nth::io::write_integer(s, id.fragment_)) { - return result_type(false); - } - if (not nth::io::write_integer(s, id.index_)) { return result_type(false); } - return result_type(true); - } - - template - friend nth::io::deserializer_result_type NthDeserialize( - D& d, FunctionIdentifier& id) { - using result_type = nth::io::deserializer_result_type; - if (not nth::io::read_integer(d, id.fragment_)) { - return result_type(false); - } - if (not nth::io::read_integer(d, id.index_)) { return result_type(false); } - if (id == Invalid()) { return result_type(false); } - return result_type(true); - } - friend bool operator==(FunctionIdentifier, FunctionIdentifier) = default; friend bool operator!=(FunctionIdentifier, FunctionIdentifier) = default; diff --git a/jasmin/core/internal/BUILD b/jasmin/core/internal/BUILD index b9ca7ba..12b3bbb 100644 --- a/jasmin/core/internal/BUILD +++ b/jasmin/core/internal/BUILD @@ -51,6 +51,7 @@ cc_library( "//jasmin/core:input", "//jasmin/core:output", "//jasmin/core:value", + "@nth_cc//nth/format", "@nth_cc//nth/meta:concepts", "@nth_cc//nth/meta:type", "@nth_cc//nth/io/deserialize", diff --git a/jasmin/core/internal/function_base.h b/jasmin/core/internal/function_base.h index 555cfe7..ac3a77e 100644 --- a/jasmin/core/internal/function_base.h +++ b/jasmin/core/internal/function_base.h @@ -61,8 +61,7 @@ struct FunctionBase { // overwrite any such `Value`. void set_value(nth::interval range, InstructionIndex::difference_type index, Value value) { - NTH_REQUIRE((v.when(internal::harden)), index + 1 < range.length()) - .Log<"Index larger than range">(); + NTH_REQUIRE((harden), index + 1 < range.length()); instructions_[range.lower_bound().value() + index + 1] = value; } diff --git a/jasmin/core/internal/instruction_traits.h b/jasmin/core/internal/instruction_traits.h index 65922a7..0489080 100644 --- a/jasmin/core/internal/instruction_traits.h +++ b/jasmin/core/internal/instruction_traits.h @@ -5,6 +5,7 @@ #include "jasmin/core/internal/function_state.h" #include "jasmin/core/output.h" #include "jasmin/core/value.h" +#include "nth/format/format.h" #include "nth/io/deserialize/deserialize.h" #include "nth/io/serialize/serialize.h" #include "nth/meta/concepts.h" @@ -25,10 +26,11 @@ struct InstructionSpecification { uint32_t returns; template - friend nth::io::serializer_result_typeNthSerialize(S& s, InstructionSpecification spec) { + friend nth::io::serializer_result_type NthSerialize( + S& s, InstructionSpecification spec) { return nth::io::serializer_result_type( - nth::io::write_integer(s, spec.parameters) and - nth::io::write_integer(s, spec.returns)); + nth::format_integer(s, spec.parameters) and + nth::format_integer(s, spec.returns)); } template diff --git a/jasmin/core/metadata.cc b/jasmin/core/metadata.cc index e36d17f..d59e73c 100644 --- a/jasmin/core/metadata.cc +++ b/jasmin/core/metadata.cc @@ -9,13 +9,12 @@ #include "jasmin/core/internal/instruction_traits.h" #include "jasmin/core/value.h" #include "nth/debug/debug.h" -#include "nth/utility/no_destructor.h" namespace jasmin { InstructionMetadata const& InstructionSetMetadata::metadata( uint16_t opcode) const { - NTH_REQUIRE((v.harden), opcode < metadata_.size()); + NTH_REQUIRE((harden), opcode < metadata_.size()); return metadata_[opcode]; } @@ -25,7 +24,7 @@ Value InstructionSetMetadata::function(uint16_t opcode) const { uint16_t InstructionSetMetadata::opcode(Value f) const { auto iter = opcode_.find(f.as()); - NTH_REQUIRE((v.harden), iter != opcode_.end()); + NTH_REQUIRE((harden), iter != opcode_.end()); return iter->second; } diff --git a/jasmin/core/metadata.h b/jasmin/core/metadata.h index 8c5b124..6acea5d 100644 --- a/jasmin/core/metadata.h +++ b/jasmin/core/metadata.h @@ -9,7 +9,7 @@ #include "jasmin/core/instruction.h" #include "jasmin/core/internal/instruction_traits.h" #include "jasmin/core/value.h" -#include "nth/utility/no_destructor.h" +#include "nth/base/indestructible.h" namespace jasmin { @@ -71,7 +71,7 @@ struct InstructionSetMetadata { // `Set`. template InstructionSetMetadata const& Metadata() { - static nth::NoDestructor metadata = + static nth::indestructible metadata = Set::instructions.reduce([](auto... is) { return InstructionSetMetadata( {InstructionMetadata{ diff --git a/jasmin/core/program_fragment.h b/jasmin/core/program_fragment.h index 716bc6e..c27db4f 100644 --- a/jasmin/core/program_fragment.h +++ b/jasmin/core/program_fragment.h @@ -10,8 +10,8 @@ #include "jasmin/core/internal/function_forward.h" #include "nth/container/flyweight_map.h" #include "nth/debug/debug.h" -#include "nth/io/deserialize/deserialize.h" -#include "nth/io/serialize/serialize.h" +#include "nth/format/format.h" +#include "nth/memory/bytes.h" #include "nth/utility/iterator_range.h" namespace jasmin { @@ -67,68 +67,6 @@ struct ProgramFragment : internal::ProgramFragmentBase { [[nodiscard]] Function const& function(function_identifier id) const; [[nodiscard]] Function& function(function_identifier id); - template S> - friend nth::io::serializer_result_type NthSerialize( - S& s, ProgramFragment const& p) { - using result_type = nth::io::serializer_result_type; - if (not nth::io::write_integer(s, p.functions_.size())) { - return result_type(false); - } - auto& registry = s.context(nth::type); - for (auto const& [name, fn] : p.functions_) { - registry.register_function(p, fn); - if (not nth::io::write_integer(s, name.size())) { - return result_type(false); - } - if (not s.write(std::span( - reinterpret_cast(name.data()), name.size()))) { - return result_type(false); - } - } - - result_type result(true); - for (auto const& [name, fn] : p.functions_) { - result = nth::io::serialize(s, fn); - if (not result) { return result; } - } - return result; - } - - template D> - friend nth::io::deserializer_result_type NthDeserialize( - D& d, ProgramFragment& p) { - using result_type = nth::io::deserializer_result_type; - size_t size; - if (not nth::io::read_integer(d, size)) { return result_type(false); } - - std::vector*> fns; - fns.reserve(size); - - auto& registry = d.context(nth::type); - for (uint32_t i = 0; i < size; ++i) { - size_t name_size; - if (not nth::io::read_integer(d, name_size)) { - return result_type(false); - } - std::string name(name_size, '\0'); - if (not d.read(std::span( - reinterpret_cast(name.data()), name.size()))) { - return result_type(false); - } - - auto [iter, inserted] = p.functions_.try_emplace(name); - if (inserted) { registry.register_function(p, iter->second); } - fns.push_back(&iter->second); - } - - result_type result(true); - for (Function* fn : fns) { - result = nth::io::deserialize(d, *fn); - if (not result) { return result; } - } - return result; - } - // Returns the number of functions managed by this `ProgramFragment`. size_t function_count() const { return functions_.size(); } @@ -153,7 +91,7 @@ ProgramFragment::declare_result ProgramFragment::declare( template Function& ProgramFragment::function(std::string const& name) { auto iter = functions_.find(name); - NTH_REQUIRE((v.harden), iter != functions_.end()); + NTH_REQUIRE((harden), iter != functions_.end()); return iter->second; } @@ -161,7 +99,7 @@ template Function const& ProgramFragment::function( std::string const& name) const { auto iter = functions_.find(name); - NTH_REQUIRE((v.harden), iter != functions_.end()); + NTH_REQUIRE((harden), iter != functions_.end()); return iter->second; } diff --git a/jasmin/core/serialization_test.cc b/jasmin/core/serialization_test.cc deleted file mode 100644 index f3661f0..0000000 --- a/jasmin/core/serialization_test.cc +++ /dev/null @@ -1,134 +0,0 @@ -#include "jasmin/core/function.h" -#include "jasmin/core/function_registry.h" -#include "jasmin/core/program_fragment.h" -#include "jasmin/instructions/common.h" -#include "nth/io/reader/reader.h" -#include "nth/io/reader/string.h" -#include "nth/io/writer/string.h" -#include "nth/io/writer/writer.h" -#include "nth/test/test.h" - -namespace jasmin { -namespace { - -struct Serializer : nth::io::string_writer { - explicit Serializer(std::string &s) : nth::io::string_writer(s) {} - - FunctionRegistry &context(decltype(nth::type)) { - return registry_; - } - - private: - FunctionRegistry registry_; -}; - -struct Deserializer : nth::io::string_reader { - explicit Deserializer(std::string_view s) : nth::io::string_reader(s) {} - - FunctionRegistry &context(decltype(nth::type)) { - return registry_; - } - - friend bool NthDeserialize(Deserializer &d, std::integral auto &x) { - return nth::io::read_integer(d, x); - } - - friend bool NthDeserialize(Deserializer &d, std::floating_point auto &x) { - return nth::io::read_fixed(d, x); - } - - private: - FunctionRegistry registry_; -}; - -NTH_TEST("round-trip/integer", auto n) { - std::string content; - Serializer serializer(content); - NTH_ASSERT(nth::io::write_integer(serializer, n)); - - decltype(n) m; - Deserializer deserializer(content); - NTH_ASSERT(nth::io::read_integer(deserializer, m)); - NTH_ASSERT(deserializer.size() == 0); - NTH_EXPECT(m == n); -} - -NTH_INVOKE_TEST("round-trip/integer") { - for (int32_t n : {0, 1, -1, 10, -10, 256, -256, 257, -257, 1'000'000, - -1'000'000, std::numeric_limits::max(), - std::numeric_limits::lowest()}) { - co_yield n; - } - - for (uint32_t n : {0u, 1u, 10u, 256u, 257u, 1'000'000u, - std::numeric_limits::max()}) { - co_yield n; - } -} - -using Set = MakeInstructionSet*>>; - -NTH_TEST("round-trip/program-fragment/empty") { - ProgramFragment p; - - std::string content; - Serializer serializer(content); - NTH_ASSERT(nth::io::serialize(serializer, p)); - - ProgramFragment q; - Deserializer deserializer(content); - NTH_ASSERT(nth::io::deserialize(deserializer, q)); - NTH_EXPECT(q.function_count() == p.function_count()); -} - -NTH_TEST("round-trip/program-fragment/functions") { - ProgramFragment p; - auto& f = p.declare("f", 0, 0).function; - f.append(); - - std::string content; - Serializer serializer(content); - NTH_ASSERT(nth::io::serialize(serializer, p)); - - ProgramFragment q; - Deserializer deserializer(content); - NTH_ASSERT(nth::io::deserialize(deserializer, q)); - NTH_EXPECT(q.function_count() == p.function_count()); - NTH_ASSERT(p.function("f").raw_instructions().size() == - q.function("f").raw_instructions().size()); - for (size_t i = 0; i < p.function("f").raw_instructions().size(); ++i) { - NTH_EXPECT(p.function("f").raw_instructions()[i].raw_value() == - q.function("f").raw_instructions()[i].raw_value()); - } -} - -NTH_TEST("round-trip/program-fragment/recursion") { - ProgramFragment p; - auto& f = p.declare("f", 0, 0).function; - f.append*>>(&f); - f.append({0, 0}); - f.append(); - - std::string content; - Serializer serializer(content); - NTH_ASSERT(nth::io::serialize(serializer, p)); - - ProgramFragment q; - Deserializer deserializer(content); - NTH_ASSERT(nth::io::deserialize(deserializer, q)); - NTH_EXPECT(q.function_count() == p.function_count()); - NTH_ASSERT(p.function("f").raw_instructions().size() == - q.function("f").raw_instructions().size()); - for (size_t i = 0; i < p.function("f").raw_instructions().size(); ++i) { - if (p.function("f").raw_instructions()[i].raw_value() != - q.function("f").raw_instructions()[i].raw_value()) { - NTH_EXPECT(p.function("f").raw_instructions()[i].raw_value() == - Value(&p.function("f")).raw_value()); - NTH_EXPECT(q.function("f").raw_instructions()[i].raw_value() == - Value(&q.function("f")).raw_value()); - } - } -} - -} // namespace -} // namespace jasmin diff --git a/jasmin/core/value.h b/jasmin/core/value.h index 464617d..47d71c5 100644 --- a/jasmin/core/value.h +++ b/jasmin/core/value.h @@ -80,8 +80,7 @@ requires(nth::type != nth::type and } inline Value Value::Load(void const* ptr, size_t bytes_to_load) { - NTH_REQUIRE((v.when(internal::harden)), bytes_to_load <= size_t{8}) - .Log<"Bytes to load must not exceed 8.">(); + NTH_REQUIRE((harden), bytes_to_load <= size_t{8}); Value v; std::memcpy(&v.value_, ptr, bytes_to_load); #if defined(JASMIN_INTERNAL_CONFIGURATION_DEBUG) @@ -91,8 +90,7 @@ inline Value Value::Load(void const* ptr, size_t bytes_to_load) { } inline void Value::Store(Value value, void* ptr, size_t bytes_to_store) { - NTH_REQUIRE((v.when(internal::harden)), bytes_to_store <= size_t{8}) - .Log<"Bytes to load must not exceed 8.">(); + NTH_REQUIRE((harden), bytes_to_store <= size_t{8}); std::memcpy(ptr, &value.value_, bytes_to_store); } @@ -116,9 +114,7 @@ T Value::as() const { } else { #if defined(JASMIN_INTERNAL_CONFIGURATION_DEBUG) NTH_REQUIRE((v.always), debug_type_id_ == internal::type_id or - debug_type_id_ == internal::type_id) - .Log<"Value type mismatch: {} != {}">(debug_type_id_, - internal::type_id); + debug_type_id_ == internal::type_id); #endif // defined(JASMIN_INTERNAL_CONFIGURATION_DEBUG) T result; diff --git a/jasmin/instructions/stack.h b/jasmin/instructions/stack.h index a91dcc3..aa11fb2 100644 --- a/jasmin/instructions/stack.h +++ b/jasmin/instructions/stack.h @@ -13,8 +13,7 @@ namespace internal { struct StackFrame { std::byte *allocate_once(size_t size_in_bytes) { - NTH_REQUIRE(data() == nullptr) - .Log<"`allocate_once` must only be called once per stack frame.">(); + NTH_REQUIRE(data() == nullptr); data_.reset(new std::byte[size_in_bytes]); return data_.get(); } diff --git a/jasmin/ssa/BUILD b/jasmin/ssa/BUILD index 9ecfccd..474a871 100644 --- a/jasmin/ssa/BUILD +++ b/jasmin/ssa/BUILD @@ -24,23 +24,6 @@ cc_library( "//jasmin/core:metadata", "@nth_cc//nth/debug", "@nth_cc//nth/container:disjoint_set", - "@nth_cc//nth/strings:interpolate", "@com_google_absl//absl/synchronization", ], ) - -cc_binary( - name = "test", - srcs = ["main.cc"], - deps = [ - ":register_coalescer", - ":ssa", - "//jasmin/core:instruction", - "//jasmin/instructions:arithmetic", - "//jasmin/instructions:compare", - "//jasmin/instructions:common", - "@nth_cc//nth/debug", - "@nth_cc//nth/debug/log:stderr_log_sink", - "@com_google_absl//absl/container:flat_hash_set", - ], -) diff --git a/jasmin/ssa/main.cc b/jasmin/ssa/main.cc deleted file mode 100644 index 51942c3..0000000 --- a/jasmin/ssa/main.cc +++ /dev/null @@ -1,52 +0,0 @@ -#include "jasmin/core/instruction.h" -#include "jasmin/instructions/arithmetic.h" -#include "jasmin/instructions/common.h" -#include "jasmin/instructions/compare.h" -#include "jasmin/ssa/register_coalescer.h" -#include "jasmin/ssa/ssa.h" -#include "nth/container/interval.h" -#include "nth/debug/debug.h" -#include "nth/debug/log/stderr_log_sink.h" - -auto FibonacciRecursive() { - using Instructions = jasmin::MakeInstructionSet< - jasmin::Duplicate, jasmin::Swap, jasmin::Push, - jasmin::Push*>, jasmin::LessThan, - jasmin::Add, jasmin::Subtract>; - jasmin::Function func(1, 1); - func.append(); - func.append>(2); - func.append>(); - nth::interval jump = - func.append_with_placeholders(); - func.append(); - func.append>(1); - func.append>(); - func.append*>>(&func); - func.append( - jasmin::InstructionSpecification{.parameters = 1, .returns = 1}); - func.append(); - func.append>(2); - func.append>(); - func.append*>>(&func); - func.append( - jasmin::InstructionSpecification{.parameters = 1, .returns = 1}); - func.append>(); - nth::interval ret = func.append(); - func.set_value(jump, 0, ret.lower_bound() - jump.lower_bound()); - return func; -} - -int main() { - nth::RegisterLogSink(nth::stderr_log_sink); - - jasmin::SsaFunction f(FibonacciRecursive()); - NTH_LOG("Function before optimization:\n{}") <<= {f}; - - jasmin::RegisterCoalescer rc; - rc.Coalesce(f); - - NTH_LOG("Function after optimization:\n{}") <<= {f}; - - return 0; -} diff --git a/jasmin/ssa/register_coalescer.cc b/jasmin/ssa/register_coalescer.cc index 04dbbea..6ad0369 100644 --- a/jasmin/ssa/register_coalescer.cc +++ b/jasmin/ssa/register_coalescer.cc @@ -46,8 +46,8 @@ void RegisterCoalescer::freshen() { } SsaValue RegisterCoalescer::get(handle_type h) { - NTH_REQUIRE((v.debug), not h.empty()); - NTH_REQUIRE((v.debug), not stale_); + NTH_REQUIRE((debug), not h.empty()); + NTH_REQUIRE((debug), not stale_); if (auto iter = constants_.find(h); iter != constants_.end()) { return *iter->second; } else { diff --git a/jasmin/ssa/ssa.cc b/jasmin/ssa/ssa.cc index e02f504..2aba91d 100644 --- a/jasmin/ssa/ssa.cc +++ b/jasmin/ssa/ssa.cc @@ -268,7 +268,7 @@ void SsaFunction::Initialize(InstructionMetadata const& (*decode)(Value), block.set_branch(SsaBranch::Return( span.subspan(span.size() - return_count_, return_count_))); } else { - NTH_REQUIRE((v.harden), not registers_on_exit.empty()); + NTH_REQUIRE((harden), not registers_on_exit.empty()); size_t size = blocks_[i + 1].parameters().size(); std::span span = registers_on_exit[i]; block.set_branch(SsaBranch::Unconditional( diff --git a/jasmin/ssa/ssa.h b/jasmin/ssa/ssa.h index 24e9c20..cd43cfc 100644 --- a/jasmin/ssa/ssa.h +++ b/jasmin/ssa/ssa.h @@ -12,8 +12,6 @@ #include "jasmin/core/value.h" #include "nth/container/disjoint_set.h" #include "nth/debug/debug.h" -#include "nth/io/string_printer.h" -#include "nth/strings/interpolate.h" namespace jasmin { namespace internal { @@ -37,11 +35,6 @@ struct SsaRegister { friend constexpr bool operator==(SsaRegister, SsaRegister) = default; constexpr uint64_t value() const { return number_; } - friend void NthPrint(auto &p, auto &f, SsaRegister const &r) { - p.write("r."); - f(p, r.value()); - } - private: uint64_t number_; }; @@ -89,16 +82,6 @@ struct SsaValue { return not(lhs == rhs); } - friend void NthPrint(auto &p, auto &f, SsaValue const &v) { - if (v.is_register()) { - f(p, v.reg()); - } else { - p.write("imm["); - f(p, v.immediate().raw_value()); - p.write("]"); - } - } - private: constexpr SsaValue() : impl_(SsaRegister()) {} @@ -141,33 +124,6 @@ struct SsaInstruction { return *(arguments_.end() - output_count_ + i); } - friend void NthPrint(auto &p, auto &f, SsaInstruction const &inst) { - p.write(" "); - for (size_t i = inst.arguments_.size() - inst.output_count_; - i < inst.arguments_.size(); ++i) { - if (inst.arguments_[i].is_register()) { - p.write(" "); - f(p, inst.arguments_[i].reg()); - } else { - p.write(" imm["); - f(p, inst.arguments_[i].immediate().raw_value()); - p.write("]"); - } - } - p.write(" = "); - f(p, internal::InstructionNameDecoder(inst.op_code_)); - for (size_t i = 0; i < inst.arguments_.size() - inst.output_count_; ++i) { - if (inst.arguments_[i].is_register()) { - p.write(" "); - f(p, inst.arguments_[i].reg()); - } else { - p.write(" imm["); - f(p, inst.arguments_[i].immediate().raw_value()); - p.write("]"); - } - } - } - private: internal::exec_fn_type op_code_; uint64_t output_count_; @@ -241,61 +197,6 @@ struct SsaBranch { }); } - friend void NthPrint(auto &p, auto &f, SsaBranch const &branch) { - std::visit( - [&](auto const &b) { - constexpr auto t = - nth::type.without_reference().without_const(); - if constexpr (t == nth::type) { - p.write(" unreachable\n"); - } else if constexpr (t == nth::type) { - p.write("return "); - std::string_view sep = ""; - for (SsaValue arg : b.block_arguments) { - f(p, arg); - p.write(std::exchange(sep, ", ")); - } - p.write("\n"); - } else if constexpr (t == nth::type) { - p.write(" br #"); - f(p, b.block); - p.write(" <- ("); - std::string_view sep = ""; - for (SsaValue arg : b.block_arguments) { - f(p, arg); - p.write(std::exchange(sep, ", ")); - } - p.write(")\n"); - } else if constexpr (t == nth::type) { - std::string true_args; - { - std::string_view sep = ""; - nth::string_printer sp(true_args); - for (SsaValue arg : b.true_arguments()) { - f(sp, arg); - sp.write(std::exchange(sep, ", ")); - } - } - std::string false_args; - { - std::string_view sep = ""; - nth::string_printer sp(false_args); - for (SsaValue arg : b.false_arguments()) { - f(sp, arg); - sp.write(std::exchange(sep, ", ")); - } - } - - nth::Interpolate<" cond br {} ? #{} <- ({}) : #{} <- ({})\n">( - p, f, b.value.reg(), b.true_block, true_args, b.false_block, - false_args); - } else if constexpr (t == nth::type) { - p.write(" return\n"); - } - }, - branch.branch_); - } - void rename(nth::disjoint_set &); private: @@ -328,21 +229,6 @@ struct SsaBasicBlock { constexpr std::span parameters() const { return parameters_; } constexpr std::span parameters() { return parameters_; } - friend void NthPrint(auto &p, auto &f, SsaBasicBlock const &block) { - p.write("block("); - std::string_view separator = ""; - for (SsaValue v : block.parameters_) { - p.write(std::exchange(separator, ", ")); - f(p, v.reg()); - } - p.write("):\n"); - for (SsaInstruction const &i : block.instructions_) { - f(p, i); - p.write("\n"); - } - f(p, block.branch_); - } - std::span instructions() const { return instructions_; } std::span instructions() { return instructions_; } @@ -367,17 +253,6 @@ struct SsaFunction { std::span blocks() const { return blocks_; } std::span blocks() { return blocks_; } - friend void NthPrint(auto &p, auto &f, SsaFunction const &fn) { - size_t i = 0; - for (SsaBasicBlock const &block : fn.blocks_) { - p.write("#"); - f(p, i++); - p.write(" "); - f(p, block); - p.write("\n"); - } - } - private: void Initialize(InstructionMetadata const &(*decode)(Value), std::span instructions,