Support #byte directive for asm templates

This commit is contained in:
gingerBill
2026-08-17 13:21:40 +01:00
parent c2dfcb3c28
commit 55377f71ef
5 changed files with 77 additions and 0 deletions

View File

@@ -1486,6 +1486,38 @@ gb_internal void check_asm_template(AsmCtx *asm_ctx, CheckerContext *ctx, Entity
}
case_end;
case_ast_node(dir, AsmDirective, instruction_);
String name = dir->name.string;
if (name == "byte") {
if (dir->operands.count == 0) {
error(dir->name, "Expected 1 or more integers for the asm directive #%.*s", LIT(name));
break;
}
array_clear(&operands);
for (Ast *expr : dir->operands) {
Operand operand = {};
check_asm_instruction_operand(asm_ctx, ctx, entity, &operand, expr, /*allow_memory_operands*/true);
array_add(&operands, operand);
}
for (auto const &op : operands) {
if (op.mode != Addressing_Constant) {
error(op.expr, "Expected an integer for the asm directive #%.*s", LIT(name));
continue;
}
ExactValue ev = exact_value_to_integer(op.value);
if (ev.kind != ExactValue_Integer) {
error(op.expr, "Expected an integer for the asm directive #%.*s", LIT(name));
continue;
}
i64 i = exact_value_to_i64(ev);
if (i < 0 || i > 255) {
error(op.expr, "Expected an integer within 0..<256 for the asm directive #%.*s, got %lld", LIT(name), cast(long long)i);
continue;
}
}
}
case_end;
default:
error(instruction_, "Unexpected instruction in asm template");
break;

View File

@@ -480,6 +480,25 @@ struct lbAsmGenerate_amd64 : lbAsmGenerate {
asm_string = this->write_label(asm_string, &label->name->Ident);
asm_string = gb_string_appendc(asm_string, ":");
case_end;
case_ast_node(dir, AsmDirective, instr_);
String name = dir->name.string;
if (name == "byte") {
asm_string = gb_string_appendc(asm_string, ".byte ");
isize op_index = 0;
for (auto const &op : dir->operands) {
if (op_index > 0) {
asm_string = gb_string_appendc(asm_string, ", ");
}
ExactValue ev = exact_value_to_integer(op->tav.value);
GB_ASSERT(ev.kind == ExactValue_Integer);
i64 i = exact_value_to_i64(ev);
asm_string = gb_string_append_fmt(asm_string, "%d", cast(int)i);
op_index += 1;
}
} else {
GB_PANIC("Invalid asm directive: %.*s", LIT(name));
}
case_end;
default:
GB_PANIC("Invalid asm instruction");
break;

View File

@@ -551,6 +551,9 @@ gb_internal Ast *clone_ast(Ast *node, AstFile *f) {
n->AsmMemoryOperand.disp = clone_ast(n->AsmMemoryOperand.disp, f);
n->AsmMemoryOperand.type = clone_ast(n->AsmMemoryOperand.type, f);
break;
case Ast_AsmDirective:
n->AsmDirective.operands = clone_ast_array(n->AsmDirective.operands, f);
break;
}
return n;
}
@@ -2573,6 +2576,17 @@ gb_internal Ast *parse_asm_instruction(AstFile *f) {
label_decl->AsmLabelDecl.name = name;
return label_decl;
}
case Token_Hash:
{
Token token = expect_token(f, Token_Hash);
Token name = expect_token(f, Token_Ident);
auto operands = parse_asm_operands(f);
Ast *dir = alloc_ast_node(f, Ast_AsmDirective);
dir->AsmDirective.token = token;
dir->AsmDirective.name = name;
dir->AsmDirective.operands = operands;
return dir;
}
}
syntax_error(f->curr_token, "Expected an asm instruction, got '%.*s'", LIT(f->curr_token.string));
advance_token(f);

View File

@@ -512,6 +512,11 @@ struct AstSplitArgs {
Ast * type; \
Token close; \
}) \
AST_KIND(AsmDirective, "asm directive", struct { \
Token token; \
Token name; \
Slice<Ast *> operands; \
}) \
AST_KIND(_ExprBegin, "", bool) \
AST_KIND(BadExpr, "bad expression", struct { Token begin, end; }) \
AST_KIND(TagExpr, "tag expression", struct { Token token, name; Ast *expr; }) \

View File

@@ -27,6 +27,8 @@ gb_internal Token ast_token(Ast *node) {
return ast_token(node->AsmInstruction.name);
case Ast_AsmMemoryOperand:
return node->AsmMemoryOperand.open;
case Ast_AsmDirective:
return node->AsmDirective.token;
case Ast_TagExpr: return node->TagExpr.token;
case Ast_BadExpr: return node->BadExpr.begin;
@@ -197,6 +199,11 @@ Token ast_end_token(Ast *node) {
return ast_end_token(node->AsmInstruction.operands[node->AsmInstruction.operands.count-1]);
}
return ast_end_token(node->AsmInstruction.name);
case Ast_AsmDirective:
if (node->AsmDirective.operands.count > 0) {
return ast_end_token(node->AsmDirective.operands[node->AsmDirective.operands.count-1]);
}
return node->AsmDirective.name;
case Ast_AsmMemoryOperand:
if (node->AsmMemoryOperand.type) {
return ast_end_token(node->AsmMemoryOperand.type);