aboutsummaryrefslogtreecommitdiff
path: root/src/llvm_backend.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/llvm_backend.cpp')
-rw-r--r--src/llvm_backend.cpp128
1 files changed, 115 insertions, 13 deletions
diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp
index 938d09a38..68d288799 100644
--- a/src/llvm_backend.cpp
+++ b/src/llvm_backend.cpp
@@ -681,6 +681,12 @@ LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
case Basic_f32: return LLVMFloatTypeInContext(ctx);
case Basic_f64: return LLVMDoubleTypeInContext(ctx);
+ case Basic_f32le: return LLVMFloatTypeInContext(ctx);
+ case Basic_f64le: return LLVMDoubleTypeInContext(ctx);
+
+ case Basic_f32be: return LLVMFloatTypeInContext(ctx);
+ case Basic_f64be: return LLVMDoubleTypeInContext(ctx);
+
// Basic_complex32,
case Basic_complex64:
{
@@ -4077,7 +4083,11 @@ lbValue lb_const_bool(lbModule *m, Type *type, bool value) {
}
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);
+ if (is_type_different_to_arch_endianness(type)) {
+ u = gb_endian_swap32(u);
+ }
LLVMValueRef i = LLVMConstInt(LLVMInt32TypeInContext(m->ctx), u, false);
return LLVMConstBitCast(i, lb_type(m, type));
}
@@ -4437,7 +4447,13 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value) {
res.value = lb_const_f32(m, f, type);
return res;
}
- res.value = LLVMConstReal(lb_type(m, original_type), value.value_float);
+ if (is_type_different_to_arch_endianness(type)) {
+ u64 u = bit_cast<u64>(value.value_float);
+ u = gb_endian_swap64(u);
+ res.value = LLVMConstReal(lb_type(m, original_type), bit_cast<f64>(u));
+ } else {
+ res.value = LLVMConstReal(lb_type(m, original_type), value.value_float);
+ }
return res;
case ExactValue_Complex:
{
@@ -4927,6 +4943,16 @@ lbValue lb_emit_unary_arith(lbProcedure *p, TokenKind op, lbValue x, Type *type)
return lb_emit_byte_swap(p, res, type);
}
+ if (op == Token_Sub && is_type_float(type) && is_type_different_to_arch_endianness(type)) {
+ Type *platform_type = integer_endian_type_to_platform_type(type);
+ lbValue v = lb_emit_byte_swap(p, x, platform_type);
+
+ lbValue res = {};
+ res.value = LLVMBuildFNeg(p->builder, v.value, "");
+ res.type = platform_type;
+
+ return lb_emit_byte_swap(p, res, type);
+ }
lbValue res = {};
@@ -5134,6 +5160,16 @@ lbValue lb_emit_arith(lbProcedure *p, TokenKind op, lbValue lhs, lbValue rhs, Ty
return lb_emit_byte_swap(p, res, type);
}
+ if (is_type_float(type) && is_type_different_to_arch_endianness(type)) {
+ Type *platform_type = integer_endian_type_to_platform_type(type);
+ lbValue x = lb_emit_conv(p, lhs, integer_endian_type_to_platform_type(lhs.type));
+ lbValue y = lb_emit_conv(p, rhs, integer_endian_type_to_platform_type(rhs.type));
+
+ lbValue res = lb_emit_arith(p, op, x, y, platform_type);
+
+ return lb_emit_byte_swap(p, res, type);
+ }
+
handle_op:
@@ -5563,6 +5599,31 @@ lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) {
i64 sz = type_size_of(src);
i64 dz = type_size_of(dst);
+
+ if (dz == sz) {
+ if (types_have_same_internal_endian(src, dst)) {
+ lbValue res = {};
+ res.type = t;
+ res.value = value.value;
+ return res;
+ } else {
+ return lb_emit_byte_swap(p, value, t);
+ }
+ }
+
+ 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);
+ lbValue res = {};
+ res = lb_emit_conv(p, value, platform_src_type);
+ res = lb_emit_conv(p, res, platform_dst_type);
+ if (is_type_different_to_arch_endianness(dst)) {
+ res = lb_emit_byte_swap(p, res, t);
+ }
+ return lb_emit_conv(p, res, t);
+ }
+
+
lbValue res = {};
res.type = t;
@@ -7803,7 +7864,6 @@ LLVMValueRef lb_lookup_runtime_procedure(lbModule *m, String const &name) {
lbValue lb_emit_byte_swap(lbProcedure *p, lbValue value, Type *platform_type) {
Type *vt = core_type(value.type);
GB_ASSERT(type_size_of(vt) == type_size_of(platform_type));
- GB_ASSERT(is_type_integer(vt));
// TODO(bill): lb_emit_byte_swap
lbValue res = {};
@@ -7812,17 +7872,29 @@ lbValue lb_emit_byte_swap(lbProcedure *p, lbValue value, Type *platform_type) {
int sz = cast(int)type_size_of(vt);
if (sz > 1) {
- String name = {};
- switch (sz) {
- case 2: name = str_lit("bswap_16"); break;
- case 4: name = str_lit("bswap_32"); break;
- case 8: name = str_lit("bswap_64"); break;
- case 16: name = str_lit("bswap_128"); break;
- default: GB_PANIC("unhandled byteswap size"); break;
- }
- LLVMValueRef fn = lb_lookup_runtime_procedure(p->module, name);
+ if (is_type_float(platform_type)) {
+ String name = {};
+ switch (sz) {
+ case 4: name = str_lit("bswap_f32"); break;
+ case 8: name = str_lit("bswap_f64"); break;
+ default: GB_PANIC("unhandled byteswap size"); break;
+ }
+ LLVMValueRef fn = lb_lookup_runtime_procedure(p->module, name);
+ res.value = LLVMBuildCall(p->builder, fn, &value.value, 1, "");
+ } else {
+ GB_ASSERT(is_type_integer(platform_type));
+ String name = {};
+ switch (sz) {
+ case 2: name = str_lit("bswap_16"); break;
+ case 4: name = str_lit("bswap_32"); break;
+ case 8: name = str_lit("bswap_64"); break;
+ case 16: name = str_lit("bswap_128"); break;
+ default: GB_PANIC("unhandled byteswap size"); break;
+ }
+ LLVMValueRef fn = lb_lookup_runtime_procedure(p->module, name);
- res.value = LLVMBuildCall(p->builder, fn, &value.value, 1, "");
+ res.value = LLVMBuildCall(p->builder, fn, &value.value, 1, "");
+ }
}
return res;
@@ -8248,6 +8320,12 @@ lbValue lb_emit_comp(lbProcedure *p, TokenKind op_kind, lbValue left, lbValue ri
lbValue y = lb_emit_byte_swap(p, right, platform_type);
left = x;
right = y;
+ } else if (is_type_float(t) && is_type_different_to_arch_endianness(t)) {
+ Type *platform_type = integer_endian_type_to_platform_type(t);
+ lbValue x = lb_emit_conv(p, left, platform_type);
+ lbValue y = lb_emit_conv(p, right, platform_type);
+ left = x;
+ right = y;
}
}
@@ -10433,7 +10511,31 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da
// case Basic_f16:
case Basic_f32:
case Basic_f64:
- tag = lb_const_ptr_cast(m, variant_ptr, t_type_info_float_ptr);
+ case Basic_f32le:
+ case Basic_f64le:
+ case Basic_f32be:
+ case Basic_f64be:
+ {
+ tag = lb_const_ptr_cast(m, 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;
+ }
+ lbValue endianness = lb_const_int(m, t_u8, endianness_value);
+
+ LLVMValueRef vals[1] = {
+ endianness.value,
+ };
+
+ lbValue res = {};
+ res.type = type_deref(tag.type);
+ res.value = LLVMConstNamedStruct(lb_type(m, res.type), vals, gb_count_of(vals));
+ lb_emit_store(p, tag, res);
+ }
break;
// case Basic_complex32: