memcopy! and memset! intrinsics

This commit is contained in:
2026-07-20 22:53:04 +02:00
parent 297f2e3078
commit dd00af7731
11 changed files with 729 additions and 11 deletions
+34 -2
View File
@@ -647,6 +647,24 @@ lower_compound_expr :: proc(state: ^State, expr_id: hir.Expr_Id) -> ir.Instructi
return append_recovery_value(state, expr.span, expr.type, expr.diagnostic)
}
memory_region_element_type :: proc(value: types.Type, store: ^types.Store) -> types.Type {
resolved := types.resolve_alias(value, store)
item, ok := types.node(store, resolved)
if !ok {
return types.INVALID
}
if item.kind == .Slice {
return item.child
}
if item.kind == .Pointer && !item.many {
array, array_ok := types.node(store, types.resolve_alias(item.child, store))
if array_ok && array.kind == .Array {
return array.child
}
}
return types.INVALID
}
lower_expr :: proc(state: ^State, expr_id: hir.Expr_Id) -> ir.Instruction_Id {
stack := state.expr_stack
state.expr_stack = nil
@@ -691,6 +709,13 @@ lower_expr :: proc(state: ^State, expr_id: hir.Expr_Id) -> ir.Instruction_Id {
target=ir.INVALID_REF, a=ir.INVALID_INSTRUCTION, b=ir.INVALID_INSTRUCTION, diagnostic=source.INVALID_DIAGNOSTIC,
})
_ = pop(&stack)
case .Undefined:
last = append_instruction(state, ir.Instruction{
op=.Poison, span=expr.span, type=expr.type,
target=ir.INVALID_REF, a=ir.INVALID_INSTRUCTION, b=ir.INVALID_INSTRUCTION,
diagnostic=source.INVALID_DIAGNOSTIC,
})
_ = pop(&stack)
case .String, .Array, .Struct, .Range, .None, .Optional_Some, .Address, .Deref,
.Index, .Slice, .Field, .Union_Tag, .Length, .Slice_Ptr, .Unwrap, .Orelse,
.Try, .Catch, .Not, .Eq, .Ne, .Lt, .Le, .Gt, .Ge, .And, .Or:
@@ -744,7 +769,7 @@ lower_expr :: proc(state: ^State, expr_id: hir.Expr_Id) -> ir.Instruction_Id {
append(&stack, Lower_Expr_Frame{expr=expr.left})
case .Add, .Sub, .Mul, .Div, .Div_Trunc, .Div_Floor, .Div_Exact, .Div_Ceil,
.Rem, .Mod, .Pointer_Add, .Bit_And, .Bit_Or, .Bit_Xor, .Shift_Left,
.Shift_Right, .Shift_Left_Saturating:
.Shift_Right, .Shift_Left_Saturating, .Mem_Copy, .Mem_Set:
stack[frame_index].stage = 2
append(&stack, Lower_Expr_Frame{expr=expr.left})
case .Call:
@@ -823,6 +848,7 @@ lower_expr :: proc(state: ^State, expr_id: hir.Expr_Id) -> ir.Instruction_Id {
}
if frame.stage == 3 {
op := ir.Opcode.Add_Checked
result_type := expr.type
#partial switch expr.kind {
case .Sub: op = .Sub_Checked
case .Mul: op = .Mul_Checked
@@ -840,10 +866,16 @@ lower_expr :: proc(state: ^State, expr_id: hir.Expr_Id) -> ir.Instruction_Id {
case .Shift_Left: op = .Shift_Left
case .Shift_Right: op = .Shift_Right
case .Shift_Left_Saturating: op = .Shift_Left_Saturating
case .Mem_Copy:
op = .Mem_Copy
result_type = memory_region_element_type(state.hir_module.exprs[expr.left].type, &state.hir_module.types)
case .Mem_Set:
op = .Mem_Set
result_type = memory_region_element_type(state.hir_module.exprs[expr.left].type, &state.hir_module.types)
}
last = append_instruction(state, ir.Instruction{
op=op,
span=expr.span, type=expr.type, target=ir.INVALID_REF,
span=expr.span, type=result_type, target=ir.INVALID_REF,
a=frame.left, b=last, diagnostic=source.INVALID_DIAGNOSTIC,
})
_ = pop(&stack)