aboutsummaryrefslogtreecommitdiff
path: root/src/llvm_backend.cpp
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2021-04-01 10:06:00 +0100
committergingerBill <bill@gingerbill.org>2021-04-01 10:06:00 +0100
commit54e6c507698bf68b040400783f05686cacaddff1 (patch)
treeebe699d8a059f4e76e0a99494823d4cc3e3bcc1d /src/llvm_backend.cpp
parenta00d7cc705668da8a8b1a6ebd52668b5e9087bb9 (diff)
Implement `f16` functionality
Diffstat (limited to 'src/llvm_backend.cpp')
-rw-r--r--src/llvm_backend.cpp111
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);