aboutsummaryrefslogtreecommitdiff
path: root/src/ir.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ir.cpp')
-rw-r--r--src/ir.cpp87
1 files changed, 83 insertions, 4 deletions
diff --git a/src/ir.cpp b/src/ir.cpp
index ecf911461..31d4036b1 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -3297,7 +3297,6 @@ irValue *ir_emit_package_call(irProcedure *proc, char const *package_name_, char
}
-
void ir_emit_defer_stmts(irProcedure *proc, irDeferExitKind kind, irBlock *block) {
isize count = proc->defer_stmts.count;
isize i = count;
@@ -4320,8 +4319,18 @@ irValue *ir_emit_arith(irProcedure *proc, TokenKind op, irValue *left, irValue *
goto handle_op;
}
Type *platform_type = integer_endian_type_to_platform_type(type);
- irValue *x = ir_emit_byte_swap(proc, left, integer_endian_type_to_platform_type(t_left));
- irValue *y = ir_emit_byte_swap(proc, right, integer_endian_type_to_platform_type(t_right));
+ irValue *x = ir_emit_conv(proc, left, integer_endian_type_to_platform_type(t_left));
+ irValue *y = ir_emit_conv(proc, right, integer_endian_type_to_platform_type(t_right));
+
+ irValue *res = ir_emit_arith(proc, op, x, y, platform_type);
+
+ return ir_emit_byte_swap(proc, res, type);
+ }
+
+ if (is_type_float(type) && is_type_different_to_arch_endianness(type)) {
+ Type *platform_type = integer_endian_type_to_platform_type(type);
+ irValue *x = ir_emit_conv(proc, left, integer_endian_type_to_platform_type(t_left));
+ irValue *y = ir_emit_conv(proc, right, integer_endian_type_to_platform_type(t_right));
irValue *res = ir_emit_arith(proc, op, x, y, platform_type);
@@ -4748,6 +4757,12 @@ irValue *ir_emit_comp(irProcedure *proc, TokenKind op_kind, irValue *left, irVal
irValue *y = ir_emit_byte_swap(proc, right, platform_type);
return ir_emit(proc, ir_instr_binary_op(proc, op_kind, x, y, t_llvm_bool));
}
+ if (is_type_float(t) && is_type_different_to_arch_endianness(t)) {
+ Type *platform_type = integer_endian_type_to_platform_type(t);
+ irValue *x = ir_emit_byte_swap(proc, left, platform_type);
+ irValue *y = ir_emit_byte_swap(proc, right, platform_type);
+ return ir_emit(proc, ir_instr_binary_op(proc, op_kind, x, y, t_llvm_bool));
+ }
}
return ir_emit(proc, ir_instr_binary_op(proc, op_kind, left, right, t_llvm_bool));
@@ -5269,6 +5284,29 @@ irValue *ir_emit_byte_swap(irProcedure *proc, irValue *value, Type *t) {
return value;
}
GB_ASSERT(type_size_of(vt) == type_size_of(t));
+ if (is_type_float(t)) {
+ i64 sz = type_size_of(t);
+
+ auto args = array_make<irValue *>(ir_allocator(), 1);
+ args[0] = value;
+
+ char const *proc_name = nullptr;
+ switch (sz*8) {
+ case 32: proc_name = "bswap_f32"; break;
+ case 64: proc_name = "bswap_f64"; break;
+ }
+ GB_ASSERT(proc_name != nullptr);
+
+ String name = make_string_c(proc_name);
+
+ AstPackage *p = proc->module->info->runtime_package;
+ Entity *e = scope_lookup_current(p->scope, name);
+ irValue **found = map_get(&proc->module->values, hash_entity(e));
+ GB_ASSERT_MSG(found != nullptr, "%.*s", LIT(name));
+ irValue *gp = *found;
+
+ return ir_emit(proc, ir_instr_call(proc, gp, nullptr, args, t, nullptr, ProcInlining_none));
+ }
return ir_emit(proc, ir_instr_conv(proc, irConv_byteswap, value, vt, t));
}
@@ -5423,13 +5461,34 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) {
// float -> float
if (is_type_float(src) && is_type_float(dst)) {
+ GB_ASSERT(!are_types_identical(src, dst));
gbAllocator a = ir_allocator();
i64 sz = type_size_of(src);
i64 dz = type_size_of(dst);
irConvKind kind = irConv_fptrunc;
+ if (dz == sz) {
+ if (types_have_same_internal_endian(src, dst)) {
+ return ir_emit_transmute(proc, value, t);
+ } else {
+ return ir_emit_byte_swap(proc, value, t);
+ }
+ }
if (dz >= sz) {
kind = irConv_fpext;
}
+ if (is_type_different_to_arch_endianness(src) || is_type_different_to_arch_endianness(dst)) {
+ Type *platform_src_type = integer_endian_type_to_platform_type(src);
+ Type *platform_dst_type = integer_endian_type_to_platform_type(dst);
+ irValue *res = nullptr;
+ res = ir_emit_conv(proc, value, platform_src_type);
+ res = ir_emit_conv(proc, res, platform_dst_type);
+ if (is_type_different_to_arch_endianness(dst)) {
+ res = ir_emit_byte_swap(proc, res, t);
+ }
+ return ir_emit_conv(proc, res, t);
+ }
+
+
return ir_emit(proc, ir_instr_conv(proc, kind, value, src_type, t));
}
@@ -5738,6 +5797,9 @@ irValue *ir_emit_transmute(irProcedure *proc, irValue *value, Type *t) {
irValue *ptr = ir_emit_uintptr_to_ptr(proc, value, t_rawptr);
return ir_emit_bitcast(proc, ptr, dst);
}
+ if (is_type_float(src) && is_type_float(dst)) {
+ return ir_emit_bitcast(proc, value, t);
+ }
if (is_type_integer(src) && (is_type_pointer(dst) || is_type_cstring(dst))) {
Type *vt = core_type(ir_type(value));
@@ -11441,9 +11503,26 @@ void ir_setup_type_info_data(irProcedure *proc) { // NOTE(bill): Setup type_info
// case Basic_f16:
case Basic_f32:
case Basic_f64:
- tag = ir_emit_conv(proc, variant_ptr, t_type_info_float_ptr);
+ case Basic_f32le:
+ case Basic_f64le:
+ case Basic_f32be:
+ case Basic_f64be:
+ {
+ tag = ir_emit_conv(proc, variant_ptr, t_type_info_float_ptr);
+
+ // NOTE(bill): This is matches the runtime layout
+ u8 endianness_value = 0;
+ if (t->Basic.flags & BasicFlag_EndianLittle) {
+ endianness_value = 1;
+ } else if (t->Basic.flags & BasicFlag_EndianBig) {
+ endianness_value = 2;
+ }
+ irValue *endianness = ir_const_u8(endianness_value);
+ ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), endianness);
+ }
break;
+
// case Basic_complex32:
case Basic_complex64:
case Basic_complex128: