mirror of
https://github.com/odin-lang/Odin.git
synced 2026-09-04 19:20:20 +00:00
Mockout inline asm for riscv
This commit is contained in:
@@ -54,7 +54,9 @@ gb_global String const asm_operand_kind_expected_strings[AsmOperand_COUNT] = {
|
||||
};
|
||||
|
||||
#include "asm_tables_amd64.cpp"
|
||||
#include "asm_tables_riscv.cpp"
|
||||
|
||||
void init_asm_tables() {
|
||||
g_asm_amd64.init();
|
||||
void init_asm_tables(i64 word_size) {
|
||||
g_asm_amd64.init(word_size);
|
||||
g_asm_riscv.init(word_size);
|
||||
}
|
||||
@@ -312,6 +312,20 @@ struct Asm_amd64 {
|
||||
// NOTE: SideEffectFlag_HINT deliberately excluded — inert, may be DCE'd.
|
||||
return ((side_effects & VOLATILE_SE) != 0);
|
||||
}
|
||||
|
||||
u8 is_call_or_mem() const {
|
||||
return (cast(u16)side_effects & SideEffectFlag_CONTROL) != 0 ||
|
||||
(cast(u16)implicit_wr & ClobberReg_RSP) != 0;
|
||||
}
|
||||
bool has_control() const {
|
||||
return (cast(u16)side_effects & SideEffectFlag_CONTROL) != 0;
|
||||
}
|
||||
bool has_halt() const {
|
||||
return (cast(u16)side_effects & SideEffectFlag_HALT) != 0;
|
||||
}
|
||||
bool is_conditional() const {
|
||||
return has_control() && (cast(u16)flags_rd != 0);
|
||||
}
|
||||
};
|
||||
|
||||
void clobber_implicit_regs(StringSet *clobber_registers_set, u16 implicit_regs) {
|
||||
@@ -424,7 +438,6 @@ struct Asm_amd64 {
|
||||
|
||||
bool has_implicit () const { return ((flags>>21u)&1) != 0; }
|
||||
u8 explicit_count() const { return cast(u8)((flags>>18u)&((1u<<3)-1)); }
|
||||
u8 op_count () const { return cast(u8)((flags>>22u)&((1u<<3)-1)); }
|
||||
bool lock_ok () const { return ((flags>>14u)&1) != 0; }
|
||||
bool rep_ok () const { return ((flags>>15u)&1) != 0; }
|
||||
};
|
||||
@@ -447,7 +460,8 @@ struct Asm_amd64 {
|
||||
StringMap<Prefix> prefix_map;
|
||||
StringMap<Register> register_map;
|
||||
|
||||
bool init() {
|
||||
bool init(i64 word_size) {
|
||||
gb_unused(word_size);
|
||||
string_map_init(&mnemonic_map, MNEMONIC_COUNT*2);
|
||||
for (u16 m = M_INVALID+1; m < MNEMONIC_COUNT; m++) {
|
||||
string_map_set(&mnemonic_map, mnemonic_strings[m], cast(Mnemonic)m);
|
||||
|
||||
@@ -1080,8 +1080,7 @@ gb_internal void check_mnemonic(AsmCtx *asm_ctx, CheckerContext *ctx, Entity *tm
|
||||
// aligned at the call boundary) or manipulates RSP directly. Plain memory access
|
||||
// through a parameter pointer does NOT require stack realignment, so
|
||||
// implies_clobber_memory() is intentionally NOT used here.
|
||||
if ((cast(u16)clobber.side_effects & asm_ctx->SideEffectFlag_CONTROL) != 0 ||
|
||||
(cast(u16)clobber.implicit_wr & asm_ctx->ClobberReg_RSP) != 0) {
|
||||
if (clobber.is_call_or_mem()) {
|
||||
asm_acc->saw_call_or_mem = true;
|
||||
}
|
||||
|
||||
@@ -1159,17 +1158,16 @@ gb_internal void check_mnemonic(AsmCtx *asm_ctx, CheckerContext *ctx, Entity *tm
|
||||
// is not merely CONTROL-with-fallthrough. We approximate "unconditional" as
|
||||
// CONTROL|HALT with no explicit label/operand fallthrough below.
|
||||
{
|
||||
u16 se = cast(u16)clobber.side_effects;
|
||||
bool control = (se & asm_ctx->SideEffectFlag_CONTROL) != 0;
|
||||
bool halt = (se & asm_ctx->SideEffectFlag_HALT) != 0;
|
||||
bool control = clobber.has_control();
|
||||
bool halt = clobber.has_halt();
|
||||
// A conditional branch reads a flag and can fall through -> not terminal.
|
||||
bool conditional = control && (cast(u16)clobber.flags_rd != 0);
|
||||
bool conditional = clobber.is_conditional();
|
||||
asm_acc->last_is_terminal = halt || (control && !conditional);
|
||||
}
|
||||
|
||||
// A branch/call inside the template means subsequent instructions may be reached
|
||||
// out of textual order; stop trusting the linear def model past this point.
|
||||
if (cast(u16)clobber.side_effects & asm_ctx->SideEffectFlag_CONTROL) {
|
||||
if (clobber.has_control()) {
|
||||
asm_acc->straight_line = false;
|
||||
}
|
||||
asm_ctx->clobber_implicit_regs(&tmpl_entity->AsmTemplate.clobber_registers_set, produced);
|
||||
@@ -2126,6 +2124,8 @@ gb_internal void check_asm_template(AsmCtx *asm_ctx, CheckerContext *ctx, Entity
|
||||
gb_internal void check_asm_template_from_entity(CheckerContext *c, Entity *e, DeclInfo *d) {
|
||||
if (build_context.metrics.arch == TargetArch_amd64) {
|
||||
check_asm_template(&g_asm_amd64, c, e, d);
|
||||
} else if (build_context.metrics.arch == TargetArch_riscv64) {
|
||||
check_asm_template(&g_asm_riscv, c, e, d);
|
||||
} else {
|
||||
error(e->token, "asm templates are not currently supported for this target");
|
||||
}
|
||||
|
||||
@@ -4321,7 +4321,7 @@ int main(int arg_count, char const **arg_ptr) {
|
||||
bool failed_to_cache_parsing = false;
|
||||
|
||||
TIME_SECTION("init asm tables");
|
||||
init_asm_tables();
|
||||
init_asm_tables(build_context.metrics.ptr_size);
|
||||
|
||||
MAIN_TIME_SECTION("parse files");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user