From 91f6660a00401cd54ada850140792daf39aa2576 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Tup=C3=BD?= Date: Wed, 27 Dec 2023 02:00:06 +0100 Subject: [PATCH] Added basic support for accessing function parameters. --- .../compiler/type_system/variable_registry.cpp | 10 +++++++--- .../compiler/type_system/variable_registry.h | 13 ++++++++++++- source/compiler/test/main.s | 15 +++++++-------- source/ir_translator/ir_translator.cpp | 12 ++++++++++++ source/type_checker/type_checker.cpp | 16 +++++++++++----- 5 files changed, 49 insertions(+), 17 deletions(-) diff --git a/source/compiler/compiler/type_system/variable_registry.cpp b/source/compiler/compiler/type_system/variable_registry.cpp index 4b61caca..f4c5e7f5 100644 --- a/source/compiler/compiler/type_system/variable_registry.cpp +++ b/source/compiler/compiler/type_system/variable_registry.cpp @@ -48,15 +48,19 @@ namespace sigma { auto variable_registry::create_load(utility::string_table_key identifier, ir::data_type type, u16 alignment) const -> handle { const handle variable = m_active_scope->get_variable(identifier); - if(variable != nullptr) { - return m_context.builder.create_load(variable->value, type, alignment, false); + ASSERT(variable, "attempting to load an invalid variable"); + + if(variable->flags & variable::FUNCTION_PARAMETER) { + return variable->value; } - return nullptr; + return m_context.builder.create_load(variable->value, type, alignment, false); } void variable_registry::create_store(utility::string_table_key identifier, handle value, u16 alignment) const { const handle variable = m_active_scope->get_variable(identifier); + // ASSERT(!(variable->flags & variable::FUNCTION_PARAMETER), "not implemented"); + if (variable != nullptr) { m_context.builder.create_store(variable->value, value, alignment, false); return; diff --git a/source/compiler/compiler/type_system/variable_registry.h b/source/compiler/compiler/type_system/variable_registry.h index f52e69b5..dd6e6142 100644 --- a/source/compiler/compiler/type_system/variable_registry.h +++ b/source/compiler/compiler/type_system/variable_registry.h @@ -7,8 +7,17 @@ namespace sigma { struct backend_context; class variable_registry { + public: struct variable { + enum variable_flags { + NONE = 0, + + // variable is a function parameter, function parameters don't need to be loaded + FUNCTION_PARAMETER = 1 + }; + handle value; + variable_flags flags; data_type type; }; @@ -22,7 +31,7 @@ namespace sigma { std::unordered_map variables; u16 trace_index = 0; }; - public: + variable_registry(backend_context& context); // NOTE: since we have two step analysis we need to traverse the scope system twice - first, @@ -57,4 +66,6 @@ namespace sigma { scope m_global_scope; handle m_active_scope; }; + + FLAG_ENUM(variable_registry::variable::variable_flags); } // namespace sigma diff --git a/source/compiler/test/main.s b/source/compiler/test/main.s index 90a5f151..1153b6df 100644 --- a/source/compiler/test/main.s +++ b/source/compiler/test/main.s @@ -21,14 +21,13 @@ // ret 0; // } -i32 main() { - i32 value = 0; - - if(false) {} - else { - value = 100; - } +i32 test(i32 x) { + // x = x + 10; + ret x; +} - printf("value is: %d\n", value); +i32 main() { + i32 val = test(100); + printf("val : %d\n", val); ret 0; } diff --git a/source/ir_translator/ir_translator.cpp b/source/ir_translator/ir_translator.cpp index 301dd0bf..0e8136da 100644 --- a/source/ir_translator/ir_translator.cpp +++ b/source/ir_translator/ir_translator.cpp @@ -46,6 +46,18 @@ namespace sigma { m_context.function_registry.declare_local_function(signature); m_context.variable_registry.trace_push_scope(); + // TODO: handle varargs + // push temporaries for function parameters + for (u64 i = 0; i < signature.parameter_types.get_size(); ++i) { + // TODO: create proxies? + const auto variable = m_context.variable_registry.get_variable(signature.parameter_types[i].identifier_key); + ASSERT(variable, "function parameter pre declaration is invalid"); + + const handle value = m_context.builder.get_function_parameter(i); + variable->flags |= variable_registry::variable::FUNCTION_PARAMETER; + variable->value = value; + } + // handle inner statements for (const handle& statement : function_node->children) { translate_node(statement); diff --git a/source/type_checker/type_checker.cpp b/source/type_checker/type_checker.cpp index 59f2636f..ce478d81 100644 --- a/source/type_checker/type_checker.cpp +++ b/source/type_checker/type_checker.cpp @@ -59,23 +59,29 @@ namespace sigma { auto type_checker::type_check_function_declaration(handle function_node, data_type expected) -> utility::result { SUPPRESS_C4100(expected); - const auto& property = function_node->get(); + const auto& signature = function_node->get(); // check if the function hasn't been declared before - if(m_context.function_registry.contains_function(property)) { + if(m_context.function_registry.contains_function(signature)) { return utility::error::create( utility::error::code::FUNCTION_ALREADY_DECLARED, - m_context.syntax.string_table.get(property.identifier_key) + m_context.syntax.string_table.get(signature.identifier_key) ); } // register the function - m_context.function_registry.pre_declare_local_function(property); + m_context.function_registry.pre_declare_local_function(signature); m_context.variable_registry.push_scope(); + // TODO: handle varargs + // push temporaries for function parameters + for(const named_data_type& parameter : signature.parameter_types) { + m_context.variable_registry.pre_declare_variable(parameter.identifier_key, parameter.type); + } + // type check inner statements for(const handle& statement : function_node->children) { - TRY(type_check_node(statement, property.return_type)); + TRY(type_check_node(statement, signature.return_type)); } m_context.variable_registry.pop_scope();