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});
 	}}