Support endian specific float on -llvm-api; fix unary - for endian floats

This commit is contained in:
gingerBill
2020-04-11 21:51:43 +01:00
parent 90593fe6ae
commit 5157619eb7
2 changed files with 125 additions and 17 deletions
+10 -4
View File
@@ -4124,6 +4124,13 @@ irValue *ir_emit_unary_arith(irProcedure *proc, TokenKind op, irValue *x, Type *
return ir_emit_byte_swap(proc, res, type); return ir_emit_byte_swap(proc, 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);
irValue *v = ir_emit_byte_swap(proc, x, platform_type);
irValue *res = ir_emit(proc, ir_instr_unary_op(proc, op, v, platform_type));
return ir_emit_byte_swap(proc, res, type);
}
return ir_emit(proc, ir_instr_unary_op(proc, op, x, type)); return ir_emit(proc, ir_instr_unary_op(proc, op, x, type));
} }
@@ -4756,11 +4763,10 @@ irValue *ir_emit_comp(irProcedure *proc, TokenKind op_kind, irValue *left, irVal
irValue *x = ir_emit_byte_swap(proc, left, platform_type); irValue *x = ir_emit_byte_swap(proc, left, platform_type);
irValue *y = ir_emit_byte_swap(proc, right, 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, x, y, t_llvm_bool));
} } else if (is_type_float(t) && is_type_different_to_arch_endianness(t)) {
if (is_type_float(t) && is_type_different_to_arch_endianness(t)) {
Type *platform_type = integer_endian_type_to_platform_type(t); Type *platform_type = integer_endian_type_to_platform_type(t);
irValue *x = ir_emit_byte_swap(proc, left, platform_type); irValue *x = ir_emit_conv(proc, left, platform_type);
irValue *y = ir_emit_byte_swap(proc, right, platform_type); irValue *y = ir_emit_conv(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, x, y, t_llvm_bool));
} }
} }
+115 -13
View File
@@ -681,6 +681,12 @@ LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
case Basic_f32: return LLVMFloatTypeInContext(ctx); case Basic_f32: return LLVMFloatTypeInContext(ctx);
case Basic_f64: return LLVMDoubleTypeInContext(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, // Basic_complex32,
case Basic_complex64: 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) { 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); 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); LLVMValueRef i = LLVMConstInt(LLVMInt32TypeInContext(m->ctx), u, false);
return LLVMConstBitCast(i, lb_type(m, type)); 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); res.value = lb_const_f32(m, f, type);
return res; 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; return res;
case ExactValue_Complex: 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); 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 = {}; 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); 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: handle_op:
@@ -5563,6 +5599,31 @@ lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) {
i64 sz = type_size_of(src); i64 sz = type_size_of(src);
i64 dz = type_size_of(dst); 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 = {}; lbValue res = {};
res.type = t; 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) { lbValue lb_emit_byte_swap(lbProcedure *p, lbValue value, Type *platform_type) {
Type *vt = core_type(value.type); Type *vt = core_type(value.type);
GB_ASSERT(type_size_of(vt) == type_size_of(platform_type)); GB_ASSERT(type_size_of(vt) == type_size_of(platform_type));
GB_ASSERT(is_type_integer(vt));
// TODO(bill): lb_emit_byte_swap // TODO(bill): lb_emit_byte_swap
lbValue res = {}; 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); int sz = cast(int)type_size_of(vt);
if (sz > 1) { if (sz > 1) {
String name = {}; if (is_type_float(platform_type)) {
switch (sz) { String name = {};
case 2: name = str_lit("bswap_16"); break; switch (sz) {
case 4: name = str_lit("bswap_32"); break; case 4: name = str_lit("bswap_f32"); break;
case 8: name = str_lit("bswap_64"); break; case 8: name = str_lit("bswap_f64"); break;
case 16: name = str_lit("bswap_128"); break; default: GB_PANIC("unhandled byteswap size"); break;
default: GB_PANIC("unhandled byteswap size"); break; }
} LLVMValueRef fn = lb_lookup_runtime_procedure(p->module, name);
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; 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); lbValue y = lb_emit_byte_swap(p, right, platform_type);
left = x; left = x;
right = y; 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_f16:
case Basic_f32: case Basic_f32:
case Basic_f64: 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; break;
// case Basic_complex32: // case Basic_complex32: