From bd95d2ae66be16a8d5d4281e28347fba0ed625b3 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 17 Aug 2026 13:32:28 +0100 Subject: [PATCH] Add `asm` directive `#align N` --- src/check_asm.cpp | 31 +++++++++++++++++++++++++++++++ src/llvm_backend_asm.cpp | 9 +++++++++ 2 files changed, 40 insertions(+) diff --git a/src/check_asm.cpp b/src/check_asm.cpp index ea50aa45e..c847b1932 100644 --- a/src/check_asm.cpp +++ b/src/check_asm.cpp @@ -1515,7 +1515,38 @@ gb_internal void check_asm_template(AsmCtx *asm_ctx, CheckerContext *ctx, Entity continue; } } + } else if (name == "align") { + if (dir->operands.count != 1) { + error(dir->name, "Expected 1 integer 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 a power-of-two 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 a power-of-two integer for the asm directive #%.*s", LIT(name)); + continue; + } + i64 i = exact_value_to_i64(ev); + if (i < 0 || !is_power_of_two(i)) { + error(op.expr, "Expected a power-of-two integer for the asm directive #%.*s, got %lld", LIT(name), cast(long long)i); + continue; + } + } + + } else { + error(dir->name, "Unknown asm directive: #%.*s", LIT(name)); } + case_end; default: diff --git a/src/llvm_backend_asm.cpp b/src/llvm_backend_asm.cpp index 19a902c99..5cca6d89b 100644 --- a/src/llvm_backend_asm.cpp +++ b/src/llvm_backend_asm.cpp @@ -495,6 +495,15 @@ struct lbAsmGenerate_amd64 : lbAsmGenerate { asm_string = gb_string_append_fmt(asm_string, "%d", cast(int)i); op_index += 1; } + } else if (name == "align") { + asm_string = gb_string_appendc(asm_string, ".p2align "); + GB_ASSERT(dir->operands.count == 1); + auto const &op = dir->operands[0]; + ExactValue ev = exact_value_to_integer(op->tav.value); + GB_ASSERT(ev.kind == ExactValue_Integer); + u64 i = exact_value_to_u64(ev); + u64 i_log2 = floor_log2(i); + asm_string = gb_string_append_fmt(asm_string, "%llu", cast(unsigned long long)i_log2); } else { GB_PANIC("Invalid asm directive: %.*s", LIT(name)); }