///|
priv struct WasmoonSemanticEnvironment {
wasm : @wasm_machv.Environment
field_paths : Map[String, Array[Int]]
runtime_symbols : @wasm_milkir.RuntimeSymbols
}
///|
fn wasmoon_semantic_environment(
use_subtype_indirect_check : Bool,
canonical_type_indices : Array[Int],
) -> WasmoonSemanticEnvironment {
let layout = vmcontext_layout()
let field_paths : Map[String, Array[Int]] = Map([])
let runtime_symbols = wasm_runtime_symbols()
let function_table_field = @semantic_machv.EnvironmentField::new(
"wasmoon.vmctx.function_table",
Ptr64,
)
field_paths.set(function_table_field.name, [layout.func_table_offset])
let canonical_type_indices = canonical_type_indices.copy()
let wasm = @wasm_machv.Environment::new(
fn(index) {
let name = "wasm.func.\{index}"
@semantic_machv.CodeSymbol::new(name)
},
fn(index) {
let field = @semantic_machv.EnvironmentField::new(
"wasmoon.vmctx.memory.\{index}.base",
Ptr64,
)
let path = if index == 0 {
[layout.memory0_base_offset]
} else {
[layout.memories_offset, index * layout.pointer_stride, 0]
}
field_paths.set(field.name, path)
field
},
function_table_field,
fn(index) {
let field = @semantic_machv.EnvironmentField::new(
"wasmoon.vmctx.table.\{index}.base",
Ptr64,
)
let path = if index == 0 {
[layout.table0_base_offset]
} else {
[layout.tables_offset, index * layout.pointer_stride]
}
field_paths.set(field.name, path)
field
},
fn(raw_type_index) {
if use_subtype_indirect_check {
return raw_type_index
}
if raw_type_index >= 0 && raw_type_index < canonical_type_indices.length() {
canonical_type_indices[raw_type_index]
} else {
raw_type_index
}
},
fn(helper) {
@semantic_machv.ExternalSymbol::new(runtime_symbols.symbol_name(helper))
},
)
{ wasm, field_paths, runtime_symbols }
}
///|
fn wasmoon_allocation_symbols(
environment : WasmoonSemanticEnvironment,
) -> Array[@semantic_machv.ExternalSymbol] {
[
@semantic_machv.ExternalSymbol::new(
environment.runtime_symbols.symbol_name(GcAllocStructSlow),
),
@semantic_machv.ExternalSymbol::new(
environment.runtime_symbols.symbol_name(GcAllocArrayFromValuesSlow),
),
@semantic_machv.ExternalSymbol::new(
environment.runtime_symbols.symbol_name(GcAllocArraySlow),
),
]
}
///|
fn build_wasmoon_aarch64_target(
semantic : @semantic_machv.Function,
environment : WasmoonSemanticEnvironment,
record_metrics? : Bool = false,
) -> AArch64TargetCompilation raise JitPipelineError {
build_aarch64_target(
semantic,
environment_field_path=fn(field : @semantic_machv.EnvironmentField) {
environment.field_paths.get(field.name)
},
allocation_symbols=wasmoon_allocation_symbols(environment),
record_metrics~,
root_scope_symbols=(
@semantic_machv.ExternalSymbol::new(gc_push_root_scope_symbol()),
@semantic_machv.ExternalSymbol::new(gc_pop_root_scope_symbol()),
),
)
}
///|
fn build_wasmoon_x64_target(
semantic : @semantic_machv.Function,
environment : WasmoonSemanticEnvironment,
record_metrics? : Bool = false,
) -> X64TargetCompilation raise JitPipelineError {
build_x64_target(
semantic,
environment_field_path=fn(field : @semantic_machv.EnvironmentField) {
environment.field_paths.get(field.name)
},
allocation_symbols=wasmoon_allocation_symbols(environment),
record_metrics~,
root_scope_symbols=(
@semantic_machv.ExternalSymbol::new(gc_push_root_scope_symbol()),
@semantic_machv.ExternalSymbol::new(gc_pop_root_scope_symbol()),
),
)
}
///|
fn lower_wasm_body_semantic_with_environment(
function : @milkir.Function,
validation_context : @wasm_milkir.WasmValidationContext,
environment : WasmoonSemanticEnvironment,
) -> @semantic_machv.Function raise JitPipelineError {
@wasm_machv.lower_function(function, validation_context, environment.wasm) catch {
error => raise SemanticLoweringFailed(cause=error)
}
}
///|
pub fn lower_wasm_body_semantic_machv(
function : @milkir.Function,
validation_context : @wasm_milkir.WasmValidationContext,
use_subtype_indirect_check? : Bool = true,
canonical_type_indices? : Array[Int] = [],
) -> @semantic_machv.Function raise JitPipelineError {
let environment = wasmoon_semantic_environment(
use_subtype_indirect_check, canonical_type_indices,
)
lower_wasm_body_semantic_with_environment(
function, validation_context, environment,
)
}
///|
/// Render every verified native compilation checkpoint without exposing
/// concrete target construction types to diagnostics consumers.
pub fn compile_wasm_body_diagnostics_for_target(
function : @milkir.Function,
validation_context : @wasm_milkir.WasmValidationContext,
target : NativeTarget,
use_subtype_indirect_check? : Bool = true,
canonical_type_indices? : Array[Int] = [],
) -> JitPipelineDiagnostics raise JitPipelineError {
let environment = wasmoon_semantic_environment(
use_subtype_indirect_check, canonical_type_indices,
)
let semantic = lower_wasm_body_semantic_with_environment(
function, validation_context, environment,
)
let semantic_machv = semantic.print()
if target is AArch64 {
let diagnostics = diagnose_aarch64_target(
semantic,
environment_field_path=fn(field : @semantic_machv.EnvironmentField) {
environment.field_paths.get(field.name)
},
allocation_symbols=wasmoon_allocation_symbols(environment),
root_scope_symbols=(
@semantic_machv.ExternalSymbol::new(gc_push_root_scope_symbol()),
@semantic_machv.ExternalSymbol::new(gc_pop_root_scope_symbol()),
),
)
return {
semantic_machv,
target_vcode: diagnostics.target_vcode,
allocated_vcode: diagnostics.allocated_vcode,
code_object: code_object_diagnostic_text(diagnostics.object),
machine_code: diagnostics.object
.code()
.map(byte => @types.to_hex_byte(byte.to_int()))
.join(" "),
}
}
let diagnostics = diagnose_x64_target(
semantic,
environment_field_path=fn(field : @semantic_machv.EnvironmentField) {
environment.field_paths.get(field.name)
},
allocation_symbols=wasmoon_allocation_symbols(environment),
root_scope_symbols=(
@semantic_machv.ExternalSymbol::new(gc_push_root_scope_symbol()),
@semantic_machv.ExternalSymbol::new(gc_pop_root_scope_symbol()),
),
)
{
semantic_machv,
target_vcode: diagnostics.target_vcode,
allocated_vcode: diagnostics.allocated_vcode,
code_object: code_object_diagnostic_text(diagnostics.object),
machine_code: diagnostics.object
.code()
.map(byte => @types.to_hex_byte(byte.to_int()))
.join(" "),
}
}
///|
fn compile_wasm_body_aarch64_target(
function : @milkir.Function,
validation_context : @wasm_milkir.WasmValidationContext,
use_subtype_indirect_check : Bool,
canonical_type_indices : Array[Int],
record_metrics? : Bool = false,
) -> AArch64TargetCompilation raise JitPipelineError {
let environment = wasmoon_semantic_environment(
use_subtype_indirect_check, canonical_type_indices,
)
let semantic_lower_tick = target_metrics_tick(record_metrics)
let semantic = lower_wasm_body_semantic_with_environment(
function, validation_context, environment,
)
record_target_stage(SemanticLowering, semantic_lower_tick) |> ignore
build_wasmoon_aarch64_target(semantic, environment, record_metrics~)
}
///|
fn compile_wasm_body_x64_target(
function : @milkir.Function,
validation_context : @wasm_milkir.WasmValidationContext,
use_subtype_indirect_check : Bool,
canonical_type_indices : Array[Int],
record_metrics? : Bool = false,
) -> X64TargetCompilation raise JitPipelineError {
let environment = wasmoon_semantic_environment(
use_subtype_indirect_check, canonical_type_indices,
)
let semantic_lower_tick = target_metrics_tick(record_metrics)
let semantic = lower_wasm_body_semantic_with_environment(
function, validation_context, environment,
)
record_target_stage(SemanticLowering, semantic_lower_tick) |> ignore
build_wasmoon_x64_target(semantic, environment, record_metrics~)
}
///|
pub fn plan_wasm_body_aarch64_code_object(
function : @milkir.Function,
validation_context : @wasm_milkir.WasmValidationContext,
use_subtype_indirect_check? : Bool = true,
canonical_type_indices? : Array[Int] = [],
) -> @code_object.UnlinkedCodeObject raise JitPipelineError {
compile_wasm_body_aarch64_target(
function, validation_context, use_subtype_indirect_check, canonical_type_indices,
).object
}
///|
pub fn plan_wasm_body_x64_code_object(
function : @milkir.Function,
validation_context : @wasm_milkir.WasmValidationContext,
use_subtype_indirect_check? : Bool = true,
canonical_type_indices? : Array[Int] = [],
) -> @code_object.UnlinkedCodeObject raise JitPipelineError {
compile_wasm_body_x64_target(
function, validation_context, use_subtype_indirect_check, canonical_type_indices,
).object
}