authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-03-22 20:59:26-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-03-22 20:59:26-04:00
logc541ac240c3ad17dda964f9de085a5e8f5472c7a
treec3e86f70fafc3c066ca85bb05a3bcb4d4100ee49
parentfe38d8142f713c1089cdc02f787184c48b8350b6

use the llvm API for creating memcpy and memset instructions


5 files changed, 31 insertions(+), 131 deletions(-)

src/all_types.hpp-9
......@@ -1415,8 +1415,6 @@ enum ZigLLVMFnId {
14151415 ZigLLVMFnIdOverflowArithmetic,
14161416 ZigLLVMFnIdFloor,
14171417 ZigLLVMFnIdCeil,
1418 ZigLLVMFnIdMemcpy,
1419 ZigLLVMFnIdMemset,
14201418};
14211419
14221420enum AddSubMul {
......@@ -1443,13 +1441,6 @@ struct ZigLLVMFnKey {
14431441 uint32_t bit_count;
14441442 bool is_signed;
14451443 } overflow_arithmetic;
1446 struct {
1447 uint32_t dest_align;
1448 uint32_t src_align;
1449 } memcpy;
1450 struct {
1451 uint32_t dest_align;
1452 } memset;
14531444 } data;
14541445};
14551446
src/analyze.cpp-9
......@@ -5681,10 +5681,6 @@ uint32_t zig_llvm_fn_key_hash(ZigLLVMFnKey x) {
56815681 return ((uint32_t)(x.data.overflow_arithmetic.bit_count) * 87135777) +
56825682 ((uint32_t)(x.data.overflow_arithmetic.add_sub_mul) * 31640542) +
56835683 ((uint32_t)(x.data.overflow_arithmetic.is_signed) ? 1062315172 : 314955820);
5684 case ZigLLVMFnIdMemcpy:
5685 return x.data.memcpy.dest_align * 2325524557 + x.data.memcpy.src_align * 519976394;
5686 case ZigLLVMFnIdMemset:
5687 return x.data.memset.dest_align * 388171592;
56885684 }
56895685 zig_unreachable();
56905686}
......@@ -5704,11 +5700,6 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) {
57045700 return (a.data.overflow_arithmetic.bit_count == b.data.overflow_arithmetic.bit_count) &&
57055701 (a.data.overflow_arithmetic.add_sub_mul == b.data.overflow_arithmetic.add_sub_mul) &&
57065702 (a.data.overflow_arithmetic.is_signed == b.data.overflow_arithmetic.is_signed);
5707 case ZigLLVMFnIdMemcpy:
5708 return (a.data.memcpy.dest_align == b.data.memcpy.dest_align) &&
5709 (a.data.memcpy.src_align == b.data.memcpy.src_align);
5710 case ZigLLVMFnIdMemset:
5711 return (a.data.memset.dest_align == b.data.memset.dest_align);
57125703 }
57135704 zig_unreachable();
57145705}
src/codegen.cpp+11-113
......@@ -328,9 +328,9 @@ static void addLLVMArgAttr(LLVMValueRef fn_val, unsigned param_index, const char
328328 return addLLVMAttr(fn_val, param_index + 1, attr_name);
329329}
330330
331static void addLLVMArgAttrInt(LLVMValueRef fn_val, unsigned param_index, const char *attr_name, uint64_t attr_val) {
332 return addLLVMAttrInt(fn_val, param_index + 1, attr_name, attr_val);
333}
331//static void addLLVMArgAttrInt(LLVMValueRef fn_val, unsigned param_index, const char *attr_name, uint64_t attr_val) {
332// return addLLVMAttrInt(fn_val, param_index + 1, attr_name, attr_val);
333//}
334334
335335static void addLLVMCallsiteAttr(LLVMValueRef call_instr, unsigned param_index, const char *attr_name) {
336336 unsigned kind_id = LLVMGetEnumAttributeKindForName(attr_name, strlen(attr_name));
......@@ -916,33 +916,6 @@ static void gen_safety_crash(CodeGen *g, PanicMsgId msg_id) {
916916 gen_panic(g, get_panic_msg_ptr_val(g, msg_id), nullptr);
917917}
918918
919static LLVMValueRef get_memcpy_fn_val(CodeGen *g, uint32_t dest_align, uint32_t src_align) {
920 ZigLLVMFnKey key = {};
921 key.id = ZigLLVMFnIdMemcpy;
922 key.data.memcpy.dest_align = dest_align;
923 key.data.memcpy.src_align = src_align;
924
925 auto existing_entry = g->llvm_fn_table.maybe_get(key);
926 if (existing_entry)
927 return existing_entry->value;
928
929 LLVMTypeRef param_types[] = {
930 LLVMPointerType(LLVMInt8Type(), 0),
931 LLVMPointerType(LLVMInt8Type(), 0),
932 LLVMIntType(g->pointer_size_bytes * 8),
933 LLVMInt1Type(),
934 };
935 LLVMTypeRef fn_type = LLVMFunctionType(LLVMVoidType(), param_types, 4, false);
936 Buf *name = buf_sprintf("llvm.memcpy.p0i8.p0i8.i%d", g->pointer_size_bytes * 8);
937 LLVMValueRef fn_val = LLVMAddFunction(g->module, buf_ptr(name), fn_type);
938 addLLVMArgAttrInt(fn_val, 0, "align", dest_align);
939 addLLVMArgAttrInt(fn_val, 1, "align", src_align);
940 assert(LLVMGetIntrinsicID(fn_val));
941
942 g->llvm_fn_table.put(key, fn_val);
943 return fn_val;
944}
945
946919static LLVMValueRef get_coro_destroy_fn_val(CodeGen *g) {
947920 if (g->coro_destroy_fn_val)
948921 return g->coro_destroy_fn_val;
......@@ -1305,15 +1278,7 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) {
13051278 LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, err_name_val, slice_len_index, "");
13061279 LLVMValueRef err_name_len = gen_load_untyped(g, len_field_ptr, 0, false, "");
13071280
1308 LLVMValueRef memcpy_fn_val = get_memcpy_fn_val(g, u8_align_bytes, u8_align_bytes);
1309 LLVMValueRef params[] = {
1310 offset_buf_ptr, // dest pointer
1311 err_name_ptr, // source pointer
1312 err_name_len, // size bytes
1313 LLVMConstNull(LLVMInt1Type()), // is volatile
1314 };
1315
1316 LLVMBuildCall(g->builder, memcpy_fn_val, params, 4, "");
1281 ZigLLVMBuildMemCpy(g->builder, offset_buf_ptr, u8_align_bytes, err_name_ptr, u8_align_bytes, err_name_len, false);
13171282
13181283 LLVMValueRef const_prefix_len = LLVMConstInt(LLVMTypeOf(err_name_len), strlen(unwrap_err_msg_text), false);
13191284 LLVMValueRef full_buf_len = LLVMBuildNUWAdd(g->builder, const_prefix_len, err_name_len, "");
......@@ -1544,19 +1509,8 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, LLVMValueRef ptr, TypeTableEntry
15441509 assert(size_bytes > 0);
15451510 assert(align_bytes > 0);
15461511
1547 LLVMValueRef volatile_bit = ptr_type->data.pointer.is_volatile ?
1548 LLVMConstAllOnes(LLVMInt1Type()) : LLVMConstNull(LLVMInt1Type());
1549
1550 LLVMValueRef memcpy_fn_val = get_memcpy_fn_val(g, align_bytes, align_bytes);
1551
1552 LLVMValueRef params[] = {
1553 dest_ptr, // dest pointer
1554 src_ptr, // source pointer
1555 LLVMConstInt(usize->type_ref, size_bytes, false),
1556 volatile_bit,
1557 };
1558
1559 LLVMBuildCall(g->builder, memcpy_fn_val, params, 4, "");
1512 ZigLLVMBuildMemCpy(g->builder, dest_ptr, align_bytes, src_ptr, align_bytes, LLVMConstInt(usize->type_ref, size_bytes, false),
1513 ptr_type->data.pointer.is_volatile);
15601514 return nullptr;
15611515 }
15621516
......@@ -2496,31 +2450,6 @@ static LLVMValueRef ir_render_bool_not(CodeGen *g, IrExecutable *executable, IrI
24962450 return LLVMBuildICmp(g->builder, LLVMIntEQ, value, zero, "");
24972451}
24982452
2499static LLVMValueRef get_memset_fn_val(CodeGen *g, uint32_t dest_align) {
2500 ZigLLVMFnKey key = {};
2501 key.id = ZigLLVMFnIdMemset;
2502 key.data.memset.dest_align = dest_align;
2503
2504 auto existing_entry = g->llvm_fn_table.maybe_get(key);
2505 if (existing_entry)
2506 return existing_entry->value;
2507
2508 LLVMTypeRef param_types[] = {
2509 LLVMPointerType(LLVMInt8Type(), 0),
2510 LLVMInt8Type(),
2511 LLVMIntType(g->pointer_size_bytes * 8),
2512 LLVMInt1Type(),
2513 };
2514 LLVMTypeRef fn_type = LLVMFunctionType(LLVMVoidType(), param_types, 4, false);
2515 Buf *name = buf_sprintf("llvm.memset.p0i8.i%d", g->pointer_size_bytes * 8);
2516 LLVMValueRef fn_val = LLVMAddFunction(g->module, buf_ptr(name), fn_type);
2517 addLLVMArgAttrInt(fn_val, 0, "align", dest_align);
2518 assert(LLVMGetIntrinsicID(fn_val));
2519
2520 g->llvm_fn_table.put(key, fn_val);
2521 return fn_val;
2522}
2523
25242453static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,
25252454 IrInstructionDeclVar *decl_var_instruction)
25262455{
......@@ -2554,21 +2483,12 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,
25542483
25552484 assert(var->align_bytes > 0);
25562485
2557 LLVMValueRef memset_fn_val = get_memset_fn_val(g, var->align_bytes);
2558
25592486 // memset uninitialized memory to 0xa
25602487 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
25612488 LLVMValueRef fill_char = LLVMConstInt(LLVMInt8Type(), 0xaa, false);
25622489 LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, var->value_ref, ptr_u8, "");
25632490 LLVMValueRef byte_count = LLVMConstInt(usize->type_ref, size_bytes, false);
2564 LLVMValueRef params[] = {
2565 dest_ptr,
2566 fill_char,
2567 byte_count,
2568 LLVMConstNull(LLVMInt1Type()), // is volatile
2569 };
2570
2571 LLVMBuildCall(g->builder, memset_fn_val, params, 4, "");
2491 ZigLLVMBuildMemSet(g->builder, dest_ptr, fill_char, byte_count, var->align_bytes, false);
25722492 }
25732493 }
25742494
......@@ -3415,19 +3335,7 @@ static LLVMValueRef ir_render_memset(CodeGen *g, IrExecutable *executable, IrIns
34153335 TypeTableEntry *ptr_type = instruction->dest_ptr->value.type;
34163336 assert(ptr_type->id == TypeTableEntryIdPointer);
34173337
3418 LLVMValueRef is_volatile = ptr_type->data.pointer.is_volatile ?
3419 LLVMConstAllOnes(LLVMInt1Type()) : LLVMConstNull(LLVMInt1Type());
3420
3421 LLVMValueRef memset_fn_val = get_memset_fn_val(g, ptr_type->data.pointer.alignment);
3422
3423 LLVMValueRef params[] = {
3424 dest_ptr_casted,
3425 char_val,
3426 len_val,
3427 is_volatile,
3428 };
3429
3430 LLVMBuildCall(g->builder, memset_fn_val, params, 4, "");
3338 ZigLLVMBuildMemSet(g->builder, dest_ptr_casted, char_val, len_val, ptr_type->data.pointer.alignment, ptr_type->data.pointer.is_volatile);
34313339 return nullptr;
34323340}
34333341
......@@ -3447,20 +3355,10 @@ static LLVMValueRef ir_render_memcpy(CodeGen *g, IrExecutable *executable, IrIns
34473355 assert(dest_ptr_type->id == TypeTableEntryIdPointer);
34483356 assert(src_ptr_type->id == TypeTableEntryIdPointer);
34493357
3450 LLVMValueRef is_volatile = (dest_ptr_type->data.pointer.is_volatile || src_ptr_type->data.pointer.is_volatile) ?
3451 LLVMConstAllOnes(LLVMInt1Type()) : LLVMConstNull(LLVMInt1Type());
3452
3453 LLVMValueRef memcpy_fn_val = get_memcpy_fn_val(g, dest_ptr_type->data.pointer.alignment,
3454 src_ptr_type->data.pointer.alignment);
3455
3456 LLVMValueRef params[] = {
3457 dest_ptr_casted,
3458 src_ptr_casted,
3459 len_val,
3460 is_volatile,
3461 };
3358 bool is_volatile = (dest_ptr_type->data.pointer.is_volatile || src_ptr_type->data.pointer.is_volatile);
34623359
3463 LLVMBuildCall(g->builder, memcpy_fn_val, params, 4, "");
3360 ZigLLVMBuildMemCpy(g->builder, dest_ptr_casted, dest_ptr_type->data.pointer.alignment,
3361 src_ptr_casted, src_ptr_type->data.pointer.alignment, len_val, is_volatile);
34643362 return nullptr;
34653363}
34663364
src/zig_llvm.cpp+14
......@@ -207,6 +207,20 @@ LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *A
207207 return wrap(unwrap(B)->Insert(call_inst));
208208}
209209
210LLVMValueRef ZigLLVMBuildMemCpy(LLVMBuilderRef B, LLVMValueRef Dst, unsigned DstAlign,
211 LLVMValueRef Src, unsigned SrcAlign, LLVMValueRef Size, bool isVolatile)
212{
213 CallInst *call_inst = unwrap(B)->CreateMemCpy(unwrap(Dst), DstAlign, unwrap(Src), SrcAlign, unwrap(Size), isVolatile);
214 return wrap(call_inst);
215}
216
217LLVMValueRef ZigLLVMBuildMemSet(LLVMBuilderRef B, LLVMValueRef Ptr, LLVMValueRef Val, LLVMValueRef Size,
218 unsigned Align, bool isVolatile)
219{
220 CallInst *call_inst = unwrap(B)->CreateMemSet(unwrap(Ptr), unwrap(Val), unwrap(Size), Align, isVolatile);
221 return wrap(call_inst);
222}
223
210224void ZigLLVMFnSetSubprogram(LLVMValueRef fn, ZigLLVMDISubprogram *subprogram) {
211225 assert( isa<Function>(unwrap(fn)) );
212226 Function *unwrapped_function = reinterpret_cast<Function*>(unwrap(fn));
src/zig_llvm.h+6
......@@ -64,6 +64,12 @@ enum ZigLLVM_FnInline {
6464ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args,
6565 unsigned NumArgs, unsigned CC, enum ZigLLVM_FnInline fn_inline, const char *Name);
6666
67ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMemCpy(LLVMBuilderRef B, LLVMValueRef Dst, unsigned DstAlign,
68 LLVMValueRef Src, unsigned SrcAlign, LLVMValueRef Size, bool isVolatile);
69
70ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMemSet(LLVMBuilderRef B, LLVMValueRef Ptr, LLVMValueRef Val, LLVMValueRef Size,
71 unsigned Align, bool isVolatile);
72
6773ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCmpXchg(LLVMBuilderRef builder, LLVMValueRef ptr, LLVMValueRef cmp,
6874 LLVMValueRef new_val, LLVMAtomicOrdering success_ordering,
6975 LLVMAtomicOrdering failure_ordering);