From a872c83069b97f8417caa816d8ddd422681d3834 Mon Sep 17 00:00:00 2001 From: Ajay Brahmakshatriya Date: Mon, 28 Oct 2024 16:09:57 -0400 Subject: [PATCH] Support out of order destruction of static_vars --- include/builder/static_var.h | 39 ++++++++++++++-- samples/outputs.var_names/sample58 | 74 ++++++++++++++++++++++++++++++ samples/outputs/sample58 | 74 ++++++++++++++++++++++++++++++ samples/sample58.cpp | 56 ++++++++++++++++++++++ 4 files changed, 239 insertions(+), 4 deletions(-) create mode 100644 samples/outputs.var_names/sample58 create mode 100644 samples/outputs/sample58 create mode 100644 samples/sample58.cpp diff --git a/include/builder/static_var.h b/include/builder/static_var.h index 2af13ad..3c7fbfe 100644 --- a/include/builder/static_var.h +++ b/include/builder/static_var.h @@ -114,8 +114,27 @@ class static_var : static_var_base { assert(builder_context::current_builder_context != nullptr); assert(builder_context::current_builder_context->static_var_tuples.size() > 0); - assert(builder_context::current_builder_context->static_var_tuples.back().ptr == (unsigned char *)&val); - builder_context::current_builder_context->static_var_tuples.pop_back(); + + /* Instead of assuming that the last variable is the static_var we are destroying, + we find the appropriate one and set its size to 0. Then we clean up all the trailing 0s + + This allows out of order destruction while still maintaining good static tags */ + + int index = -1; + for (int i = builder_context::current_builder_context->static_var_tuples.size() - 1; i >= 0; i--) { + if (builder_context::current_builder_context->static_var_tuples[i].ptr == (unsigned char*) &val) { + index = i; + builder_context::current_builder_context->static_var_tuples[i].size = 0; + break; + } + } + assert(index != -1 && "Static variable to destroy not valid"); + + while (!builder_context::current_builder_context->static_var_tuples.empty() + && builder_context::current_builder_context->static_var_tuples.back().size == 0) { + builder_context::current_builder_context->static_var_tuples.pop_back(); + } + } operator builder() { try_get_name(); @@ -188,8 +207,20 @@ class static_var : static_var_base { ~static_var() { assert(builder_context::current_builder_context != nullptr); assert(builder_context::current_builder_context->static_var_tuples.size() > 0); - assert(builder_context::current_builder_context->static_var_tuples.back().ptr == (unsigned char *)val); - builder_context::current_builder_context->static_var_tuples.pop_back(); + int index = -1; + for (int i = builder_context::current_builder_context->static_var_tuples.size() - 1; i >= 0; i--) { + if (builder_context::current_builder_context->static_var_tuples[i].ptr == (unsigned char*) val) { + index = i; + builder_context::current_builder_context->static_var_tuples[i].size = 0; + break; + } + } + assert(index != -1 && "Static variable to destroy not valid"); + + while (!builder_context::current_builder_context->static_var_tuples.empty() + && builder_context::current_builder_context->static_var_tuples.back().size == 0) { + builder_context::current_builder_context->static_var_tuples.pop_back(); + } delete[] val; } virtual std::string serialize() override { diff --git a/samples/outputs.var_names/sample58 b/samples/outputs.var_names/sample58 new file mode 100644 index 0000000..b7c2ff6 --- /dev/null +++ b/samples/outputs.var_names/sample58 @@ -0,0 +1,74 @@ +FUNC_DECL + SCALAR_TYPE (VOID) + VAR (arg0) + STMT_BLOCK + DECL_STMT + SCALAR_TYPE (INT) + VAR (var0) + VAR_EXPR + VAR (arg0) + DECL_STMT + SCALAR_TYPE (INT) + VAR (y_1) + NO_INITIALIZATION + DECL_STMT + SCALAR_TYPE (INT) + VAR (c_2) + VAR_EXPR + VAR (var0) + IF_STMT + EQUALS_EXPR + INT_CONST (0) + VAR_EXPR + VAR (c_2) + STMT_BLOCK + DECL_STMT + SCALAR_TYPE (FLOAT) + VAR (c_3) + FLOAT_CONST (2) + STMT_BLOCK + IF_STMT + EQUALS_EXPR + INT_CONST (1) + VAR_EXPR + VAR (c_2) + STMT_BLOCK + DECL_STMT + SCALAR_TYPE (FLOAT) + VAR (c_4) + FLOAT_CONST (3) + STMT_BLOCK + IF_STMT + EQUALS_EXPR + INT_CONST (2) + VAR_EXPR + VAR (c_2) + STMT_BLOCK + DECL_STMT + SCALAR_TYPE (FLOAT) + VAR (c_5) + FLOAT_CONST (5) + STMT_BLOCK + DECL_STMT + SCALAR_TYPE (FLOAT) + VAR (c_6) + FLOAT_CONST (2) +void bar (int arg0) { + int var0 = arg0; + int y_1; + int c_2 = var0; + if (0 == c_2) { + float c_3 = 2.0f; + } else { + if (1 == c_2) { + float c_4 = 3.0f; + } else { + if (2 == c_2) { + float c_5 = 5.0f; + } else { + float c_6 = 2.0f; + } + } + } +} + diff --git a/samples/outputs/sample58 b/samples/outputs/sample58 new file mode 100644 index 0000000..7dbb89f --- /dev/null +++ b/samples/outputs/sample58 @@ -0,0 +1,74 @@ +FUNC_DECL + SCALAR_TYPE (VOID) + VAR (arg0) + STMT_BLOCK + DECL_STMT + SCALAR_TYPE (INT) + VAR (var0) + VAR_EXPR + VAR (arg0) + DECL_STMT + SCALAR_TYPE (INT) + VAR (var1) + NO_INITIALIZATION + DECL_STMT + SCALAR_TYPE (INT) + VAR (var2) + VAR_EXPR + VAR (var0) + IF_STMT + EQUALS_EXPR + INT_CONST (0) + VAR_EXPR + VAR (var2) + STMT_BLOCK + DECL_STMT + SCALAR_TYPE (FLOAT) + VAR (var3) + FLOAT_CONST (2) + STMT_BLOCK + IF_STMT + EQUALS_EXPR + INT_CONST (1) + VAR_EXPR + VAR (var2) + STMT_BLOCK + DECL_STMT + SCALAR_TYPE (FLOAT) + VAR (var4) + FLOAT_CONST (3) + STMT_BLOCK + IF_STMT + EQUALS_EXPR + INT_CONST (2) + VAR_EXPR + VAR (var2) + STMT_BLOCK + DECL_STMT + SCALAR_TYPE (FLOAT) + VAR (var5) + FLOAT_CONST (5) + STMT_BLOCK + DECL_STMT + SCALAR_TYPE (FLOAT) + VAR (var6) + FLOAT_CONST (2) +void bar (int arg0) { + int var0 = arg0; + int var1; + int var2 = var0; + if (0 == var2) { + float var3 = 2.0f; + } else { + if (1 == var2) { + float var4 = 3.0f; + } else { + if (2 == var2) { + float var5 = 5.0f; + } else { + float var6 = 2.0f; + } + } + } +} + diff --git a/samples/sample58.cpp b/samples/sample58.cpp new file mode 100644 index 0000000..099e6b9 --- /dev/null +++ b/samples/sample58.cpp @@ -0,0 +1,56 @@ +#include "blocks/c_code_generator.h" +#include "builder/builder.h" +#include "builder/builder_context.h" +#include "builder/dyn_var.h" +#include "builder/static_var.h" +#include "builder/lib/utils.h" +#include +using builder::dyn_var; +using builder::static_var; + +static static_var magic(dyn_var x, int range) { + for (static_var y = 0; y < range; y++) { + if (y == x) return y; + } + return 0; +} + + +float arr[] = {2.0, 3.0, 5.0}; + + +static void bar(dyn_var x) { + /* Test out of order deinitialization of static variables and arrays */ + + auto sv1 = new static_var(); + auto sv2 = new static_var(); + + auto sva1 = new static_var(); + sva1->resize(5); + auto sva2 = new static_var(); + sva2->resize(5); + + + dyn_var y; + + delete sv1; + delete sv2; + delete sva1; + delete sva2; + + + // Test case that breaks without out of order deinitialization + static_var z = magic(x, 3); + dyn_var c = arr[z]; + + + +} + +int main(int argc, char *argv[]) { + builder::builder_context context; + auto ast = context.extract_function_ast(bar, "bar"); + ast->dump(std::cout, 0); + block::c_code_generator::generate_code(ast, std::cout, 0); + return 0; +}