mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-17 22:46:50 +00:00
Merge commit '9809f5d21990d9e24b3e9876ea7da756fd4e9def' into libgccjit-codegen
This commit is contained in:
commit
7f32dd546f
@ -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]]
|
||||
|
@ -115,3 +115,21 @@ p loc->m_line
|
||||
|
||||
* Build the stage2 compiler (`rustup toolchain link debug-current build/x86_64-unknown-linux-gnu/stage2`).
|
||||
* Clean and rebuild the codegen with `debug-current` in the file `rust-toolchain`.
|
||||
|
||||
### How to build a cross-compiling libgccjit
|
||||
|
||||
#### Building libgccjit
|
||||
|
||||
* Follow these instructions: https://preshing.com/20141119/how-to-build-a-gcc-cross-compiler/ with the following changes:
|
||||
* Configure gcc with `../gcc/configure --enable-host-shared --disable-multilib --enable-languages=c,jit,c++ --disable-bootstrap --enable-checking=release --prefix=/opt/m68k-gcc/ --target=m68k-linux --without-headers`.
|
||||
* Some shells, like fish, don't define the environment variable `$MACHTYPE`.
|
||||
* Add `CFLAGS="-Wno-error=attributes -g -O2"` at the end of the configure command for building glibc (`CFLAGS="-Wno-error=attributes -Wno-error=array-parameter -Wno-error=stringop-overflow -Wno-error=array-bounds -g -O2"` for glibc 2.31, which is useful for Debian).
|
||||
|
||||
#### Configuring rustc_codegen_gcc
|
||||
|
||||
* Set `TARGET_TRIPLE="m68k-unknown-linux-gnu"` in config.sh.
|
||||
* Since rustc doesn't support this architecture yet, set it back to `TARGET_TRIPLE="mips-unknown-linux-gnu"` (or another target having the same attributes). Alternatively, create a [target specification file](https://book.avr-rust.com/005.1-the-target-specification-json-file.html) (note that the `arch` specified in this file must be supported by the rust compiler).
|
||||
* Set `linker='-Clinker=m68k-linux-gcc'`.
|
||||
* Set the path to the cross-compiling libgccjit in `gcc_path`.
|
||||
* Disable the 128-bit integer types if the target doesn't support them by using `let i128_type = context.new_type::<i64>();` in `context.rs` (same for u128_type).
|
||||
* (might not be necessary) Disable the compilation of libstd.so (and possibly libcore.so?).
|
||||
|
@ -21,12 +21,15 @@ fi
|
||||
|
||||
HOST_TRIPLE=$(rustc -vV | grep host | cut -d: -f2 | tr -d " ")
|
||||
TARGET_TRIPLE=$HOST_TRIPLE
|
||||
#TARGET_TRIPLE="aarch64-unknown-linux-gnu"
|
||||
#TARGET_TRIPLE="m68k-unknown-linux-gnu"
|
||||
|
||||
linker=''
|
||||
RUN_WRAPPER=''
|
||||
if [[ "$HOST_TRIPLE" != "$TARGET_TRIPLE" ]]; then
|
||||
if [[ "$TARGET_TRIPLE" == "aarch64-unknown-linux-gnu" ]]; then
|
||||
if [[ "$TARGET_TRIPLE" == "m68k-unknown-linux-gnu" ]]; then
|
||||
TARGET_TRIPLE="mips-unknown-linux-gnu"
|
||||
linker='-Clinker=m68k-linux-gcc'
|
||||
elif [[ "$TARGET_TRIPLE" == "aarch64-unknown-linux-gnu" ]]; then
|
||||
# We are cross-compiling for aarch64. Use the correct linker and run tests in qemu.
|
||||
linker='-Clinker=aarch64-linux-gnu-gcc'
|
||||
RUN_WRAPPER='qemu-aarch64 -L /usr/aarch64-linux-gnu'
|
||||
@ -35,7 +38,7 @@ if [[ "$HOST_TRIPLE" != "$TARGET_TRIPLE" ]]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
export RUSTFLAGS="$linker -Cpanic=abort -Cdebuginfo=2 -Clto=off -Zpanic-abort-tests -Zcodegen-backend=$(pwd)/target/${CHANNEL:-debug}/librustc_codegen_gcc.$dylib_ext --sysroot $(pwd)/build_sysroot/sysroot"
|
||||
export RUSTFLAGS="$linker -Cpanic=abort -Zsymbol-mangling-version=v0 -Cdebuginfo=2 -Clto=off -Zpanic-abort-tests -Zcodegen-backend=$(pwd)/target/${CHANNEL:-debug}/librustc_codegen_gcc.$dylib_ext --sysroot $(pwd)/build_sysroot/sysroot"
|
||||
|
||||
# FIXME(antoyo): remove once the atomic shim is gone
|
||||
if [[ `uname` == 'Darwin' ]]; then
|
||||
|
@ -1 +1 @@
|
||||
nightly-2021-09-17
|
||||
nightly-2021-09-28
|
||||
|
@ -6,7 +6,7 @@ use rustc_codegen_ssa::traits::{AsmBuilderMethods, AsmMethods, BaseTypeMethods,
|
||||
|
||||
use rustc_hir::LlvmInlineAsmInner;
|
||||
use rustc_middle::{bug, ty::Instance};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::{Span, Symbol};
|
||||
use rustc_target::asm::*;
|
||||
|
||||
use std::borrow::Cow;
|
||||
@ -173,7 +173,20 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
|
||||
continue
|
||||
},
|
||||
(Register(reg_name), None) => {
|
||||
clobbers.push(reg_name);
|
||||
// `clobber_abi` can add lots of clobbers that are not supported by the target,
|
||||
// such as AVX-512 registers, so we just ignore unsupported registers
|
||||
let is_target_supported = reg.reg_class().supported_types(asm_arch).iter()
|
||||
.any(|&(_, feature)| {
|
||||
if let Some(feature) = feature {
|
||||
self.tcx.sess.target_features.contains(&Symbol::intern(feature))
|
||||
} else {
|
||||
true // Register class is unconditionally supported
|
||||
}
|
||||
});
|
||||
|
||||
if is_target_supported && !clobbers.contains(®_name) {
|
||||
clobbers.push(reg_name);
|
||||
}
|
||||
continue
|
||||
}
|
||||
};
|
||||
@ -526,16 +539,20 @@ fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister {
|
||||
let constraint = match reg {
|
||||
// For vector registers LLVM wants the register name to match the type size.
|
||||
InlineAsmRegOrRegClass::Reg(reg) => {
|
||||
// TODO(antoyo): add support for vector register.
|
||||
match reg.name() {
|
||||
"ax" => "a",
|
||||
"bx" => "b",
|
||||
"cx" => "c",
|
||||
"dx" => "d",
|
||||
"si" => "S",
|
||||
"di" => "D",
|
||||
// For registers like r11, we have to create a register variable: https://stackoverflow.com/a/31774784/389119
|
||||
name => return ConstraintOrRegister::Register(name),
|
||||
match reg {
|
||||
InlineAsmReg::X86(_) => {
|
||||
// TODO(antoyo): add support for vector register.
|
||||
//
|
||||
// // For explicit registers, we have to create a register variable: https://stackoverflow.com/a/31774784/389119
|
||||
return ConstraintOrRegister::Register(match reg.name() {
|
||||
// Some of registers' names does not map 1-1 from rust to gcc
|
||||
"st(0)" => "st",
|
||||
|
||||
name => name,
|
||||
});
|
||||
}
|
||||
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
},
|
||||
InlineAsmRegOrRegClass::RegClass(reg) => match reg {
|
||||
|
@ -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 {
|
||||
|
@ -31,11 +31,12 @@ use rustc_codegen_ssa::traits::{
|
||||
StaticBuilderMethods,
|
||||
};
|
||||
use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
|
||||
use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt, LayoutError, LayoutOfHelpers, TyAndLayout};
|
||||
use rustc_middle::ty::layout::{FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, HasTyCtxt, LayoutError, LayoutOfHelpers, TyAndLayout};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::def_id::DefId;
|
||||
use rustc_target::abi::{
|
||||
self,
|
||||
call::FnAbi,
|
||||
Align,
|
||||
HasDataLayout,
|
||||
Size,
|
||||
@ -347,6 +348,20 @@ impl<'tcx> LayoutOfHelpers<'tcx> for Builder<'_, '_, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> FnAbiOfHelpers<'tcx> for Builder<'_, '_, 'tcx> {
|
||||
type FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>;
|
||||
|
||||
#[inline]
|
||||
fn handle_fn_abi_err(
|
||||
&self,
|
||||
err: FnAbiError<'tcx>,
|
||||
span: Span,
|
||||
fn_abi_request: FnAbiRequest<'tcx>,
|
||||
) -> ! {
|
||||
self.cx.handle_fn_abi_err(err, span, fn_abi_request)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'gcc, 'tcx> Deref for Builder<'_, 'gcc, 'tcx> {
|
||||
type Target = CodegenCx<'gcc, 'tcx>;
|
||||
|
||||
@ -505,7 +520,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
|
||||
}
|
||||
@ -1052,11 +1066,18 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
|
||||
}
|
||||
|
||||
/* Comparisons */
|
||||
fn icmp(&mut self, op: IntPredicate, lhs: RValue<'gcc>, mut rhs: RValue<'gcc>) -> RValue<'gcc> {
|
||||
if lhs.get_type() != rhs.get_type() {
|
||||
fn icmp(&mut self, op: IntPredicate, mut lhs: RValue<'gcc>, mut rhs: RValue<'gcc>) -> RValue<'gcc> {
|
||||
let left_type = lhs.get_type();
|
||||
let right_type = rhs.get_type();
|
||||
if left_type != right_type {
|
||||
// NOTE: because libgccjit cannot compare function pointers.
|
||||
if left_type.is_function_ptr_type().is_some() && right_type.is_function_ptr_type().is_some() {
|
||||
lhs = self.context.new_cast(None, lhs, self.usize_type.make_pointer());
|
||||
rhs = self.context.new_cast(None, rhs, self.usize_type.make_pointer());
|
||||
}
|
||||
// NOTE: hack because we try to cast a vector type to the same vector type.
|
||||
if format!("{:?}", lhs.get_type()) != format!("{:?}", rhs.get_type()) {
|
||||
rhs = self.context.new_cast(None, rhs, lhs.get_type());
|
||||
else if format!("{:?}", left_type) != format!("{:?}", right_type) {
|
||||
rhs = self.context.new_cast(None, rhs, left_type);
|
||||
}
|
||||
}
|
||||
self.context.new_comparison(None, op.to_gcc_comparison(), lhs, rhs)
|
||||
@ -1210,6 +1231,17 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
|
||||
else {
|
||||
panic!("Unexpected type {:?}", value_type);
|
||||
};
|
||||
|
||||
let lvalue_type = lvalue.to_rvalue().get_type();
|
||||
let value =
|
||||
// NOTE: sometimes, rustc will create a value with the wrong type.
|
||||
if lvalue_type != value.get_type() {
|
||||
self.context.new_cast(None, value, lvalue_type)
|
||||
}
|
||||
else {
|
||||
value
|
||||
};
|
||||
|
||||
self.llbb().add_assignment(None, lvalue, value);
|
||||
|
||||
aggregate_value
|
||||
@ -1413,7 +1445,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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,7 @@
|
||||
use gccjit::{FunctionType, RValue};
|
||||
use rustc_codegen_ssa::traits::BaseTypeMethods;
|
||||
use rustc_middle::ty::{Instance, TypeFoldable};
|
||||
use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt};
|
||||
use rustc_target::abi::call::FnAbi;
|
||||
use rustc_middle::ty::{self, Instance, TypeFoldable};
|
||||
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt};
|
||||
|
||||
use crate::abi::FnAbiGccExt;
|
||||
use crate::context::CodegenCx;
|
||||
@ -20,13 +19,13 @@ 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;
|
||||
}
|
||||
|
||||
let sym = tcx.symbol_name(instance).name;
|
||||
|
||||
let fn_abi = FnAbi::of_instance(cx, instance, &[]);
|
||||
let fn_abi = cx.fn_abi_of_instance(instance, ty::List::empty());
|
||||
|
||||
let func =
|
||||
if let Some(func) = cx.get_declared_value(&sym) {
|
||||
@ -72,7 +71,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
|
||||
}
|
||||
|
@ -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,25 @@ 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);
|
||||
global
|
||||
// TODO(antoyo): set linkage.
|
||||
}
|
||||
|
||||
@ -76,10 +73,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 +180,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 +191,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 +253,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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -310,6 +302,7 @@ pub trait SignType<'gcc, 'tcx> {
|
||||
fn is_signed(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool;
|
||||
fn is_unsigned(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool;
|
||||
fn to_signed(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc>;
|
||||
fn to_unsigned(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc>;
|
||||
}
|
||||
|
||||
impl<'gcc, 'tcx> SignType<'gcc, 'tcx> for Type<'gcc> {
|
||||
@ -341,6 +334,27 @@ impl<'gcc, 'tcx> SignType<'gcc, 'tcx> for Type<'gcc> {
|
||||
self.clone()
|
||||
}
|
||||
}
|
||||
|
||||
fn to_unsigned(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc> {
|
||||
if self.is_i8(cx) {
|
||||
cx.u8_type
|
||||
}
|
||||
else if self.is_i16(cx) {
|
||||
cx.u16_type
|
||||
}
|
||||
else if self.is_i32(cx) {
|
||||
cx.u32_type
|
||||
}
|
||||
else if self.is_i64(cx) {
|
||||
cx.u64_type
|
||||
}
|
||||
else if self.is_i128(cx) {
|
||||
cx.u128_type
|
||||
}
|
||||
else {
|
||||
self.clone()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait TypeReflection<'gcc, 'tcx> {
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -21,10 +21,10 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::mir::mono::CodegenUnit;
|
||||
use rustc_middle::ty::{self, Instance, ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt};
|
||||
use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt, LayoutError, TyAndLayout, LayoutOfHelpers};
|
||||
use rustc_middle::ty::layout::{FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, HasTyCtxt, LayoutError, TyAndLayout, LayoutOfHelpers};
|
||||
use rustc_session::Session;
|
||||
use rustc_span::{Span, Symbol};
|
||||
use rustc_target::abi::{HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx};
|
||||
use rustc_target::abi::{call::FnAbi, HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx};
|
||||
use rustc_target::spec::{HasTargetSpec, Target, TlsModel};
|
||||
|
||||
use crate::callee::get_fn;
|
||||
@ -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
|
||||
}
|
||||
@ -436,6 +401,43 @@ impl<'gcc, 'tcx> LayoutOfHelpers<'tcx> for CodegenCx<'gcc, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'gcc, 'tcx> FnAbiOfHelpers<'tcx> for CodegenCx<'gcc, 'tcx> {
|
||||
type FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>;
|
||||
|
||||
#[inline]
|
||||
fn handle_fn_abi_err(
|
||||
&self,
|
||||
err: FnAbiError<'tcx>,
|
||||
span: Span,
|
||||
fn_abi_request: FnAbiRequest<'tcx>,
|
||||
) -> ! {
|
||||
if let FnAbiError::Layout(LayoutError::SizeOverflow(_)) = err {
|
||||
self.sess().span_fatal(span, &err.to_string())
|
||||
} else {
|
||||
match fn_abi_request {
|
||||
FnAbiRequest::OfFnPtr { sig, extra_args } => {
|
||||
span_bug!(
|
||||
span,
|
||||
"`fn_abi_of_fn_ptr({}, {:?})` failed: {}",
|
||||
sig,
|
||||
extra_args,
|
||||
err
|
||||
);
|
||||
}
|
||||
FnAbiRequest::OfInstance { instance, extra_args } => {
|
||||
span_bug!(
|
||||
span,
|
||||
"`fn_abi_of_instance({}, {:?})` failed: {}",
|
||||
instance,
|
||||
extra_args,
|
||||
err
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, 'gcc> HasParamEnv<'tcx> for CodegenCx<'gcc, 'tcx> {
|
||||
fn param_env(&self) -> ParamEnv<'tcx> {
|
||||
ParamEnv::reveal_all()
|
||||
|
@ -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.
|
||||
}
|
||||
|
||||
|
@ -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, ¶ms, 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, ¶m_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, ¶ms, 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>> {
|
||||
|
@ -18,7 +18,7 @@ use rustc_target::spec::PanicStrategy;
|
||||
|
||||
use crate::abi::GccType;
|
||||
use crate::builder::Builder;
|
||||
use crate::common::TypeReflection;
|
||||
use crate::common::{SignType, TypeReflection};
|
||||
use crate::context::CodegenCx;
|
||||
use crate::type_of::LayoutGccExt;
|
||||
use crate::intrinsic::simd::generic_simd_intrinsic;
|
||||
@ -520,163 +520,176 @@ fn int_type_width_signed<'gcc, 'tcx>(ty: Ty<'tcx>, cx: &CodegenCx<'gcc, 'tcx>) -
|
||||
|
||||
impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
||||
fn bit_reverse(&mut self, width: u64, value: RValue<'gcc>) -> RValue<'gcc> {
|
||||
let typ = value.get_type();
|
||||
let result_type = value.get_type();
|
||||
let typ = result_type.to_unsigned(self.cx);
|
||||
|
||||
let value =
|
||||
if result_type.is_signed(self.cx) {
|
||||
self.context.new_bitcast(None, value, typ)
|
||||
}
|
||||
else {
|
||||
value
|
||||
};
|
||||
|
||||
let context = &self.cx.context;
|
||||
match width {
|
||||
8 => {
|
||||
// First step.
|
||||
let left = self.and(value, context.new_rvalue_from_int(typ, 0xF0));
|
||||
let left = self.lshr(left, context.new_rvalue_from_int(typ, 4));
|
||||
let right = self.and(value, context.new_rvalue_from_int(typ, 0x0F));
|
||||
let right = self.shl(right, context.new_rvalue_from_int(typ, 4));
|
||||
let step1 = self.or(left, right);
|
||||
let result =
|
||||
match width {
|
||||
8 => {
|
||||
// First step.
|
||||
let left = self.and(value, context.new_rvalue_from_int(typ, 0xF0));
|
||||
let left = self.lshr(left, context.new_rvalue_from_int(typ, 4));
|
||||
let right = self.and(value, context.new_rvalue_from_int(typ, 0x0F));
|
||||
let right = self.shl(right, context.new_rvalue_from_int(typ, 4));
|
||||
let step1 = self.or(left, right);
|
||||
|
||||
// Second step.
|
||||
let left = self.and(step1, context.new_rvalue_from_int(typ, 0xCC));
|
||||
let left = self.lshr(left, context.new_rvalue_from_int(typ, 2));
|
||||
let right = self.and(step1, context.new_rvalue_from_int(typ, 0x33));
|
||||
let right = self.shl(right, context.new_rvalue_from_int(typ, 2));
|
||||
let step2 = self.or(left, right);
|
||||
// Second step.
|
||||
let left = self.and(step1, context.new_rvalue_from_int(typ, 0xCC));
|
||||
let left = self.lshr(left, context.new_rvalue_from_int(typ, 2));
|
||||
let right = self.and(step1, context.new_rvalue_from_int(typ, 0x33));
|
||||
let right = self.shl(right, context.new_rvalue_from_int(typ, 2));
|
||||
let step2 = self.or(left, right);
|
||||
|
||||
// Third step.
|
||||
let left = self.and(step2, context.new_rvalue_from_int(typ, 0xAA));
|
||||
let left = self.lshr(left, context.new_rvalue_from_int(typ, 1));
|
||||
let right = self.and(step2, context.new_rvalue_from_int(typ, 0x55));
|
||||
let right = self.shl(right, context.new_rvalue_from_int(typ, 1));
|
||||
let step3 = self.or(left, right);
|
||||
// Third step.
|
||||
let left = self.and(step2, context.new_rvalue_from_int(typ, 0xAA));
|
||||
let left = self.lshr(left, context.new_rvalue_from_int(typ, 1));
|
||||
let right = self.and(step2, context.new_rvalue_from_int(typ, 0x55));
|
||||
let right = self.shl(right, context.new_rvalue_from_int(typ, 1));
|
||||
let step3 = self.or(left, right);
|
||||
|
||||
step3
|
||||
},
|
||||
16 => {
|
||||
// First step.
|
||||
let left = self.and(value, context.new_rvalue_from_int(typ, 0x5555));
|
||||
let left = self.shl(left, context.new_rvalue_from_int(typ, 1));
|
||||
let right = self.and(value, context.new_rvalue_from_int(typ, 0xAAAA));
|
||||
let right = self.lshr(right, context.new_rvalue_from_int(typ, 1));
|
||||
let step1 = self.or(left, right);
|
||||
step3
|
||||
},
|
||||
16 => {
|
||||
// First step.
|
||||
let left = self.and(value, context.new_rvalue_from_int(typ, 0x5555));
|
||||
let left = self.shl(left, context.new_rvalue_from_int(typ, 1));
|
||||
let right = self.and(value, context.new_rvalue_from_int(typ, 0xAAAA));
|
||||
let right = self.lshr(right, context.new_rvalue_from_int(typ, 1));
|
||||
let step1 = self.or(left, right);
|
||||
|
||||
// Second step.
|
||||
let left = self.and(step1, context.new_rvalue_from_int(typ, 0x3333));
|
||||
let left = self.shl(left, context.new_rvalue_from_int(typ, 2));
|
||||
let right = self.and(step1, context.new_rvalue_from_int(typ, 0xCCCC));
|
||||
let right = self.lshr(right, context.new_rvalue_from_int(typ, 2));
|
||||
let step2 = self.or(left, right);
|
||||
// Second step.
|
||||
let left = self.and(step1, context.new_rvalue_from_int(typ, 0x3333));
|
||||
let left = self.shl(left, context.new_rvalue_from_int(typ, 2));
|
||||
let right = self.and(step1, context.new_rvalue_from_int(typ, 0xCCCC));
|
||||
let right = self.lshr(right, context.new_rvalue_from_int(typ, 2));
|
||||
let step2 = self.or(left, right);
|
||||
|
||||
// Third step.
|
||||
let left = self.and(step2, context.new_rvalue_from_int(typ, 0x0F0F));
|
||||
let left = self.shl(left, context.new_rvalue_from_int(typ, 4));
|
||||
let right = self.and(step2, context.new_rvalue_from_int(typ, 0xF0F0));
|
||||
let right = self.lshr(right, context.new_rvalue_from_int(typ, 4));
|
||||
let step3 = self.or(left, right);
|
||||
// Third step.
|
||||
let left = self.and(step2, context.new_rvalue_from_int(typ, 0x0F0F));
|
||||
let left = self.shl(left, context.new_rvalue_from_int(typ, 4));
|
||||
let right = self.and(step2, context.new_rvalue_from_int(typ, 0xF0F0));
|
||||
let right = self.lshr(right, context.new_rvalue_from_int(typ, 4));
|
||||
let step3 = self.or(left, right);
|
||||
|
||||
// Fourth step.
|
||||
let left = self.and(step3, context.new_rvalue_from_int(typ, 0x00FF));
|
||||
let left = self.shl(left, context.new_rvalue_from_int(typ, 8));
|
||||
let right = self.and(step3, context.new_rvalue_from_int(typ, 0xFF00));
|
||||
let right = self.lshr(right, context.new_rvalue_from_int(typ, 8));
|
||||
let step4 = self.or(left, right);
|
||||
// Fourth step.
|
||||
let left = self.and(step3, context.new_rvalue_from_int(typ, 0x00FF));
|
||||
let left = self.shl(left, context.new_rvalue_from_int(typ, 8));
|
||||
let right = self.and(step3, context.new_rvalue_from_int(typ, 0xFF00));
|
||||
let right = self.lshr(right, context.new_rvalue_from_int(typ, 8));
|
||||
let step4 = self.or(left, right);
|
||||
|
||||
step4
|
||||
},
|
||||
32 => {
|
||||
// TODO(antoyo): Refactor with other implementations.
|
||||
// First step.
|
||||
let left = self.and(value, context.new_rvalue_from_long(typ, 0x55555555));
|
||||
let left = self.shl(left, context.new_rvalue_from_long(typ, 1));
|
||||
let right = self.and(value, context.new_rvalue_from_long(typ, 0xAAAAAAAA));
|
||||
let right = self.lshr(right, context.new_rvalue_from_long(typ, 1));
|
||||
let step1 = self.or(left, right);
|
||||
step4
|
||||
},
|
||||
32 => {
|
||||
// TODO(antoyo): Refactor with other implementations.
|
||||
// First step.
|
||||
let left = self.and(value, context.new_rvalue_from_long(typ, 0x55555555));
|
||||
let left = self.shl(left, context.new_rvalue_from_long(typ, 1));
|
||||
let right = self.and(value, context.new_rvalue_from_long(typ, 0xAAAAAAAA));
|
||||
let right = self.lshr(right, context.new_rvalue_from_long(typ, 1));
|
||||
let step1 = self.or(left, right);
|
||||
|
||||
// Second step.
|
||||
let left = self.and(step1, context.new_rvalue_from_long(typ, 0x33333333));
|
||||
let left = self.shl(left, context.new_rvalue_from_long(typ, 2));
|
||||
let right = self.and(step1, context.new_rvalue_from_long(typ, 0xCCCCCCCC));
|
||||
let right = self.lshr(right, context.new_rvalue_from_long(typ, 2));
|
||||
let step2 = self.or(left, right);
|
||||
// Second step.
|
||||
let left = self.and(step1, context.new_rvalue_from_long(typ, 0x33333333));
|
||||
let left = self.shl(left, context.new_rvalue_from_long(typ, 2));
|
||||
let right = self.and(step1, context.new_rvalue_from_long(typ, 0xCCCCCCCC));
|
||||
let right = self.lshr(right, context.new_rvalue_from_long(typ, 2));
|
||||
let step2 = self.or(left, right);
|
||||
|
||||
// Third step.
|
||||
let left = self.and(step2, context.new_rvalue_from_long(typ, 0x0F0F0F0F));
|
||||
let left = self.shl(left, context.new_rvalue_from_long(typ, 4));
|
||||
let right = self.and(step2, context.new_rvalue_from_long(typ, 0xF0F0F0F0));
|
||||
let right = self.lshr(right, context.new_rvalue_from_long(typ, 4));
|
||||
let step3 = self.or(left, right);
|
||||
// Third step.
|
||||
let left = self.and(step2, context.new_rvalue_from_long(typ, 0x0F0F0F0F));
|
||||
let left = self.shl(left, context.new_rvalue_from_long(typ, 4));
|
||||
let right = self.and(step2, context.new_rvalue_from_long(typ, 0xF0F0F0F0));
|
||||
let right = self.lshr(right, context.new_rvalue_from_long(typ, 4));
|
||||
let step3 = self.or(left, right);
|
||||
|
||||
// Fourth step.
|
||||
let left = self.and(step3, context.new_rvalue_from_long(typ, 0x00FF00FF));
|
||||
let left = self.shl(left, context.new_rvalue_from_long(typ, 8));
|
||||
let right = self.and(step3, context.new_rvalue_from_long(typ, 0xFF00FF00));
|
||||
let right = self.lshr(right, context.new_rvalue_from_long(typ, 8));
|
||||
let step4 = self.or(left, right);
|
||||
// Fourth step.
|
||||
let left = self.and(step3, context.new_rvalue_from_long(typ, 0x00FF00FF));
|
||||
let left = self.shl(left, context.new_rvalue_from_long(typ, 8));
|
||||
let right = self.and(step3, context.new_rvalue_from_long(typ, 0xFF00FF00));
|
||||
let right = self.lshr(right, context.new_rvalue_from_long(typ, 8));
|
||||
let step4 = self.or(left, right);
|
||||
|
||||
// Fifth step.
|
||||
let left = self.and(step4, context.new_rvalue_from_long(typ, 0x0000FFFF));
|
||||
let left = self.shl(left, context.new_rvalue_from_long(typ, 16));
|
||||
let right = self.and(step4, context.new_rvalue_from_long(typ, 0xFFFF0000));
|
||||
let right = self.lshr(right, context.new_rvalue_from_long(typ, 16));
|
||||
let step5 = self.or(left, right);
|
||||
// Fifth step.
|
||||
let left = self.and(step4, context.new_rvalue_from_long(typ, 0x0000FFFF));
|
||||
let left = self.shl(left, context.new_rvalue_from_long(typ, 16));
|
||||
let right = self.and(step4, context.new_rvalue_from_long(typ, 0xFFFF0000));
|
||||
let right = self.lshr(right, context.new_rvalue_from_long(typ, 16));
|
||||
let step5 = self.or(left, right);
|
||||
|
||||
step5
|
||||
},
|
||||
64 => {
|
||||
// First step.
|
||||
let left = self.shl(value, context.new_rvalue_from_long(typ, 32));
|
||||
let right = self.lshr(value, context.new_rvalue_from_long(typ, 32));
|
||||
let step1 = self.or(left, right);
|
||||
step5
|
||||
},
|
||||
64 => {
|
||||
// First step.
|
||||
let left = self.shl(value, context.new_rvalue_from_long(typ, 32));
|
||||
let right = self.lshr(value, context.new_rvalue_from_long(typ, 32));
|
||||
let step1 = self.or(left, right);
|
||||
|
||||
// Second step.
|
||||
let left = self.and(step1, context.new_rvalue_from_long(typ, 0x0001FFFF0001FFFF));
|
||||
let left = self.shl(left, context.new_rvalue_from_long(typ, 15));
|
||||
let right = self.and(step1, context.new_rvalue_from_long(typ, 0xFFFE0000FFFE0000u64 as i64)); // TODO(antoyo): transmute the number instead?
|
||||
let right = self.lshr(right, context.new_rvalue_from_long(typ, 17));
|
||||
let step2 = self.or(left, right);
|
||||
// Second step.
|
||||
let left = self.and(step1, context.new_rvalue_from_long(typ, 0x0001FFFF0001FFFF));
|
||||
let left = self.shl(left, context.new_rvalue_from_long(typ, 15));
|
||||
let right = self.and(step1, context.new_rvalue_from_long(typ, 0xFFFE0000FFFE0000u64 as i64)); // TODO(antoyo): transmute the number instead?
|
||||
let right = self.lshr(right, context.new_rvalue_from_long(typ, 17));
|
||||
let step2 = self.or(left, right);
|
||||
|
||||
// Third step.
|
||||
let left = self.lshr(step2, context.new_rvalue_from_long(typ, 10));
|
||||
let left = self.xor(step2, left);
|
||||
let temp = self.and(left, context.new_rvalue_from_long(typ, 0x003F801F003F801F));
|
||||
// Third step.
|
||||
let left = self.lshr(step2, context.new_rvalue_from_long(typ, 10));
|
||||
let left = self.xor(step2, left);
|
||||
let temp = self.and(left, context.new_rvalue_from_long(typ, 0x003F801F003F801F));
|
||||
|
||||
let left = self.shl(temp, context.new_rvalue_from_long(typ, 10));
|
||||
let left = self.or(temp, left);
|
||||
let step3 = self.xor(left, step2);
|
||||
let left = self.shl(temp, context.new_rvalue_from_long(typ, 10));
|
||||
let left = self.or(temp, left);
|
||||
let step3 = self.xor(left, step2);
|
||||
|
||||
// Fourth step.
|
||||
let left = self.lshr(step3, context.new_rvalue_from_long(typ, 4));
|
||||
let left = self.xor(step3, left);
|
||||
let temp = self.and(left, context.new_rvalue_from_long(typ, 0x0E0384210E038421));
|
||||
// Fourth step.
|
||||
let left = self.lshr(step3, context.new_rvalue_from_long(typ, 4));
|
||||
let left = self.xor(step3, left);
|
||||
let temp = self.and(left, context.new_rvalue_from_long(typ, 0x0E0384210E038421));
|
||||
|
||||
let left = self.shl(temp, context.new_rvalue_from_long(typ, 4));
|
||||
let left = self.or(temp, left);
|
||||
let step4 = self.xor(left, step3);
|
||||
let left = self.shl(temp, context.new_rvalue_from_long(typ, 4));
|
||||
let left = self.or(temp, left);
|
||||
let step4 = self.xor(left, step3);
|
||||
|
||||
// Fifth step.
|
||||
let left = self.lshr(step4, context.new_rvalue_from_long(typ, 2));
|
||||
let left = self.xor(step4, left);
|
||||
let temp = self.and(left, context.new_rvalue_from_long(typ, 0x2248884222488842));
|
||||
// Fifth step.
|
||||
let left = self.lshr(step4, context.new_rvalue_from_long(typ, 2));
|
||||
let left = self.xor(step4, left);
|
||||
let temp = self.and(left, context.new_rvalue_from_long(typ, 0x2248884222488842));
|
||||
|
||||
let left = self.shl(temp, context.new_rvalue_from_long(typ, 2));
|
||||
let left = self.or(temp, left);
|
||||
let step5 = self.xor(left, step4);
|
||||
let left = self.shl(temp, context.new_rvalue_from_long(typ, 2));
|
||||
let left = self.or(temp, left);
|
||||
let step5 = self.xor(left, step4);
|
||||
|
||||
step5
|
||||
},
|
||||
128 => {
|
||||
// TODO(antoyo): find a more efficient implementation?
|
||||
let sixty_four = self.context.new_rvalue_from_long(typ, 64);
|
||||
let high = self.context.new_cast(None, value >> sixty_four, self.u64_type);
|
||||
let low = self.context.new_cast(None, value, self.u64_type);
|
||||
step5
|
||||
},
|
||||
128 => {
|
||||
// TODO(antoyo): find a more efficient implementation?
|
||||
let sixty_four = self.context.new_rvalue_from_long(typ, 64);
|
||||
let high = self.context.new_cast(None, value >> sixty_four, self.u64_type);
|
||||
let low = self.context.new_cast(None, value, self.u64_type);
|
||||
|
||||
let reversed_high = self.bit_reverse(64, high);
|
||||
let reversed_low = self.bit_reverse(64, low);
|
||||
let reversed_high = self.bit_reverse(64, high);
|
||||
let reversed_low = self.bit_reverse(64, low);
|
||||
|
||||
let new_low = self.context.new_cast(None, reversed_high, typ);
|
||||
let new_high = self.context.new_cast(None, reversed_low, typ) << sixty_four;
|
||||
let new_low = self.context.new_cast(None, reversed_high, typ);
|
||||
let new_high = self.context.new_cast(None, reversed_low, typ) << sixty_four;
|
||||
|
||||
new_low | new_high
|
||||
},
|
||||
_ => {
|
||||
panic!("cannot bit reverse with width = {}", width);
|
||||
},
|
||||
}
|
||||
new_low | new_high
|
||||
},
|
||||
_ => {
|
||||
panic!("cannot bit reverse with width = {}", width);
|
||||
},
|
||||
};
|
||||
|
||||
self.context.new_bitcast(None, result, result_type)
|
||||
}
|
||||
|
||||
fn count_leading_zeroes(&self, width: u64, arg: RValue<'gcc>) -> RValue<'gcc> {
|
||||
@ -746,6 +759,15 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
||||
}
|
||||
|
||||
fn count_trailing_zeroes(&self, _width: u64, arg: RValue<'gcc>) -> RValue<'gcc> {
|
||||
let result_type = arg.get_type();
|
||||
let arg =
|
||||
if result_type.is_signed(self.cx) {
|
||||
let new_type = result_type.to_unsigned(self.cx);
|
||||
self.context.new_bitcast(None, arg, new_type)
|
||||
}
|
||||
else {
|
||||
arg
|
||||
};
|
||||
let arg_type = arg.get_type();
|
||||
let (count_trailing_zeroes, expected_type) =
|
||||
if arg_type.is_uchar(&self.cx) || arg_type.is_ushort(&self.cx) || arg_type.is_uint(&self.cx) {
|
||||
@ -796,7 +818,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
||||
|
||||
let res = self.context.new_array_access(None, result, index);
|
||||
|
||||
return self.context.new_cast(None, res, arg_type);
|
||||
return self.context.new_bitcast(None, res, result_type);
|
||||
}
|
||||
else {
|
||||
unimplemented!("count_trailing_zeroes for {:?}", arg_type);
|
||||
@ -810,7 +832,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
||||
arg
|
||||
};
|
||||
let res = self.context.new_call(None, count_trailing_zeroes, &[arg]);
|
||||
self.context.new_cast(None, res, arg_type)
|
||||
self.context.new_bitcast(None, res, result_type)
|
||||
}
|
||||
|
||||
fn int_width(&self, typ: Type<'gcc>) -> i64 {
|
||||
@ -819,7 +841,16 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
||||
|
||||
fn pop_count(&self, value: RValue<'gcc>) -> RValue<'gcc> {
|
||||
// TODO(antoyo): use the optimized version with fewer operations.
|
||||
let value_type = value.get_type();
|
||||
let result_type = value.get_type();
|
||||
let value_type = result_type.to_unsigned(self.cx);
|
||||
|
||||
let value =
|
||||
if result_type.is_signed(self.cx) {
|
||||
self.context.new_bitcast(None, value, value_type)
|
||||
}
|
||||
else {
|
||||
value
|
||||
};
|
||||
|
||||
if value_type.is_u128(&self.cx) {
|
||||
// TODO(antoyo): implement in the normal algorithm below to have a more efficient
|
||||
@ -830,7 +861,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
||||
let high = self.context.new_call(None, popcount, &[high]);
|
||||
let low = self.context.new_cast(None, value, self.cx.ulonglong_type);
|
||||
let low = self.context.new_call(None, popcount, &[low]);
|
||||
return high + low;
|
||||
let res = high + low;
|
||||
return self.context.new_bitcast(None, res, result_type);
|
||||
}
|
||||
|
||||
// First step.
|
||||
@ -855,7 +887,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
||||
let value = left + right;
|
||||
|
||||
if value_type.is_u8(&self.cx) {
|
||||
return value;
|
||||
return self.context.new_bitcast(None, value, result_type);
|
||||
}
|
||||
|
||||
// Fourth step.
|
||||
@ -866,7 +898,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
||||
let value = left + right;
|
||||
|
||||
if value_type.is_u16(&self.cx) {
|
||||
return value;
|
||||
return self.context.new_bitcast(None, value, result_type);
|
||||
}
|
||||
|
||||
// Fifth step.
|
||||
@ -877,7 +909,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
||||
let value = left + right;
|
||||
|
||||
if value_type.is_u32(&self.cx) {
|
||||
return value;
|
||||
return self.context.new_bitcast(None, value, result_type);
|
||||
}
|
||||
|
||||
// Sixth step.
|
||||
@ -887,7 +919,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
||||
let right = shifted & mask;
|
||||
let value = left + right;
|
||||
|
||||
value
|
||||
self.context.new_bitcast(None, value, result_type)
|
||||
}
|
||||
|
||||
// Algorithm from: https://blog.regehr.org/archives/1063
|
||||
|
@ -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;
|
||||
@ -64,13 +63,11 @@ use rustc_errors::{ErrorReported, Handler};
|
||||
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
|
||||
use rustc_middle::middle::cstore::EncodedMetadata;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::config::{CrateType, Lto, OptLevel, OutputFilenames};
|
||||
use rustc_session::config::{Lto, OptLevel, OutputFilenames};
|
||||
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> {
|
||||
@ -109,16 +106,8 @@ impl CodegenBackend for GccCodegenBackend {
|
||||
Ok((codegen_results, work_products))
|
||||
}
|
||||
|
||||
fn link(&self, sess: &Session, mut codegen_results: CodegenResults, outputs: &OutputFilenames) -> Result<(), ErrorReported> {
|
||||
fn link(&self, sess: &Session, codegen_results: CodegenResults, outputs: &OutputFilenames) -> Result<(), ErrorReported> {
|
||||
use rustc_codegen_ssa::back::link::link_binary;
|
||||
if let Some(symbols) = codegen_results.crate_info.exported_symbols.get_mut(&CrateType::Dylib) {
|
||||
// TODO:(antoyo): remove when global initializer work without calling a function at runtime.
|
||||
// HACK: since this codegen add some symbols (e.g. __gccGlobalCrateInit) and the UI
|
||||
// tests load libstd.so as a dynamic library, and rustc use a version-script to specify
|
||||
// the symbols visibility, we add * to export all symbols.
|
||||
// It seems other symbols from libstd/libcore are causing some issues here as well.
|
||||
symbols.push("*".to_string());
|
||||
}
|
||||
|
||||
link_binary::<crate::archive::ArArchiveBuilder<'_>>(
|
||||
sess,
|
||||
@ -203,6 +192,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 +263,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;
|
||||
|
@ -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";
|
@ -2,9 +2,8 @@ use rustc_codegen_ssa::traits::PreDefineMethods;
|
||||
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
||||
use rustc_middle::mir::mono::{Linkage, Visibility};
|
||||
use rustc_middle::ty::{self, Instance, TypeFoldable};
|
||||
use rustc_middle::ty::layout::{FnAbiExt, LayoutOf};
|
||||
use rustc_middle::ty::layout::{FnAbiOf, LayoutOf};
|
||||
use rustc_span::def_id::DefId;
|
||||
use rustc_target::abi::call::FnAbi;
|
||||
|
||||
use crate::base;
|
||||
use crate::context::CodegenCx;
|
||||
@ -18,12 +17,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);
|
||||
@ -32,7 +26,7 @@ impl<'gcc, 'tcx> PreDefineMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
||||
fn predefine_fn(&self, instance: Instance<'tcx>, linkage: Linkage, _visibility: Visibility, symbol_name: &str) {
|
||||
assert!(!instance.substs.needs_infer());
|
||||
|
||||
let fn_abi = FnAbi::of_instance(self, instance, &[]);
|
||||
let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty());
|
||||
self.linkage.set(base::linkage_to_gcc(linkage));
|
||||
let _decl = self.declare_fn(symbol_name, &fn_abi);
|
||||
//let attrs = self.tcx.codegen_fn_attrs(instance.def_id());
|
||||
|
@ -4,7 +4,7 @@ use gccjit::{Struct, Type};
|
||||
use crate::rustc_codegen_ssa::traits::{BaseTypeMethods, DerivedTypeMethods, LayoutTypeMethods};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::{self, Ty, TypeFoldable};
|
||||
use rustc_middle::ty::layout::{FnAbiExt, LayoutOf, TyAndLayout};
|
||||
use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout};
|
||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||
use rustc_target::abi::{self, Abi, F32, F64, FieldsShape, Int, Integer, Pointer, PointeeInfo, Size, TyAbiInterface, Variants};
|
||||
use rustc_target::abi::call::{CastTarget, FnAbi, Reg};
|
||||
@ -160,7 +160,7 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
|
||||
ty::Adt(def, _) if def.is_box() => {
|
||||
cx.type_ptr_to(cx.layout_of(self.ty.boxed_ty()).gcc_type(cx, true))
|
||||
}
|
||||
ty::FnPtr(sig) => cx.fn_ptr_backend_type(&FnAbi::of_fn_ptr(cx, sig, &[])),
|
||||
ty::FnPtr(sig) => cx.fn_ptr_backend_type(&cx.fn_abi_of_fn_ptr(sig, ty::List::empty())),
|
||||
_ => self.scalar_gcc_type_at(cx, scalar, Size::ZERO),
|
||||
};
|
||||
cx.scalar_types.borrow_mut().insert(self.ty, ty);
|
||||
|
@ -17,6 +17,7 @@ export LIBRARY_PATH="$GCC_PATH"
|
||||
if [[ "$1" == "--release" ]]; then
|
||||
export CHANNEL='release'
|
||||
CARGO_INCREMENTAL=1 cargo rustc --release
|
||||
shift
|
||||
else
|
||||
echo $LD_LIBRARY_PATH
|
||||
export CHANNEL='debug'
|
||||
@ -25,52 +26,60 @@ fi
|
||||
|
||||
source config.sh
|
||||
|
||||
rm -r target/out || true
|
||||
mkdir -p target/out/gccjit
|
||||
function clean() {
|
||||
rm -r target/out || true
|
||||
mkdir -p target/out/gccjit
|
||||
}
|
||||
|
||||
echo "[BUILD] mini_core"
|
||||
$RUSTC example/mini_core.rs --crate-name mini_core --crate-type lib,dylib --target $TARGET_TRIPLE
|
||||
function mini_tests() {
|
||||
echo "[BUILD] mini_core"
|
||||
$RUSTC example/mini_core.rs --crate-name mini_core --crate-type lib,dylib --target $TARGET_TRIPLE
|
||||
|
||||
echo "[BUILD] example"
|
||||
$RUSTC example/example.rs --crate-type lib --target $TARGET_TRIPLE
|
||||
echo "[BUILD] example"
|
||||
$RUSTC example/example.rs --crate-type lib --target $TARGET_TRIPLE
|
||||
|
||||
echo "[AOT] mini_core_hello_world"
|
||||
$RUSTC example/mini_core_hello_world.rs --crate-name mini_core_hello_world --crate-type bin -g --target $TARGET_TRIPLE
|
||||
$RUN_WRAPPER ./target/out/mini_core_hello_world abc bcd
|
||||
echo "[AOT] mini_core_hello_world"
|
||||
$RUSTC example/mini_core_hello_world.rs --crate-name mini_core_hello_world --crate-type bin -g --target $TARGET_TRIPLE
|
||||
$RUN_WRAPPER ./target/out/mini_core_hello_world abc bcd
|
||||
}
|
||||
|
||||
echo "[BUILD] sysroot"
|
||||
time ./build_sysroot/build_sysroot.sh
|
||||
function build_sysroot() {
|
||||
echo "[BUILD] sysroot"
|
||||
time ./build_sysroot/build_sysroot.sh
|
||||
}
|
||||
|
||||
echo "[AOT] arbitrary_self_types_pointers_and_wrappers"
|
||||
$RUSTC example/arbitrary_self_types_pointers_and_wrappers.rs --crate-name arbitrary_self_types_pointers_and_wrappers --crate-type bin --target $TARGET_TRIPLE
|
||||
$RUN_WRAPPER ./target/out/arbitrary_self_types_pointers_and_wrappers
|
||||
function std_tests() {
|
||||
echo "[AOT] arbitrary_self_types_pointers_and_wrappers"
|
||||
$RUSTC example/arbitrary_self_types_pointers_and_wrappers.rs --crate-name arbitrary_self_types_pointers_and_wrappers --crate-type bin --target $TARGET_TRIPLE
|
||||
$RUN_WRAPPER ./target/out/arbitrary_self_types_pointers_and_wrappers
|
||||
|
||||
echo "[AOT] alloc_system"
|
||||
$RUSTC example/alloc_system.rs --crate-type lib --target "$TARGET_TRIPLE"
|
||||
echo "[AOT] alloc_system"
|
||||
$RUSTC example/alloc_system.rs --crate-type lib --target "$TARGET_TRIPLE"
|
||||
|
||||
echo "[AOT] alloc_example"
|
||||
$RUSTC example/alloc_example.rs --crate-type bin --target $TARGET_TRIPLE
|
||||
$RUN_WRAPPER ./target/out/alloc_example
|
||||
echo "[AOT] alloc_example"
|
||||
$RUSTC example/alloc_example.rs --crate-type bin --target $TARGET_TRIPLE
|
||||
$RUN_WRAPPER ./target/out/alloc_example
|
||||
|
||||
echo "[AOT] dst_field_align"
|
||||
# FIXME(antoyo): Re-add -Zmir-opt-level=2 once rust-lang/rust#67529 is fixed.
|
||||
$RUSTC example/dst-field-align.rs --crate-name dst_field_align --crate-type bin --target $TARGET_TRIPLE
|
||||
$RUN_WRAPPER ./target/out/dst_field_align || (echo $?; false)
|
||||
echo "[AOT] dst_field_align"
|
||||
# FIXME(antoyo): Re-add -Zmir-opt-level=2 once rust-lang/rust#67529 is fixed.
|
||||
$RUSTC example/dst-field-align.rs --crate-name dst_field_align --crate-type bin --target $TARGET_TRIPLE
|
||||
$RUN_WRAPPER ./target/out/dst_field_align || (echo $?; false)
|
||||
|
||||
echo "[AOT] std_example"
|
||||
$RUSTC example/std_example.rs --crate-type bin --target $TARGET_TRIPLE
|
||||
$RUN_WRAPPER ./target/out/std_example --target $TARGET_TRIPLE
|
||||
echo "[AOT] std_example"
|
||||
$RUSTC example/std_example.rs --crate-type bin --target $TARGET_TRIPLE
|
||||
$RUN_WRAPPER ./target/out/std_example --target $TARGET_TRIPLE
|
||||
|
||||
echo "[AOT] subslice-patterns-const-eval"
|
||||
$RUSTC example/subslice-patterns-const-eval.rs --crate-type bin -Cpanic=abort --target $TARGET_TRIPLE
|
||||
$RUN_WRAPPER ./target/out/subslice-patterns-const-eval
|
||||
echo "[AOT] subslice-patterns-const-eval"
|
||||
$RUSTC example/subslice-patterns-const-eval.rs --crate-type bin -Cpanic=abort --target $TARGET_TRIPLE
|
||||
$RUN_WRAPPER ./target/out/subslice-patterns-const-eval
|
||||
|
||||
echo "[AOT] track-caller-attribute"
|
||||
$RUSTC example/track-caller-attribute.rs --crate-type bin -Cpanic=abort --target $TARGET_TRIPLE
|
||||
$RUN_WRAPPER ./target/out/track-caller-attribute
|
||||
echo "[AOT] track-caller-attribute"
|
||||
$RUSTC example/track-caller-attribute.rs --crate-type bin -Cpanic=abort --target $TARGET_TRIPLE
|
||||
$RUN_WRAPPER ./target/out/track-caller-attribute
|
||||
|
||||
echo "[BUILD] mod_bench"
|
||||
$RUSTC example/mod_bench.rs --crate-type bin --target $TARGET_TRIPLE
|
||||
echo "[BUILD] mod_bench"
|
||||
$RUSTC example/mod_bench.rs --crate-type bin --target $TARGET_TRIPLE
|
||||
}
|
||||
|
||||
# FIXME(antoyo): linker gives multiple definitions error on Linux
|
||||
#echo "[BUILD] sysroot in release mode"
|
||||
@ -95,11 +104,13 @@ $RUSTC example/mod_bench.rs --crate-type bin --target $TARGET_TRIPLE
|
||||
#fi
|
||||
#popd
|
||||
|
||||
pushd build_sysroot/sysroot_src/library/core/tests
|
||||
echo "[TEST] libcore"
|
||||
rm -r ./target || true
|
||||
../../../../../cargo.sh test
|
||||
popd
|
||||
function test_libcore() {
|
||||
pushd build_sysroot/sysroot_src/library/core/tests
|
||||
echo "[TEST] libcore"
|
||||
rm -r ./target || true
|
||||
../../../../../cargo.sh test
|
||||
popd
|
||||
}
|
||||
|
||||
# TODO(antoyo): uncomment when it works.
|
||||
#pushd regex
|
||||
@ -130,20 +141,21 @@ popd
|
||||
#echo "[BENCH RUN] mod_bench"
|
||||
#hyperfine --runs ${RUN_RUNS:-10} ./target/out/mod_bench{,_inline} ./target/out/mod_bench_llvm_*
|
||||
|
||||
echo
|
||||
echo "[TEST] rust-lang/rust"
|
||||
function test_rustc() {
|
||||
echo
|
||||
echo "[TEST] rust-lang/rust"
|
||||
|
||||
rust_toolchain=$(cat rust-toolchain)
|
||||
rust_toolchain=$(cat rust-toolchain)
|
||||
|
||||
git clone https://github.com/rust-lang/rust.git || true
|
||||
cd rust
|
||||
git fetch
|
||||
git checkout $(rustc -V | cut -d' ' -f3 | tr -d '(')
|
||||
export RUSTFLAGS=
|
||||
git clone https://github.com/rust-lang/rust.git || true
|
||||
cd rust
|
||||
git fetch
|
||||
git checkout $(rustc -V | cut -d' ' -f3 | tr -d '(')
|
||||
export RUSTFLAGS=
|
||||
|
||||
rm config.toml || true
|
||||
rm config.toml || true
|
||||
|
||||
cat > config.toml <<EOF
|
||||
cat > config.toml <<EOF
|
||||
[rust]
|
||||
codegen-backends = []
|
||||
deny-warnings = false
|
||||
@ -154,24 +166,52 @@ local-rebuild = true
|
||||
rustc = "$HOME/.rustup/toolchains/$rust_toolchain-$TARGET_TRIPLE/bin/rustc"
|
||||
EOF
|
||||
|
||||
rustc -V | cut -d' ' -f3 | tr -d '('
|
||||
git checkout $(rustc -V | cut -d' ' -f3 | tr -d '(') src/test
|
||||
rustc -V | cut -d' ' -f3 | tr -d '('
|
||||
git checkout $(rustc -V | cut -d' ' -f3 | tr -d '(') src/test
|
||||
|
||||
for test in $(rg -i --files-with-matches "//(\[\w+\])?~|// error-pattern:|// build-fail|// run-fail|-Cllvm-args" src/test/ui); do
|
||||
rm $test
|
||||
done
|
||||
for test in $(rg -i --files-with-matches "//(\[\w+\])?~|// error-pattern:|// build-fail|// run-fail|-Cllvm-args" src/test/ui); do
|
||||
rm $test
|
||||
done
|
||||
|
||||
git checkout -- src/test/ui/issues/auxiliary/issue-3136-a.rs # contains //~ERROR, but shouldn't be removed
|
||||
git checkout -- src/test/ui/issues/auxiliary/issue-3136-a.rs # contains //~ERROR, but shouldn't be removed
|
||||
|
||||
rm -r src/test/ui/{abi*,extern/,llvm-asm/,panic-runtime/,panics/,unsized-locals/,proc-macro/,threads-sendsync/,thinlto/,simd*,borrowck/,test*,*lto*.rs} || true
|
||||
for test in $(rg --files-with-matches "catch_unwind|should_panic|thread|lto" src/test/ui); do
|
||||
rm $test
|
||||
done
|
||||
git checkout src/test/ui/type-alias-impl-trait/auxiliary/cross_crate_ice.rs
|
||||
git checkout src/test/ui/type-alias-impl-trait/auxiliary/cross_crate_ice2.rs
|
||||
rm src/test/ui/llvm-asm/llvm-asm-in-out-operand.rs || true # TODO(antoyo): Enable back this test if I ever implement the llvm_asm! macro.
|
||||
rm -r src/test/ui/{abi*,extern/,llvm-asm/,panic-runtime/,panics/,unsized-locals/,proc-macro/,threads-sendsync/,thinlto/,simd*,borrowck/,test*,*lto*.rs} || true
|
||||
for test in $(rg --files-with-matches "catch_unwind|should_panic|thread|lto" src/test/ui); do
|
||||
rm $test
|
||||
done
|
||||
git checkout src/test/ui/type-alias-impl-trait/auxiliary/cross_crate_ice.rs
|
||||
git checkout src/test/ui/type-alias-impl-trait/auxiliary/cross_crate_ice2.rs
|
||||
rm src/test/ui/llvm-asm/llvm-asm-in-out-operand.rs || true # TODO(antoyo): Enable back this test if I ever implement the llvm_asm! macro.
|
||||
|
||||
RUSTC_ARGS="-Zpanic-abort-tests -Zcodegen-backend="$(pwd)"/../target/"$CHANNEL"/librustc_codegen_gcc."$dylib_ext" --sysroot "$(pwd)"/../build_sysroot/sysroot -Cpanic=abort"
|
||||
RUSTC_ARGS="-Zpanic-abort-tests -Zsymbol-mangling-version=v0 -Zcodegen-backend="$(pwd)"/../target/"$CHANNEL"/librustc_codegen_gcc."$dylib_ext" --sysroot "$(pwd)"/../build_sysroot/sysroot -Cpanic=abort"
|
||||
|
||||
echo "[TEST] rustc test suite"
|
||||
COMPILETEST_FORCE_STAGE0=1 ./x.py test --run always --stage 0 src/test/ui/ --rustc-args "$RUSTC_ARGS"
|
||||
echo "[TEST] rustc test suite"
|
||||
COMPILETEST_FORCE_STAGE0=1 ./x.py test --run always --stage 0 src/test/ui/ --rustc-args "$RUSTC_ARGS"
|
||||
}
|
||||
|
||||
function clean_ui_tests() {
|
||||
find rust/build/x86_64-unknown-linux-gnu/test/ui/ -name stamp -exec rm -rf {} \;
|
||||
}
|
||||
|
||||
case $1 in
|
||||
"--test-rustc")
|
||||
test_rustc
|
||||
;;
|
||||
|
||||
"--test-libcore")
|
||||
test_libcore
|
||||
;;
|
||||
|
||||
"--clean-ui-tests")
|
||||
clean_ui_tests
|
||||
;;
|
||||
|
||||
*)
|
||||
clean
|
||||
mini_tests
|
||||
build_sysroot
|
||||
std_tests
|
||||
test_libcore
|
||||
test_rustc
|
||||
;;
|
||||
esac
|
||||
|
Loading…
Reference in New Issue
Block a user