From b305ce6d763e80da9bcdd5d8afed1e33094d6225 Mon Sep 17 00:00:00 2001 From: Ajay Brahmakshatriya Date: Wed, 17 Jan 2024 15:29:38 -0500 Subject: [PATCH] Added support for deferred init static vars --- include/builder/builder_context.h | 1 + include/builder/dyn_var.h | 7 ------ include/builder/forward_declarations.h | 7 ++++++ include/builder/static_var.h | 20 +++++++++++++++++ samples/outputs.var_names/sample53 | 30 ++++++++++++++++++++++++++ samples/outputs/sample53 | 30 ++++++++++++++++++++++++++ samples/sample53.cpp | 6 ++++++ src/builder/builder_context.cpp | 1 + src/util/tracer.cpp | 14 ++++++++++++ 9 files changed, 109 insertions(+), 7 deletions(-) diff --git a/include/builder/builder_context.h b/include/builder/builder_context.h index 08b6e10..840fbca 100644 --- a/include/builder/builder_context.h +++ b/include/builder/builder_context.h @@ -122,6 +122,7 @@ class builder_context { std::string current_label; std::vector static_var_tuples; + std::vector deferred_static_var_tuples; std::vector assume_variables; diff --git a/include/builder/dyn_var.h b/include/builder/dyn_var.h index ee58214..4864e7f 100644 --- a/include/builder/dyn_var.h +++ b/include/builder/dyn_var.h @@ -90,13 +90,6 @@ struct with_name { with_name(const std::string &n, bool wd = false) : name(n), with_decl(wd) {} }; -// constructor helper to defer the initialization of dyn_var -// This allows declaring dyn_var outside the context, but initialize -// them later -struct defer_init { - // No members -}; - template class dyn_var_impl : public var { public: diff --git a/include/builder/forward_declarations.h b/include/builder/forward_declarations.h index 15da3ea..71b02a3 100644 --- a/include/builder/forward_declarations.h +++ b/include/builder/forward_declarations.h @@ -42,6 +42,13 @@ struct extract_signature; template struct extract_signature_from_lambda; +// constructor helper to defer the initialization of dyn_var +// This allows declaring dyn_var outside the context, but initialize +// them later +struct defer_init { + // No members +}; + // This class does nothing // Apart from just being used in the copy constructor to // tell the constructor to no create without context diff --git a/include/builder/static_var.h b/include/builder/static_var.h index e1dc2a4..2af13ad 100644 --- a/include/builder/static_var.h +++ b/include/builder/static_var.h @@ -34,6 +34,7 @@ class static_var : static_var_base { static_assert(sizeof(T) < MAX_TRACKING_VAR_SIZE, "Currently builder::static_var supports variables of max size " "= " TOSTRING(MAX_TRACKING_VARIABLE_SIZE)); T val; + bool is_deferred = false; mutable bool name_checked = false; void try_get_name() const { @@ -91,7 +92,26 @@ class static_var : static_var_base { val = v; try_get_name(); } + + static_var(const defer_init &) { + // Just like dynamic variables, no registration happens here + is_deferred = true; + } + void deferred_init(void) { + assert(builder_context::current_builder_context != nullptr); + // Deferred static variables are kept separate because they are never untracked + // in the destructor + builder_context::current_builder_context->deferred_static_var_tuples.push_back( + tracking_tuple((unsigned char *)&val, sizeof(T), this)); + try_get_name(); + } + ~static_var() { + if (is_deferred) { + // Must be a deferred init object + return; + } + 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); diff --git a/samples/outputs.var_names/sample53 b/samples/outputs.var_names/sample53 index b049c23..51134d3 100644 --- a/samples/outputs.var_names/sample53 +++ b/samples/outputs.var_names/sample53 @@ -6,5 +6,35 @@ void foo (void) { } else { obj_0 = 2; } + if ((obj_0 % 2) == 0) { + obj_0 = obj_0 + 0; + } + if ((obj_0 % 2) == 0) { + obj_0 = obj_0 + 1; + } + if ((obj_0 % 2) == 0) { + obj_0 = obj_0 + 2; + } + if ((obj_0 % 2) == 0) { + obj_0 = obj_0 + 3; + } + if ((obj_0 % 2) == 0) { + obj_0 = obj_0 + 4; + } + if ((obj_0 % 2) == 0) { + obj_0 = obj_0 + 5; + } + if ((obj_0 % 2) == 0) { + obj_0 = obj_0 + 6; + } + if ((obj_0 % 2) == 0) { + obj_0 = obj_0 + 7; + } + if ((obj_0 % 2) == 0) { + obj_0 = obj_0 + 8; + } + if ((obj_0 % 2) == 0) { + obj_0 = obj_0 + 9; + } } diff --git a/samples/outputs/sample53 b/samples/outputs/sample53 index 0988e23..ec75462 100644 --- a/samples/outputs/sample53 +++ b/samples/outputs/sample53 @@ -6,5 +6,35 @@ void foo (void) { } else { var0 = 2; } + if ((var0 % 2) == 0) { + var0 = var0 + 0; + } + if ((var0 % 2) == 0) { + var0 = var0 + 1; + } + if ((var0 % 2) == 0) { + var0 = var0 + 2; + } + if ((var0 % 2) == 0) { + var0 = var0 + 3; + } + if ((var0 % 2) == 0) { + var0 = var0 + 4; + } + if ((var0 % 2) == 0) { + var0 = var0 + 5; + } + if ((var0 % 2) == 0) { + var0 = var0 + 6; + } + if ((var0 % 2) == 0) { + var0 = var0 + 7; + } + if ((var0 % 2) == 0) { + var0 = var0 + 8; + } + if ((var0 % 2) == 0) { + var0 = var0 + 9; + } } diff --git a/samples/sample53.cpp b/samples/sample53.cpp index 291d5e7..28950e9 100644 --- a/samples/sample53.cpp +++ b/samples/sample53.cpp @@ -11,11 +11,13 @@ using builder::static_var; struct external_object_t { dyn_var member = builder::defer_init(); + static_var counter = builder::defer_init(); }; static void foo(external_object_t &obj) { // Init not obj.member.deferred_init(); + obj.counter.deferred_init(); dyn_var x = 0; if (x) { @@ -23,6 +25,10 @@ static void foo(external_object_t &obj) { } else { obj.member = 2; } + + for (obj.counter = 0; obj.counter < 10; obj.counter++) + if (obj.member % 2 == 0) + obj.member += obj.counter; } int main(int argc, char *argv[]) { diff --git a/src/builder/builder_context.cpp b/src/builder/builder_context.cpp index 610a949..0d47559 100644 --- a/src/builder/builder_context.cpp +++ b/src/builder/builder_context.cpp @@ -426,6 +426,7 @@ block::stmt::Ptr builder_context::extract_ast_from_function_internal(std::vector } ret_ast = ast; } + current_builder_context = nullptr; // Update the memoized table with the stmt block we just created for (unsigned int i = 0; i < current_block_stmt->stmts.size(); i++) { diff --git a/src/util/tracer.cpp b/src/util/tracer.cpp index 1ee0971..5f17fba 100644 --- a/src/util/tracer.cpp +++ b/src/util/tracer.cpp @@ -33,6 +33,13 @@ tag get_offset_in_function_impl(builder::builder_context *current_builder_contex } // Now add snapshots of static vars assert(current_builder_context != nullptr); + + for (builder::tracking_tuple tuple : current_builder_context->deferred_static_var_tuples) { + new_tag.static_var_snapshots.push_back(tuple.snapshot()); + if (builder::builder_context::current_builder_context->enable_d2x) { + new_tag.static_var_key_values.push_back({tuple.var_ref->var_name, tuple.var_ref->serialize()}); + } + } for (builder::tracking_tuple tuple : current_builder_context->static_var_tuples) { new_tag.static_var_snapshots.push_back(tuple.snapshot()); if (builder::builder_context::current_builder_context->enable_d2x) { @@ -59,6 +66,13 @@ tag get_offset_in_function_impl(builder::builder_context *current_builder_contex // Now add snapshots of static vars assert(current_builder_context != nullptr); + + for (builder::tracking_tuple tuple : current_builder_context->deferred_static_var_tuples) { + new_tag.static_var_snapshots.push_back(tuple.snapshot()); + if (builder::builder_context::current_builder_context->enable_d2x) { + new_tag.static_var_key_values.push_back({tuple.var_ref->var_name, tuple.var_ref->serialize()}); + } + } for (builder::tracking_tuple tuple : current_builder_context->static_var_tuples) { new_tag.static_var_snapshots.push_back(tuple.snapshot()); if (builder::builder_context::current_builder_context->enable_d2x) {