From 9c7adab475b458430896f0c87f2608cd04cd81dd Mon Sep 17 00:00:00 2001 From: Ajay Brahmakshatriya Date: Thu, 11 Dec 2025 16:11:53 -0500 Subject: [PATCH] Added support for attributes on function arguments --- include/builder/dyn_var.h | 22 +++++++++++++++++++++ include/builder/forward_declarations.h | 6 ++++++ include/builder/signature_extract.h | 8 ++++---- samples/outputs.var_names/sample69 | 6 ++++++ samples/outputs/sample69 | 6 ++++++ samples/sample69.cpp | 27 ++++++++++++++++++++++++++ src/blocks/c_code_generator.cpp | 10 +++++++++- 7 files changed, 80 insertions(+), 5 deletions(-) create mode 100644 samples/outputs.var_names/sample69 create mode 100644 samples/outputs/sample69 create mode 100644 samples/sample69.cpp diff --git a/include/builder/dyn_var.h b/include/builder/dyn_var.h index e310087..10fc4c6 100644 --- a/include/builder/dyn_var.h +++ b/include/builder/dyn_var.h @@ -207,6 +207,17 @@ class dyn_var_impl : public var { var_name = v.name; } + dyn_var_impl(const with_block_var& v) { + create_dyn_var(!v.with_decl); + // Swap out the variable + block_var = v.var; + var_name = v.var->var_name; + // If a declaration was created, swap out the var too + if (v.with_decl) { + block_decl_stmt->decl_var = v.var; + } + } + dyn_var_impl(const defer_init &) { // Do nothing here // Defer init "automatically" supports custom types @@ -343,6 +354,17 @@ class dyn_var_impl : public var { // TODO: Consider using dynamic_cast here return (const dyn_var *)this; } + + void add_attribute(std::string s) { + std::vector attrs; + if (block_var->hasMetadata>("attributes")) { + attrs = block_var->getMetadata>("attributes"); + } + if (std::find(attrs.begin(), attrs.end(), s) == attrs.end()) { + attrs.push_back(s); + } + block_var->setMetadata>("attributes", attrs); + } }; template diff --git a/include/builder/forward_declarations.h b/include/builder/forward_declarations.h index 2918f1b..4690820 100644 --- a/include/builder/forward_declarations.h +++ b/include/builder/forward_declarations.h @@ -56,6 +56,12 @@ struct with_name { with_name(const std::string &n, bool wd = false) : name(n), with_decl(wd) {} }; +struct with_block_var { + block::var::Ptr var; + bool with_decl; + with_block_var(block::var::Ptr v, bool wd = false): var(v), with_decl(wd) {} +}; + // Generator states for non-deterministic values struct nd_var_gen_base; diff --git a/include/builder/signature_extract.h b/include/builder/signature_extract.h index 16d117d..fb5bedd 100644 --- a/include/builder/signature_extract.h +++ b/include/builder/signature_extract.h @@ -46,7 +46,7 @@ struct extract_signature_impl, std::tuple static void fill_invocation(invocation_state* i_state, F func, int arg_index, ProcessedArgTypes...processed_args, OtherParams&&...other_params) { - // We don't need to heap allocate objects anymore, just throw in a with_name, it has all + // We don't need to heap allocate objects anymore, just throw in a with_block_var, it has all // the information to create the dyn_var when invoking the actual funciton std::string arg_name = "arg" + std::to_string(arg_index); auto var = std::make_shared(); @@ -54,8 +54,8 @@ struct extract_signature_impl, std::tuplevar_type = dyn_var::create_block_type(); var->var_type->static_offset = var->static_offset = tracer::get_unique_tag(); i_state->generated_func_decl->args.push_back(var); - // We explain below by with_name is wrapped in a tuple - extract_signature_impl>, std::tuple, ReturnType>::fill_invocation(i_state, func, arg_index + 1, std::forward(processed_args)..., std::tuple(with_name(arg_name)), std::forward(other_params)...); + // We explain below by with_block_var is wrapped in a tuple + extract_signature_impl>, std::tuple, ReturnType>::fill_invocation(i_state, func, arg_index + 1, std::forward(processed_args)..., std::tuple(with_block_var(var)), std::forward(other_params)...); } }; @@ -82,7 +82,7 @@ struct extract_signature_impl, std::tuple<>, vo // Take other_args but discard them template static void fill_invocation(invocation_state* i_state, F func, int arg_index, ProcessedArgTypes...processed_args, OtherParams&&...other_params) { - // All conversions from with_name to dyn_var will happen INSIDE the lambda and hence the lifetype of the + // All conversions from with_block_var to dyn_var will happen INSIDE the lambda and hence the lifetype of the // dyn_var will be valid for the run // Mark the lambda to be mutable otherwise if func accepts a reference it won't bind correctly // since captured variables are const when captured by value diff --git a/samples/outputs.var_names/sample69 b/samples/outputs.var_names/sample69 new file mode 100644 index 0000000..2d85b68 --- /dev/null +++ b/samples/outputs.var_names/sample69 @@ -0,0 +1,6 @@ +void bar (int* restrict arg0, int* restrict arg1, int arg2) { + for (int i_0 = 0; i_0 < arg2; (i_0 = i_0 + 1) - 1) { + arg0[i_0] = arg1[i_0]; + } +} + diff --git a/samples/outputs/sample69 b/samples/outputs/sample69 new file mode 100644 index 0000000..d955777 --- /dev/null +++ b/samples/outputs/sample69 @@ -0,0 +1,6 @@ +void bar (int* restrict arg0, int* restrict arg1, int arg2) { + for (int var0 = 0; var0 < arg2; (var0 = var0 + 1) - 1) { + arg0[var0] = arg1[var0]; + } +} + diff --git a/samples/sample69.cpp b/samples/sample69.cpp new file mode 100644 index 0000000..d2a172d --- /dev/null +++ b/samples/sample69.cpp @@ -0,0 +1,27 @@ +// Include the headers +#include "blocks/c_code_generator.h" +#include "builder/static_var.h" +#include "builder/dyn_var.h" +#include + +// Include the BuildIt types +using builder::dyn_var; +using builder::static_var; + + +static void bar(dyn_var x, dyn_var y, dyn_var size) { + x.add_attribute("restrict"); + y.add_attribute("restrict"); + for (builder::dyn_var i = 0; i < size; i++) { + x[i] = y[i]; + } +} + +int main(int argc, char* argv[]) { + builder::builder_context context; + auto ast = context.extract_function_ast(bar, "bar"); + auto fd = block::to(ast); + block::c_code_generator::generate_code(ast, std::cout, 0); + return 0; +} + diff --git a/src/blocks/c_code_generator.cpp b/src/blocks/c_code_generator.cpp index 8f31d97..86e040e 100644 --- a/src/blocks/c_code_generator.cpp +++ b/src/blocks/c_code_generator.cpp @@ -688,7 +688,15 @@ void c_code_generator::visit(func_decl::Ptr a) { if (printDelim) oss << ", "; printDelim = true; - oss << complex_type_helper(arg->var_type, " " + arg->var_name); + std::string name = ""; + if (arg->hasMetadata>("attributes")) { + const auto &attributes = arg->getMetadata>("attributes"); + for (auto attr : attributes) { + name = name + " " + attr; + } + } + name = name + " " + arg->var_name; + oss << complex_type_helper(arg->var_type, name); } if (a->is_variadic) { oss << ", ...";