Skip to content

Commit 27a9590

Browse files
committed
Add f16/f128 +/-/*///% support
1 parent 87c425b commit 27a9590

File tree

6 files changed

+135
-7
lines changed

6 files changed

+135
-7
lines changed

build_system/build_backend.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ pub(crate) fn build_backend(
1818
let mut cmd = CG_CLIF.build(&bootstrap_host_compiler, dirs);
1919

2020
let mut rustflags = rustflags_from_env("RUSTFLAGS");
21-
rustflags.push("-Zallow-features=rustc_private".to_owned());
21+
rustflags.push("-Zallow-features=rustc_private,f16,f128".to_owned());
2222
rustflags_to_cmd_env(&mut cmd, "RUSTFLAGS", &rustflags);
2323

2424
if env::var("CG_CLIF_EXPENSIVE_CHECKS").is_ok() {

src/base.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
1515

1616
use crate::constant::ConstantCx;
1717
use crate::debuginfo::{FunctionDebugContext, TypeDebugContext};
18-
use crate::enable_verifier;
1918
use crate::prelude::*;
2019
use crate::pretty_clif::CommentWriter;
20+
use crate::{codegen_f16_f128, enable_verifier};
2121

2222
pub(crate) struct CodegenedFunction {
2323
symbol_name: String,
@@ -635,6 +635,15 @@ fn codegen_stmt<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, cur_block: Block, stmt:
635635
let val = operand.load_scalar(fx);
636636
match layout.ty.kind() {
637637
ty::Int(_) => CValue::by_val(fx.bcx.ins().ineg(val), layout),
638+
// FIXME(bytecodealliance/wasmtime#8312): Remove
639+
// once backend lowerings have been added to
640+
// Cranelift.
641+
ty::Float(FloatTy::F16) => {
642+
CValue::by_val(codegen_f16_f128::neg_f16(fx, val), layout)
643+
}
644+
ty::Float(FloatTy::F128) => {
645+
CValue::by_val(codegen_f16_f128::neg_f128(fx, val), layout)
646+
}
638647
ty::Float(_) => CValue::by_val(fx.bcx.ins().fneg(val), layout),
639648
_ => unreachable!("un op Neg for {:?}", layout.ty),
640649
}

src/codegen_f16_f128.rs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
use crate::prelude::*;
2+
3+
pub(crate) fn f16_to_f32(fx: &mut FunctionCx<'_, '_, '_>, value: Value) -> Value {
4+
let (value, arg_ty) =
5+
if fx.tcx.sess.target.vendor == "apple" && fx.tcx.sess.target.arch == "x86_64" {
6+
(
7+
fx.bcx.ins().bitcast(types::I16, MemFlags::new(), value),
8+
lib_call_arg_param(fx.tcx, types::I16, false),
9+
)
10+
} else {
11+
(value, AbiParam::new(types::F16))
12+
};
13+
fx.lib_call("__extendhfsf2", vec![arg_ty], vec![AbiParam::new(types::F32)], &[value])[0]
14+
}
15+
16+
pub(crate) fn f32_to_f16(fx: &mut FunctionCx<'_, '_, '_>, value: Value) -> Value {
17+
let ret_ty = if fx.tcx.sess.target.vendor == "apple" && fx.tcx.sess.target.arch == "x86_64" {
18+
types::I16
19+
} else {
20+
types::F16
21+
};
22+
let ret = fx.lib_call(
23+
"__truncsfhf2",
24+
vec![AbiParam::new(types::F32)],
25+
vec![AbiParam::new(ret_ty)],
26+
&[value],
27+
)[0];
28+
if ret_ty == types::I16 { fx.bcx.ins().bitcast(types::F16, MemFlags::new(), ret) } else { ret }
29+
}
30+
31+
pub(crate) fn codegen_f128_binop(
32+
fx: &mut FunctionCx<'_, '_, '_>,
33+
bin_op: BinOp,
34+
lhs: Value,
35+
rhs: Value,
36+
) -> Value {
37+
let name = match bin_op {
38+
BinOp::Add => "__addtf3",
39+
BinOp::Sub => "__subtf3",
40+
BinOp::Mul => "__multf3",
41+
BinOp::Div => "__divtf3",
42+
_ => unreachable!("handled in `codegen_float_binop`"),
43+
};
44+
fx.lib_call(
45+
name,
46+
vec![AbiParam::new(types::F128), AbiParam::new(types::F128)],
47+
vec![AbiParam::new(types::F128)],
48+
&[lhs, rhs],
49+
)[0]
50+
}
51+
52+
pub(crate) fn neg_f16(fx: &mut FunctionCx<'_, '_, '_>, value: Value) -> Value {
53+
let bits = fx.bcx.ins().bitcast(types::I16, MemFlags::new(), value);
54+
let bits = fx.bcx.ins().bxor_imm(bits, 0x8000);
55+
fx.bcx.ins().bitcast(types::F16, MemFlags::new(), bits)
56+
}
57+
58+
pub(crate) fn neg_f128(fx: &mut FunctionCx<'_, '_, '_>, value: Value) -> Value {
59+
let bits = fx.bcx.ins().bitcast(types::I128, MemFlags::new(), value);
60+
let (low, high) = fx.bcx.ins().isplit(bits);
61+
let high = fx.bcx.ins().bxor_imm(high, 0x8000_0000_0000_0000_u64 as i64);
62+
let bits = fx.bcx.ins().iconcat(low, high);
63+
fx.bcx.ins().bitcast(types::F128, MemFlags::new(), bits)
64+
}

src/compiler_builtins.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,17 @@ builtin_functions! {
5656
fn __fixdfti(f: f64) -> i128;
5757
fn __fixunssfti(f: f32) -> u128;
5858
fn __fixunsdfti(f: f64) -> u128;
59+
// float -> float
60+
fn __extendhfsf2(f: f16) -> f32;
61+
fn __truncsfhf2(f: f32) -> f16;
5962
// float binops
63+
fn __addtf3(a: f128, b: f128) -> f128;
64+
fn __subtf3(a: f128, b: f128) -> f128;
65+
fn __multf3(a: f128, b: f128) -> f128;
66+
fn __divtf3(a: f128, b: f128) -> f128;
6067
fn fmodf(a: f32, b: f32) -> f32;
6168
fn fmod(a: f64, b: f64) -> f64;
69+
fn fmodf128(a: f128, b: f128) -> f128;
6270
// Cranelift float libcalls
6371
fn fmaf(a: f32, b: f32, c: f32) -> f32;
6472
fn fma(a: f64, b: f64, c: f64) -> f64;

src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
#![cfg_attr(doc, feature(rustdoc_internals))]
77
// Note: please avoid adding other feature gates where possible
88
#![feature(rustc_private)]
9+
// Only used to define intrinsics in `compiler_builtins.rs`.
10+
#![feature(f16)]
11+
#![feature(f128)]
912
// Note: please avoid adding other feature gates where possible
1013
#![warn(rust_2018_idioms)]
1114
#![warn(unreachable_pub)]
@@ -57,6 +60,7 @@ mod allocator;
5760
mod analyze;
5861
mod base;
5962
mod cast;
63+
mod codegen_f16_f128;
6064
mod codegen_i128;
6165
mod common;
6266
mod compiler_builtins;

src/num.rs

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! Various operations on integer and floating-point numbers
22
3+
use crate::codegen_f16_f128;
34
use crate::prelude::*;
45

56
fn bin_op_to_intcc(bin_op: BinOp, signed: bool) -> IntCC {
@@ -350,25 +351,60 @@ pub(crate) fn codegen_float_binop<'tcx>(
350351
let lhs = in_lhs.load_scalar(fx);
351352
let rhs = in_rhs.load_scalar(fx);
352353

354+
// FIXME(bytecodealliance/wasmtime#8312): Remove once backend lowerings have
355+
// been added to Cranelift.
356+
let (lhs, rhs) = if *in_lhs.layout().ty.kind() == ty::Float(FloatTy::F16) {
357+
(codegen_f16_f128::f16_to_f32(fx, lhs), codegen_f16_f128::f16_to_f32(fx, rhs))
358+
} else {
359+
(lhs, rhs)
360+
};
353361
let b = fx.bcx.ins();
354362
let res = match bin_op {
363+
// FIXME(bytecodealliance/wasmtime#8312): Remove once backend lowerings
364+
// have been added to Cranelift.
365+
BinOp::Add | BinOp::Sub | BinOp::Mul | BinOp::Div
366+
if *in_lhs.layout().ty.kind() == ty::Float(FloatTy::F128) =>
367+
{
368+
codegen_f16_f128::codegen_f128_binop(fx, bin_op, lhs, rhs)
369+
}
355370
BinOp::Add => b.fadd(lhs, rhs),
356371
BinOp::Sub => b.fsub(lhs, rhs),
357372
BinOp::Mul => b.fmul(lhs, rhs),
358373
BinOp::Div => b.fdiv(lhs, rhs),
359374
BinOp::Rem => {
360-
let (name, ty) = match in_lhs.layout().ty.kind() {
361-
ty::Float(FloatTy::F32) => ("fmodf", types::F32),
362-
ty::Float(FloatTy::F64) => ("fmod", types::F64),
375+
let (name, ty, lhs, rhs) = match in_lhs.layout().ty.kind() {
376+
ty::Float(FloatTy::F16) => (
377+
"fmodf",
378+
types::F32,
379+
// FIXME(bytecodealliance/wasmtime#8312): Already converted
380+
// by the FIXME above.
381+
// fx.bcx.ins().fpromote(types::F32, lhs),
382+
// fx.bcx.ins().fpromote(types::F32, rhs),
383+
lhs,
384+
rhs,
385+
),
386+
ty::Float(FloatTy::F32) => ("fmodf", types::F32, lhs, rhs),
387+
ty::Float(FloatTy::F64) => ("fmod", types::F64, lhs, rhs),
388+
ty::Float(FloatTy::F128) => ("fmodf128", types::F128, lhs, rhs),
363389
_ => bug!(),
364390
};
365391

366-
fx.lib_call(
392+
let ret_val = fx.lib_call(
367393
name,
368394
vec![AbiParam::new(ty), AbiParam::new(ty)],
369395
vec![AbiParam::new(ty)],
370396
&[lhs, rhs],
371-
)[0]
397+
)[0];
398+
399+
let ret_val = if *in_lhs.layout().ty.kind() == ty::Float(FloatTy::F16) {
400+
// FIXME(bytecodealliance/wasmtime#8312): Use native Cranelift
401+
// operation once Cranelift backend lowerings have been
402+
// implemented.
403+
codegen_f16_f128::f32_to_f16(fx, ret_val)
404+
} else {
405+
ret_val
406+
};
407+
return CValue::by_val(ret_val, in_lhs.layout());
372408
}
373409
BinOp::Eq | BinOp::Lt | BinOp::Le | BinOp::Ne | BinOp::Ge | BinOp::Gt => {
374410
let fltcc = match bin_op {
@@ -386,6 +422,13 @@ pub(crate) fn codegen_float_binop<'tcx>(
386422
_ => unreachable!("{:?}({:?}, {:?})", bin_op, in_lhs, in_rhs),
387423
};
388424

425+
// FIXME(bytecodealliance/wasmtime#8312): Remove once backend lowerings have
426+
// been added to Cranelift.
427+
let res = if *in_lhs.layout().ty.kind() == ty::Float(FloatTy::F16) {
428+
codegen_f16_f128::f32_to_f16(fx, res)
429+
} else {
430+
res
431+
};
389432
CValue::by_val(res, in_lhs.layout())
390433
}
391434

0 commit comments

Comments
 (0)