Skip to content
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 @@ -3770,7 +3770,6 @@ dependencies = [
"rustc_data_structures",
"rustc_errors",
"rustc_fs_util",
"rustc_hashes",
"rustc_hir",
"rustc_index",
"rustc_llvm",
Expand Down
157 changes: 61 additions & 96 deletions compiler/rustc_codegen_gcc/src/common.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
use gccjit::{LValue, RValue, ToRValue, Type};
use rustc_abi::Primitive::Pointer;
use rustc_abi::{self as abi, HasDataLayout};
use rustc_codegen_ssa::traits::{
BaseTypeCodegenMethods, ConstCodegenMethods, MiscCodegenMethods, StaticCodegenMethods,
};
use rustc_middle::mir::Mutability;
use rustc_middle::mir::interpret::{GlobalAlloc, PointerArithmetic, Scalar};
use rustc_abi as abi;
use rustc_abi::HasDataLayout;
use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, ConstCodegenMethods};
use rustc_middle::mir::interpret::ConstAllocation;
use rustc_middle::ty::layout::LayoutOf;

use crate::consts::const_alloc_to_gcc;
Expand Down Expand Up @@ -114,7 +111,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,99 +226,67 @@ 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));
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.
// FIXME(antoyo): perhaps only use bitcast for pointers?
self.context.new_cast(None, value, ty)
} else {
// FIXME(bjorn3): assert size is correct
self.const_bitcast(value, ty)
}
}
Scalar::Ptr(ptr, _size) => {
let (prov, offset) = ptr.prov_and_relative_offset();
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 {
let val = alloc.inner().align.bytes().wrapping_add(offset.bytes());
let val = self.const_usize(self.tcx.truncate_to_target_usize(val));
return if matches!(layout.primitive(), Pointer(_)) {
self.context.new_cast(None, val, ty)
} else {
self.const_bitcast(val, ty)
};
}

let value = match alloc.inner().mutability {
Mutability::Mut => self.static_addr_of_mut(
const_alloc_to_gcc(self, alloc),
alloc.inner().align,
None,
),
_ => self.static_addr_of(alloc, None),
};
if !self.sess().fewer_names() {
// FIXME(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();
self.static_addr_of(alloc, None)
}
GlobalAlloc::TypeId { .. } => {
let val = self.const_usize(offset.bytes());
// This is still a variable of pointer type, even though we only use the provenance
// of that pointer in CTFE and Miri. But to make LLVM's type system happy,
// we need an int-to-ptr cast here (it doesn't matter at all which provenance that picks).
return self.context.new_cast(None, val, ty);
}
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_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(&self, alloc: ConstAllocation<'_>, kind: Option<&str>) -> RValue<'gcc> {
let cv = const_alloc_to_gcc(self, alloc);
let align = alloc.inner().align;

if alloc.inner().mutability.is_not()
&& 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;
if alignment > global_variable.get_alignment() {
global_variable.set_alignment(alignment);
}
}
return *variable;
}
let global_value = match kind {
Some(kind) if !self.tcx.sess.fewer_names() => {
let name = self.generate_local_symbol_name(kind);
// FIXME(antoyo): check if it's okay that no link_section is set.

let typ = self.val_ty(cv).get_aligned(align.bytes());
self.declare_private_global(&name[..], typ)
}
_ => {
let typ = self.val_ty(cv).get_aligned(align.bytes());
self.declare_unnamed_global(typ)
}
};
global_value.global_set_initializer_rvalue(cv);
// FIXME(antoyo): set unnamed address.
let rvalue = global_value.get_address(None);
self.global_lvalues.borrow_mut().insert(rvalue, global_value);
if alloc.inner().mutability.is_not() {
#[cfg(feature = "master")]
self.global_lvalues
.borrow()
.get(&rvalue)
.expect("`static_addr_of_mut` did not add the global to `self.global_lvalues`")
.global_set_readonly();
self.const_globals.borrow_mut().insert(cv, rvalue);
}
rvalue
}
}

pub trait SignType<'gcc, 'tcx> {
Expand Down
57 changes: 7 additions & 50 deletions compiler/rustc_codegen_gcc/src/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,30 +56,6 @@ fn set_global_alignment<'gcc, 'tcx>(
}

impl<'gcc, 'tcx> StaticCodegenMethods for CodegenCx<'gcc, 'tcx> {
fn static_addr_of(&self, alloc: ConstAllocation<'_>, kind: Option<&str>) -> RValue<'gcc> {
let cv = const_alloc_to_gcc(self, alloc);
let align = alloc.inner().align;

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;
if alignment > global_variable.get_alignment() {
global_variable.set_alignment(alignment);
}
}
return *variable;
}
let global_value = self.static_addr_of_mut(cv, align, kind);
#[cfg(feature = "master")]
self.global_lvalues
.borrow()
.get(&global_value)
.expect("`static_addr_of_mut` did not add the global to `self.global_lvalues`")
.global_set_readonly();
self.const_globals.borrow_mut().insert(cv, global_value);
global_value
}

fn codegen_static(&mut self, def_id: DefId) {
let attrs = self.tcx.codegen_fn_attrs(def_id);

Expand Down Expand Up @@ -175,6 +151,13 @@ impl<'gcc, 'tcx> StaticCodegenMethods for CodegenCx<'gcc, 'tcx> {
self.add_used_global(global.to_rvalue());
}
}

fn set_value_name(&self, _val: Self::Value, _gen_name: impl FnOnce() -> String) {
// FIXME(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 All @@ -189,32 +172,6 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
function.add_attribute(FnAttribute::Used);
}

pub fn static_addr_of_mut(
&self,
cv: RValue<'gcc>,
align: Align,
kind: Option<&str>,
) -> RValue<'gcc> {
let global = match kind {
Some(kind) if !self.tcx.sess.fewer_names() => {
let name = self.generate_local_symbol_name(kind);
// FIXME(antoyo): check if it's okay that no link_section is set.

let typ = self.val_ty(cv).get_aligned(align.bytes());
self.declare_private_global(&name[..], typ)
}
_ => {
let typ = self.val_ty(cv).get_aligned(align.bytes());
self.declare_unnamed_global(typ)
}
};
global.global_set_initializer_rvalue(cv);
// FIXME(antoyo): set unnamed address.
let rvalue = global.get_address(None);
self.global_lvalues.borrow_mut().insert(rvalue, global);
rvalue
}

pub fn get_static(&self, def_id: DefId) -> LValue<'gcc> {
let instance = Instance::mono(self.tcx, def_id);
let DefKind::Static { nested, .. } = self.tcx.def_kind(def_id) else { bug!() };
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, new_array_type};
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 @@ -24,7 +24,6 @@ rustc_codegen_ssa = { path = "../rustc_codegen_ssa" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
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