Added $$memmove built-in.

This commit is contained in:
Dmitry Atamanov
2022-10-08 15:45:35 +05:00
committed by Christoffer Lerno
parent 73ac0b8ea0
commit 7fa129932d
11 changed files with 131 additions and 18 deletions

View File

@@ -45,6 +45,11 @@ macro void set(void* dst, char val, usize len, usize $dst_align = 0, bool $is_vo
$$memset(dst, val, len, $is_volatile, $dst_align);
}
macro void move(void* dst, void* src, usize len, usize $dst_align = 0, usize $src_align = 0, bool $is_volatile = false)
{
$$memmove(dst, src, len, $is_volatile, $dst_align, $src_align);
}
macro void clear(void* dst, usize len, usize $dst_align = 0, bool $is_volatile = false)
{
$$memset(dst, (char)0, len, $is_volatile, $dst_align);

View File

@@ -824,6 +824,7 @@ typedef enum
BUILTIN_MAX,
BUILTIN_MEMCOPY,
BUILTIN_MEMSET,
BUILTIN_MEMMOVE,
BUILTIN_MIN,
BUILTIN_NEARBYINT,
BUILTIN_POPCOUNT,

View File

@@ -651,6 +651,7 @@ static void llvm_codegen_setup()
intrinsic_id.maxnum = lookup_intrinsic("llvm.maxnum");
intrinsic_id.memcpy = lookup_intrinsic("llvm.memcpy");
intrinsic_id.memset = lookup_intrinsic("llvm.memset");
intrinsic_id.memmove = lookup_intrinsic("llvm.memmove");
intrinsic_id.minimum = lookup_intrinsic("llvm.minimum");
intrinsic_id.minnum = lookup_intrinsic("llvm.minnum");
intrinsic_id.nearbyint = lookup_intrinsic("llvm.nearbyint");

View File

@@ -240,6 +240,7 @@ INLINE void llvm_emit_memset_builtin(GenContext *c, BEValue *be_value, Expr *exp
Expr **args = expr->call_expr.arguments;
LLVMValueRef arg_slots[4];
llvm_emit_intrinsic_args(c, args, arg_slots, 4);
arg_slots[0] = llvm_emit_bitcast(c, arg_slots[0], type_voidptr);
LLVMTypeRef call_type[2] = { llvm_get_type(c, type_voidptr), llvm_get_type(c, type_usize) };
LLVMValueRef result = llvm_emit_call_intrinsic(c, intrinsic_id.memset, call_type, 2, arg_slots, 4);
assert(args[4]->const_expr.const_kind == CONST_INTEGER);
@@ -248,6 +249,25 @@ INLINE void llvm_emit_memset_builtin(GenContext *c, BEValue *be_value, Expr *exp
llvm_value_set(be_value, result, type_void);
}
INLINE void llvm_emit_memmove_builtin(GenContext *c, BEValue *be_value, Expr *expr)
{
Expr **args = expr->call_expr.arguments;
LLVMValueRef arg_slots[4];
llvm_emit_intrinsic_args(c, args, arg_slots, 4);
arg_slots[0] = llvm_emit_bitcast(c, arg_slots[0], type_voidptr);
arg_slots[1] = llvm_emit_bitcast(c, arg_slots[1], type_voidptr);
LLVMTypeRef call_type[3];
call_type[0] = call_type[1] = llvm_get_type(c, type_voidptr);
call_type[2] = llvm_get_type(c, type_usize);
LLVMValueRef result = llvm_emit_call_intrinsic(c, intrinsic_id.memmove, call_type, 3, arg_slots, 4);
assert(args[4]->const_expr.const_kind == CONST_INTEGER);
assert(args[5]->const_expr.const_kind == CONST_INTEGER);
uint64_t dst_align = int_to_u64(args[4]->const_expr.ixx);
uint64_t src_align = int_to_u64(args[5]->const_expr.ixx);
if (dst_align > 0) llvm_attribute_add_call(c, result, attribute_id.align, 1, dst_align);
if (src_align > 0) llvm_attribute_add_call(c, result, attribute_id.align, 2, src_align);
llvm_value_set(be_value, result, type_void);
}
INLINE void llvm_emit_prefetch(GenContext *c, BEValue *be_value, Expr *expr)
{
Expr **args = expr->call_expr.arguments;
@@ -379,6 +399,9 @@ void llvm_emit_builtin_call(GenContext *c, BEValue *result_value, Expr *expr)
case BUILTIN_MEMSET:
llvm_emit_memset_builtin(c, result_value, expr);
return;
case BUILTIN_MEMMOVE:
llvm_emit_memmove_builtin(c, result_value, expr);
return;
case BUILTIN_SYSCLOCK:
llvm_value_set(result_value, llvm_emit_call_intrinsic(c, intrinsic_id.readcyclecounter, NULL, 0, NULL, 0), expr->type);
return;

View File

@@ -146,6 +146,7 @@ typedef struct
unsigned maxnum;
unsigned memcpy;
unsigned memset;
unsigned memmove;
unsigned minimum;
unsigned minnum;
unsigned nearbyint;

View File

@@ -304,6 +304,7 @@ bool sema_expr_analyse_builtin_call(SemaContext *context, Expr *expr)
}
break;
case BUILTIN_MEMCOPY:
case BUILTIN_MEMMOVE:
if (!sema_check_builtin_args(args,
(BuiltinArg[]) { BA_POINTER, BA_POINTER, BA_SIZE, BA_BOOL, BA_SIZE, BA_SIZE },
arg_count)) return false;
@@ -557,6 +558,7 @@ static inline unsigned builtin_expected_args(BuiltinFunction func)
case BUILTIN_MEMSET:
return 5;
case BUILTIN_MEMCOPY:
case BUILTIN_MEMMOVE:
return 6;
case BUILTIN_SHUFFLEVECTOR:
case BUILTIN_NONE:

View File

@@ -199,6 +199,7 @@ void symtab_init(uint32_t capacity)
builtin_list[BUILTIN_LOG10] = KW_DEF("log10");
builtin_list[BUILTIN_MEMCOPY] = KW_DEF("memcpy");
builtin_list[BUILTIN_MEMSET] = KW_DEF("memset");
builtin_list[BUILTIN_MEMMOVE] = KW_DEF("memmove");
builtin_list[BUILTIN_NEARBYINT] = KW_DEF("nearbyint");
builtin_list[BUILTIN_POPCOUNT] = KW_DEF("popcount");
builtin_list[BUILTIN_POW] = KW_DEF("pow");

View File

@@ -0,0 +1,18 @@
// #target: macos-x64
module test;
fn void main()
{
ushort src = 1;
ushort dst = 2;
$$memcpy(&dst, &src, ushort.sizeof, false, $alignof(dst), $alignof(src));
$$memmove(&dst, &src, ushort.sizeof, false, $alignof(dst), $alignof(src));
$$memset(&dst, 0u8, ushort.sizeof, false, $alignof(dst));
}
/* #expect: test.ll
call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 2 %0, i8* align 2 %1, i64 2, i1 false)
call void @llvm.memmove.p0i8.p0i8.i64(i8* align 2 %2, i8* align 2 %3, i64 2, i1 false)
call void @llvm.memset.p0i8.i64(i8* align 2 %4, i8 0, i64 2, i1 false)

View File

@@ -85,7 +85,7 @@ after_check: ; preds = %if.then2
br label %noerr_block
panic_block: ; preds = %assign_optional
call void @std_core_builtin_panic(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.zstr, i64 0, i64 0), i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.zstr.1, i64 0, i64 0), i8* getelementptr inbounds ([21 x i8], [21 x i8]* @.zstr.2, i64 0, i64 0), i32 250)
call void @std_core_builtin_panic(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.zstr, i64 0, i64 0), i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.zstr.1, i64 0, i64 0), i8* getelementptr inbounds ([21 x i8], [21 x i8]* @.zstr.2, i64 0, i64 0), i32 255)
unreachable
noerr_block: ; preds = %after_check
@@ -265,7 +265,7 @@ after_check: ; preds = %if.then
br label %noerr_block
panic_block: ; preds = %assign_optional
call void @std_core_builtin_panic(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.zstr.3, i64 0, i64 0), i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.zstr.4, i64 0, i64 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.zstr.5, i64 0, i64 0), i32 250)
call void @std_core_builtin_panic(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.zstr.3, i64 0, i64 0), i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.zstr.4, i64 0, i64 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.zstr.5, i64 0, i64 0), i32 255)
unreachable
noerr_block: ; preds = %after_check
@@ -515,7 +515,7 @@ after_check86: ; preds = %if.then81
br label %noerr_block88
panic_block87: ; preds = %assign_optional85
call void @std_core_builtin_panic(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.zstr.12, i64 0, i64 0), i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.zstr.13, i64 0, i64 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.zstr.14, i64 0, i64 0), i32 250)
call void @std_core_builtin_panic(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.zstr.12, i64 0, i64 0), i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.zstr.13, i64 0, i64 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.zstr.14, i64 0, i64 0), i32 255)
unreachable
noerr_block88: ; preds = %after_check86
@@ -571,7 +571,7 @@ after_check102: ; preds = %if.then97
br label %noerr_block104
panic_block103: ; preds = %assign_optional101
call void @std_core_builtin_panic(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.zstr.15, i64 0, i64 0), i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.zstr.16, i64 0, i64 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.zstr.17, i64 0, i64 0), i32 250)
call void @std_core_builtin_panic(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.zstr.15, i64 0, i64 0), i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.zstr.16, i64 0, i64 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.zstr.17, i64 0, i64 0), i32 255)
unreachable
noerr_block104: ; preds = %after_check102
@@ -668,7 +668,7 @@ after_check143: ; preds = %if.then138
br label %noerr_block145
panic_block144: ; preds = %assign_optional142
call void @std_core_builtin_panic(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.zstr.21, i64 0, i64 0), i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.zstr.22, i64 0, i64 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.zstr.23, i64 0, i64 0), i32 250)
call void @std_core_builtin_panic(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.zstr.21, i64 0, i64 0), i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.zstr.22, i64 0, i64 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.zstr.23, i64 0, i64 0), i32 255)
unreachable
noerr_block145: ; preds = %after_check143
@@ -728,7 +728,7 @@ after_check166: ; preds = %if.then161
br label %noerr_block168
panic_block167: ; preds = %assign_optional165
call void @std_core_builtin_panic(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.zstr.25, i64 0, i64 0), i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.zstr.26, i64 0, i64 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.zstr.27, i64 0, i64 0), i32 250)
call void @std_core_builtin_panic(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.zstr.25, i64 0, i64 0), i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.zstr.26, i64 0, i64 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.zstr.27, i64 0, i64 0), i32 255)
unreachable
noerr_block168: ; preds = %after_check166
@@ -782,7 +782,7 @@ after_check183: ; preds = %if.then178
br label %noerr_block185
panic_block184: ; preds = %assign_optional182
call void @std_core_builtin_panic(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.zstr.28, i64 0, i64 0), i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.zstr.29, i64 0, i64 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.zstr.30, i64 0, i64 0), i32 250)
call void @std_core_builtin_panic(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.zstr.28, i64 0, i64 0), i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.zstr.29, i64 0, i64 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.zstr.30, i64 0, i64 0), i32 255)
unreachable
noerr_block185: ; preds = %after_check183
@@ -816,7 +816,7 @@ after_check193: ; preds = %if.then188
br label %noerr_block195
panic_block194: ; preds = %assign_optional192
call void @std_core_builtin_panic(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.zstr.31, i64 0, i64 0), i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.zstr.32, i64 0, i64 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.zstr.33, i64 0, i64 0), i32 250)
call void @std_core_builtin_panic(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.zstr.31, i64 0, i64 0), i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.zstr.32, i64 0, i64 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.zstr.33, i64 0, i64 0), i32 255)
unreachable
noerr_block195: ; preds = %after_check193
@@ -853,7 +853,7 @@ after_check210: ; preds = %if.then205
br label %noerr_block212
panic_block211: ; preds = %assign_optional209
call void @std_core_builtin_panic(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.zstr.35, i64 0, i64 0), i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.zstr.36, i64 0, i64 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.zstr.37, i64 0, i64 0), i32 250)
call void @std_core_builtin_panic(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.zstr.35, i64 0, i64 0), i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.zstr.36, i64 0, i64 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.zstr.37, i64 0, i64 0), i32 255)
unreachable
noerr_block212: ; preds = %after_check210
@@ -895,3 +895,46 @@ voiderr220: ; preds = %after_check219, %if
call void @std_core_mem_allocator_Allocator_reset(%Allocator* %242, i64 %243)
ret void
}
; Function Attrs: nounwind
define i32 @main(i32 %0, i8** %1) #0 {
entry:
call void @test_main()
ret i32 0
}
; Function Attrs: argmemonly nofree nounwind willreturn writeonly
declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i1 immarg) #1
declare void @"std_map$$int.test_Foo_HashMap_init"(%HashMap.0*, i32, float, %Allocator*)
declare i64 @std_io_printfln(i64*, i8*, i64, i8*, i64)
declare i8 @"std_map$$int.test_Foo_HashMap_set"(%HashMap.0*, i32, i64, i8*)
declare i64 @"std_map$$int.test_Foo_HashMap_get"(%Foo*, %HashMap.0*, i32)
declare i8 @"std_map$$int.test_Foo_HashMap_has_key"(%HashMap.0*, i32)
declare { i8*, i64 } @"std_map$$int.test_Foo_HashMap_value_list"(%HashMap.0*, %Allocator*)
declare void @"std_map$$int.double_HashMap_init"(%HashMap.3*, i32, float, %Allocator*)
declare i8 @"std_map$$int.double_HashMap_set"(%HashMap.3*, i32, double)
declare i8 @"std_map$$int.double_HashMap_has_value"(%HashMap.3*, double)
declare { i8*, i64 } @"std_map$$int.double_HashMap_key_list"(%HashMap.3*, %Allocator*)
declare { i8*, i64 } @"std_map$$int.double_HashMap_value_list"(%HashMap.3*, %Allocator*)
declare void @std_core_mem_allocator_Allocator_reset(%Allocator*, i64)
declare i8* @std_core_string_new_with_capacity(i64, %Allocator*)
declare i64 @std_core_string_String_printf(i64*, i8**, i8*, i64, i8*, i64)
declare { i8*, i64 } @std_core_string_String_str(i8*)
; Function Attrs: argmemonly nofree nounwind willreturn
declare void @llvm.memcpy.p0i8.p0i8.i32(i8* noalias nocapture writeonly, i8* noalias nocapture readonly, i32, i1 immarg) #2

View File

@@ -0,0 +1,18 @@
// #target: macos-x64
module test;
fn void main()
{
ushort src = 1;
ushort dst = 2;
$$memcpy(&dst, &src, ushort.sizeof, false, $alignof(dst), $alignof(src));
$$memmove(&dst, &src, ushort.sizeof, false, $alignof(dst), $alignof(src));
$$memset(&dst, 0u8, ushort.sizeof, false, $alignof(dst));
}
/* #expect: test.ll
call void @llvm.memcpy.p0.p0.i64(ptr align 2 %dst, ptr align 2 %src, i64 2, i1 false)
call void @llvm.memmove.p0.p0.i64(ptr align 2 %dst, ptr align 2 %src, i64 2, i1 false)
call void @llvm.memset.p0.i64(ptr align 2 %dst, i8 0, i64 2, i1 false)

View File

@@ -83,7 +83,7 @@ after_check: ; preds = %if.then2
br label %noerr_block
panic_block: ; preds = %assign_optional
call void @std_core_builtin_panic(ptr @.zstr, ptr @.zstr.1, ptr @.zstr.2, i32 250)
call void @std_core_builtin_panic(ptr @.zstr, ptr @.zstr.1, ptr @.zstr.2, i32 255)
unreachable
noerr_block: ; preds = %after_check
@@ -253,7 +253,7 @@ after_check: ; preds = %if.then
br label %noerr_block
panic_block: ; preds = %assign_optional
call void @std_core_builtin_panic(ptr @.zstr.3, ptr @.zstr.4, ptr @.zstr.5, i32 250)
call void @std_core_builtin_panic(ptr @.zstr.3, ptr @.zstr.4, ptr @.zstr.5, i32 255)
unreachable
noerr_block: ; preds = %after_check
@@ -476,7 +476,7 @@ after_check86: ; preds = %if.then81
br label %noerr_block88
panic_block87: ; preds = %assign_optional85
call void @std_core_builtin_panic(ptr @.zstr.12, ptr @.zstr.13, ptr @.zstr.14, i32 250)
call void @std_core_builtin_panic(ptr @.zstr.12, ptr @.zstr.13, ptr @.zstr.14, i32 255)
unreachable
noerr_block88: ; preds = %after_check86
@@ -526,7 +526,7 @@ after_check101: ; preds = %if.then96
br label %noerr_block103
panic_block102: ; preds = %assign_optional100
call void @std_core_builtin_panic(ptr @.zstr.15, ptr @.zstr.16, ptr @.zstr.17, i32 250)
call void @std_core_builtin_panic(ptr @.zstr.15, ptr @.zstr.16, ptr @.zstr.17, i32 255)
unreachable
noerr_block103: ; preds = %after_check101
@@ -615,7 +615,7 @@ after_check141: ; preds = %if.then136
br label %noerr_block143
panic_block142: ; preds = %assign_optional140
call void @std_core_builtin_panic(ptr @.zstr.21, ptr @.zstr.22, ptr @.zstr.23, i32 250)
call void @std_core_builtin_panic(ptr @.zstr.21, ptr @.zstr.22, ptr @.zstr.23, i32 255)
unreachable
noerr_block143: ; preds = %after_check141
@@ -669,7 +669,7 @@ after_check163: ; preds = %if.then158
br label %noerr_block165
panic_block164: ; preds = %assign_optional162
call void @std_core_builtin_panic(ptr @.zstr.25, ptr @.zstr.26, ptr @.zstr.27, i32 250)
call void @std_core_builtin_panic(ptr @.zstr.25, ptr @.zstr.26, ptr @.zstr.27, i32 255)
unreachable
noerr_block165: ; preds = %after_check163
@@ -718,7 +718,7 @@ after_check179: ; preds = %if.then174
br label %noerr_block181
panic_block180: ; preds = %assign_optional178
call void @std_core_builtin_panic(ptr @.zstr.28, ptr @.zstr.29, ptr @.zstr.30, i32 250)
call void @std_core_builtin_panic(ptr @.zstr.28, ptr @.zstr.29, ptr @.zstr.30, i32 255)
unreachable
noerr_block181: ; preds = %after_check179
@@ -751,7 +751,7 @@ after_check189: ; preds = %if.then184
br label %noerr_block191
panic_block190: ; preds = %assign_optional188
call void @std_core_builtin_panic(ptr @.zstr.31, ptr @.zstr.32, ptr @.zstr.33, i32 250)
call void @std_core_builtin_panic(ptr @.zstr.31, ptr @.zstr.32, ptr @.zstr.33, i32 255)
unreachable
noerr_block191: ; preds = %after_check189
@@ -786,7 +786,7 @@ after_check205: ; preds = %if.then200
br label %noerr_block207
panic_block206: ; preds = %assign_optional204
call void @std_core_builtin_panic(ptr @.zstr.35, ptr @.zstr.36, ptr @.zstr.37, i32 250)
call void @std_core_builtin_panic(ptr @.zstr.35, ptr @.zstr.36, ptr @.zstr.37, i32 255)
unreachable
noerr_block207: ; preds = %after_check205