Skip to content

Move scalar_to_backend to ssa #142960

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3449,7 +3449,6 @@ dependencies = [
"rustc_errors",
"rustc_fluent_macro",
"rustc_fs_util",
"rustc_hashes",
"rustc_hir",
"rustc_index",
"rustc_llvm",
Expand Down
154 changes: 40 additions & 114 deletions compiler/rustc_codegen_gcc/src/common.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
use gccjit::{LValue, RValue, ToRValue, Type};
use rustc_abi as abi;
use rustc_abi::HasDataLayout;
use rustc_abi::Primitive::Pointer;
use rustc_codegen_ssa::traits::{
BaseTypeCodegenMethods, ConstCodegenMethods, MiscCodegenMethods, StaticCodegenMethods,
BaseTypeCodegenMethods, ConstCodegenMethods, StaticCodegenMethods,
};
use rustc_middle::mir::Mutability;
use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc, Scalar};
use rustc_middle::mir::interpret::ConstAllocation;
use rustc_middle::ty::layout::LayoutOf;

use crate::context::CodegenCx;
Expand Down Expand Up @@ -42,6 +40,22 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
// SIMD builtins require a constant value.
self.bitcast_if_needed(value, typ)
}

pub fn const_data_from_alloc(&self, alloc: ConstAllocation<'_>) -> RValue<'gcc> {
// We ignore the alignment for the purpose of deduping RValues
// The alignment is not handled / used in any way by `const_alloc_to_gcc`,
// so it is OK to overwrite it here.
let mut mock_alloc = alloc.inner().clone();
mock_alloc.align = rustc_abi::Align::MAX;
// Check if the rvalue is already in the cache - if so, just return it directly.
if let Some(res) = self.const_cache.borrow().get(&mock_alloc) {
return *res;
}
// Rvalue not in the cache - convert and add it.
let res = crate::consts::const_alloc_to_gcc_uncached(self, alloc);
self.const_cache.borrow_mut().insert(mock_alloc, res);
res
}
}

pub fn bytes_in_context<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, bytes: &[u8]) -> RValue<'gcc> {
Expand Down Expand Up @@ -110,7 +124,7 @@ pub fn type_is_pointer(typ: Type<'_>) -> bool {
typ.get_pointee().is_some()
}

impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> {
impl<'gcc, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
fn const_null(&self, typ: Type<'gcc>) -> RValue<'gcc> {
if type_is_pointer(typ) { self.context.new_null(typ) } else { self.const_int(typ, 0) }
}
Expand Down Expand Up @@ -229,120 +243,32 @@ impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> {
None
}

fn scalar_to_backend(&self, cv: Scalar, layout: abi::Scalar, ty: Type<'gcc>) -> RValue<'gcc> {
let bitsize = if layout.is_bool() { 1 } else { layout.size(self).bits() };
match cv {
Scalar::Int(int) => {
let data = int.to_bits(layout.size(self));

// FIXME(antoyo): there's some issues with using the u128 code that follows, so hard-code
// the paths for floating-point values.
// TODO: Remove this code?
/*if ty == self.float_type {
return self
.context
.new_rvalue_from_double(ty, f32::from_bits(data as u32) as f64);
}
if ty == self.double_type {
return self.context.new_rvalue_from_double(ty, f64::from_bits(data as u64));
}*/

let value = self.const_uint_big(self.type_ix(bitsize), data);
let bytesize = layout.size(self).bytes();
if bitsize > 1 && ty.is_integral() && bytesize as u32 == ty.get_size() {
// NOTE: since the intrinsic _xabort is called with a bitcast, which
// is non-const, but expects a constant, do a normal cast instead of a bitcast.
// FIXME(antoyo): fix bitcast to work in constant contexts.
// TODO(antoyo): perhaps only use bitcast for pointers?
self.context.new_cast(None, value, ty)
} else {
// TODO(bjorn3): assert size is correct
self.const_bitcast(value, ty)
}
}
Scalar::Ptr(ptr, _size) => {
let (prov, offset) = ptr.into_parts(); // we know the `offset` is relative
let alloc_id = prov.alloc_id();
let base_addr = match self.tcx.global_alloc(alloc_id) {
GlobalAlloc::Memory(alloc) => {
// For ZSTs directly codegen an aligned pointer.
// This avoids generating a zero-sized constant value and actually needing a
// real address at runtime.
if alloc.inner().len() == 0 {
assert_eq!(offset.bytes(), 0);
let val = self.const_usize(alloc.inner().align.bytes());
return if matches!(layout.primitive(), Pointer(_)) {
self.context.new_cast(None, val, ty)
} else {
self.const_bitcast(val, ty)
};
}

let init = self.const_data_from_alloc(alloc);
let alloc = alloc.inner();
let value = match alloc.mutability {
Mutability::Mut => self.static_addr_of_mut(init, alloc.align, None),
_ => self.static_addr_of(init, alloc.align, None),
};
if !self.sess().fewer_names() {
// TODO(antoyo): set value name.
}
value
}
GlobalAlloc::Function { instance, .. } => self.get_fn_addr(instance),
GlobalAlloc::VTable(ty, dyn_ty) => {
let alloc = self
.tcx
.global_alloc(self.tcx.vtable_allocation((
ty,
dyn_ty.principal().map(|principal| {
self.tcx.instantiate_bound_regions_with_erased(principal)
}),
)))
.unwrap_memory();
let init = self.const_data_from_alloc(alloc);
self.static_addr_of(init, alloc.inner().align, None)
}
GlobalAlloc::Static(def_id) => {
assert!(self.tcx.is_static(def_id));
self.get_static(def_id).get_address(None)
}
};
let ptr_type = base_addr.get_type();
let base_addr = self.context.new_cast(None, base_addr, self.usize_type);
let offset =
self.context.new_rvalue_from_long(self.usize_type, offset.bytes() as i64);
let ptr = self.context.new_cast(None, base_addr + offset, ptr_type);
if !matches!(layout.primitive(), Pointer(_)) {
self.const_bitcast(ptr.dereference(None).to_rvalue(), ty)
} else {
self.context.new_cast(None, ptr, ty)
}
}
}
}

fn const_data_from_alloc(&self, alloc: ConstAllocation<'_>) -> Self::Value {
// We ignore the alignment for the purpose of deduping RValues
// The alignment is not handled / used in any way by `const_alloc_to_gcc`,
// so it is OK to overwrite it here.
let mut mock_alloc = alloc.inner().clone();
mock_alloc.align = rustc_abi::Align::MAX;
// Check if the rvalue is already in the cache - if so, just return it directly.
if let Some(res) = self.const_cache.borrow().get(&mock_alloc) {
return *res;
}
// Rvalue not in the cache - convert and add it.
let res = crate::consts::const_alloc_to_gcc_uncached(self, alloc);
self.const_cache.borrow_mut().insert(mock_alloc, res);
res
}

fn const_ptr_byte_offset(&self, base_addr: Self::Value, offset: abi::Size) -> Self::Value {
self.context
.new_array_access(None, base_addr, self.const_usize(offset.bytes()))
.get_address(None)
}
fn const_bitcast(&self, val: Self::Value, ty: Self::Type) -> Self::Value {
self.const_bitcast(val, ty)
}
fn const_pointercast(&self, val: Self::Value, ty: Self::Type) -> Self::Value {
self.context.new_cast(None, val, ty)
}
fn const_int_to_ptr(&self, val: Self::Value, ty: Self::Type) -> Self::Value {
self.context.new_cast(None, val, ty)
}
fn const_ptr_to_int(&self, val: Self::Value, ty: Self::Type) -> Self::Value {
self.context.new_cast(None, val, ty)
}

fn static_addr_of_const(&self, alloc: ConstAllocation<'_>, kind: Option<&str>) -> Self::Value {
self.static_addr_of(alloc, kind)
}

fn static_addr_of_mut(&self, alloc: ConstAllocation<'_>, kind: Option<&str>) -> Self::Value {
let cv = self.const_data_from_alloc(alloc);
self.static_addr_of_mut(cv, alloc.inner().align, kind)
}
}

pub trait SignType<'gcc, 'tcx> {
Expand Down
15 changes: 14 additions & 1 deletion compiler/rustc_codegen_gcc/src/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ fn set_global_alignment<'gcc, 'tcx>(
}

impl<'gcc, 'tcx> StaticCodegenMethods for CodegenCx<'gcc, 'tcx> {
fn static_addr_of(&self, cv: RValue<'gcc>, align: Align, kind: Option<&str>) -> RValue<'gcc> {
fn static_addr_of(&self, alloc: ConstAllocation<'_>, kind: Option<&str>) -> RValue<'gcc> {
let align = alloc.inner().align;
let cv = self.const_data_from_alloc(alloc);
if let Some(variable) = self.const_globals.borrow().get(&cv) {
if let Some(global_variable) = self.global_lvalues.borrow().get(variable) {
let alignment = align.bits() as i32;
Expand Down Expand Up @@ -150,6 +152,17 @@ impl<'gcc, 'tcx> StaticCodegenMethods for CodegenCx<'gcc, 'tcx> {
self.add_used_global(global.to_rvalue());
}
}

fn get_value_name(&self, _val: Self::Value) -> &[u8] {
// TODO(antoyo)
&[]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I should really finish to add this API in libgccjit. ^^'

}
fn set_value_name(&self, _val: Self::Value, _name: &[u8]) {
// TODO(antoyo)
}
fn get_static(&self, def_id: DefId) -> Self::Value {
self.get_static(def_id).get_address(None)
}
}

impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
Expand Down
32 changes: 16 additions & 16 deletions compiler/rustc_codegen_gcc/src/type_.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,6 @@ use crate::context::CodegenCx;
use crate::type_of::LayoutGccExt;

impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
pub fn type_ix(&self, num_bits: u64) -> Type<'gcc> {
// gcc only supports 1, 2, 4 or 8-byte integers.
// FIXME(antoyo): this is misleading to use the next power of two as rustc_codegen_ssa
// sometimes use 96-bit numbers and the following code will give an integer of a different
// size.
let bytes = (num_bits / 8).next_power_of_two() as i32;
match bytes {
1 => self.i8_type,
2 => self.i16_type,
4 => self.i32_type,
8 => self.i64_type,
16 => self.i128_type,
_ => panic!("unexpected num_bits: {}", num_bits),
}
}

pub fn type_void(&self) -> Type<'gcc> {
self.context.new_type::<()>()
}
Expand Down Expand Up @@ -148,6 +132,22 @@ impl<'gcc, 'tcx> BaseTypeCodegenMethods for CodegenCx<'gcc, 'tcx> {
self.isize_type
}

fn type_ix(&self, num_bits: u64) -> Type<'gcc> {
// gcc only supports 1, 2, 4 or 8-byte integers.
// FIXME(antoyo): this is misleading to use the next power of two as rustc_codegen_ssa
// sometimes use 96-bit numbers and the following code will give an integer of a different
// size.
let bytes = (num_bits / 8).next_power_of_two() as i32;
match bytes {
1 => self.i8_type,
2 => self.i16_type,
4 => self.i32_type,
8 => self.i64_type,
16 => self.i128_type,
_ => panic!("unexpected num_bits: {}", num_bits),
}
}

fn type_f16(&self) -> Type<'gcc> {
#[cfg(feature = "master")]
if self.supports_f16_type {
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_codegen_llvm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_fs_util = { path = "../rustc_fs_util" }
rustc_hashes = { path = "../rustc_hashes" }
rustc_hir = { path = "../rustc_hir" }
rustc_index = { path = "../rustc_index" }
rustc_llvm = { path = "../rustc_llvm" }
Expand Down
Loading
Loading