From 5c821f7a18937e46943f170fa612ac8b5441a0b0 Mon Sep 17 00:00:00 2001 From: asoffer Date: Sun, 17 Dec 2023 12:39:29 -0500 Subject: [PATCH] Rebase on new version of Jasmin. --- WORKSPACE | 12 +-- common/BUILD | 2 +- common/module_id.h | 2 +- ir/BUILD | 20 ++--- ir/builtin_module.cc | 4 +- ir/deserialize.cc | 10 +-- ir/emit.cc | 111 ++++++++++++++++----------- ir/emit.h | 18 +++-- ir/foreign_function.cc | 8 +- ir/function.cc | 58 +++++++------- ir/function.h | 155 ++++++++++++++++++-------------------- ir/ir.cc | 59 ++++++++------- ir/module.h | 2 +- ir/serialize.cc | 10 +-- toolchain/BUILD | 3 +- toolchain/run_bytecode.cc | 6 +- type/BUILD | 2 +- type/type.h | 2 +- 18 files changed, 256 insertions(+), 228 deletions(-) diff --git a/WORKSPACE b/WORKSPACE index 9be8e1b9..ffd99b56 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -3,14 +3,14 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") http_archive( name = "asoffer_nth", - urls = ["https://github.com/asoffer/nth/archive/ca567073993e891dd53a40a4871f9ef8f666bf75.zip"], - strip_prefix = "nth-ca567073993e891dd53a40a4871f9ef8f666bf75", - sha256 = "edc4bf4e6f5fcccdea2eab8be537ec1ac40ee18095cb48878a25be3d50ce413d", + urls = ["https://github.com/asoffer/nth/archive/b818c47608dfad8085394c4aa81523b8549a1e03.zip"], + strip_prefix = "nth-b818c47608dfad8085394c4aa81523b8549a1e03", + sha256 = "f0b4c1a239eb49392b46b5c9d8871ff42d59abee5ab369248874ba3c0a4cd424", ) http_archive( name = "asoffer_jasmin", - urls = ["https://github.com/asoffer/jasmin/archive/a2b29865b04d44c0920b2107b15c7ebb397d089a.zip"], - strip_prefix = "jasmin-a2b29865b04d44c0920b2107b15c7ebb397d089a", - sha256 = "6a237d210c3511d61ff0d77d56641b4c96d84c7ba5dab2780abf7c29f1a28250", + urls = ["https://github.com/asoffer/jasmin/archive/093567c8764721fa5efd939967c86e224b77bf76.zip"], + strip_prefix = "jasmin-093567c8764721fa5efd939967c86e224b77bf76", + sha256 = "30d0c6cdc8dfb44b1dbcfe0b32c5dedc9973afe457626f585c7b097dc3c786c4", ) diff --git a/common/BUILD b/common/BUILD index 63aa0a9f..faab9063 100644 --- a/common/BUILD +++ b/common/BUILD @@ -62,7 +62,7 @@ cc_library( name = "module_id", hdrs = ["module_id.h"], deps = [ - "@asoffer_jasmin//jasmin:value", + "@asoffer_jasmin//jasmin/core:value", ], ) diff --git a/common/module_id.h b/common/module_id.h index 6f72bbea..daf566b4 100644 --- a/common/module_id.h +++ b/common/module_id.h @@ -5,7 +5,7 @@ #include #include -#include "jasmin/value.h" +#include "jasmin/core/value.h" namespace ic { diff --git a/ir/BUILD b/ir/BUILD index 7edc487a..df5ce761 100644 --- a/ir/BUILD +++ b/ir/BUILD @@ -36,6 +36,7 @@ cc_library( ":module", ":module_cc_proto", "//type:deserialize", + "@asoffer_jasmin//jasmin/core:metadata", "@asoffer_nth//nth/base:attributes", "@asoffer_nth//nth/debug", "@asoffer_nth//nth/debug/log", @@ -64,10 +65,11 @@ cc_library( "//parse:tree", "//type", "@asoffer_jasmin//jasmin/instructions:arithmetic", - "@asoffer_jasmin//jasmin:execute", + "@asoffer_jasmin//jasmin/core:execute", "@asoffer_nth//nth/debug", "@asoffer_nth//nth/debug/log", "@asoffer_nth//nth/container:interval_map", + "@asoffer_nth//nth/container:stack", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/container:btree", ], @@ -92,15 +94,14 @@ cc_library( "//common:module_id", "//common:resources", "//type", - "@asoffer_jasmin//jasmin:function", - "@asoffer_jasmin//jasmin:instruction", + "@asoffer_jasmin//jasmin/core:function", + "@asoffer_jasmin//jasmin/core:instruction", + "@asoffer_jasmin//jasmin/core:value", "@asoffer_jasmin//jasmin/instructions:arithmetic", "@asoffer_jasmin//jasmin/instructions:bool", - "@asoffer_jasmin//jasmin/instructions:core", + "@asoffer_jasmin//jasmin/instructions:common", "@asoffer_jasmin//jasmin/instructions:compare", "@asoffer_jasmin//jasmin/instructions:stack", - "@asoffer_jasmin//jasmin:value", - "@asoffer_jasmin//jasmin:value_stack", "@asoffer_nth//nth/container:flyweight_map", "@com_google_absl//absl/container:flat_hash_map", ], @@ -132,8 +133,8 @@ cc_library( "//parse:tree", "//type", "//type:cast", - "@asoffer_jasmin//jasmin:execute", - "@asoffer_jasmin//jasmin:value_stack", + "@asoffer_jasmin//jasmin/core:execute", + "@asoffer_jasmin//jasmin/core:value", "@asoffer_nth//nth/debug", "@asoffer_nth//nth/debug/log", "@com_google_absl//absl/container:flat_hash_map", @@ -164,7 +165,7 @@ cc_library( ":scope", "//common:identifier", "//type", - "@asoffer_jasmin//jasmin:value", + "@asoffer_jasmin//jasmin/core:value", "@asoffer_nth//nth/debug", "@asoffer_nth//nth/debug/log", "@com_google_absl//absl/container:inlined_vector", @@ -232,6 +233,7 @@ cc_library( ":module_cc_proto", "//common:resources", "//type:serialize", + "@asoffer_jasmin//jasmin/core:metadata", "@asoffer_nth//nth/debug", "@asoffer_nth//nth/debug/log", ], diff --git a/ir/builtin_module.cc b/ir/builtin_module.cc index 48de1f56..b959c13c 100644 --- a/ir/builtin_module.cc +++ b/ir/builtin_module.cc @@ -62,9 +62,9 @@ nth::NoDestructor Slice([] { nth::NoDestructor ForeignType([] { IrFunction f(3, 1); f.append(); - f.append(1); + f.append(); f.append(); - f.append(1); + f.append(); f.append(); return f; }()); diff --git a/ir/deserialize.cc b/ir/deserialize.cc index 8067c641..df7b64ab 100644 --- a/ir/deserialize.cc +++ b/ir/deserialize.cc @@ -3,6 +3,7 @@ #include "common/resources.h" #include "ir/builtin_module.h" #include "ir/foreign_function.h" +#include "jasmin/core/metadata.h" #include "nth/debug/debug.h" #include "nth/debug/log/log.h" #include "type/deserialize.h" @@ -26,11 +27,7 @@ bool Deserializer::DeserializeFunction(ModuleProto const& module_proto, IrFunction& f) { for (auto const& instruction : proto.instructions()) { uint64_t op_code = static_cast(instruction.op_code()); - - jasmin::Value op_code_value = jasmin::Value::Uninitialized(); - op_code_value.set_raw_value(reinterpret_cast( - InstructionSet::InstructionFunction(op_code))); - f.raw_append(op_code_value); + f.raw_append(jasmin::Metadata.metadata(op_code).function); switch (op_code) { case InstructionProto::PUSH_STRING_LITERAL: { auto const& string_literals = module_proto.string_literals(); @@ -74,7 +71,8 @@ bool Deserializer::DeserializeFunction(ModuleProto const& module_proto, } } break; default: { - auto op_code_metadata = InstructionSet::OpCodeMetadata(op_code_value); + auto op_code_metadata = + jasmin::Metadata.metadata(op_code); if (op_code_metadata.immediate_value_count != instruction.content().size()) { return false; diff --git a/ir/emit.cc b/ir/emit.cc index fc2b19f4..0494d8e6 100644 --- a/ir/emit.cc +++ b/ir/emit.cc @@ -4,51 +4,55 @@ #include "common/module_id.h" #include "common/resources.h" #include "ir/serialize.h" -#include "jasmin/execute.h" +#include "jasmin/core/execute.h" #include "jasmin/instructions/arithmetic.h" +#include "nth/container/interval.h" +#include "nth/container/stack.h" #include "nth/debug/debug.h" #include "nth/debug/log/log.h" namespace ic { namespace { +size_t ValueSize = 8; + void StoreStackValue(IrFunction& f, type::ByteWidth offset, type::Type t) { type::ByteWidth type_width = type::Contour(t).byte_width(); type::ByteWidth end = offset + type_width; type::ByteWidth position = - end.aligned_backward_to(type::Alignment(jasmin::ValueSize)); + end.aligned_backward_to(type::Alignment(ValueSize)); if (position != end) { f.append(position.value()); f.append((end - position).value()); } while (position != offset) { - position -= type::ByteWidth(jasmin::ValueSize); + position -= type::ByteWidth(ValueSize); f.append(position.value()); - f.append(jasmin::ValueSize); + f.append(ValueSize); } } void Load(IrFunction& f, type::ByteWidth width) { - size_t i = jasmin::ValueSize; - for (; i < width.value(); i += jasmin::ValueSize) { + size_t i = ValueSize; + for (; i < width.value(); i += ValueSize) { f.append(); - f.append(jasmin::ValueSize); + f.append(ValueSize); f.append(); f.append(); - f.append(jasmin::ValueSize); + f.append(ValueSize); f.append(); } - f.append(width.value() - (i - jasmin::ValueSize)); + f.append(width.value() - (i - ValueSize)); } void LoadStackValue(IrFunction& f, type::ByteWidth offset, type::Type t) { type::ByteWidth type_width = type::Contour(t).byte_width(); type::ByteWidth end = offset + type_width; - while (offset + type::ByteWidth(jasmin::ValueSize) <= end) { + while (offset + type::ByteWidth(ValueSize) <= end) { f.append(offset.value()); - f.append(jasmin::ValueSize); - offset += type::ByteWidth(jasmin::ValueSize); + f.append(ValueSize); + offset += type::ByteWidth(ValueSize); } if (offset < end) { f.append(offset.value()); @@ -108,8 +112,7 @@ void HandleParseTreeNodeScopeBlockStart(ParseNodeIndex index, context.current_function().append(); } -void HandleParseTreeNodeScopeBlock(ParseNodeIndex index, - EmitContext& context) { +void HandleParseTreeNodeScopeBlock(ParseNodeIndex index, EmitContext& context) { // TODO: NTH_UNIMPLEMENTED(); } @@ -120,11 +123,12 @@ void HandleParseTreeNodeScopeBodyStart(ParseNodeIndex index, } void HandleParseTreeNodeScope(ParseNodeIndex index, EmitContext& context) { - jasmin::OpCodeRange final_jump = context.queue.front().branches.back(); - auto land = context.current_function().append(); + nth::interval final_jump = + context.queue.front().branches.back(); + auto land = context.current_function().append(); context.queue.front().branches.pop_back(); context.current_function().set_value( - final_jump, 0, jasmin::OpCodeRange::Distance(land, final_jump)); + final_jump, 0, land.lower_bound() - final_jump.lower_bound()); } void HandleParseTreeNodeScopeLiteral(ParseNodeIndex index, @@ -250,7 +254,7 @@ void HandleParseTreeNodeDeclaration(ParseNodeIndex index, if (decl_info.kind.constant()) { auto& f = context.current_function(); f.append(); - jasmin::ValueStack value_stack; + nth::stack value_stack; jasmin::Execute(f, value_stack); auto const* info = context.lexical_scopes.identifier( context.current_lexical_scope_index(), @@ -274,7 +278,8 @@ void HandleParseTreeNodeDeclaration(ParseNodeIndex index, if (decl_info.kind.constant()) { auto& f = context.current_function(); f.append(); - jasmin::ValueStack value_stack; + nth::stack value_stack; + jasmin::Execute(f, value_stack); auto const* info = context.lexical_scopes.identifier( context.current_lexical_scope_index(), @@ -313,7 +318,10 @@ void HandleParseTreeNodeStatement(ParseNodeIndex index, EmitContext& context) { .Log<"For {}">(context.tree.first_descendant_index(index)); size_t size_to_drop = iter->second.second; if (size_to_drop != 0) { - context.current_function().append(size_to_drop); + // TODO: Add a Drop function with an immediate value. + for (size_t i = 0; i < size_to_drop; ++i) { + context.current_function().append(); + } } } break; default: break; @@ -462,7 +470,7 @@ void HandleParseTreeNodeMemberExpression(ParseNodeIndex index, if (context.Node(index).token.Identifier() == Identifier("count")) { context.current_function().append(); } - context.current_function().append(1); + context.current_function().append(); } else { // TODO: Fix this bug. decltype(context.constants.mapped_range(index - 1)) mapped_range = nullptr; @@ -474,7 +482,7 @@ void HandleParseTreeNodeMemberExpression(ParseNodeIndex index, } // auto const* mapped_range = context.constants.mapped_range(index - 1); NTH_REQUIRE((v.harden), mapped_range != nullptr); - context.current_function().append(1); + context.current_function().append(); ModuleId module_id; bool successfully_deserialized = @@ -501,7 +509,7 @@ void HandleParseTreeNodeIndexExpression(ParseNodeIndex index, auto t = qt.type().AsSlice().element_type(); auto size = type::Contour(t).byte_width(); f.append(); - f.append(1); + f.append(); f.append(size.value()); f.append>(); f.append(); @@ -528,10 +536,12 @@ void HandleParseTreeNodeIndexExpression(ParseNodeIndex index, void HandleParseTreeNodeCallExpression(ParseNodeIndex index, EmitContext& context) { - auto iter = context.rotation_count.find(index); - NTH_REQUIRE((v.harden), iter != context.rotation_count.end()); - context.current_function().append(iter->second + 1); - context.current_function().append(); + auto iter = context.instruction_spec.find(index); + NTH_REQUIRE((v.harden), iter != context.instruction_spec.end()); + auto rotation_spec = iter->second; + rotation_spec.returns = 0; + context.current_function().append(rotation_spec); + context.current_function().append(iter->second); } void HandleParseTreeNodePointer(ParseNodeIndex index, EmitContext& context) { @@ -561,7 +571,9 @@ void HandleParseTreeNodeImport(ParseNodeIndex index, EmitContext& context) { void HandleParseTreeNodeFunctionTypeParameters(ParseNodeIndex index, EmitContext& context) { context.current_function().append( - context.Node(index).child_count); + jasmin::InstructionSpecification{ + .parameters = static_cast(context.Node(index).child_count), + .returns = 1}); } void HandleParseTreeNodeWhileLoopStart(ParseNodeIndex index, @@ -582,20 +594,22 @@ void HandleParseTreeNodeWhileLoop(ParseNodeIndex index, EmitContext& context) { // TODO: You don't really need all these no-ops. context.pop_lexical_scope(); - jasmin::OpCodeRange jump_to_land = context.queue.front().branches.back(); + nth::interval jump_to_land = + context.queue.front().branches.back(); context.queue.front().branches.pop_back(); - jasmin::OpCodeRange restart = context.queue.front().branches.back(); + nth::interval restart = + context.queue.front().branches.back(); context.queue.front().branches.pop_back(); auto land = context.current_function().append_with_placeholders(); context.current_function().set_value( - land, 0, jasmin::OpCodeRange::Distance(restart, land)); + land, 0, restart.lower_bound() - land.lower_bound()); land = context.current_function().append(); context.current_function().set_value( - jump_to_land, 0, jasmin::OpCodeRange::Distance(land, jump_to_land)); + jump_to_land, 0, land.lower_bound() - jump_to_land.lower_bound()); } void HandleParseTreeNodeIfStatementTrueBranchStart(ParseNodeIndex index, @@ -608,21 +622,25 @@ void HandleParseTreeNodeIfStatementTrueBranchStart(ParseNodeIndex index, void HandleParseTreeNodeIfStatementFalseBranchStart(ParseNodeIndex index, EmitContext& context) { - jasmin::OpCodeRange jump = context.queue.front().branches.back(); + nth::interval jump = + context.queue.front().branches.back(); context.queue.front().branches.back() = context.current_function().append_with_placeholders(); - jasmin::OpCodeRange land = context.current_function().append(); - context.current_function().set_value( - jump, 0, jasmin::OpCodeRange::Distance(land, jump)); + nth::interval land = + context.current_function().append(); + context.current_function().set_value(jump, 0, + land.lower_bound() - jump.lower_bound()); } void HandleParseTreeNodeIfStatement(ParseNodeIndex index, EmitContext& context) { - jasmin::OpCodeRange jump = context.queue.front().branches.back(); + nth::interval jump = + context.queue.front().branches.back(); context.queue.front().branches.pop_back(); - jasmin::OpCodeRange land = context.current_function().append(); - context.current_function().set_value( - jump, 0, jasmin::OpCodeRange::Distance(land, jump)); + nth::interval land = + context.current_function().append(); + context.current_function().set_value(jump, 0, + land.lower_bound() - jump.lower_bound()); context.pop_lexical_scope(); } @@ -647,7 +665,8 @@ void HandleParseTreeNodeAssignedValueStart(ParseNodeIndex index, } void HandleParseTreeNodeAssignment(ParseNodeIndex index, EmitContext& context) { - context.current_function().append(2); + context.current_function().append( + jasmin::InstructionSpecification{.parameters = 2, .returns = 0}); context.current_function().append(1); } @@ -685,9 +704,9 @@ void EmitContext::Push(std::span vs, type::Type t) { current_function().append(vs[0].as()); return; } else if (t == type::Scope) { - auto & c = current_function(); + auto& c = current_function(); NTH_REQUIRE((v.harden), vs.size() == 1); - vs[0].as()->AppendTo(c); + vs[0].as()->AppendTo(c); return; } switch (t.kind()) { @@ -808,9 +827,9 @@ void EmitIr(EmitContext& context) { } void EmitContext::Evaluate(nth::interval subtree, - jasmin::ValueStack& value_stack, + nth::stack& value_stack, std::vector types) { - jasmin::ValueStack vs; + nth::stack vs; size_t size = 0; for (type::Type t : types) { size += type::JasminSize(t); } IrFunction f(0, size); @@ -821,7 +840,7 @@ void EmitContext::Evaluate(nth::interval subtree, f.append(); jasmin::Execute(f, vs); - for (jasmin::Value v : vs) { value_stack.push(v); } + for (jasmin::Value v : vs.top_span(vs.size())) { value_stack.push(v); } constants.insert_or_assign( subtree, ComputedConstants(subtree.upper_bound() - 1, std::move(vs), std::move(types))); diff --git a/ir/emit.h b/ir/emit.h index 9f1079dd..3d7c0d62 100644 --- a/ir/emit.h +++ b/ir/emit.h @@ -1,6 +1,7 @@ #ifndef ICARUS_IR_EMIT_H #define ICARUS_IR_EMIT_H +#include #include #include @@ -12,9 +13,10 @@ #include "ir/lexical_scope.h" #include "ir/local_storage.h" #include "ir/module.h" -#include "jasmin/value_stack.h" #include "nth/base/attributes.h" +#include "nth/container/interval.h" #include "nth/container/interval_map.h" +#include "nth/container/stack.h" #include "parse/declaration.h" #include "parse/node_index.h" #include "parse/tree.h" @@ -56,7 +58,8 @@ struct EmitContext { Module const& module(ModuleId id) const { return modules[id]; } struct ComputedConstants { - explicit ComputedConstants(ParseNodeIndex index, jasmin::ValueStack value, + explicit ComputedConstants(ParseNodeIndex index, + nth::stack value, std::vector types) : index_(index), value_(std::move(value)), types_(std::move(types)) {} @@ -67,12 +70,12 @@ struct EmitContext { std::span types() const { return types_; } std::span value_span() const { - return std::span(value_.begin(), value_.end()); + return value_.top_span(value_.size()); } private: ParseNodeIndex index_; - jasmin::ValueStack value_; + nth::stack value_; std::vector types_; }; @@ -81,7 +84,7 @@ struct EmitContext { void Push(ComputedConstants const& c); void Evaluate(nth::interval subtree, - jasmin::ValueStack& value_stack, std::vector types); + nth::stack& value_stack, std::vector types); ParseNode const& Node(ParseNodeIndex index) const { return tree[index]; } @@ -90,7 +93,8 @@ struct EmitContext { absl::flat_hash_map> statement_expression_info; - absl::flat_hash_map rotation_count; + absl::flat_hash_map + instruction_spec; absl::flat_hash_map> declarator; @@ -187,7 +191,7 @@ struct EmitContext { nth::interval range; std::vector declaration_stack; - std::vector branches; + std::vector> branches; std::vector lexical_scopes = {LexicalScope::Index::Root()}; std::vector function_stack = { LexicalScope::Index::Root()}; diff --git a/ir/foreign_function.cc b/ir/foreign_function.cc index 89563b2b..d532d51c 100644 --- a/ir/foreign_function.cc +++ b/ir/foreign_function.cc @@ -9,7 +9,7 @@ #include "ir/function.h" #include "ir/function_id.h" #include "ir/global_function_registry.h" -#include "jasmin/instruction.h" +#include "jasmin/core/instruction.h" #include "type/type.h" namespace ic { @@ -63,7 +63,11 @@ IrFunction const& InsertForeignFunction(std::string_view name, void* result = dlsym(RTLD_DEFAULT, std::string(name).c_str()); char const* error = dlerror(); if (error != nullptr) { NTH_UNIMPLEMENTED("{}") <<= {error}; } - fn.append(t, result); + + auto const& parameters = fn.append( + {.parameters = static_cast(t.parameters().size()), + .returns = static_cast(t.returns().size())}, + t, result); } p->append(); global_function_registry.Register( diff --git a/ir/function.cc b/ir/function.cc index 7e9c9929..fd6c869d 100644 --- a/ir/function.cc +++ b/ir/function.cc @@ -9,13 +9,12 @@ #include "ir/function_id.h" #include "ir/global_function_registry.h" #include "ir/program_arguments.h" -#include "jasmin/value.h" -#include "jasmin/value_stack.h" +#include "jasmin/core/value.h" namespace ic { namespace { -ffi_type* FfiType(type::Type t) { +[[maybe_unused]] ffi_type* FfiType(type::Type t) { if (t == type::Char) { return std::is_signed_v ? &ffi_type_schar : &ffi_type_uchar; } @@ -32,7 +31,7 @@ ffi_type* FfiType(type::Type t) { return &ffi_type_pointer; } -template +template T Read(ffi_arg const& value) { T result; std::memcpy(&result, &value, sizeof(T)); @@ -41,22 +40,23 @@ T Read(ffi_arg const& value) { } // namespace -void LoadProgramArguments::execute(jasmin::ValueStack& value_stack) { +std::array LoadProgramArguments::execute( + std::span) { Slice arguments = ProgramArguments(); - value_stack.push(arguments.data()); - value_stack.push(arguments.count()); + return {jasmin::Value(arguments.data()), jasmin::Value(arguments.count())}; } -void RegisterForeignFunction::execute(jasmin::ValueStack& value_stack) { - type::Type t = value_stack.pop(); - size_t length = value_stack.pop(); - char const* data = value_stack.pop(); +jasmin::Value RegisterForeignFunction::consume(std::span inputs) { + char const* data = inputs[0].as(); + size_t length = inputs[1].as(); + type::Type t = inputs[2].as(); auto const& f = InsertForeignFunction(std::string_view(data, length), t.AsFunction(), false); - value_stack.push(&f); + return &f; } -void InvokeForeignFunction::execute(jasmin::ValueStack& value_stack, +void InvokeForeignFunction::consume(std::span input, + std::span output, type::FunctionType type, void const* fn_ptr) { std::span returns = type.returns(); @@ -73,10 +73,10 @@ void InvokeForeignFunction::execute(jasmin::ValueStack& value_stack, argument_types.reserve(parameters.size()); argument_values.reserve(parameters.size()); - for (auto iter = value_stack.end() - parameters.size(); - iter != value_stack.end(); ++iter, ++parameter_iter) { + for (auto iter = input.begin(); iter != input.end(); + ++iter, ++parameter_iter) { argument_types.push_back(FfiType(parameter_iter->type)); - argument_values.push_back(const_cast(iter->address())); + argument_values.push_back(static_cast(&*iter)); } ffi_status status = @@ -89,34 +89,32 @@ void InvokeForeignFunction::execute(jasmin::ValueStack& value_stack, reinterpret_cast(const_cast(fn_ptr)), &return_value, argument_values.data()); - for (size_t i = 0; i < parameters.size(); ++i) { value_stack.pop_value(); } - if (not returns.empty()) { type::Type t = returns[0]; if (t == type::Char) { - value_stack.push(Read(return_value)); + output[0] = Read(return_value); } else if (t == type::I8) { - value_stack.push(Read(return_value)); + output[0] = Read(return_value); } else if (t == type::I16) { - value_stack.push(Read(return_value)); + output[0] = Read(return_value); } else if (t == type::I32) { - value_stack.push(Read(return_value)); + output[0] = Read(return_value); } else if (t == type::I64) { - value_stack.push(Read(return_value)); + output[0] = Read(return_value); } else if (t == type::U8) { - value_stack.push(Read(return_value)); + output[0] = Read(return_value); } else if (t == type::U16) { - value_stack.push(Read(return_value)); + output[0] = Read(return_value); } else if (t == type::U32) { - value_stack.push(Read(return_value)); + output[0] = Read(return_value); } else if (t == type::U64) { - value_stack.push(Read(return_value)); + output[0] = Read(return_value); } else if (t == type::F32) { - value_stack.push(Read(return_value)); + output[0] = Read(return_value); } else if (t == type::F64) { - value_stack.push(Read(return_value)); + output[0] = Read(return_value); } else { - value_stack.push(Read(return_value)); + output[0] = Read(return_value); } } } diff --git a/ir/function.h b/ir/function.h index 1f699b9b..8dc26bc2 100644 --- a/ir/function.h +++ b/ir/function.h @@ -1,101 +1,98 @@ #ifndef ICARUS_IR_FUNCTION_H #define ICARUS_IR_FUNCTION_H -#include -#include +#include #include #include "common/identifier.h" #include "ir/function_id.h" -#include "jasmin/function.h" -#include "jasmin/instruction.h" +#include "jasmin/core/function.h" +#include "jasmin/core/instruction.h" +#include "jasmin/core/value.h" +#include "jasmin/instructions/arithmetic.h" #include "jasmin/instructions/bool.h" +#include "jasmin/instructions/common.h" #include "jasmin/instructions/compare.h" -#include "jasmin/instructions/core.h" -#include "jasmin/instructions/arithmetic.h" #include "jasmin/instructions/stack.h" -#include "jasmin/value.h" -#include "jasmin/value_stack.h" #include "type/type.h" namespace ic { -struct Store : jasmin::StackMachineInstruction { - static void execute(jasmin::ValueStack& value_stack, uint8_t size) { - void* location = value_stack.pop(); - jasmin::Value value = value_stack.pop_value(); +struct Store : jasmin::Instruction { + static void consume(std::span input, uint8_t size) { + void* location = input[0].as(); + jasmin::Value value = input[1]; jasmin::Value::Store(value, location, size); } static constexpr std::string_view debug() { return "store"; } }; -struct PushFunction : jasmin::StackMachineInstruction { +struct PushFunction : jasmin::Instruction { static std::string_view name() { return "push-function"; } - static void execute(jasmin::ValueStack& value_stack, jasmin::Value v) { - value_stack.push(v); + static jasmin::Value execute(std::span, jasmin::Value v) { + return v; } }; -struct PushStringLiteral : jasmin::StackMachineInstruction { +struct PushStringLiteral : jasmin::Instruction { static std::string_view name() { return "push-string-literal"; } - static void execute(jasmin::ValueStack& value_stack, char const* data, - size_t length) { - value_stack.push(data); - value_stack.push(length); + static std::array execute(std::span, + char const* data, size_t length) { + return {jasmin::Value(data), jasmin::Value(length)}; } }; -struct PushType : jasmin::StackMachineInstruction { +struct PushType : jasmin::Instruction { static std::string_view name() { return "push-type"; } - - static void execute(jasmin::ValueStack& value_stack, type::Type t) { - value_stack.push(t); + static type::Type execute(std::span, type::Type t) { + return t; } }; -struct RegisterForeignFunction - : jasmin::StackMachineInstruction { +struct RegisterForeignFunction : jasmin::Instruction { static std::string_view name() { return "register-foreign-function"; } - static void execute(jasmin::ValueStack& value_stack); + static jasmin::Value consume(std::span inputs); }; - -struct InvokeForeignFunction - : jasmin::StackMachineInstruction { +struct InvokeForeignFunction : jasmin::Instruction { static std::string_view name() { return "invoke-foreign-function"; } - static void execute(jasmin::ValueStack& value_stack, type::FunctionType type, + static void consume(std::span input, + std::span output, type::FunctionType type, void const* fn_ptr); }; -struct TypeKind : jasmin::StackMachineInstruction { +struct TypeKind : jasmin::Instruction { static std::string_view name() { return "type-kind"; } - static type::Type::Kind execute(type::Type t) { return t.kind(); } + static type::Type::Kind consume(std::span inputs) { + return inputs[0].as().kind(); + } }; -struct ConstructParametersType - : jasmin::StackMachineInstruction { +struct ConstructParametersType : jasmin::Instruction { static std::string_view name() { return "construct-parameters-type"; } - static void execute(jasmin::ValueStack& value_stack, size_t count) { + static void consume(std::span inputs, + std::span outputs) { std::vector parameters; - parameters.resize(count, {.name = Identifier("").value()}); - for (int32_t i = count - 1; i >= 0; --i) { - parameters[i].type = value_stack.pop(); + parameters.reserve(inputs.size()); + for (jasmin::Value value : inputs) { + parameters.emplace_back().type = value.as(); } - value_stack.push(type::Type(type::Parameters(std::move(parameters)))); + outputs[0] = type::Type(type::Parameters(std::move(parameters))); } }; -struct ConstructFunctionType - : jasmin::StackMachineInstruction { +struct ConstructFunctionType : jasmin::Instruction { static std::string_view name() { return "construct-function-type"; } - static type::Type execute(type::Type parameter, type::Type return_type) { + static type::Type consume(std::span inputs) { + auto parameter = inputs[0].as(); + auto return_type = inputs[1].as(); if (parameter.kind() == type::Type::Kind::Parameters) { return type::Function(parameter.AsParameters(), std::vector{return_type}); } else { @@ -106,75 +103,73 @@ struct ConstructFunctionType } }; -struct ConstructOpaqueType - : jasmin::StackMachineInstruction { +struct ConstructOpaqueType : jasmin::Instruction { static std::string_view name() { return "construct-opaque-type"; } - static type::Type execute() { return type::Opaque(); } + static type::Type execute(std::span) { + return type::Opaque(); + } }; -struct ConstructPointerType - : jasmin::StackMachineInstruction { +struct ConstructPointerType : jasmin::Instruction { static std::string_view name() { return "construct-pointer-type"; } - static type::Type execute(type::Type pointee) { - return type::Ptr(pointee); + static type::Type consume(std::span inputs) { + return type::Ptr(inputs[0].as()); } }; struct ConstructBufferPointerType - : jasmin::StackMachineInstruction { + : jasmin::Instruction { static std::string_view name() { return "construct-buffer-pointer-type"; } - static type::Type execute(type::Type pointee) { - return type::BufPtr(pointee); + static type::Type consume(std::span inputs) { + return type::BufPtr(inputs[0].as()); } }; -struct ConstructSliceType - : jasmin::StackMachineInstruction { +struct ConstructSliceType : jasmin::Instruction { static std::string_view name() { return "construct-slice-type"; } - static type::Type execute(type::Type pointee) { - return type::Slice(pointee); + static type::Type consume(std::span inputs) { + return type::Slice(inputs[0].as()); } }; -struct NoOp : jasmin::StackMachineInstruction { +struct NoOp : jasmin::Instruction { static std::string_view name() { return "no-op"; } - static void execute(jasmin::ValueStack& vs) {} + static void execute(std::span) {} }; -struct AddPointer : jasmin::StackMachineInstruction { - static std::byte const* execute(std::byte const* ptr, uint64_t amount) { - return ptr + amount; +struct AddPointer : jasmin::Instruction { + static std::byte const* execute(std::span inputs) { + return inputs[0].as() + inputs[1].as(); } }; -struct AsciiEncode : jasmin::StackMachineInstruction { - static char execute(uint8_t n) { return n; } +struct AsciiEncode : jasmin::Instruction { + static void execute(std::span inputs) { + inputs[0] = static_cast(inputs[0].as()); + } }; -struct AsciiDecode : jasmin::StackMachineInstruction { - static uint8_t execute(char c) { return c; } +struct AsciiDecode : jasmin::Instruction { + static void execute(std::span inputs) { + inputs[0] = static_cast(inputs[0].as()); + } }; -struct LoadProgramArguments - : jasmin::StackMachineInstruction { - static void execute(jasmin::ValueStack& value_stack); +struct LoadProgramArguments : jasmin::Instruction { + static std::array execute(std::span); }; -struct Rotate : jasmin::StackMachineInstruction { - static void execute(jasmin::ValueStack& value_stack, size_t n) { - NTH_REQUIRE((v.harden), n >= 1); - std::stack stack; - for (size_t i = 1; i < n; ++i) { stack.push(value_stack.pop_value()); } - jasmin::Value v = value_stack.pop_value(); - while (not stack.empty()) { - value_stack.push(stack.top()); - stack.pop(); - } - value_stack.push(v); +struct Rotate : jasmin::Instruction { + static void execute(std::span values, + std::span) { + NTH_REQUIRE((v.harden), values.size() >= 1); + jasmin::Value v = values[0]; + for (size_t i = 1; i < values.size(); ++i) { values[i - 1] = values[i]; } + values.back() = v; } }; diff --git a/ir/ir.cc b/ir/ir.cc index 7a0ff725..80bcfede 100644 --- a/ir/ir.cc +++ b/ir/ir.cc @@ -11,8 +11,9 @@ #include "common/string.h" #include "ir/lexical_scope.h" #include "ir/type_stack.h" -#include "jasmin/execute.h" -#include "jasmin/value_stack.h" +#include "jasmin/core/execute.h" +#include "jasmin/core/value.h" +#include "nth/container/stack.h" #include "nth/debug/debug.h" #include "parse/node_index.h" #include "parse/tree.h" @@ -75,14 +76,16 @@ struct IrContext { std::optional EvaluateAs(ParseNodeIndex subtree_root_index) { T result; nth::interval range = emit.tree.subtree_range(subtree_root_index); - jasmin::ValueStack value_stack; + nth::stack value_stack; emit.Evaluate(range, value_stack, {FromConstant()}); if constexpr (nth::type == nth::type) { - size_t length = value_stack.pop(); - char const* ptr = value_stack.pop(); + size_t length = value_stack.top().as(); + value_stack.pop(); + char const* ptr = value_stack.top().as(); + value_stack.pop(); return std::string_view(ptr, length); - } else if (IcarusDeserializeValue( - std::span(value_stack.begin(), value_stack.end()), result)) { + } else if (IcarusDeserializeValue(value_stack.top_span(value_stack.size()), + result)) { return result; } else { return std::nullopt; @@ -721,10 +724,13 @@ void HandleParseTreeNodeCallExpression(ParseNodeIndex index, IrContext& context, auto const& parameters = *fn_type.parameters(); // TODO: Properly implement function call type-checking. if (parameters.size() == node.child_count - 2) { - auto type_iter = context.type_stack().rbegin(); - auto& argument_width_count = context.emit.rotation_count[index]; + auto type_iter = context.type_stack().rbegin(); + auto [iter, inserted] = context.emit.instruction_spec.try_emplace(index); + auto& spec = iter->second; + NTH_REQUIRE((v.harden), inserted); + ++spec.parameters; for (size_t i = 0; i < parameters.size(); ++i) { - argument_width_count += type::JasminSize((*type_iter)[0].type()); + spec.parameters += type::JasminSize((*type_iter)[0].type()); ++type_iter; } auto const& returns = fn_type.returns(); @@ -733,6 +739,7 @@ void HandleParseTreeNodeCallExpression(ParseNodeIndex index, IrContext& context, } std::vector return_qts; for (type::Type r : returns) { + spec.returns += type::JasminSize(r); return_qts.push_back(type::QualifiedType::Unqualified(r)); } context.type_stack().push(return_qts); @@ -741,7 +748,7 @@ void HandleParseTreeNodeCallExpression(ParseNodeIndex index, IrContext& context, case type::Evaluation::PreferCompileTime: NTH_UNIMPLEMENTED(); case type::Evaluation::RequireCompileTime: { nth::interval range = context.emit.tree.subtree_range(index); - jasmin::ValueStack value_stack; + nth::stack value_stack; context.emit.Evaluate(range, value_stack, returns); auto module_id = context.EvaluateAs(index); if (module_id == ModuleId::Invalid()) { @@ -761,39 +768,37 @@ void HandleParseTreeNodeCallExpression(ParseNodeIndex index, IrContext& context, } } else if (invocable_type.type().kind() == type::Type::Kind::GenericFunction) { - auto& rotation_count = context.emit.rotation_count[index]; - std::vector argument_indices; + auto& spec = context.emit.instruction_spec[index]; + ++spec.parameters; + std::vector> argument_indices; + auto type_iter = context.type_stack().rbegin(); for (auto iter = context.ChildIndices(index).begin(); context.Node(*iter).kind != ParseNode::Kind::InvocationArgumentStart; - ++iter) { - argument_indices.push_back(*iter); + ++iter, ++type_iter) { + NTH_REQUIRE((v.debug), type_iter != context.type_stack().rend()); + argument_indices.emplace_back(*iter, type_iter); } std::reverse(argument_indices.begin(), argument_indices.end()); - jasmin::ValueStack value_stack; + nth::stack value_stack; - auto iter = context.type_stack().rbegin(); - for (size_t i = 1; i < argument_indices.size(); ++i) { - NTH_REQUIRE((v.debug), iter != context.type_stack().rend()); - ++iter; - } - for (auto index : argument_indices) { - auto t = (*iter)[0].type(); + for (auto [index, type_iter] : argument_indices) { + auto t = (*type_iter)[0].type(); nth::interval range = context.emit.tree.subtree_range(index); context.emit.Evaluate(range, value_stack, {t}); - rotation_count += type::JasminSize(t); - ++iter; + spec.parameters += type::JasminSize(t); } + auto g = invocable_type.type().AsGenericFunction(); jasmin::Execute(*static_cast(g.data()), value_stack); - auto t = value_stack.pop(); + auto t = value_stack.top().as(); context.type_stack().push({type::QualifiedType::Constant(t)}); NTH_REQUIRE((v.debug), t.kind() == type::Type::Kind::Function); if (g.evaluation() == type::Evaluation::PreferCompileTime or g.evaluation() == type::Evaluation::RequireCompileTime) { - jasmin::ValueStack value_stack; + nth::stack value_stack; context.emit.Evaluate(context.emit.tree.subtree_range(index), value_stack, {t}); } diff --git a/ir/module.h b/ir/module.h index e25505ba..e3d5cb1c 100644 --- a/ir/module.h +++ b/ir/module.h @@ -10,7 +10,7 @@ #include "ir/function.h" #include "ir/global_function_registry.h" #include "ir/scope.h" -#include "jasmin/value.h" +#include "jasmin/core/value.h" #include "type/type.h" namespace ic { diff --git a/ir/serialize.cc b/ir/serialize.cc index e2bb9597..1a6de389 100644 --- a/ir/serialize.cc +++ b/ir/serialize.cc @@ -3,6 +3,7 @@ #include "common/resources.h" #include "ir/foreign_function.h" #include "ir/module.h" +#include "jasmin/core/metadata.h" #include "nth/debug/debug.h" #include "nth/debug/log/log.h" #include "type/serialize.h" @@ -13,12 +14,11 @@ namespace { void SerializeContent(jasmin::Value op_code_value, InstructionProto& instruction, std::span& immediate_values) { - auto op_code_metadata = InstructionSet::OpCodeMetadata(op_code_value); - auto op_code = - static_cast(op_code_metadata.op_code_value); + auto op_code = jasmin::Metadata.opcode(op_code_value); + auto op_code_metadata = jasmin::Metadata.metadata(op_code); size_t immediate_count = op_code_metadata.immediate_value_count; - instruction.set_op_code(op_code); - switch (op_code) { + instruction.set_op_code(static_cast(op_code)); + switch (static_cast(op_code)) { case InstructionProto::PUSH_STRING_LITERAL: instruction.mutable_content()->Add(resources.StringLiteralIndex( std::string(immediate_values[0].as(), diff --git a/toolchain/BUILD b/toolchain/BUILD index b0dbfa46..579ff4e9 100644 --- a/toolchain/BUILD +++ b/toolchain/BUILD @@ -59,8 +59,9 @@ cc_binary( "//ir:module_cc_proto", "//ir:program_arguments", "//lexer:token_buffer", - "@asoffer_jasmin//jasmin:execute", + "@asoffer_jasmin//jasmin/core:execute", "@asoffer_nth//nth/commandline:main", + "@asoffer_nth//nth/container:stack", "@asoffer_nth//nth/debug/log", "@asoffer_nth//nth/io:file", "@asoffer_nth//nth/io:file_path", diff --git a/toolchain/run_bytecode.cc b/toolchain/run_bytecode.cc index 5ae8d638..b4b6d3e2 100644 --- a/toolchain/run_bytecode.cc +++ b/toolchain/run_bytecode.cc @@ -14,9 +14,11 @@ #include "ir/module.h" #include "ir/module.pb.h" #include "ir/program_arguments.h" -#include "jasmin/execute.h" +#include "jasmin/core/execute.h" +#include "jasmin/core/value.h" #include "lexer/token_buffer.h" #include "nth/commandline/commandline.h" +#include "nth/container/stack.h" #include "nth/debug/log/log.h" #include "nth/debug/log/stderr_log_sink.h" #include "nth/io/file.h" @@ -92,7 +94,7 @@ nth::exit_code Run(nth::FlagValueSet flags, std::span ar } NTH_LOG((v.when(debug::run)), "{}") <<= {proto.DebugString()}; - jasmin::ValueStack value_stack; + nth::stack value_stack; jasmin::Execute(module.initializer(), value_stack); return nth::exit_code::success; } diff --git a/type/BUILD b/type/BUILD index 1f00bd01..9a62ed9a 100644 --- a/type/BUILD +++ b/type/BUILD @@ -72,7 +72,7 @@ cc_library( ":type_system_cc_proto", "//common/language:primitive_types", "//common/language:type_kind", - "@asoffer_jasmin//jasmin:value", + "@asoffer_jasmin//jasmin/core:value", "@asoffer_nth//nth/container:flyweight_set", "@asoffer_nth//nth/debug", "@asoffer_nth//nth/utility:no_destructor", diff --git a/type/type.h b/type/type.h index 6919d717..3977fb5d 100644 --- a/type/type.h +++ b/type/type.h @@ -8,7 +8,7 @@ #include #include -#include "jasmin/value.h" +#include "jasmin/core/value.h" #include "nth/container/flyweight_set.h" #include "type/type_contour.h" #include "type/type_system.pb.h"