From dd8fb87384ef3465d478b8de70f493b82f9b8315 Mon Sep 17 00:00:00 2001 From: Ajay Brahmakshatriya Date: Sun, 24 Sep 2023 13:11:04 -0400 Subject: [PATCH] Fixed the bug with labels not being duplicated across branches --- include/blocks/label_inserter.h | 11 ++++++ samples/outputs.var_names/sample50 | 56 ++++++++++++++++++++++++++++++ samples/outputs/sample50 | 56 ++++++++++++++++++++++++++++++ samples/sample50.cpp | 30 ++++++++++++++++ src/blocks/label_inserter.cpp | 24 ++++++------- src/builder/builder_context.cpp | 4 ++- 6 files changed, 168 insertions(+), 13 deletions(-) create mode 100644 samples/outputs.var_names/sample50 create mode 100644 samples/outputs/sample50 create mode 100644 samples/sample50.cpp diff --git a/include/blocks/label_inserter.h b/include/blocks/label_inserter.h index 0a201fd..6285816 100644 --- a/include/blocks/label_inserter.h +++ b/include/blocks/label_inserter.h @@ -23,8 +23,19 @@ class label_creator : public block_visitor { class label_inserter : public block_visitor { public: using block_visitor::visit; + + // The main table to hold static tag to label mapping + // this table holds the jump target that is in the parent of the + // jump statement std::unordered_map offset_to_label; + // A backup table which has atleast one label that we can jump to + // Only used when feature_unstructured is used + std::unordered_map backup_offset_to_label; + + bool feature_unstructured; + virtual void visit(goto_stmt::Ptr); + virtual void visit(label_stmt::Ptr); }; } // namespace block #endif diff --git a/samples/outputs.var_names/sample50 b/samples/outputs.var_names/sample50 new file mode 100644 index 0000000..5a1ea6d --- /dev/null +++ b/samples/outputs.var_names/sample50 @@ -0,0 +1,56 @@ +FUNC_DECL + SCALAR_TYPE (VOID) + STMT_BLOCK + DECL_STMT + SCALAR_TYPE (INT) + VAR (k_0) + INT_CONST (0) + DECL_STMT + SCALAR_TYPE (INT) + VAR (t_1) + INT_CONST (0) + WHILE_STMT + INT_CONST (1) + STMT_BLOCK + IF_STMT + NE_EXPR + VAR_EXPR + VAR (k_0) + INT_CONST (1) + STMT_BLOCK + IF_STMT + EQUALS_EXPR + VAR_EXPR + VAR (k_0) + INT_CONST (2) + STMT_BLOCK + WHILE_STMT + NE_EXPR + VAR_EXPR + VAR (k_0) + INT_CONST (3) + STMT_BLOCK + STMT_BLOCK + STMT_BLOCK + WHILE_STMT + NE_EXPR + VAR_EXPR + VAR (k_0) + INT_CONST (3) + STMT_BLOCK +void bar (void) { + int k_0 = 0; + int t_1 = 0; + while (1) { + if (k_0 != 1) { + if (k_0 == 2) { + while (k_0 != 3) { + } + } + } else { + while (k_0 != 3) { + } + } + } +} + diff --git a/samples/outputs/sample50 b/samples/outputs/sample50 new file mode 100644 index 0000000..b9e7541 --- /dev/null +++ b/samples/outputs/sample50 @@ -0,0 +1,56 @@ +FUNC_DECL + SCALAR_TYPE (VOID) + STMT_BLOCK + DECL_STMT + SCALAR_TYPE (INT) + VAR (var0) + INT_CONST (0) + DECL_STMT + SCALAR_TYPE (INT) + VAR (var1) + INT_CONST (0) + WHILE_STMT + INT_CONST (1) + STMT_BLOCK + IF_STMT + NE_EXPR + VAR_EXPR + VAR (var0) + INT_CONST (1) + STMT_BLOCK + IF_STMT + EQUALS_EXPR + VAR_EXPR + VAR (var0) + INT_CONST (2) + STMT_BLOCK + WHILE_STMT + NE_EXPR + VAR_EXPR + VAR (var0) + INT_CONST (3) + STMT_BLOCK + STMT_BLOCK + STMT_BLOCK + WHILE_STMT + NE_EXPR + VAR_EXPR + VAR (var0) + INT_CONST (3) + STMT_BLOCK +void bar (void) { + int var0 = 0; + int var1 = 0; + while (1) { + if (var0 != 1) { + if (var0 == 2) { + while (var0 != 3) { + } + } + } else { + while (var0 != 3) { + } + } + } +} + diff --git a/samples/sample50.cpp b/samples/sample50.cpp new file mode 100644 index 0000000..41ef02a --- /dev/null +++ b/samples/sample50.cpp @@ -0,0 +1,30 @@ +#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 +using builder::dyn_var; +using builder::static_var; + +static void bar(void) { + dyn_var k = 0; + dyn_var t = 0; + while (1) { + while (k != 1) { + + if (k == 2) + break; + } + while (k != 3) { + } + } +} + +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; +} diff --git a/src/blocks/label_inserter.cpp b/src/blocks/label_inserter.cpp index 7afd019..8d9446b 100644 --- a/src/blocks/label_inserter.cpp +++ b/src/blocks/label_inserter.cpp @@ -5,15 +5,6 @@ namespace block { void label_collector::visit(goto_stmt::Ptr a) { collected_labels.push_back(a->temporary_label_number); } -static void erase_tag(std::vector &list, tracer::tag &erase) { - std::vector new_list; - for (unsigned int i = 0; i < list.size(); i++) { - if (list[i] != erase) { - new_list.push_back(list[i]); - } - } - list = new_list; -} void label_creator::visit(stmt_block::Ptr a) { std::vector new_stmts; @@ -30,8 +21,7 @@ void label_creator::visit(stmt_block::Ptr a) { new_label_stmt->static_offset.clear(); new_label_stmt->label1 = new_label; new_stmts.push_back(new_label_stmt); - // collected_labels.erase(stmt->static_offset); - erase_tag(collected_labels, stmt->static_offset); + offset_to_label[stmt->static_offset.stringify()] = new_label; } new_stmts.push_back(stmt); @@ -39,7 +29,17 @@ void label_creator::visit(stmt_block::Ptr a) { } a->stmts = new_stmts; } + +void label_inserter::visit(label_stmt::Ptr a) { + offset_to_label[a->label1->static_offset.stringify()] = a->label1; +} + void label_inserter::visit(goto_stmt::Ptr a) { - a->label1 = offset_to_label[a->temporary_label_number.stringify()]; + // Pick any jump target with feature unstructured + // otherwise pick the one that is in the parent block + if (feature_unstructured) + a->label1 = backup_offset_to_label[a->temporary_label_number.stringify()]; + else + a->label1 = offset_to_label[a->temporary_label_number.stringify()]; } } // namespace block diff --git a/src/builder/builder_context.cpp b/src/builder/builder_context.cpp index 0b7aefc..0a3ccd0 100644 --- a/src/builder/builder_context.cpp +++ b/src/builder/builder_context.cpp @@ -144,6 +144,7 @@ static void trim_ast_at_offset(block::stmt::Ptr ast, tracer::tag offset) { static std::pair, std::vector> trim_common_from_back(block::stmt::Ptr ast1, block::stmt::Ptr ast2) { + std::vector trimmed_stmts; std::vector &ast1_stmts = block::to(ast1)->stmts; std::vector &ast2_stmts = block::to(ast2)->stmts; @@ -280,7 +281,8 @@ block::stmt::Ptr builder_context::extract_ast_from_function_impl(void) { ast->accept(&creator); block::label_inserter inserter; - inserter.offset_to_label = creator.offset_to_label; + inserter.backup_offset_to_label = creator.offset_to_label; + inserter.feature_unstructured = feature_unstructured; ast->accept(&inserter); // At this point it is safe to remove statements that are