Merge pull request #17 from zedar/add_support_for_float16_float128
Add support for Float16, Float32, Float64 and Float128
This commit is contained in:
commit
70d36558ee
8
Cargo.lock
generated
8
Cargo.lock
generated
@ -79,16 +79,16 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gccjit"
|
name = "gccjit"
|
||||||
version = "1.0.0"
|
version = "2.0.0"
|
||||||
source = "git+https://github.com/antoyo/gccjit.rs#9f8f67edc006d543b17529a001803ffece48349e"
|
source = "git+https://github.com/antoyo/gccjit.rs#f1545d7c2c13e42d78eaac8032d49ab8f7d43b6e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"gccjit_sys",
|
"gccjit_sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gccjit_sys"
|
name = "gccjit_sys"
|
||||||
version = "0.0.1"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/antoyo/gccjit.rs#9f8f67edc006d543b17529a001803ffece48349e"
|
source = "git+https://github.com/antoyo/gccjit.rs#f1545d7c2c13e42d78eaac8032d49ab8f7d43b6e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
@ -6,7 +6,9 @@ resolver = "2"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
core = { path = "./sysroot_src/library/core" }
|
core = { path = "./sysroot_src/library/core" }
|
||||||
compiler_builtins = "0.1"
|
# TODO: after the sync, revert to using version 0.1.
|
||||||
|
# compiler_builtins = "0.1"
|
||||||
|
compiler_builtins = "=0.1.109"
|
||||||
alloc = { path = "./sysroot_src/library/alloc" }
|
alloc = { path = "./sysroot_src/library/alloc" }
|
||||||
std = { path = "./sysroot_src/library/std", features = ["panic_unwind", "backtrace"] }
|
std = { path = "./sysroot_src/library/std", features = ["panic_unwind", "backtrace"] }
|
||||||
test = { path = "./sysroot_src/library/test" }
|
test = { path = "./sysroot_src/library/test" }
|
||||||
|
@ -1 +1 @@
|
|||||||
b6f163f52
|
d61ce945badf4c9d8237a13ca135e3c46ad13be3
|
||||||
|
21
src/base.rs
21
src/base.rs
@ -2,7 +2,7 @@
|
|||||||
use std::env;
|
use std::env;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
use gccjit::{FunctionType, GlobalKind};
|
use gccjit::{CType, FunctionType, GlobalKind};
|
||||||
use rustc_codegen_ssa::base::maybe_create_entry_wrapper;
|
use rustc_codegen_ssa::base::maybe_create_entry_wrapper;
|
||||||
use rustc_codegen_ssa::mono_item::MonoItemExt;
|
use rustc_codegen_ssa::mono_item::MonoItemExt;
|
||||||
use rustc_codegen_ssa::traits::DebugInfoMethods;
|
use rustc_codegen_ssa::traits::DebugInfoMethods;
|
||||||
@ -181,7 +181,24 @@ fn module_codegen(
|
|||||||
context.set_allow_unreachable_blocks(true);
|
context.set_allow_unreachable_blocks(true);
|
||||||
|
|
||||||
{
|
{
|
||||||
let cx = CodegenCx::new(&context, cgu, tcx, target_info.supports_128bit_int());
|
// TODO: to make it less error-prone (calling get_target_info() will add the flag
|
||||||
|
// -fsyntax-only), forbid the compilation when get_target_info() is called on a
|
||||||
|
// context.
|
||||||
|
let f16_type_supported = target_info.supports_target_dependent_type(CType::Float16);
|
||||||
|
let f32_type_supported = target_info.supports_target_dependent_type(CType::Float32);
|
||||||
|
let f64_type_supported = target_info.supports_target_dependent_type(CType::Float64);
|
||||||
|
let f128_type_supported = target_info.supports_target_dependent_type(CType::Float128);
|
||||||
|
// TODO: improve this to avoid passing that many arguments.
|
||||||
|
let cx = CodegenCx::new(
|
||||||
|
&context,
|
||||||
|
cgu,
|
||||||
|
tcx,
|
||||||
|
target_info.supports_128bit_int(),
|
||||||
|
f16_type_supported,
|
||||||
|
f32_type_supported,
|
||||||
|
f64_type_supported,
|
||||||
|
f128_type_supported,
|
||||||
|
);
|
||||||
|
|
||||||
let mono_items = cgu.items_in_deterministic_order(tcx);
|
let mono_items = cgu.items_in_deterministic_order(tcx);
|
||||||
for &(mono_item, data) in &mono_items {
|
for &(mono_item, data) in &mono_items {
|
||||||
|
@ -748,6 +748,24 @@ fn frem(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
|
|||||||
// FIXME(antoyo): this seems to produce the wrong result.
|
// FIXME(antoyo): this seems to produce the wrong result.
|
||||||
return self.context.new_call(self.location, fmodf, &[a, b]);
|
return self.context.new_call(self.location, fmodf, &[a, b]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "master")]
|
||||||
|
match self.cx.type_kind(a_type) {
|
||||||
|
TypeKind::Half | TypeKind::Float => {
|
||||||
|
let fmodf = self.context.get_builtin_function("fmodf");
|
||||||
|
return self.context.new_call(self.location, fmodf, &[a, b]);
|
||||||
|
}
|
||||||
|
TypeKind::Double => {
|
||||||
|
let fmod = self.context.get_builtin_function("fmod");
|
||||||
|
return self.context.new_call(self.location, fmod, &[a, b]);
|
||||||
|
}
|
||||||
|
TypeKind::FP128 => {
|
||||||
|
let fmodl = self.context.get_builtin_function("fmodl");
|
||||||
|
return self.context.new_call(self.location, fmodl, &[a, b]);
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(vector_type) = a_type_unqualified.dyncast_vector() {
|
if let Some(vector_type) = a_type_unqualified.dyncast_vector() {
|
||||||
assert_eq!(a_type_unqualified, b.get_type().unqualified());
|
assert_eq!(a_type_unqualified, b.get_type().unqualified());
|
||||||
|
|
||||||
|
@ -68,6 +68,10 @@ pub struct CodegenCx<'gcc, 'tcx> {
|
|||||||
pub sizet_type: Type<'gcc>,
|
pub sizet_type: Type<'gcc>,
|
||||||
|
|
||||||
pub supports_128bit_integers: bool,
|
pub supports_128bit_integers: bool,
|
||||||
|
pub supports_f16_type: bool,
|
||||||
|
pub supports_f32_type: bool,
|
||||||
|
pub supports_f64_type: bool,
|
||||||
|
pub supports_f128_type: bool,
|
||||||
|
|
||||||
pub float_type: Type<'gcc>,
|
pub float_type: Type<'gcc>,
|
||||||
pub double_type: Type<'gcc>,
|
pub double_type: Type<'gcc>,
|
||||||
@ -125,11 +129,16 @@ pub struct CodegenCx<'gcc, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
context: &'gcc Context<'gcc>,
|
context: &'gcc Context<'gcc>,
|
||||||
codegen_unit: &'tcx CodegenUnit<'tcx>,
|
codegen_unit: &'tcx CodegenUnit<'tcx>,
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
supports_128bit_integers: bool,
|
supports_128bit_integers: bool,
|
||||||
|
supports_f16_type: bool,
|
||||||
|
supports_f32_type: bool,
|
||||||
|
supports_f64_type: bool,
|
||||||
|
supports_f128_type: bool,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let check_overflow = tcx.sess.overflow_checks();
|
let check_overflow = tcx.sess.overflow_checks();
|
||||||
|
|
||||||
@ -305,6 +314,10 @@ pub fn new(
|
|||||||
sizet_type,
|
sizet_type,
|
||||||
|
|
||||||
supports_128bit_integers,
|
supports_128bit_integers,
|
||||||
|
supports_f16_type,
|
||||||
|
supports_f32_type,
|
||||||
|
supports_f64_type,
|
||||||
|
supports_f128_type,
|
||||||
|
|
||||||
float_type,
|
float_type,
|
||||||
double_type,
|
double_type,
|
||||||
|
12
src/lib.rs
12
src/lib.rs
@ -89,7 +89,6 @@
|
|||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
use errors::LTONotSupported;
|
use errors::LTONotSupported;
|
||||||
#[cfg(not(feature = "master"))]
|
|
||||||
use gccjit::CType;
|
use gccjit::CType;
|
||||||
use gccjit::{Context, OptimizationLevel};
|
use gccjit::{Context, OptimizationLevel};
|
||||||
#[cfg(feature = "master")]
|
#[cfg(feature = "master")]
|
||||||
@ -147,6 +146,10 @@ fn cpu_supports(&self, _feature: &str) -> bool {
|
|||||||
fn supports_128bit_int(&self) -> bool {
|
fn supports_128bit_int(&self) -> bool {
|
||||||
self.supports_128bit_integers.load(Ordering::SeqCst)
|
self.supports_128bit_integers.load(Ordering::SeqCst)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn supports_target_dependent_type(&self, _typ: CType) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -168,6 +171,10 @@ fn cpu_supports(&self, feature: &str) -> bool {
|
|||||||
fn supports_128bit_int(&self) -> bool {
|
fn supports_128bit_int(&self) -> bool {
|
||||||
self.info.lock().expect("lock").supports_128bit_int()
|
self.info.lock().expect("lock").supports_128bit_int()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn supports_target_dependent_type(&self, typ: CType) -> bool {
|
||||||
|
self.info.lock().expect("lock").supports_target_dependent_type(typ)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -438,7 +445,8 @@ fn run_link(
|
|||||||
pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> {
|
pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> {
|
||||||
#[cfg(feature = "master")]
|
#[cfg(feature = "master")]
|
||||||
let info = {
|
let info = {
|
||||||
// Check whether the target supports 128-bit integers.
|
// Check whether the target supports 128-bit integers, and sized floating point types (like
|
||||||
|
// Float16).
|
||||||
let context = Context::default();
|
let context = Context::default();
|
||||||
Arc::new(Mutex::new(IntoDynSyncSend(context.get_target_info())))
|
Arc::new(Mutex::new(IntoDynSyncSend(context.get_target_info())))
|
||||||
};
|
};
|
||||||
|
70
src/type_.rs
70
src/type_.rs
@ -1,3 +1,8 @@
|
|||||||
|
#[cfg(feature = "master")]
|
||||||
|
use std::convert::TryInto;
|
||||||
|
|
||||||
|
#[cfg(feature = "master")]
|
||||||
|
use gccjit::CType;
|
||||||
use gccjit::{RValue, Struct, Type};
|
use gccjit::{RValue, Struct, Type};
|
||||||
use rustc_codegen_ssa::common::TypeKind;
|
use rustc_codegen_ssa::common::TypeKind;
|
||||||
use rustc_codegen_ssa::traits::{BaseTypeMethods, DerivedTypeMethods, TypeMembershipMethods};
|
use rustc_codegen_ssa::traits::{BaseTypeMethods, DerivedTypeMethods, TypeMembershipMethods};
|
||||||
@ -121,19 +126,35 @@ fn type_isize(&self) -> Type<'gcc> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn type_f16(&self) -> Type<'gcc> {
|
fn type_f16(&self) -> Type<'gcc> {
|
||||||
unimplemented!("f16_f128")
|
#[cfg(feature = "master")]
|
||||||
|
if self.supports_f16_type {
|
||||||
|
return self.context.new_c_type(CType::Float16);
|
||||||
|
}
|
||||||
|
bug!("unsupported float width 16")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn type_f32(&self) -> Type<'gcc> {
|
fn type_f32(&self) -> Type<'gcc> {
|
||||||
|
#[cfg(feature = "master")]
|
||||||
|
if self.supports_f32_type {
|
||||||
|
return self.context.new_c_type(CType::Float32);
|
||||||
|
}
|
||||||
self.float_type
|
self.float_type
|
||||||
}
|
}
|
||||||
|
|
||||||
fn type_f64(&self) -> Type<'gcc> {
|
fn type_f64(&self) -> Type<'gcc> {
|
||||||
|
#[cfg(feature = "master")]
|
||||||
|
if self.supports_f64_type {
|
||||||
|
return self.context.new_c_type(CType::Float64);
|
||||||
|
}
|
||||||
self.double_type
|
self.double_type
|
||||||
}
|
}
|
||||||
|
|
||||||
fn type_f128(&self) -> Type<'gcc> {
|
fn type_f128(&self) -> Type<'gcc> {
|
||||||
unimplemented!("f16_f128")
|
#[cfg(feature = "master")]
|
||||||
|
if self.supports_f128_type {
|
||||||
|
return self.context.new_c_type(CType::Float128);
|
||||||
|
}
|
||||||
|
bug!("unsupported float width 128")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn type_func(&self, params: &[Type<'gcc>], return_type: Type<'gcc>) -> Type<'gcc> {
|
fn type_func(&self, params: &[Type<'gcc>], return_type: Type<'gcc>) -> Type<'gcc> {
|
||||||
@ -161,6 +182,41 @@ fn type_struct(&self, fields: &[Type<'gcc>], packed: bool) -> Type<'gcc> {
|
|||||||
typ
|
typ
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "master")]
|
||||||
|
fn type_kind(&self, typ: Type<'gcc>) -> TypeKind {
|
||||||
|
if self.is_int_type_or_bool(typ) {
|
||||||
|
TypeKind::Integer
|
||||||
|
} else if typ.get_pointee().is_some() {
|
||||||
|
TypeKind::Pointer
|
||||||
|
} else if typ.is_vector() {
|
||||||
|
TypeKind::Vector
|
||||||
|
} else if typ.dyncast_array().is_some() {
|
||||||
|
TypeKind::Array
|
||||||
|
} else if typ.is_struct().is_some() {
|
||||||
|
TypeKind::Struct
|
||||||
|
} else if typ.dyncast_function_ptr_type().is_some() {
|
||||||
|
TypeKind::Function
|
||||||
|
} else if typ.is_compatible_with(self.float_type) {
|
||||||
|
TypeKind::Float
|
||||||
|
} else if typ.is_compatible_with(self.double_type) {
|
||||||
|
TypeKind::Double
|
||||||
|
} else if typ.is_floating_point() {
|
||||||
|
match typ.get_size() {
|
||||||
|
2 => TypeKind::Half,
|
||||||
|
4 => TypeKind::Float,
|
||||||
|
8 => TypeKind::Double,
|
||||||
|
16 => TypeKind::FP128,
|
||||||
|
size => unreachable!("Floating-point type of size {}", size),
|
||||||
|
}
|
||||||
|
} else if typ == self.type_void() {
|
||||||
|
TypeKind::Void
|
||||||
|
} else {
|
||||||
|
// TODO(antoyo): support other types.
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "master"))]
|
||||||
fn type_kind(&self, typ: Type<'gcc>) -> TypeKind {
|
fn type_kind(&self, typ: Type<'gcc>) -> TypeKind {
|
||||||
if self.is_int_type_or_bool(typ) {
|
if self.is_int_type_or_bool(typ) {
|
||||||
TypeKind::Integer
|
TypeKind::Integer
|
||||||
@ -210,6 +266,16 @@ fn vector_length(&self, _ty: Type<'gcc>) -> usize {
|
|||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "master")]
|
||||||
|
fn float_width(&self, typ: Type<'gcc>) -> usize {
|
||||||
|
if typ.is_floating_point() {
|
||||||
|
(typ.get_size() * u8::BITS).try_into().unwrap()
|
||||||
|
} else {
|
||||||
|
panic!("Cannot get width of float type {:?}", typ);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "master"))]
|
||||||
fn float_width(&self, typ: Type<'gcc>) -> usize {
|
fn float_width(&self, typ: Type<'gcc>) -> usize {
|
||||||
let f32 = self.context.new_type::<f32>();
|
let f32 = self.context.new_type::<f32>();
|
||||||
let f64 = self.context.new_type::<f64>();
|
let f64 = self.context.new_type::<f64>();
|
||||||
|
Loading…
Reference in New Issue
Block a user