diff --git a/source/ast/tag_types.h b/source/ast/tag_types.h index 33efae066616feb65c73872ad6110bda6cb15108..24e5b8fa2a29b436e85fca9a2878217bfde5a1ac 100644 --- a/source/ast/tag_types.h +++ b/source/ast/tag_types.h @@ -28,15 +28,17 @@ namespace idlc { unused = 1 << 13, bind_memberof_caller = 1 << 14, bind_memberof_callee = 1 << 15, + alloc_stack_caller = 1 << 16, + alloc_stack_callee = 1 << 17, is_bind_memberof = bind_memberof_caller | bind_memberof_callee, is_bind = (bind_callee | bind_caller), is_dealloc = (dealloc_callee | dealloc_caller), is_alloc = (alloc_callee | alloc_caller), is_alloc_once = (alloc_once_callee | alloc_once_caller), + is_alloc_stack = (alloc_stack_callee | alloc_stack_caller), is_ioremap = (ioremap_callee | ioremap_caller), is_ptr = is_bind | is_dealloc | is_alloc | is_ioremap | is_alloc_once | shared - | is_bind_memberof, - + | is_bind_memberof | is_alloc_stack, is_val = out | in | unused, in_out = out | in, io_only = in_out, diff --git a/source/backend/.generation.cpp.swp b/source/backend/.generation.cpp.swp new file mode 100644 index 0000000000000000000000000000000000000000..e94fa722c2139cd0b8d09d490bf691d31c9a1751 Binary files /dev/null and b/source/backend/.generation.cpp.swp differ diff --git a/source/backend/.helpers.cpp.swp b/source/backend/.helpers.cpp.swp new file mode 100644 index 0000000000000000000000000000000000000000..80b1a790b04bc2aa55e7ee9d88a3b2befc63409e Binary files /dev/null and b/source/backend/.helpers.cpp.swp differ diff --git a/source/backend/generation.cpp b/source/backend/generation.cpp index aeb98be67e4694f267c1a6a09bd61241802e8593..7ee13bd648dfb6a741a345cf4c49374df5f06cbf 100644 --- a/source/backend/generation.cpp +++ b/source/backend/generation.cpp @@ -193,7 +193,29 @@ namespace idlc { const auto& specifier = pgraph->c_specifier; auto ptr_name = concat(name, "_ptr"); - os << "\t" << specifier << "* " << ptr_name << " = &" << name << ";\n"; + + // TODO: Doesn't really work for multi-dimensional arrays + auto p = std::get_if<node_ref<pointer>>(&pgraph->type); + + if (p && (side == marshal_side::callee)) { + auto p_array = std::get_if<node_ref<static_array>>(&p->get()->referent->type); + auto raw_specifier = p->get()->referent->c_specifier; + + if (flags_set(p->get()->pointer_annots.kind, annotation_kind::alloc_stack_callee)) { + if (p_array) { + os << "\t" << raw_specifier << " __" << name << "[" << p_array->get()->size << "];\n"; + os << "\t" << specifier << " " << name << " = __" << name << ";\n"; + } else { + os << "\t" << raw_specifier << " __" << name << ";\n"; + os << "\t" << specifier << " " << name << " = &__" << name << ";\n"; + } + os << "\t" << specifier << "* " << ptr_name << " = &" << name << ";\n"; + } else { + os << "\t" << specifier << "* " << ptr_name << " = &" << name << ";\n"; + } + } else { + os << "\t" << specifier << "* " << ptr_name << " = &" << name << ";\n"; + } roots.emplace_back(std::move(ptr_name), pgraph.get()); } @@ -365,8 +387,13 @@ namespace idlc { const auto n_args = gsl::narrow<gsl::index>(rpc.arg_pgraphs.size()); for (gsl::index i {}; i < n_args; ++i) { - const auto& type = rpc.arg_pgraphs.at(i)->c_specifier; + const auto& pgraph = rpc.arg_pgraphs.at(i); + const auto& type = pgraph->c_specifier; const auto name = rpc.arguments->at(i)->name; + + auto p = std::get_if<node_ref<pointer>>(&pgraph->type); + if (p && flags_set(p->get()->pointer_annots.kind, annotation_kind::alloc_stack_callee)) + continue; os << "\t" << type << " " << name << " = 0;\n"; } diff --git a/source/backend/walks.h b/source/backend/walks.h index fba5537314a64d003781b02e6f609dc1e10986d5..27124ca9deedfe07edcccc46cd6eab131cbc7e01 100644 --- a/source/backend/walks.h +++ b/source/backend/walks.h @@ -157,6 +157,10 @@ namespace idlc { return true; // No need to walk these (yet) } + else if (flags_set(node.pointer_annots.kind, annotation_kind::alloc_stack_callee)) { + // No need to pack the pointer if it's a stack allocation on the other side + return true; + } else { this->new_line() << "glue_pack(__pos, msg, ext, __adjusted);\n"; } @@ -490,6 +494,19 @@ namespace idlc { std::terminate(); } + static constexpr bool should_alloc_stack(const annotation& ann) + { + switch (side) { + case marshal_side::caller: + return flags_set(ann.kind, annotation_kind::alloc_stack_caller); + + case marshal_side::callee: + return flags_set(ann.kind, annotation_kind::alloc_stack_callee); + } + + std::terminate(); + } + static constexpr absl::string_view get_visitor_name(projection& node) { switch (side) { @@ -505,6 +522,10 @@ namespace idlc { [[nodiscard]] bool marshal_pointer_value(pointer& node) { + // No need to unpack the pointer for stack allocation + if (should_alloc_stack(node.pointer_annots)) + return true; + if (!is_clear(node.pointer_annots.kind & annotation_kind::is_bind_memberof)) { // special case! early return marshal_bind_memberof_pointer(node); diff --git a/source/parser/idl.peg b/source/parser/idl.peg index b66a0f04720178b8e44515572c3179a89df6b5cc..cf8021701d18674e53f8040a48169854044bcd3b 100644 --- a/source/parser/idl.peg +++ b/source/parser/idl.peg @@ -86,6 +86,7 @@ tok_kw_in = "in" tok_kw_out = "out" tok_kw_alloc = "alloc" tok_kw_alloc_once = "alloc_once" +tok_kw_alloc_stack = "alloc_stack" tok_kw_dealloc = "dealloc" tok_kw_bind = "bind" tok_kw_caller = "caller" @@ -364,6 +365,12 @@ ptr_attr = tok_kw_in {{ value = share(annotation {annotation_kind::in}); }} | tok_kw_alloc_once tok_space? tok_lpar tok_space? tok_kw_callee tok_space? tok_rpar {{ value = share(annotation {annotation_kind::alloc_once_callee}); }} + | tok_kw_alloc_stack tok_space? tok_lpar tok_space? tok_kw_caller tok_space? tok_rpar {{ + value = share(annotation {annotation_kind::alloc_stack_caller, nullptr, nullptr}); + }} + | tok_kw_alloc_stack tok_space? tok_lpar tok_space? tok_kw_callee tok_space? tok_rpar {{ + value = share(annotation {annotation_kind::alloc_stack_callee, nullptr, nullptr}); + }} | tok_kw_alloc tok_space? tok_lpar tok_space? tok_kw_caller tok_space? tok_rpar {{ value = share(annotation {annotation_kind::alloc_caller}); }}