Fix global initialization (#91)

* Make define_global() return a RValue directly
* Return LValue in functions declaring a global variable
* Remove useless cast
* Fix bytes_in_context to use an array rvalue
* Remove global_names which is unused
* Make const_struct create a constant struct
* Correctly initialize global in static_addr_of_mut
* Fix global variable initialization
* Remove workaround for ARGV
This commit is contained in:
antoyo 2021-09-26 12:20:02 -04:00 committed by GitHub
parent 4e7e822f39
commit 64c561dc22
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 93 additions and 283 deletions

38
Cargo.lock generated
View File

@ -25,9 +25,9 @@ checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]]
name = "bitflags"
version = "1.2.1"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "cfg-if"
@ -56,7 +56,7 @@ dependencies = [
[[package]]
name = "gccjit"
version = "1.0.0"
source = "git+https://github.com/antoyo/gccjit.rs#54be27e41fff7b6ab532e2e21a82df50a12b9ad3"
source = "git+https://github.com/antoyo/gccjit.rs#2d4fea7319f80531b2e5d264fca9f1c498a3a62e"
dependencies = [
"gccjit_sys",
]
@ -64,7 +64,7 @@ dependencies = [
[[package]]
name = "gccjit_sys"
version = "0.0.1"
source = "git+https://github.com/antoyo/gccjit.rs#54be27e41fff7b6ab532e2e21a82df50a12b9ad3"
source = "git+https://github.com/antoyo/gccjit.rs#2d4fea7319f80531b2e5d264fca9f1c498a3a62e"
dependencies = [
"libc 0.1.12",
]
@ -85,7 +85,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
dependencies = [
"cfg-if",
"libc 0.2.98",
"libc 0.2.102",
"wasi",
]
@ -101,7 +101,7 @@ version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [
"libc 0.2.98",
"libc 0.2.102",
]
[[package]]
@ -122,7 +122,7 @@ checksum = "96bd995a092cac79868250589869b5a5d656b02a02bd74c8ebdc566dc7203090"
dependencies = [
"fm",
"getopts",
"libc 0.2.98",
"libc 0.2.102",
"num_cpus",
"termcolor",
"threadpool",
@ -138,15 +138,15 @@ checksum = "e32a70cf75e5846d53a673923498228bbec6a8624708a9ea5645f075d6276122"
[[package]]
name = "libc"
version = "0.2.98"
version = "0.2.102"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790"
checksum = "a2a5ac8f984bfcf3a823267e5fde638acc3325f6496633a5da6bb6eb2171e103"
[[package]]
name = "memchr"
version = "2.4.0"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc"
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
[[package]]
name = "num_cpus"
@ -155,7 +155,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
dependencies = [
"hermit-abi",
"libc 0.2.98",
"libc 0.2.102",
]
[[package]]
@ -181,7 +181,7 @@ version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
dependencies = [
"libc 0.2.98",
"libc 0.2.102",
"rand_chacha",
"rand_core",
"rand_hc",
@ -217,9 +217,9 @@ dependencies = [
[[package]]
name = "redox_syscall"
version = "0.2.9"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ab49abadf3f9e1c4bc499e8845e152ad87d2ad2d30371841171169e9d75feee"
checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff"
dependencies = [
"bitflags",
]
@ -284,7 +284,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
dependencies = [
"cfg-if",
"libc 0.2.98",
"libc 0.2.102",
"rand",
"redox_syscall",
"remove_dir_all",
@ -311,9 +311,9 @@ dependencies = [
[[package]]
name = "unicode-width"
version = "0.1.8"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
[[package]]
name = "wait-timeout"
@ -321,7 +321,7 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6"
dependencies = [
"libc 0.2.98",
"libc 0.2.102",
]
[[package]]

View File

@ -1,5 +1,4 @@
use std::env;
use std::sync::Once;
use std::time::Instant;
use gccjit::{
@ -7,7 +6,6 @@ use gccjit::{
FunctionType,
GlobalKind,
};
use rustc_hir::def_id::LOCAL_CRATE;
use rustc_middle::dep_graph;
use rustc_middle::middle::cstore::EncodedMetadata;
use rustc_middle::middle::exported_symbols;
@ -20,7 +18,7 @@ use rustc_codegen_ssa::traits::DebugInfoMethods;
use rustc_session::config::DebugInfo;
use rustc_span::Symbol;
use crate::{GccContext, create_function_calling_initializers};
use crate::GccContext;
use crate::builder::Builder;
use crate::context::CodegenCx;
@ -97,15 +95,6 @@ pub fn compile_codegen_unit<'tcx>(tcx: TyCtxt<'tcx>, cgu_name: Symbol) -> (Modul
{
let cx = CodegenCx::new(&context, cgu, tcx);
static START: Once = Once::new();
START.call_once(|| {
let initializer_name = format!("__gccGlobalCrateInit{}", tcx.crate_name(LOCAL_CRATE));
let func = context.new_function(None, FunctionType::Exported, context.new_type::<()>(), &[], initializer_name, false);
let block = func.new_block("initial");
create_function_calling_initializers(tcx, &context, block);
block.end_with_void_return(None);
});
let mono_items = cgu.items_in_deterministic_order(tcx);
for &(mono_item, (linkage, visibility)) in &mono_items {
mono_item.predefine::<Builder<'_, '_, '_>>(&cx, linkage, visibility);
@ -124,8 +113,6 @@ pub fn compile_codegen_unit<'tcx>(tcx: TyCtxt<'tcx>, cgu_name: Symbol) -> (Modul
if cx.sess().opts.debuginfo != DebugInfo::None {
cx.debuginfo_finalize();
}
cx.global_init_block.end_with_void_return(None);
}
ModuleCodegen {

View File

@ -505,7 +505,6 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
// FIXME(antoyo): rustc_codegen_ssa::mir::intrinsic uses different types for a and b but they
// should be the same.
let typ = a.get_type().to_signed(self);
let a = self.context.new_cast(None, a, typ);
let b = self.context.new_cast(None, b, typ);
a / b
}
@ -1413,7 +1412,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
impl<'a, 'gcc, 'tcx> StaticBuilderMethods for Builder<'a, 'gcc, 'tcx> {
fn get_static(&mut self, def_id: DefId) -> RValue<'gcc> {
// Forward to the `get_static` method of `CodegenCx`
self.cx().get_static(def_id)
self.cx().get_static(def_id).get_address(None)
}
}

View File

@ -20,7 +20,7 @@ pub fn get_fn<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, instance: Instance<'tcx>)
assert!(!instance.substs.needs_infer());
assert!(!instance.substs.has_escaping_bound_vars());
if let Some(&func) = cx.instances.borrow().get(&instance) {
if let Some(&func) = cx.function_instances.borrow().get(&instance) {
return func;
}
@ -72,7 +72,7 @@ pub fn get_fn<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, instance: Instance<'tcx>)
func
};
cx.instances.borrow_mut().insert(instance, func);
cx.function_instances.borrow_mut().insert(instance, func);
func
}

View File

@ -1,6 +1,7 @@
use std::convert::TryFrom;
use std::convert::TryInto;
use gccjit::LValue;
use gccjit::{Block, CType, RValue, Type, ToRValue};
use rustc_codegen_ssa::mir::place::PlaceRef;
use rustc_codegen_ssa::traits::{
@ -10,7 +11,6 @@ use rustc_codegen_ssa::traits::{
MiscMethods,
StaticMethods,
};
use rustc_middle::bug;
use rustc_middle::mir::Mutability;
use rustc_middle::ty::ScalarInt;
use rustc_middle::ty::layout::{TyAndLayout, LayoutOf};
@ -27,28 +27,27 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
bytes_in_context(self, bytes)
}
fn const_cstr(&self, symbol: Symbol, _null_terminated: bool) -> RValue<'gcc> {
fn const_cstr(&self, symbol: Symbol, _null_terminated: bool) -> LValue<'gcc> {
// TODO(antoyo): handle null_terminated.
if let Some(&value) = self.const_cstr_cache.borrow().get(&symbol) {
return value.to_rvalue();
return value;
}
let global = self.global_string(&*symbol.as_str());
self.const_cstr_cache.borrow_mut().insert(symbol, global.dereference(None));
self.const_cstr_cache.borrow_mut().insert(symbol, global);
global
}
fn global_string(&self, string: &str) -> RValue<'gcc> {
fn global_string(&self, string: &str) -> LValue<'gcc> {
// TODO(antoyo): handle non-null-terminated strings.
let string = self.context.new_string_literal(&*string);
let sym = self.generate_local_symbol_name("str");
// NOTE: TLS is always off for a string litteral.
// NOTE: string litterals do not have a link section.
let global = self.define_global(&sym, self.val_ty(string), false, None)
.unwrap_or_else(|| bug!("symbol `{}` is already defined", sym));
self.global_init_block.add_assignment(None, global.dereference(None), string);
global.to_rvalue()
let global = self.declare_private_global(&sym, self.val_ty(string));
global.global_set_initializer_value(string); // TODO: only set if not imported?
global
// TODO(antoyo): set linkage.
}
@ -76,10 +75,13 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
pub fn bytes_in_context<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, bytes: &[u8]) -> RValue<'gcc> {
let context = &cx.context;
let typ = context.new_array_type(None, context.new_type::<u8>(), bytes.len() as i32);
let global = cx.declare_unnamed_global(typ);
global.global_set_initializer(bytes);
global.to_rvalue()
let byte_type = context.new_type::<u8>();
let typ = context.new_array_type(None, byte_type, bytes.len() as i32);
let elements: Vec<_> =
bytes.iter()
.map(|&byte| context.new_rvalue_from_int(byte_type, byte as i32))
.collect();
context.new_rvalue_from_array(None, typ, &elements)
}
pub fn type_is_pointer<'gcc>(typ: Type<'gcc>) -> bool {
@ -180,7 +182,7 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
fn const_str(&self, s: Symbol) -> (RValue<'gcc>, RValue<'gcc>) {
let len = s.as_str().len();
let cs = self.const_ptrcast(self.const_cstr(s, false),
let cs = self.const_ptrcast(self.const_cstr(s, false).get_address(None),
self.type_ptr_to(self.layout_of(self.tcx.types.str_).gcc_type(self, true)),
);
(cs, self.const_usize(len as u64))
@ -191,16 +193,9 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
.map(|value| value.get_type())
.collect();
// TODO(antoyo): cache the type? It's anonymous, so probably not.
let name = fields.iter().map(|typ| format!("{:?}", typ)).collect::<Vec<_>>().join("_");
let typ = self.type_struct(&fields, packed);
let structure = self.global_init_func.new_local(None, typ, &name);
let struct_type = typ.is_struct().expect("struct type");
for (index, value) in values.iter().enumerate() {
let field = struct_type.get_field(index as i32);
let field_lvalue = structure.access_field(None, field);
self.global_init_block.add_assignment(None, field_lvalue, *value);
}
self.lvalue_to_rvalue(structure)
self.context.new_rvalue_from_struct(None, struct_type, values)
}
fn const_to_opt_uint(&self, _v: RValue<'gcc>) -> Option<u64> {
@ -260,19 +255,18 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
},
GlobalAlloc::Static(def_id) => {
assert!(self.tcx.is_static(def_id));
self.get_static(def_id)
self.get_static(def_id).get_address(None)
},
};
let ptr_type = base_addr.get_type();
let base_addr = self.const_bitcast(base_addr, self.usize_type);
let offset = self.context.new_rvalue_from_long(self.usize_type, offset.bytes() as i64);
let ptr = self.const_bitcast(base_addr + offset, ptr_type);
let value = ptr.dereference(None);
if layout.value != Pointer {
self.const_bitcast(value.to_rvalue(), ty)
self.const_bitcast(ptr.dereference(None).to_rvalue(), ty)
}
else {
self.const_bitcast(value.get_address(None), ty)
self.const_bitcast(ptr, ty)
}
}
}

View File

@ -1,4 +1,4 @@
use gccjit::{RValue, Type};
use gccjit::{LValue, RValue, ToRValue, Type};
use rustc_codegen_ssa::traits::{BaseTypeMethods, ConstMethods, DerivedTypeMethods, StaticMethods};
use rustc_hir as hir;
use rustc_hir::Node;
@ -14,7 +14,6 @@ use rustc_target::abi::{self, Align, HasDataLayout, Primitive, Size, WrappingRan
use crate::base;
use crate::context::CodegenCx;
use crate::mangled_std_symbols::{ARGC, ARGV, ARGV_INIT_ARRAY};
use crate::type_of::LayoutGccExt;
impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
@ -45,17 +44,13 @@ impl<'gcc, 'tcx> StaticMethods for CodegenCx<'gcc, 'tcx> {
fn codegen_static(&self, def_id: DefId, is_mutable: bool) {
let attrs = self.tcx.codegen_fn_attrs(def_id);
let instance = Instance::mono(self.tcx, def_id);
let name = &*self.tcx.symbol_name(instance).name;
let (value, alloc) =
let value =
match codegen_static_initializer(&self, def_id) {
Ok(value) => value,
Ok((value, _)) => value,
// Error has already been reported
Err(_) => return,
};
let is_tls = attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL);
let global = self.get_static(def_id);
// boolean SSA values are i1, but they have to be stored in i8 slots,
@ -73,45 +68,16 @@ impl<'gcc, 'tcx> StaticMethods for CodegenCx<'gcc, 'tcx> {
let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all());
let gcc_type = self.layout_of(ty).gcc_type(self, true);
let global =
if val_llty == gcc_type {
global
// TODO(antoyo): set alignment.
let value =
if value.get_type() != gcc_type {
self.context.new_bitcast(None, value, gcc_type)
}
else {
// If we created the global with the wrong type,
// correct the type.
// TODO(antoyo): set value name, linkage and visibility.
let new_global = self.get_or_insert_global(&name, val_llty, is_tls, attrs.link_section);
// To avoid breaking any invariants, we leave around the old
// global for the moment; we'll replace all references to it
// with the new global later. (See base::codegen_backend.)
//self.statics_to_rauw.borrow_mut().push((global, new_global));
new_global
value
};
// TODO(antoyo): set alignment and initializer.
let value = self.rvalue_as_lvalue(value);
let value = value.get_address(None);
let dest_typ = global.get_type();
let value = self.context.new_cast(None, value, dest_typ);
// NOTE: do not init the variables related to argc/argv because it seems we cannot
// overwrite those variables.
// FIXME(antoyo): correctly support global variable initialization.
let skip_init = [
ARGV_INIT_ARRAY,
ARGC,
ARGV,
];
if !skip_init.iter().any(|symbol_name| name.starts_with(symbol_name)) {
// TODO(antoyo): switch to set_initializer when libgccjit supports that.
let memcpy = self.context.get_builtin_function("memcpy");
let dst = self.context.new_cast(None, global, self.type_i8p());
let src = self.context.new_cast(None, value, self.type_ptr_to(self.type_void()));
let size = self.context.new_rvalue_from_long(self.sizet_type, alloc.size().bytes() as i64);
self.global_init_block.add_eval(None, self.context.new_call(None, memcpy, &[dst, src, size]));
}
global.global_set_initializer_value(value);
// As an optimization, all shared statics which do not have interior
// mutability are placed into read-only memory.
@ -175,7 +141,7 @@ impl<'gcc, 'tcx> StaticMethods for CodegenCx<'gcc, 'tcx> {
}
if attrs.flags.contains(CodegenFnAttrFlags::USED) {
self.add_used_global(global);
self.add_used_global(global.to_rvalue());
}
}
@ -191,38 +157,31 @@ impl<'gcc, 'tcx> StaticMethods for CodegenCx<'gcc, 'tcx> {
impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
pub fn static_addr_of_mut(&self, cv: RValue<'gcc>, align: Align, kind: Option<&str>) -> RValue<'gcc> {
let (name, gv) =
let global =
match kind {
Some(kind) if !self.tcx.sess.fewer_names() => {
let name = self.generate_local_symbol_name(kind);
// TODO(antoyo): check if it's okay that TLS is off here.
// TODO(antoyo): check if it's okay that link_section is None here.
// TODO(antoyo): set alignment here as well.
let gv = self.define_global(&name[..], self.val_ty(cv), false, None).unwrap_or_else(|| {
bug!("symbol `{}` is already defined", name);
});
let global = self.define_global(&name[..], self.val_ty(cv), false, None);
// TODO(antoyo): set linkage.
(name, gv)
global
}
_ => {
let index = self.global_gen_sym_counter.get();
let name = format!("global_{}_{}", index, self.codegen_unit.name());
let typ = self.val_ty(cv).get_aligned(align.bytes());
let global = self.define_private_global(typ);
(name, global)
let global = self.declare_unnamed_global(typ);
global
},
};
// FIXME(antoyo): I think the name coming from generate_local_symbol_name() above cannot be used
// globally.
// NOTE: global seems to only be global in a module. So save the name instead of the value
// to import it later.
self.global_names.borrow_mut().insert(cv, name);
self.global_init_block.add_assignment(None, gv.dereference(None), cv);
global.global_set_initializer_value(cv);
// TODO(antoyo): set unnamed address.
gv
global.get_address(None)
}
pub fn get_static(&self, def_id: DefId) -> RValue<'gcc> {
pub fn get_static(&self, def_id: DefId) -> LValue<'gcc> {
let instance = Instance::mono(self.tcx, def_id);
let fn_attrs = self.tcx.codegen_fn_attrs(def_id);
if let Some(&global) = self.instances.borrow().get(&instance) {
@ -380,7 +339,7 @@ pub fn codegen_static_initializer<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, def_id
Ok((const_alloc_to_gcc(cx, alloc), alloc))
}
fn check_and_apply_linkage<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, attrs: &CodegenFnAttrs, ty: Ty<'tcx>, sym: &str, span: Span) -> RValue<'gcc> {
fn check_and_apply_linkage<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, attrs: &CodegenFnAttrs, ty: Ty<'tcx>, sym: &str, span: Span) -> LValue<'gcc> {
let is_tls = attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL);
let llty = cx.layout_of(ty).gcc_type(cx, true);
if let Some(linkage) = attrs.linkage {
@ -410,13 +369,9 @@ fn check_and_apply_linkage<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, attrs: &Codeg
// zero.
let mut real_name = "_rust_extern_with_linkage_".to_string();
real_name.push_str(&sym);
let global2 =
cx.define_global(&real_name, llty, is_tls, attrs.link_section).unwrap_or_else(|| {
cx.sess().span_fatal(span, &format!("symbol `{}` is already defined", &sym))
});
let global2 = cx.define_global(&real_name, llty, is_tls, attrs.link_section);
// TODO(antoyo): set linkage.
let lvalue = global2.dereference(None);
cx.global_init_block.add_assignment(None, lvalue, global1);
global2.global_set_initializer_value(global1.get_address(None));
// TODO(antoyo): use global_set_initializer() when it will work.
global2
}

View File

@ -46,10 +46,6 @@ pub struct CodegenCx<'gcc, 'tcx> {
pub current_func: RefCell<Option<Function<'gcc>>>,
pub normal_function_addresses: RefCell<FxHashSet<RValue<'gcc>>>,
/// The function where globals are initialized.
pub global_init_func: Function<'gcc>,
pub global_init_block: Block<'gcc>,
pub functions: RefCell<FxHashMap<String, Function<'gcc>>>,
pub tls_model: gccjit::TlsModel,
@ -89,23 +85,20 @@ pub struct CodegenCx<'gcc, 'tcx> {
pub types_with_fields_to_set: RefCell<FxHashMap<Type<'gcc>, (Struct<'gcc>, TyAndLayout<'tcx>)>>,
/// Cache instances of monomorphic and polymorphic items
pub instances: RefCell<FxHashMap<Instance<'tcx>, RValue<'gcc>>>,
pub instances: RefCell<FxHashMap<Instance<'tcx>, LValue<'gcc>>>,
/// Cache function instances of monomorphic and polymorphic items
pub function_instances: RefCell<FxHashMap<Instance<'tcx>, RValue<'gcc>>>,
/// Cache generated vtables
pub vtables: RefCell<FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), RValue<'gcc>>>,
/// Cache of emitted const globals (value -> global)
pub const_globals: RefCell<FxHashMap<RValue<'gcc>, RValue<'gcc>>>,
pub init_argv_var: RefCell<String>,
pub argv_initialized: Cell<bool>,
/// Cache of constant strings,
pub const_cstr_cache: RefCell<FxHashMap<Symbol, LValue<'gcc>>>,
/// Cache of globals.
pub globals: RefCell<FxHashMap<String, RValue<'gcc>>>,
// TODO(antoyo): remove global_names.
pub global_names: RefCell<FxHashMap<RValue<'gcc>, String>>,
/// A counter that is used for generating local symbol names
local_gen_sym_counter: Cell<usize>,
@ -118,16 +111,9 @@ pub struct CodegenCx<'gcc, 'tcx> {
/// NOTE: a hack is used because the rustc API is not suitable to libgccjit and as such,
/// `const_undef()` returns struct as pointer so that they can later be assigned a value.
/// As such, this set remembers which of these pointers were returned by this function so that
/// they can be derefered later.
/// they can be deferenced later.
/// FIXME(antoyo): fix the rustc API to avoid having this hack.
pub structs_as_pointer: RefCell<FxHashSet<RValue<'gcc>>>,
/// Store the pointer of different types for safety.
/// When casting the values back to their original types, check that they are indeed that type
/// with these sets.
/// FIXME(antoyo): remove when the API supports more types.
#[cfg(debug_assertions)]
lvalues: RefCell<FxHashSet<LValue<'gcc>>>,
}
impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
@ -180,10 +166,6 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
functions.insert(builtin.to_string(), context.get_builtin_function(builtin));
}
let global_init_func = context.new_function(None, FunctionType::Exported, context.new_type::<()>(), &[],
&format!("__gccGlobalInit{}", unit_name(&codegen_unit)), false);
let global_init_block = global_init_func.new_block("initial");
Self {
check_overflow,
codegen_unit,
@ -192,8 +174,6 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
current_func: RefCell::new(None),
normal_function_addresses: Default::default(),
functions: RefCell::new(functions),
global_init_func,
global_init_block,
tls_model,
@ -221,15 +201,11 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
double_type,
linkage: Cell::new(FunctionType::Internal),
#[cfg(debug_assertions)]
lvalues: Default::default(),
instances: Default::default(),
function_instances: Default::default(),
vtables: Default::default(),
const_globals: Default::default(),
init_argv_var: RefCell::new(String::new()),
argv_initialized: Cell::new(false),
const_cstr_cache: Default::default(),
global_names: Default::default(),
globals: Default::default(),
scalar_types: Default::default(),
types: Default::default(),
@ -244,12 +220,6 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
}
}
pub fn lvalue_to_rvalue(&self, value: LValue<'gcc>) -> RValue<'gcc> {
#[cfg(debug_assertions)]
self.lvalues.borrow_mut().insert(value);
unsafe { std::mem::transmute(value) }
}
pub fn rvalue_as_function(&self, value: RValue<'gcc>) -> Function<'gcc> {
let function: Function<'gcc> = unsafe { std::mem::transmute(value) };
debug_assert!(self.functions.borrow().values().find(|value| **value == function).is_some(),
@ -257,11 +227,6 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
function
}
pub fn rvalue_as_lvalue(&self, value: RValue<'gcc>) -> LValue<'gcc> {
let lvalue: LValue<'gcc> = unsafe { std::mem::transmute(value) };
lvalue
}
pub fn sess(&self) -> &Session {
&self.tcx.sess
}

View File

@ -1,11 +1,9 @@
use gccjit::{FunctionType, RValue};
use gccjit::RValue;
use rustc_codegen_ssa::mir::debuginfo::{FunctionDebugContext, VariableKind};
use rustc_codegen_ssa::traits::{BuilderMethods, DebugInfoBuilderMethods, DebugInfoMethods};
use rustc_middle::middle::cstore::CrateDepKind;
use rustc_codegen_ssa::traits::{DebugInfoBuilderMethods, DebugInfoMethods};
use rustc_middle::mir;
use rustc_middle::ty::{Instance, Ty};
use rustc_span::{SourceFile, Span, Symbol};
use rustc_span::def_id::LOCAL_CRATE;
use rustc_target::abi::Size;
use rustc_target::abi::call::FnAbi;
@ -20,25 +18,6 @@ impl<'a, 'gcc, 'tcx> DebugInfoBuilderMethods for Builder<'a, 'gcc, 'tcx> {
}
fn insert_reference_to_gdb_debug_scripts_section_global(&mut self) {
// TODO(antoyo): replace with gcc_jit_context_new_global_with_initializer() if it's added:
// https://gcc.gnu.org/pipermail/jit/2020q3/001225.html
//
// Call the function to initialize global values here.
// We assume this is only called for the main function.
use std::iter;
for crate_num in self.cx.tcx.crates(()).iter().copied().chain(iter::once(LOCAL_CRATE)) {
// FIXME(antoyo): better way to find if a crate is of proc-macro type?
if crate_num == LOCAL_CRATE || self.cx.tcx.dep_kind(crate_num) != CrateDepKind::MacrosOnly {
// NOTE: proc-macro crates are not included in the executable, so don't call their
// initialization routine.
let initializer_name = format!("__gccGlobalCrateInit{}", self.cx.tcx.crate_name(crate_num));
let codegen_init_func = self.context.new_function(None, FunctionType::Extern, self.context.new_type::<()>(), &[],
initializer_name, false);
self.llbb().add_eval(None, self.context.new_call(None, codegen_init_func, &[]));
}
}
// TODO(antoyo): insert reference to gdb debug scripts section global.
}

View File

@ -7,10 +7,9 @@ use rustc_target::abi::call::FnAbi;
use crate::abi::FnAbiGccExt;
use crate::context::{CodegenCx, unit_name};
use crate::intrinsic::llvm;
use crate::mangled_std_symbols::{ARGV_INIT_ARRAY, ARGV_INIT_WRAPPER};
impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
pub fn get_or_insert_global(&self, name: &str, ty: Type<'gcc>, is_tls: bool, link_section: Option<Symbol>) -> RValue<'gcc> {
pub fn get_or_insert_global(&self, name: &str, ty: Type<'gcc>, is_tls: bool, link_section: Option<Symbol>) -> LValue<'gcc> {
if self.globals.borrow().contains_key(name) {
let typ = self.globals.borrow().get(name).expect("global").get_type();
let global = self.context.new_global(None, GlobalKind::Imported, typ, name);
@ -20,7 +19,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
if let Some(link_section) = link_section {
global.set_link_section(&link_section.as_str());
}
global.get_address(None)
global
}
else {
self.declare_global(name, ty, is_tls, link_section)
@ -34,13 +33,10 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
self.context.new_global(None, GlobalKind::Exported, ty, &name)
}
pub fn declare_global_with_linkage(&self, name: &str, ty: Type<'gcc>, linkage: GlobalKind) -> RValue<'gcc> {
let global = self.context.new_global(None, linkage, ty, name)
.get_address(None);
self.globals.borrow_mut().insert(name.to_string(), global);
// NOTE: global seems to only be global in a module. So save the name instead of the value
// to import it later.
self.global_names.borrow_mut().insert(global, name.to_string());
pub fn declare_global_with_linkage(&self, name: &str, ty: Type<'gcc>, linkage: GlobalKind) -> LValue<'gcc> {
let global = self.context.new_global(None, linkage, ty, name);
let global_address = global.get_address(None);
self.globals.borrow_mut().insert(name.to_string(), global_address);
global
}
@ -51,19 +47,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
unsafe { std::mem::transmute(func) }
}
pub fn declare_global(&self, name: &str, ty: Type<'gcc>, is_tls: bool, link_section: Option<Symbol>) -> RValue<'gcc> {
// FIXME(antoyo): correctly support global variable initialization.
if name.starts_with(ARGV_INIT_ARRAY) {
// NOTE: hack to avoid having to update the names in mangled_std_symbols: we save the
// name of the variable now to actually declare it later.
*self.init_argv_var.borrow_mut() = name.to_string();
let global = self.context.new_global(None, GlobalKind::Imported, ty, name);
if let Some(link_section) = link_section {
global.set_link_section(&link_section.as_str());
}
return global.get_address(None);
}
pub fn declare_global(&self, name: &str, ty: Type<'gcc>, is_tls: bool, link_section: Option<Symbol>) -> LValue<'gcc> {
let global = self.context.new_global(None, GlobalKind::Exported, ty, name);
if is_tls {
global.set_tls_model(self.tls_model);
@ -71,11 +55,15 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
if let Some(link_section) = link_section {
global.set_link_section(&link_section.as_str());
}
let global = global.get_address(None);
self.globals.borrow_mut().insert(name.to_string(), global);
// NOTE: global seems to only be global in a module. So save the name instead of the value
// to import it later.
self.global_names.borrow_mut().insert(global, name.to_string());
let global_address = global.get_address(None);
self.globals.borrow_mut().insert(name.to_string(), global_address);
global
}
pub fn declare_private_global(&self, name: &str, ty: Type<'gcc>) -> LValue<'gcc> {
let global = self.context.new_global(None, GlobalKind::Internal, ty, name);
let global_address = global.get_address(None);
self.globals.borrow_mut().insert(name.to_string(), global_address);
global
}
@ -94,51 +82,14 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
}
pub fn declare_fn(&self, name: &str, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> RValue<'gcc> {
// NOTE: hack to avoid having to update the names in mangled_std_symbols: we found the name
// of the variable earlier, so we declare it now.
// Since we don't correctly support initializers yet, we initialize this variable manually
// for now.
if name.starts_with(ARGV_INIT_WRAPPER) && !self.argv_initialized.get() {
let global_name = &*self.init_argv_var.borrow();
let return_type = self.type_void();
let params = [
self.context.new_parameter(None, self.int_type, "argc"),
self.context.new_parameter(None, self.u8_type.make_pointer().make_pointer(), "argv"),
self.context.new_parameter(None, self.u8_type.make_pointer().make_pointer(), "envp"),
];
let function = self.context.new_function(None, FunctionType::Extern, return_type, &params, name, false);
let initializer = function.get_address(None);
let param_types = [
self.int_type,
self.u8_type.make_pointer().make_pointer(),
self.u8_type.make_pointer().make_pointer(),
];
let ty = self.context.new_function_pointer_type(None, return_type, &param_types, false);
let global = self.context.new_global(None, GlobalKind::Exported, ty, global_name);
global.set_link_section(".init_array.00099");
global.global_set_initializer_value(initializer);
let global = global.get_address(None);
self.globals.borrow_mut().insert(global_name.to_string(), global);
// NOTE: global seems to only be global in a module. So save the name instead of the value
// to import it later.
self.global_names.borrow_mut().insert(global, global_name.to_string());
self.argv_initialized.set(true);
}
let (return_type, params, variadic) = fn_abi.gcc_type(self);
let func = declare_raw_fn(self, name, () /*fn_abi.llvm_cconv()*/, return_type, &params, variadic);
// FIXME(antoyo): this is a wrong cast. That requires changing the compiler API.
unsafe { std::mem::transmute(func) }
}
pub fn define_global(&self, name: &str, ty: Type<'gcc>, is_tls: bool, link_section: Option<Symbol>) -> Option<RValue<'gcc>> {
Some(self.get_or_insert_global(name, ty, is_tls, link_section))
}
pub fn define_private_global(&self, ty: Type<'gcc>) -> RValue<'gcc> {
let global = self.declare_unnamed_global(ty);
global.get_address(None)
pub fn define_global(&self, name: &str, ty: Type<'gcc>, is_tls: bool, link_section: Option<Symbol>) -> LValue<'gcc> {
self.get_or_insert_global(name, ty, is_tls, link_section)
}
pub fn get_declared_value(&self, name: &str) -> Option<RValue<'gcc>> {

View File

@ -43,7 +43,6 @@ mod coverageinfo;
mod debuginfo;
mod declare;
mod intrinsic;
mod mangled_std_symbols;
mod mono_item;
mod type_;
mod type_of;
@ -51,7 +50,7 @@ mod type_of;
use std::any::Any;
use std::sync::Arc;
use gccjit::{Block, Context, FunctionType, OptimizationLevel};
use gccjit::{Context, OptimizationLevel};
use rustc_ast::expand::allocator::AllocatorKind;
use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen};
use rustc_codegen_ssa::base::codegen_crate;
@ -69,8 +68,6 @@ use rustc_session::Session;
use rustc_span::Symbol;
use rustc_span::fatal_error::FatalError;
use crate::context::unit_name;
pub struct PrintOnPanic<F: Fn() -> String>(pub F);
impl<F: Fn() -> String> Drop for PrintOnPanic<F> {
@ -203,6 +200,7 @@ impl WriteBackendMethods for GccCodegenBackend {
fn run_fat_lto(_cgcx: &CodegenContext<Self>, mut modules: Vec<FatLTOInput<Self>>, _cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>) -> Result<LtoModuleCodegen<Self>, FatalError> {
// TODO(antoyo): implement LTO by sending -flto to libgccjit and adding the appropriate gcc linker plugins.
// NOTE: implemented elsewhere.
// TODO: what is implemented elsewhere ^ ?
let module =
match modules.remove(0) {
FatLTOInput::InMemory(module) => module,
@ -273,15 +271,6 @@ fn to_gcc_opt_level(optlevel: Option<OptLevel>) -> OptimizationLevel {
}
}
fn create_function_calling_initializers<'gcc, 'tcx>(tcx: TyCtxt<'tcx>, context: &Context<'gcc>, block: Block<'gcc>) {
let codegen_units = tcx.collect_and_partition_mono_items(()).1;
for codegen_unit in codegen_units {
let codegen_init_func = context.new_function(None, FunctionType::Extern, context.new_type::<()>(), &[],
&format!("__gccGlobalInit{}", unit_name(&codegen_unit)), false);
block.add_eval(None, context.new_call(None, codegen_init_func, &[]));
}
}
fn handle_native(name: &str) -> &str {
if name != "native" {
return name;

View File

@ -1,4 +0,0 @@
pub const ARGV_INIT_ARRAY: &str = "_ZN3std3sys4unix4args3imp15ARGV_INIT_ARRAY";
pub const ARGV_INIT_WRAPPER: &str = "_ZN3std3sys4unix4args3imp15ARGV_INIT_ARRAY12init_wrapper";
pub const ARGC: &str = "_ZN3std3sys4unix4args3imp4ARGC";
pub const ARGV: &str = "_ZN3std3sys4unix4args3imp4ARGV";

View File

@ -18,12 +18,7 @@ impl<'gcc, 'tcx> PreDefineMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
let gcc_type = self.layout_of(ty).gcc_type(self, true);
let is_tls = attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL);
let global = self.define_global(symbol_name, gcc_type, is_tls, attrs.link_section).unwrap_or_else(|| {
self.sess().span_fatal(
self.tcx.def_span(def_id),
&format!("symbol `{}` is already defined", symbol_name),
)
});
let global = self.define_global(symbol_name, gcc_type, is_tls, attrs.link_section);
// TODO(antoyo): set linkage and visibility.
self.instances.borrow_mut().insert(instance, global);