mirror of
https://github.com/odin-lang/Odin.git
synced 2026-08-18 03:12:10 +00:00
Support #byte directive for asm templates
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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; }) \
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user