diff options
| author | gingerBill <bill@gingerbill.org> | 2021-04-01 10:06:00 +0100 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2021-04-01 10:06:00 +0100 |
| commit | 54e6c507698bf68b040400783f05686cacaddff1 (patch) | |
| tree | ebe699d8a059f4e76e0a99494823d4cc3e3bcc1d /src/llvm_backend.cpp | |
| parent | a00d7cc705668da8a8b1a6ebd52668b5e9087bb9 (diff) | |
Implement `f16` functionality
Diffstat (limited to 'src/llvm_backend.cpp')
| -rw-r--r-- | src/llvm_backend.cpp | 111 |
1 files changed, 97 insertions, 14 deletions
diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index e8028eece..efa19a3bf 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -961,17 +961,34 @@ LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { case Basic_rune: return LLVMInt32TypeInContext(ctx); - // Basic_f16, + + case Basic_f16: return LLVMHalfTypeInContext(ctx); case Basic_f32: return LLVMFloatTypeInContext(ctx); case Basic_f64: return LLVMDoubleTypeInContext(ctx); + case Basic_f16le: return LLVMHalfTypeInContext(ctx); case Basic_f32le: return LLVMFloatTypeInContext(ctx); case Basic_f64le: return LLVMDoubleTypeInContext(ctx); + case Basic_f16be: return LLVMHalfTypeInContext(ctx); case Basic_f32be: return LLVMFloatTypeInContext(ctx); case Basic_f64be: return LLVMDoubleTypeInContext(ctx); - // Basic_complex32, + case Basic_complex32: + { + char const *name = "..complex32"; + LLVMTypeRef type = LLVMGetTypeByName(m->mod, name); + if (type != nullptr) { + return type; + } + type = LLVMStructCreateNamed(ctx, name); + LLVMTypeRef fields[2] = { + lb_type(m, t_f16), + lb_type(m, t_f16), + }; + LLVMStructSetBody(type, fields, 2, false); + return type; + } case Basic_complex64: { char const *name = "..complex64"; @@ -1003,6 +1020,23 @@ LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { return type; } + case Basic_quaternion64: + { + char const *name = "..quaternion64"; + LLVMTypeRef type = LLVMGetTypeByName(m->mod, name); + if (type != nullptr) { + return type; + } + type = LLVMStructCreateNamed(ctx, name); + LLVMTypeRef fields[4] = { + lb_type(m, t_f16), + lb_type(m, t_f16), + lb_type(m, t_f16), + lb_type(m, t_f16), + }; + LLVMStructSetBody(type, fields, 4, false); + return type; + } case Basic_quaternion128: { char const *name = "..quaternion128"; @@ -1622,7 +1656,8 @@ LLVMMetadataRef lb_debug_type_internal(lbModule *m, Type *type) { case Basic_rune: return lb_debug_type_basic_type(m, str_lit("rune"), 32, LLVMDWARFTypeEncoding_Utf); - // Basic_f16, + + case Basic_f16: return lb_debug_type_basic_type(m, str_lit("f16"), 16, LLVMDWARFTypeEncoding_Float); case Basic_f32: return lb_debug_type_basic_type(m, str_lit("f32"), 32, LLVMDWARFTypeEncoding_Float); case Basic_f64: return lb_debug_type_basic_type(m, str_lit("f64"), 64, LLVMDWARFTypeEncoding_Float); @@ -1642,6 +1677,8 @@ LLVMMetadataRef lb_debug_type_internal(lbModule *m, Type *type) { case Basic_u64le: return lb_debug_type_basic_type(m, str_lit("u64le"), 64, LLVMDWARFTypeEncoding_Unsigned, LLVMDIFlagLittleEndian); case Basic_i128le: return lb_debug_type_basic_type(m, str_lit("i128le"), 128, LLVMDWARFTypeEncoding_Signed, LLVMDIFlagLittleEndian); case Basic_u128le: return lb_debug_type_basic_type(m, str_lit("u128le"), 128, LLVMDWARFTypeEncoding_Unsigned, LLVMDIFlagLittleEndian); + + case Basic_f16le: return lb_debug_type_basic_type(m, str_lit("f16le"), 16, LLVMDWARFTypeEncoding_Float, LLVMDIFlagLittleEndian); case Basic_f32le: return lb_debug_type_basic_type(m, str_lit("f32le"), 32, LLVMDWARFTypeEncoding_Float, LLVMDIFlagLittleEndian); case Basic_f64le: return lb_debug_type_basic_type(m, str_lit("f64le"), 64, LLVMDWARFTypeEncoding_Float, LLVMDIFlagLittleEndian); @@ -1653,10 +1690,18 @@ LLVMMetadataRef lb_debug_type_internal(lbModule *m, Type *type) { case Basic_u64be: return lb_debug_type_basic_type(m, str_lit("u64be"), 64, LLVMDWARFTypeEncoding_Unsigned, LLVMDIFlagBigEndian); case Basic_i128be: return lb_debug_type_basic_type(m, str_lit("i128be"), 128, LLVMDWARFTypeEncoding_Signed, LLVMDIFlagBigEndian); case Basic_u128be: return lb_debug_type_basic_type(m, str_lit("u128be"), 128, LLVMDWARFTypeEncoding_Unsigned, LLVMDIFlagBigEndian); + + case Basic_f16be: return lb_debug_type_basic_type(m, str_lit("f16be"), 16, LLVMDWARFTypeEncoding_Float, LLVMDIFlagLittleEndian); case Basic_f32be: return lb_debug_type_basic_type(m, str_lit("f32be"), 32, LLVMDWARFTypeEncoding_Float, LLVMDIFlagLittleEndian); case Basic_f64be: return lb_debug_type_basic_type(m, str_lit("f64be"), 64, LLVMDWARFTypeEncoding_Float, LLVMDIFlagLittleEndian); - // Basic_complex32, + case Basic_complex32: + { + LLVMMetadataRef elements[2] = {}; + elements[0] = lb_debug_struct_field(m, str_lit("real"), t_f16, 0); + elements[1] = lb_debug_struct_field(m, str_lit("imag"), t_f16, 4); + return lb_debug_basic_struct(m, str_lit("complex32"), 64, 32, elements, gb_count_of(elements)); + } case Basic_complex64: { LLVMMetadataRef elements[2] = {}; @@ -1672,6 +1717,15 @@ LLVMMetadataRef lb_debug_type_internal(lbModule *m, Type *type) { return lb_debug_basic_struct(m, str_lit("complex128"), 128, 64, elements, gb_count_of(elements)); } + case Basic_quaternion64: + { + LLVMMetadataRef elements[4] = {}; + elements[0] = lb_debug_struct_field(m, str_lit("imag"), t_f16, 0); + elements[1] = lb_debug_struct_field(m, str_lit("jmag"), t_f16, 4); + elements[2] = lb_debug_struct_field(m, str_lit("kmag"), t_f16, 8); + elements[3] = lb_debug_struct_field(m, str_lit("real"), t_f16, 12); + return lb_debug_basic_struct(m, str_lit("quaternion64"), 128, 32, elements, gb_count_of(elements)); + } case Basic_quaternion128: { LLVMMetadataRef elements[4] = {}; @@ -5262,6 +5316,17 @@ lbValue lb_const_bool(lbModule *m, Type *type, bool value) { return res; } +LLVMValueRef lb_const_f16(lbModule *m, f32 f, Type *type=t_f16) { + GB_ASSERT(type_size_of(type) == 2); + + u16 u = f32_to_f16(f); + if (is_type_different_to_arch_endianness(type)) { + u = gb_endian_swap16(u); + } + LLVMValueRef i = LLVMConstInt(LLVMInt16TypeInContext(m->ctx), u, false); + return LLVMConstBitCast(i, lb_type(m, type)); +} + LLVMValueRef lb_const_f32(lbModule *m, f32 f, Type *type=t_f32) { GB_ASSERT(type_size_of(type) == 4); u32 u = bit_cast<u32>(f); @@ -5761,11 +5826,6 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc } return res; case ExactValue_Float: - if (type_size_of(type) == 4) { - f32 f = cast(f32)value.value_float; - res.value = lb_const_f32(m, f, type); - return res; - } if (is_type_different_to_arch_endianness(type)) { u64 u = bit_cast<u64>(value.value_float); u = gb_endian_swap64(u); @@ -5778,6 +5838,10 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc { LLVMValueRef values[2] = {}; switch (8*type_size_of(type)) { + case 32: + values[0] = lb_const_f16(m, cast(f32)value.value_complex->real); + values[1] = lb_const_f16(m, cast(f32)value.value_complex->imag); + break; case 64: values[0] = lb_const_f32(m, cast(f32)value.value_complex->real); values[1] = lb_const_f32(m, cast(f32)value.value_complex->imag); @@ -5796,6 +5860,13 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc { LLVMValueRef values[4] = {}; switch (8*type_size_of(type)) { + case 64: + // @QuaternionLayout + values[3] = lb_const_f16(m, cast(f32)value.value_quaternion->real); + values[0] = lb_const_f16(m, cast(f32)value.value_quaternion->imag); + values[1] = lb_const_f16(m, cast(f32)value.value_quaternion->jmag); + values[2] = lb_const_f16(m, cast(f32)value.value_quaternion->kmag); + break; case 128: // @QuaternionLayout values[3] = lb_const_f32(m, cast(f32)value.value_quaternion->real); @@ -7340,9 +7411,10 @@ bool lb_is_type_aggregate(Type *t) { case Basic_any: return true; - // case Basic_complex32: + case Basic_complex32: case Basic_complex64: case Basic_complex128: + case Basic_quaternion64: case Basic_quaternion128: case Basic_quaternion256: return true; @@ -7663,7 +7735,9 @@ lbValue lb_emit_struct_ev(lbProcedure *p, lbValue s, i32 index) { case 1: result_type = t_typeid; break; } break; - case Basic_complex64: case Basic_complex128: + case Basic_complex32: + case Basic_complex64: + case Basic_complex128: { Type *ft = base_complex_elem_type(t); switch (index) { @@ -7672,7 +7746,9 @@ lbValue lb_emit_struct_ev(lbProcedure *p, lbValue s, i32 index) { } break; } - case Basic_quaternion128: case Basic_quaternion256: + case Basic_quaternion64: + case Basic_quaternion128: + case Basic_quaternion256: { Type *ft = base_complex_elem_type(t); switch (index) { @@ -8816,6 +8892,7 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv, auto args = array_make<lbValue>(permanent_allocator(), 1); args[0] = x; switch (sz) { + case 64: return lb_emit_runtime_call(p, "abs_quaternion64", args); case 128: return lb_emit_runtime_call(p, "abs_quaternion128", args); case 256: return lb_emit_runtime_call(p, "abs_quaternion256", args); } @@ -8825,6 +8902,7 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv, auto args = array_make<lbValue>(permanent_allocator(), 1); args[0] = x; switch (sz) { + case 32: return lb_emit_runtime_call(p, "abs_complex32", args); case 64: return lb_emit_runtime_call(p, "abs_complex64", args); case 128: return lb_emit_runtime_call(p, "abs_complex128", args); } @@ -8834,6 +8912,7 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv, auto args = array_make<lbValue>(permanent_allocator(), 1); args[0] = x; switch (sz) { + case 16: return lb_emit_runtime_call(p, "abs_f16", args); case 32: return lb_emit_runtime_call(p, "abs_f32", args); case 64: return lb_emit_runtime_call(p, "abs_f64", args); } @@ -9566,6 +9645,7 @@ lbValue lb_emit_byte_swap(lbProcedure *p, lbValue value, Type *platform_type) { if (is_type_float(platform_type)) { String name = {}; switch (sz) { + case 2: name = str_lit("bswap_f16"); break; case 4: name = str_lit("bswap_f32"); break; case 8: name = str_lit("bswap_f64"); break; default: GB_PANIC("unhandled byteswap size"); break; @@ -12678,11 +12758,13 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da tag = lb_const_ptr_cast(m, variant_ptr, t_type_info_rune_ptr); break; - // case Basic_f16: + case Basic_f16: case Basic_f32: case Basic_f64: + case Basic_f16le: case Basic_f32le: case Basic_f64le: + case Basic_f16be: case Basic_f32be: case Basic_f64be: { @@ -12708,12 +12790,13 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da } break; - // case Basic_complex32: + case Basic_complex32: case Basic_complex64: case Basic_complex128: tag = lb_const_ptr_cast(m, variant_ptr, t_type_info_complex_ptr); break; + case Basic_quaternion64: case Basic_quaternion128: case Basic_quaternion256: tag = lb_const_ptr_cast(m, variant_ptr, t_type_info_quaternion_ptr); |