Merge pull request #17 from zedar/add_support_for_float16_float128

Add support for Float16, Float32, Float64 and Float128
This commit is contained in:
antoyo 2024-06-25 09:33:02 -04:00 committed by GitHub
commit 70d36558ee
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 136 additions and 12 deletions

8
Cargo.lock generated
View File

@ -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",
] ]

View File

@ -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" }

View File

@ -1 +1 @@
b6f163f52 d61ce945badf4c9d8237a13ca135e3c46ad13be3

View File

@ -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 {

View File

@ -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());

View File

@ -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,

View File

@ -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())))
}; };

View File

@ -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>();