Add #no_init suffix directive for asm specifications.

This commit is contained in:
gingerBill
2026-08-24 19:10:32 +01:00
parent dfa473f2c8
commit 3e159a4e10
4 changed files with 93 additions and 43 deletions

View File

@@ -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<Ast *> 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);