diff --git a/src/check_asm.cpp b/src/check_asm.cpp index 98ab7fc49..f8fa94d0f 100644 --- a/src/check_asm.cpp +++ b/src/check_asm.cpp @@ -793,6 +793,26 @@ gb_internal void check_asm_specs(AsmCtx *asm_ctx, CheckerContext *ctx, Scope *sc error(spec->value, "Input parameters, and thus tied parameters, cannot be pinned to a flag style register"); } } + + + for (Ast *dir_ : spec->directives) { + ast_node(dir, BasicDirective, dir_); + String name = dir->name.string; + if (name == "no_init") { + i32 input_index = -1; + check_asm_find_group(input, *asm_template_entity_decls, &input_index); + if (input_index >= 0) { + auto *i = &(*asm_template_entity_decls)[input_index]; + i->no_init = true; + if (i->tie >= 0) { + auto *o = &(*asm_template_entity_decls)[i->tie]; + o->no_init = true; + } + } + } else { + error(dir_, "Invalid directive for an asm specification, got '#%.*s'", LIT(name)); + } + } } } @@ -2451,6 +2471,9 @@ gb_internal void check_asm_template(AsmCtx *asm_ctx, CheckerContext *ctx, Entity // straight-line instruction stream. Seeded with input-pinned registers (they // carry their argument at entry); grows as instructions write registers. for (auto const &ed : ate->decls) { + if (ed.no_init) { + ptr_set_add(&asm_acc.defined_params, ed.entity); + } switch (ed.param_group) { case AsmTemplateEntityDeclParamGroup_Input: if (ed.pin.len != 0) { @@ -2683,6 +2706,9 @@ gb_internal void check_asm_template(AsmCtx *asm_ctx, CheckerContext *ctx, Entity if (ed.tie >= 0) { continue; } + if (ed.no_init) { + continue; + } if (!asm_acc.straight_line) { continue; } diff --git a/src/entity.cpp b/src/entity.cpp index f6045e341..b70f09045 100644 --- a/src/entity.cpp +++ b/src/entity.cpp @@ -196,6 +196,8 @@ struct AsmTemplateEntityDecl { i32 view_of; // total_index of the source operand this is a width-view of, else -1 i32 view_bits; // the view width in bits, otherwise 0 + + bool no_init; }; // An Entity is a named "thing" in the language diff --git a/src/parser.cpp b/src/parser.cpp index 1173305f8..f8ccb79a6 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -533,10 +533,11 @@ gb_internal Ast *clone_ast(Ast *node, AstFile *f) { case Ast_AsmRegister: break; case Ast_AsmSpec: - n->AsmSpec.name = clone_ast(n->AsmSpec.name, f); - n->AsmSpec.tied_name = clone_ast(n->AsmSpec.tied_name, f); - n->AsmSpec.type = clone_ast(n->AsmSpec.type, f); - n->AsmSpec.value = clone_ast(n->AsmSpec.value, f); + n->AsmSpec.name = clone_ast(n->AsmSpec.name, f); + n->AsmSpec.tied_name = clone_ast(n->AsmSpec.tied_name, f); + n->AsmSpec.type = clone_ast(n->AsmSpec.type, f); + n->AsmSpec.value = clone_ast(n->AsmSpec.value, f); + n->AsmSpec.directives = clone_ast_array(n->AsmSpec.directives, f); break; case Ast_AsmClobber: n->AsmClobber.value = clone_ast(n->AsmClobber.value, f); @@ -2694,6 +2695,60 @@ gb_internal Ast *parse_asm_signature(AstFile *f, Token asm_token) { return ast_proc_type(f, asm_token, params, results, tags, cc, is_generic, diverging); } +gb_internal Ast *parse_asm_spec(AstFile *f) { + Ast *name = parse_ident(f); + Ast *tied_name = nullptr; + Ast *type = nullptr; + Ast *value = nullptr; + if (allow_token(f, Token_ArrowRight)) { + tied_name = parse_ident(f); + } + if (allow_token(f, Token_Colon)) { + type = parse_type(f); + } + if (allow_token(f, Token_Eq)) { + if (f->curr_token.kind == Token_Ident) { + value = parse_ident(f); + } else if (f->curr_token.kind == Token_Mod) { + value = parse_asm_register(f); + } else { + error(f->curr_token, "Expected a register or scratch parameter"); + Ast *dummy = parse_expr(f, true); + gb_unused(dummy); + } + } + + if (tied_name != nullptr) { + if (type != nullptr) { + syntax_error(f->curr_token, "An asm specification for tied values cannot declare a type"); + } + } else if (type == nullptr && value == nullptr) { + syntax_error(f->curr_token, "An asm specification must specify at least either a type or a value if the value is not tied"); + } + + Array directives = {}; + directives.allocator = heap_allocator(); + + while (f->curr_token.kind == Token_Hash) { + Token token = expect_token(f, Token_Hash); + Token name = expect_token_after(f, Token_Ident, "hash for directive"); + if (name.kind == Token_Ident) { + Ast *directive = ast_basic_directive(f, token, name); + array_add(&directives, directive); + } + } + + + Ast *spec = alloc_ast_node(f, Ast_AsmSpec); + spec->AsmSpec.name = name; + spec->AsmSpec.tied_name = tied_name; + spec->AsmSpec.type = type; + spec->AsmSpec.value = value; + spec->AsmSpec.directives = directives; + return spec; +} + + gb_internal Ast *parse_asm_template(AstFile *f) { Token token = expect_token(f, Token_asm); @@ -2718,41 +2773,7 @@ gb_internal Ast *parse_asm_template(AstFile *f) { f->curr_token.kind != Token_EOF) { Ast *spec = nullptr; if (f->curr_token.kind == Token_Ident) { - Ast *name = parse_ident(f); - Ast *tied_name = nullptr; - Ast *type = nullptr; - Ast *value = nullptr; - if (allow_token(f, Token_ArrowRight)) { - tied_name = parse_ident(f); - } - if (allow_token(f, Token_Colon)) { - type = parse_type(f); - } - if (allow_token(f, Token_Eq)) { - if (f->curr_token.kind == Token_Ident) { - value = parse_ident(f); - } else if (f->curr_token.kind == Token_Mod) { - value = parse_asm_register(f); - } else { - error(f->curr_token, "Expected a register or scratch parameter"); - Ast *dummy = parse_expr(f, true); - gb_unused(dummy); - } - } - - if (tied_name != nullptr) { - if (type != nullptr) { - syntax_error(f->curr_token, "An asm specification for tied values cannot declare a type"); - } - } else if (type == nullptr && value == nullptr) { - syntax_error(f->curr_token, "An asm specification must specify at least either a type or a value if the value is not tied"); - } - - spec = alloc_ast_node(f, Ast_AsmSpec); - spec->AsmSpec.name = name; - spec->AsmSpec.tied_name = tied_name; - spec->AsmSpec.type = type; - spec->AsmSpec.value = value; + spec = parse_asm_spec(f); } else if (f->curr_token.kind == Token_Hash) { Token hash = expect_token(f, Token_Hash); Token name = expect_token(f, Token_Ident); diff --git a/src/parser.hpp b/src/parser.hpp index efc8be219..ad82834ed 100644 --- a/src/parser.hpp +++ b/src/parser.hpp @@ -489,10 +489,11 @@ struct AstSplitArgs { Token flag; \ }) \ AST_KIND(AsmSpec, "asm specification", struct { \ - Ast *name; \ - Ast *tied_name; \ - Ast *type; \ - Ast *value; \ + Ast * name; \ + Ast * tied_name; \ + Ast * type; \ + Ast * value; \ + Array directives; \ }) \ AST_KIND(AsmClobber, "asm clobber", struct { \ Token token; \