Implement f16 functionality

This commit is contained in:
gingerBill
2021-04-01 10:06:00 +01:00
parent a00d7cc705
commit 54e6c50769
16 changed files with 499 additions and 76 deletions
+97 -14
View File
@@ -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);