Merge pull request #282 from rust-lang/sync_from_rust_2023_06_11
Sync from rust 2023 06 11
This commit is contained in:
commit
1bbee3e217
17
Readme.md
17
Readme.md
@ -193,7 +193,7 @@ Using git-subtree with `rustc` requires a patched git to make it work.
|
||||
The PR that is needed is [here](https://github.com/gitgitgadget/git/pull/493).
|
||||
Use the following instructions to install it:
|
||||
|
||||
```
|
||||
```bash
|
||||
git clone git@github.com:tqc/git.git
|
||||
cd git
|
||||
git checkout tqc/subtree
|
||||
@ -204,6 +204,21 @@ make
|
||||
cp git-subtree ~/bin
|
||||
```
|
||||
|
||||
Then, do a sync with this command:
|
||||
|
||||
```bash
|
||||
PATH="$HOME/bin:$PATH" ~/bin/git-subtree push -P compiler/rustc_codegen_gcc/ ../rustc_codegen_gcc/ sync_branch_name
|
||||
cd ../rustc_codegen_gcc
|
||||
git checkout master
|
||||
git pull
|
||||
git checkout sync_branch_name
|
||||
git merge master
|
||||
```
|
||||
|
||||
TODO: write a script that does the above.
|
||||
|
||||
https://rust-lang.zulipchat.com/#narrow/stream/301329-t-devtools/topic/subtree.20madness/near/258877725
|
||||
|
||||
### How to use [mem-trace](https://github.com/antoyo/mem-trace)
|
||||
|
||||
`rustc` needs to be built without `jemalloc` so that `mem-trace` can overload `malloc` since `jemalloc` is linked statically, so a `LD_PRELOAD`-ed library won't a chance to intercept the calls to `malloc`.
|
||||
|
@ -9,6 +9,7 @@ compiler_builtins = "0.1"
|
||||
alloc = { path = "./sysroot_src/library/alloc" }
|
||||
std = { path = "./sysroot_src/library/std", features = ["panic_unwind", "backtrace"] }
|
||||
test = { path = "./sysroot_src/library/test" }
|
||||
proc_macro = { path = "./sysroot_src/library/proc_macro" }
|
||||
|
||||
[patch.crates-io]
|
||||
rustc-std-workspace-core = { path = "./sysroot_src/library/rustc-std-workspace-core" }
|
||||
|
@ -1,4 +1,4 @@
|
||||
#![feature(start, box_syntax, core_intrinsics, alloc_error_handler, lang_items)]
|
||||
#![feature(start, core_intrinsics, alloc_error_handler, lang_items)]
|
||||
#![no_std]
|
||||
|
||||
extern crate alloc;
|
||||
@ -38,7 +38,7 @@ fn eh_personality() -> ! {
|
||||
|
||||
#[start]
|
||||
fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
||||
let world: Box<&str> = box "Hello World!\0";
|
||||
let world: Box<&str> = Box::new("Hello World!\0");
|
||||
unsafe {
|
||||
puts(*world as *const str as *const u8);
|
||||
}
|
||||
|
@ -1,12 +1,6 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||
// SPDX-FileCopyrightText: The Rust Project Developers (see https://thanks.rust-lang.org)
|
||||
|
||||
#![no_std]
|
||||
#![feature(allocator_api, rustc_private)]
|
||||
#![cfg_attr(any(unix, target_os = "redox"), feature(libc))]
|
||||
@ -21,6 +15,7 @@
|
||||
const MIN_ALIGN: usize = 8;
|
||||
#[cfg(any(target_arch = "x86_64",
|
||||
target_arch = "aarch64",
|
||||
target_arch = "loongarch64",
|
||||
target_arch = "mips64",
|
||||
target_arch = "s390x",
|
||||
target_arch = "sparc64"))]
|
||||
|
@ -451,6 +451,9 @@ pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
|
||||
drop_in_place(to_drop);
|
||||
}
|
||||
|
||||
#[lang = "unpin"]
|
||||
pub auto trait Unpin {}
|
||||
|
||||
#[lang = "deref"]
|
||||
pub trait Deref {
|
||||
type Target: ?Sized;
|
||||
@ -488,9 +491,23 @@ impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Unique<U>> for Unique<T> where T: Uns
|
||||
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized, A: Allocator> CoerceUnsized<Box<U, A>> for Box<T, A> {}
|
||||
|
||||
impl<T> Box<T> {
|
||||
pub fn new(val: T) -> Box<T> {
|
||||
unsafe {
|
||||
let size = intrinsics::size_of::<T>();
|
||||
let ptr = libc::malloc(size);
|
||||
intrinsics::copy(&val as *const T as *const u8, ptr, size);
|
||||
Box(Unique { pointer: NonNull(ptr as *const T), _marker: PhantomData }, Global)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized, A: Allocator> Drop for Box<T, A> {
|
||||
fn drop(&mut self) {
|
||||
// drop is currently performed by compiler.
|
||||
// inner value is dropped by compiler.
|
||||
unsafe {
|
||||
libc::free(self.0.pointer.0 as *mut u8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -507,11 +524,6 @@ unsafe fn allocate(size: usize, _align: usize) -> *mut u8 {
|
||||
libc::malloc(size)
|
||||
}
|
||||
|
||||
#[lang = "box_free"]
|
||||
unsafe fn box_free<T: ?Sized>(ptr: Unique<T>, _alloc: ()) {
|
||||
libc::free(ptr.pointer.0 as *mut u8);
|
||||
}
|
||||
|
||||
#[lang = "drop"]
|
||||
pub trait Drop {
|
||||
fn drop(&mut self);
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Adapted from https://github.com/sunfishcode/mir2cranelift/blob/master/rust-examples/nocore-hello-world.rs
|
||||
|
||||
#![feature(
|
||||
no_core, unboxed_closures, start, lang_items, box_syntax, never_type, linkage,
|
||||
no_core, unboxed_closures, start, lang_items, never_type, linkage,
|
||||
extern_types, thread_local
|
||||
)]
|
||||
#![no_core]
|
||||
@ -163,7 +163,7 @@ fn main() {
|
||||
let ptr: *const u8 = hello as *const [u8] as *const u8;
|
||||
puts(ptr);
|
||||
|
||||
let world: Box<&str> = box "World!\0";
|
||||
let world: Box<&str> = Box::new("World!\0");
|
||||
puts(*world as *const str as *const u8);
|
||||
world as Box<dyn SomeTrait>;
|
||||
|
||||
@ -226,10 +226,10 @@ unsafe fn uninitialized<T>() -> T {
|
||||
}
|
||||
}
|
||||
|
||||
let _ = box NoisyDrop {
|
||||
let _ = Box::new(NoisyDrop {
|
||||
text: "Boxed outer got dropped!\0",
|
||||
inner: NoisyDropInner,
|
||||
} as Box<dyn SomeTrait>;
|
||||
}) as Box<dyn SomeTrait>;
|
||||
|
||||
const FUNC_REF: Option<fn()> = Some(main);
|
||||
#[allow(unreachable_code)]
|
||||
|
@ -1,4 +1,4 @@
|
||||
#![feature(start, box_syntax, core_intrinsics, lang_items)]
|
||||
#![feature(start, core_intrinsics, lang_items)]
|
||||
#![no_std]
|
||||
|
||||
#[link(name = "c")]
|
||||
|
@ -54,8 +54,8 @@ tests/ui/issues/issue-40883.rs
|
||||
tests/ui/issues/issue-43853.rs
|
||||
tests/ui/issues/issue-47364.rs
|
||||
tests/ui/macros/rfc-2011-nicer-assert-messages/assert-without-captures-does-not-create-unnecessary-code.rs
|
||||
tests/ui/rfc-2091-track-caller/std-panic-locations.rs
|
||||
tests/ui/rfcs/rfc1857-drop-order.rs
|
||||
tests/ui/rfcs/rfc-2091-track-caller/std-panic-locations.rs
|
||||
tests/ui/rfcs/rfc-1857-stabilize-drop-order/drop-order.rs
|
||||
tests/ui/simd/issue-17170.rs
|
||||
tests/ui/simd/issue-39720.rs
|
||||
tests/ui/simd/issue-89193.rs
|
||||
@ -66,3 +66,5 @@ tests/ui/generator/panic-safe.rs
|
||||
tests/ui/issues/issue-14875.rs
|
||||
tests/ui/issues/issue-29948.rs
|
||||
tests/ui/panic-while-printing.rs
|
||||
tests/ui/enum-discriminant/get_discr.rs
|
||||
tests/ui/panics/nested_panic_caught.rs
|
||||
|
68
messages.ftl
Normal file
68
messages.ftl
Normal file
@ -0,0 +1,68 @@
|
||||
codegen_gcc_invalid_minimum_alignment =
|
||||
invalid minimum global alignment: {$err}
|
||||
|
||||
codegen_gcc_invalid_monomorphization_basic_integer =
|
||||
invalid monomorphization of `{$name}` intrinsic: expected basic integer type, found `{$ty}`
|
||||
|
||||
codegen_gcc_invalid_monomorphization_expected_signed_unsigned =
|
||||
invalid monomorphization of `{$name}` intrinsic: expected element type `{$elem_ty}` of vector type `{$vec_ty}` to be a signed or unsigned integer type
|
||||
|
||||
codegen_gcc_invalid_monomorphization_expected_simd =
|
||||
invalid monomorphization of `{$name}` intrinsic: expected SIMD {$expected_ty} type, found non-SIMD `{$found_ty}`
|
||||
|
||||
codegen_gcc_invalid_monomorphization_inserted_type =
|
||||
invalid monomorphization of `{$name}` intrinsic: expected inserted type `{$in_elem}` (element of input `{$in_ty}`), found `{$out_ty}`
|
||||
|
||||
codegen_gcc_invalid_monomorphization_invalid_bitmask =
|
||||
invalid monomorphization of `{$name}` intrinsic: invalid bitmask `{$ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]`
|
||||
|
||||
codegen_gcc_invalid_monomorphization_invalid_float_vector =
|
||||
invalid monomorphization of `{$name}` intrinsic: unsupported element type `{$elem_ty}` of floating-point vector `{$vec_ty}`
|
||||
|
||||
codegen_gcc_invalid_monomorphization_mask_type =
|
||||
invalid monomorphization of `{$name}` intrinsic: mask element type is `{$ty}`, expected `i_`
|
||||
|
||||
codegen_gcc_invalid_monomorphization_mismatched_lengths =
|
||||
invalid monomorphization of `{$name}` intrinsic: mismatched lengths: mask length `{$m_len}` != other vector length `{$v_len}`
|
||||
|
||||
codegen_gcc_invalid_monomorphization_not_float =
|
||||
invalid monomorphization of `{$name}` intrinsic: `{$ty}` is not a floating-point type
|
||||
|
||||
codegen_gcc_invalid_monomorphization_return_element =
|
||||
invalid monomorphization of `{$name}` intrinsic: expected return element type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}` with element type `{$out_ty}`
|
||||
|
||||
codegen_gcc_invalid_monomorphization_return_integer_type =
|
||||
invalid monomorphization of `{$name}` intrinsic: expected return type with integer elements, found `{$ret_ty}` with non-integer `{$out_ty}`
|
||||
|
||||
codegen_gcc_invalid_monomorphization_return_length =
|
||||
invalid monomorphization of `{$name}` intrinsic: expected return type of length {$in_len}, found `{$ret_ty}` with length {$out_len}
|
||||
|
||||
codegen_gcc_invalid_monomorphization_return_length_input_type =
|
||||
invalid monomorphization of `{$name}` intrinsic: expected return type with length {$in_len} (same as input type `{$in_ty}`), found `{$ret_ty}` with length {$out_len}
|
||||
|
||||
codegen_gcc_invalid_monomorphization_return_type =
|
||||
invalid monomorphization of `{$name}` intrinsic: expected return type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}`
|
||||
|
||||
codegen_gcc_invalid_monomorphization_simd_shuffle =
|
||||
invalid monomorphization of `{$name}` intrinsic: simd_shuffle index must be an array of `u32`, got `{$ty}`
|
||||
|
||||
codegen_gcc_invalid_monomorphization_unrecognized =
|
||||
invalid monomorphization of `{$name}` intrinsic: unrecognized intrinsic `{$name}`
|
||||
|
||||
codegen_gcc_invalid_monomorphization_unsupported_cast =
|
||||
invalid monomorphization of `{$name}` intrinsic: unsupported cast from `{$in_ty}` with element `{$in_elem}` to `{$ret_ty}` with element `{$out_elem}`
|
||||
|
||||
codegen_gcc_invalid_monomorphization_unsupported_element =
|
||||
invalid monomorphization of `{$name}` intrinsic: unsupported {$name} from `{$in_ty}` with element `{$elem_ty}` to `{$ret_ty}`
|
||||
|
||||
codegen_gcc_invalid_monomorphization_unsupported_operation =
|
||||
invalid monomorphization of `{$name}` intrinsic: unsupported operation on `{$in_ty}` with element `{$in_elem}`
|
||||
|
||||
codegen_gcc_lto_not_supported =
|
||||
LTO is not supported. You may get a linker error.
|
||||
|
||||
codegen_gcc_tied_target_features = the target features {$features} must all be either enabled or disabled together
|
||||
.help = add the missing features in a `target_feature` attribute
|
||||
|
||||
codegen_gcc_unwinding_inline_asm =
|
||||
GCC backend does not support unwinding from inline asm
|
@ -1,49 +0,0 @@
|
||||
From dd82e95c9de212524e14fc60155de1ae40156dfc Mon Sep 17 00:00:00 2001
|
||||
From: bjorn3 <bjorn3@users.noreply.github.com>
|
||||
Date: Sun, 24 Nov 2019 15:34:06 +0100
|
||||
Subject: [PATCH] [core] Ignore failing tests
|
||||
|
||||
---
|
||||
library/core/tests/iter.rs | 4 ++++
|
||||
library/core/tests/num/bignum.rs | 10 ++++++++++
|
||||
library/core/tests/num/mod.rs | 5 +++--
|
||||
library/core/tests/time.rs | 1 +
|
||||
4 files changed, 18 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/library/core/tests/array.rs b/library/core/tests/array.rs
|
||||
index 4bc44e9..8e3c7a4 100644
|
||||
--- a/library/core/tests/array.rs
|
||||
+++ b/library/core/tests/array.rs
|
||||
@@ -242,6 +242,7 @@ fn iterator_drops() {
|
||||
assert_eq!(i.get(), 5);
|
||||
}
|
||||
|
||||
+/*
|
||||
// This test does not work on targets without panic=unwind support.
|
||||
// To work around this problem, test is marked is should_panic, so it will
|
||||
// be automagically skipped on unsuitable targets, such as
|
||||
@@ -283,6 +284,7 @@ fn array_default_impl_avoids_leaks_on_panic() {
|
||||
assert_eq!(COUNTER.load(Relaxed), 0);
|
||||
panic!("test succeeded")
|
||||
}
|
||||
+*/
|
||||
|
||||
#[test]
|
||||
fn empty_array_is_always_default() {
|
||||
@@ -304,6 +304,7 @@ fn array_map() {
|
||||
assert_eq!(b, [1, 2, 3]);
|
||||
}
|
||||
|
||||
+/*
|
||||
// See note on above test for why `should_panic` is used.
|
||||
#[test]
|
||||
#[should_panic(expected = "test succeeded")]
|
||||
@@ -332,6 +333,7 @@ fn array_map_drop_safety() {
|
||||
assert_eq!(DROPPED.load(Ordering::SeqCst), num_to_create);
|
||||
panic!("test succeeded")
|
||||
}
|
||||
+*/
|
||||
|
||||
#[test]
|
||||
fn cell_allows_array_cycle() {
|
||||
-- 2.21.0 (Apple Git-122)
|
@ -1,3 +1,3 @@
|
||||
[toolchain]
|
||||
channel = "nightly-2023-03-02"
|
||||
channel = "nightly-2023-06-19"
|
||||
components = ["rust-src", "rustc-dev", "llvm-tools-preview"]
|
||||
|
@ -1,11 +1,13 @@
|
||||
#[cfg(feature="master")]
|
||||
use gccjit::FnAttribute;
|
||||
use gccjit::{FunctionType, GlobalKind, ToRValue};
|
||||
use rustc_ast::expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS};
|
||||
use rustc_ast::expand::allocator::{
|
||||
alloc_error_handler_name, default_fn_name, global_fn_name, AllocatorKind, AllocatorTy,
|
||||
ALLOCATOR_METHODS, NO_ALLOC_SHIM_IS_UNSTABLE,
|
||||
};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::config::OomStrategy;
|
||||
use rustc_span::symbol::sym;
|
||||
|
||||
use crate::GccContext;
|
||||
|
||||
@ -22,6 +24,7 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut GccContext, _module_nam
|
||||
let i8p = i8.make_pointer();
|
||||
let void = context.new_type::<()>();
|
||||
|
||||
if kind == AllocatorKind::Default {
|
||||
for method in ALLOCATOR_METHODS {
|
||||
let mut types = Vec::with_capacity(method.inputs.len());
|
||||
for ty in method.inputs.iter() {
|
||||
@ -44,7 +47,7 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut GccContext, _module_nam
|
||||
panic!("invalid allocator output")
|
||||
}
|
||||
};
|
||||
let name = format!("__rust_{}", method.name);
|
||||
let name = global_fn_name(method.name);
|
||||
|
||||
let args: Vec<_> = types.iter().enumerate()
|
||||
.map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index)))
|
||||
@ -59,7 +62,7 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut GccContext, _module_nam
|
||||
// TODO(antoyo): emit unwind tables.
|
||||
}
|
||||
|
||||
let callee = kind.fn_name(method.name);
|
||||
let callee = default_fn_name(method.name);
|
||||
let args: Vec<_> = types.iter().enumerate()
|
||||
.map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index)))
|
||||
.collect();
|
||||
@ -86,6 +89,7 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut GccContext, _module_nam
|
||||
// TODO(@Commeownist): Check if we need to emit some extra debugging info in certain circumstances
|
||||
// as described in https://github.com/rust-lang/rust/commit/77a96ed5646f7c3ee8897693decc4626fe380643
|
||||
}
|
||||
}
|
||||
|
||||
let types = [usize, usize];
|
||||
let name = "__rust_alloc_error_handler".to_string();
|
||||
@ -99,7 +103,7 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut GccContext, _module_nam
|
||||
func.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden));
|
||||
}
|
||||
|
||||
let callee = alloc_error_handler_kind.fn_name(sym::oom);
|
||||
let callee = alloc_error_handler_name(alloc_error_handler_kind);
|
||||
let args: Vec<_> = types.iter().enumerate()
|
||||
.map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index)))
|
||||
.collect();
|
||||
@ -123,4 +127,9 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut GccContext, _module_nam
|
||||
let value = tcx.sess.opts.unstable_opts.oom.should_panic();
|
||||
let value = context.new_rvalue_from_int(i8, value as i32);
|
||||
global.global_set_initializer_rvalue(value);
|
||||
|
||||
let name = NO_ALLOC_SHIM_IS_UNSTABLE.to_string();
|
||||
let global = context.new_global(None, GlobalKind::Exported, i8, name);
|
||||
let value = context.new_rvalue_from_int(i8, 0);
|
||||
global.global_set_initializer_rvalue(value);
|
||||
}
|
||||
|
15
src/asm.rs
15
src/asm.rs
@ -501,7 +501,7 @@ fn codegen_inline_asm(&mut self, template: &[InlineAsmTemplatePiece], rust_opera
|
||||
if options.contains(InlineAsmOptions::NORETURN) {
|
||||
let builtin_unreachable = self.context.get_builtin_function("__builtin_unreachable");
|
||||
let builtin_unreachable: RValue<'gcc> = unsafe { std::mem::transmute(builtin_unreachable) };
|
||||
self.call(self.type_void(), None, builtin_unreachable, &[], None);
|
||||
self.call(self.type_void(), None, None, builtin_unreachable, &[], None);
|
||||
}
|
||||
|
||||
// Write results to outputs.
|
||||
@ -518,7 +518,6 @@ fn codegen_inline_asm(&mut self, template: &[InlineAsmTemplatePiece], rust_opera
|
||||
OperandValue::Immediate(op.tmp_var.to_rvalue()).store(self, place);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -593,6 +592,11 @@ fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister {
|
||||
InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => "r",
|
||||
InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => "w",
|
||||
InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => "r",
|
||||
InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::reg) => "r",
|
||||
InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) => "f",
|
||||
InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => "r",
|
||||
InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_addr) => "a",
|
||||
InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_data) => "d",
|
||||
InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => "d", // more specific than "r"
|
||||
InlineAsmRegClass::Mips(MipsInlineAsmRegClass::freg) => "f",
|
||||
InlineAsmRegClass::Msp430(Msp430InlineAsmRegClass::reg) => "r",
|
||||
@ -664,6 +668,11 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl
|
||||
InlineAsmRegClass::Avr(_) => unimplemented!(),
|
||||
InlineAsmRegClass::Bpf(_) => unimplemented!(),
|
||||
InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => cx.type_i32(),
|
||||
InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::reg) => cx.type_i32(),
|
||||
InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) => cx.type_f32(),
|
||||
InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => cx.type_i32(),
|
||||
InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_addr) => cx.type_i32(),
|
||||
InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_data) => cx.type_i32(),
|
||||
InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => cx.type_i32(),
|
||||
InlineAsmRegClass::Mips(MipsInlineAsmRegClass::freg) => cx.type_f32(),
|
||||
InlineAsmRegClass::Msp430(_) => unimplemented!(),
|
||||
@ -798,6 +807,7 @@ fn modifier_to_gcc(arch: InlineAsmArch, reg: InlineAsmRegClass, modifier: Option
|
||||
}
|
||||
}
|
||||
InlineAsmRegClass::Hexagon(_) => None,
|
||||
InlineAsmRegClass::LoongArch(_) => None,
|
||||
InlineAsmRegClass::Mips(_) => None,
|
||||
InlineAsmRegClass::Nvptx(_) => None,
|
||||
InlineAsmRegClass::PowerPC(_) => None,
|
||||
@ -849,6 +859,7 @@ fn modifier_to_gcc(arch: InlineAsmArch, reg: InlineAsmRegClass, modifier: Option
|
||||
InlineAsmRegClass::Avr(_) => None,
|
||||
InlineAsmRegClass::S390x(_) => None,
|
||||
InlineAsmRegClass::Msp430(_) => None,
|
||||
InlineAsmRegClass::M68k(_) => None,
|
||||
InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
|
||||
bug!("LLVM backend does not support SPIR-V")
|
||||
}
|
||||
|
@ -13,7 +13,7 @@
|
||||
use rustc_span::symbol::sym;
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
|
||||
use crate::context::CodegenCx;
|
||||
use crate::{context::CodegenCx, errors::TiedTargetFeatures};
|
||||
|
||||
// Given a map from target_features to whether they are enabled or disabled,
|
||||
// ensure only valid combinations are allowed.
|
||||
@ -123,10 +123,11 @@ pub fn from_fn_attrs<'gcc, 'tcx>(
|
||||
let span = cx.tcx
|
||||
.get_attr(instance.def_id(), sym::target_feature)
|
||||
.map_or_else(|| cx.tcx.def_span(instance.def_id()), |a| a.span);
|
||||
let msg = format!("the target features {} must all be either enabled or disabled together", features.join(", "));
|
||||
let mut err = cx.tcx.sess.struct_span_err(span, &msg);
|
||||
err.help("add the missing features in a `target_feature` attribute");
|
||||
err.emit();
|
||||
cx.tcx.sess.create_err(TiedTargetFeatures {
|
||||
features: features.join(", "),
|
||||
span,
|
||||
})
|
||||
.emit();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -35,6 +35,7 @@
|
||||
};
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
|
||||
use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
|
||||
use rustc_middle::ty::layout::{FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, HasTyCtxt, LayoutError, LayoutOfHelpers, TyAndLayout};
|
||||
use rustc_span::Span;
|
||||
@ -180,6 +181,8 @@ fn check_call<'b>(&mut self, _typ: &str, func: Function<'gcc>, args: &'b [RValue
|
||||
})
|
||||
.collect();
|
||||
|
||||
debug_assert_eq!(casted_args.len(), args.len());
|
||||
|
||||
Cow::Owned(casted_args)
|
||||
}
|
||||
|
||||
@ -206,7 +209,7 @@ fn check_ptr_call<'b>(&mut self, _typ: &str, func_ptr: RValue<'gcc>, args: &'b [
|
||||
|
||||
let func_name = format!("{:?}", func_ptr);
|
||||
|
||||
let casted_args: Vec<_> = param_types
|
||||
let mut casted_args: Vec<_> = param_types
|
||||
.into_iter()
|
||||
.zip(args.iter())
|
||||
.enumerate()
|
||||
@ -236,6 +239,11 @@ fn check_ptr_call<'b>(&mut self, _typ: &str, func_ptr: RValue<'gcc>, args: &'b [
|
||||
})
|
||||
.collect();
|
||||
|
||||
// NOTE: to take into account variadic functions.
|
||||
for i in casted_args.len()..args.len() {
|
||||
casted_args.push(args[i]);
|
||||
}
|
||||
|
||||
Cow::Owned(casted_args)
|
||||
}
|
||||
|
||||
@ -279,8 +287,17 @@ fn function_call(&mut self, func: RValue<'gcc>, args: &[RValue<'gcc>], _funclet:
|
||||
}
|
||||
}
|
||||
|
||||
fn function_ptr_call(&mut self, func_ptr: RValue<'gcc>, args: &[RValue<'gcc>], _funclet: Option<&Funclet>) -> RValue<'gcc> {
|
||||
let gcc_func = func_ptr.get_type().dyncast_function_ptr_type().expect("function ptr");
|
||||
fn function_ptr_call(&mut self, typ: Type<'gcc>, mut func_ptr: RValue<'gcc>, args: &[RValue<'gcc>], _funclet: Option<&Funclet>) -> RValue<'gcc> {
|
||||
let gcc_func =
|
||||
match func_ptr.get_type().dyncast_function_ptr_type() {
|
||||
Some(func) => func,
|
||||
None => {
|
||||
// NOTE: due to opaque pointers now being used, we need to cast here.
|
||||
let new_func_type = typ.dyncast_function_ptr_type().expect("function ptr");
|
||||
func_ptr = self.context.new_cast(None, func_ptr, typ);
|
||||
new_func_type
|
||||
},
|
||||
};
|
||||
let func_name = format!("{:?}", func_ptr);
|
||||
let previous_arg_count = args.len();
|
||||
let orig_args = args;
|
||||
@ -423,16 +440,17 @@ fn ret_void(&mut self) {
|
||||
self.llbb().end_with_void_return(None)
|
||||
}
|
||||
|
||||
fn ret(&mut self, value: RValue<'gcc>) {
|
||||
let value =
|
||||
fn ret(&mut self, mut value: RValue<'gcc>) {
|
||||
if self.structs_as_pointer.borrow().contains(&value) {
|
||||
// NOTE: hack to workaround a limitation of the rustc API: see comment on
|
||||
// CodegenCx.structs_as_pointer
|
||||
value.dereference(None).to_rvalue()
|
||||
value = value.dereference(None).to_rvalue();
|
||||
}
|
||||
let expected_return_type = self.current_func().get_return_type();
|
||||
if !expected_return_type.is_compatible_with(value.get_type()) {
|
||||
// NOTE: due to opaque pointers now being used, we need to cast here.
|
||||
value = self.context.new_cast(None, value, expected_return_type);
|
||||
}
|
||||
else {
|
||||
value
|
||||
};
|
||||
self.llbb().end_with_return(None, value);
|
||||
}
|
||||
|
||||
@ -455,12 +473,12 @@ fn switch(&mut self, value: RValue<'gcc>, default_block: Block<'gcc>, cases: imp
|
||||
}
|
||||
|
||||
#[cfg(feature="master")]
|
||||
fn invoke(&mut self, typ: Type<'gcc>, _fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, func: RValue<'gcc>, args: &[RValue<'gcc>], then: Block<'gcc>, catch: Block<'gcc>, _funclet: Option<&Funclet>) -> RValue<'gcc> {
|
||||
fn invoke(&mut self, typ: Type<'gcc>, fn_attrs: Option<&CodegenFnAttrs>, _fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, func: RValue<'gcc>, args: &[RValue<'gcc>], then: Block<'gcc>, catch: Block<'gcc>, _funclet: Option<&Funclet>) -> RValue<'gcc> {
|
||||
let try_block = self.current_func().new_block("try");
|
||||
|
||||
let current_block = self.block.clone();
|
||||
self.block = try_block;
|
||||
let call = self.call(typ, None, func, args, None); // TODO(antoyo): use funclet here?
|
||||
let call = self.call(typ, fn_attrs, None, func, args, None); // TODO(antoyo): use funclet here?
|
||||
self.block = current_block;
|
||||
|
||||
let return_value = self.current_func()
|
||||
@ -483,8 +501,8 @@ fn invoke(&mut self, typ: Type<'gcc>, _fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, f
|
||||
}
|
||||
|
||||
#[cfg(not(feature="master"))]
|
||||
fn invoke(&mut self, typ: Type<'gcc>, fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, func: RValue<'gcc>, args: &[RValue<'gcc>], then: Block<'gcc>, catch: Block<'gcc>, _funclet: Option<&Funclet>) -> RValue<'gcc> {
|
||||
let call_site = self.call(typ, None, func, args, None);
|
||||
fn invoke(&mut self, typ: Type<'gcc>, fn_attrs: &CodegenFnAttrs, fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, func: RValue<'gcc>, args: &[RValue<'gcc>], then: Block<'gcc>, catch: Block<'gcc>, _funclet: Option<&Funclet>) -> RValue<'gcc> {
|
||||
let call_site = self.call(typ, fn_attrs, None, func, args, None);
|
||||
let condition = self.context.new_rvalue_from_int(self.bool_type, 1);
|
||||
self.llbb().end_with_conditional(None, condition, then, catch);
|
||||
if let Some(_fn_abi) = fn_abi {
|
||||
@ -718,17 +736,25 @@ fn byte_array_alloca(&mut self, _len: RValue<'gcc>, _align: Align) -> RValue<'gc
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
fn load(&mut self, pointee_ty: Type<'gcc>, ptr: RValue<'gcc>, _align: Align) -> RValue<'gcc> {
|
||||
fn load(&mut self, pointee_ty: Type<'gcc>, ptr: RValue<'gcc>, align: Align) -> RValue<'gcc> {
|
||||
let block = self.llbb();
|
||||
let function = block.get_function();
|
||||
// NOTE: instead of returning the dereference here, we have to assign it to a variable in
|
||||
// the current basic block. Otherwise, it could be used in another basic block, causing a
|
||||
// dereference after a drop, for instance.
|
||||
// TODO(antoyo): handle align of the load instruction.
|
||||
let ptr = self.context.new_cast(None, ptr, pointee_ty.make_pointer());
|
||||
// FIXME(antoyo): this check that we don't call get_aligned() a second time on a type.
|
||||
// Ideally, we shouldn't need to do this check.
|
||||
let aligned_type =
|
||||
if pointee_ty == self.cx.u128_type || pointee_ty == self.cx.i128_type {
|
||||
pointee_ty
|
||||
}
|
||||
else {
|
||||
pointee_ty.get_aligned(align.bytes())
|
||||
};
|
||||
let ptr = self.context.new_cast(None, ptr, aligned_type.make_pointer());
|
||||
let deref = ptr.dereference(None).to_rvalue();
|
||||
unsafe { RETURN_VALUE_COUNT += 1 };
|
||||
let loaded_value = function.new_local(None, pointee_ty, &format!("loadedValue{}", unsafe { RETURN_VALUE_COUNT }));
|
||||
let loaded_value = function.new_local(None, aligned_type, &format!("loadedValue{}", unsafe { RETURN_VALUE_COUNT }));
|
||||
block.add_assignment(None, loaded_value, deref);
|
||||
loaded_value.to_rvalue()
|
||||
}
|
||||
@ -757,7 +783,7 @@ fn load_operand(&mut self, place: PlaceRef<'tcx, RValue<'gcc>>) -> OperandRef<'t
|
||||
assert_eq!(place.llextra.is_some(), place.layout.is_unsized());
|
||||
|
||||
if place.layout.is_zst() {
|
||||
return OperandRef::new_zst(self, place.layout);
|
||||
return OperandRef::zero_sized(place.layout);
|
||||
}
|
||||
|
||||
fn scalar_load_metadata<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>, load: RValue<'gcc>, scalar: &abi::Scalar) {
|
||||
@ -908,7 +934,9 @@ fn gep(&mut self, _typ: Type<'gcc>, ptr: RValue<'gcc>, indices: &[RValue<'gcc>])
|
||||
self.context.new_bitcast(None, result, ptr_type)
|
||||
}
|
||||
|
||||
fn inbounds_gep(&mut self, _typ: Type<'gcc>, ptr: RValue<'gcc>, indices: &[RValue<'gcc>]) -> RValue<'gcc> {
|
||||
fn inbounds_gep(&mut self, typ: Type<'gcc>, ptr: RValue<'gcc>, indices: &[RValue<'gcc>]) -> RValue<'gcc> {
|
||||
// NOTE: due to opaque pointers now being used, we need to cast here.
|
||||
let ptr = self.context.new_cast(None, ptr, typ.make_pointer());
|
||||
// NOTE: array indexing is always considered in bounds in GCC (TODO(antoyo): to be verified).
|
||||
let mut indices = indices.into_iter();
|
||||
let index = indices.next().expect("first index in inbounds_gep");
|
||||
@ -937,6 +965,8 @@ fn struct_gep(&mut self, value_type: Type<'gcc>, ptr: RValue<'gcc>, idx: u64) ->
|
||||
element.get_address(None)
|
||||
}
|
||||
else if let Some(struct_type) = value_type.is_struct() {
|
||||
// NOTE: due to opaque pointers now being used, we need to bitcast here.
|
||||
let ptr = self.bitcast_if_needed(ptr, value_type.make_pointer());
|
||||
ptr.dereference_field(None, struct_type.get_field(idx as i32)).get_address(None)
|
||||
}
|
||||
else {
|
||||
@ -1226,6 +1256,11 @@ fn cleanup_landing_pad(&mut self, _pers_fn: RValue<'gcc>) -> (RValue<'gcc>, RVal
|
||||
(value1, value2)
|
||||
}
|
||||
|
||||
fn filter_landing_pad(&mut self, pers_fn: RValue<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) {
|
||||
// TODO(antoyo): generate the correct landing pad
|
||||
self.cleanup_landing_pad(pers_fn)
|
||||
}
|
||||
|
||||
#[cfg(feature="master")]
|
||||
fn resume(&mut self, exn0: RValue<'gcc>, _exn1: RValue<'gcc>) {
|
||||
let exn_type = exn0.get_type();
|
||||
@ -1350,7 +1385,8 @@ fn lifetime_end(&mut self, _ptr: RValue<'gcc>, _size: Size) {
|
||||
|
||||
fn call(
|
||||
&mut self,
|
||||
_typ: Type<'gcc>,
|
||||
typ: Type<'gcc>,
|
||||
_fn_attrs: Option<&CodegenFnAttrs>,
|
||||
fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>,
|
||||
func: RValue<'gcc>,
|
||||
args: &[RValue<'gcc>],
|
||||
@ -1363,7 +1399,7 @@ fn call(
|
||||
}
|
||||
else {
|
||||
// If it's a not function that was defined, it's a function pointer.
|
||||
self.function_ptr_call(func, args, funclet)
|
||||
self.function_ptr_call(typ, func, args, funclet)
|
||||
};
|
||||
if let Some(_fn_abi) = fn_abi {
|
||||
// TODO(bjorn3): Apply function attributes
|
||||
@ -1836,7 +1872,8 @@ pub fn vector_select(&mut self, cond: RValue<'gcc>, then_val: RValue<'gcc>, else
|
||||
|
||||
#[cfg(feature="master")]
|
||||
let (cond, element_type) = {
|
||||
let then_val_vector_type = then_val.get_type().dyncast_vector().expect("vector type");
|
||||
// TODO(antoyo): dyncast_vector should not require a call to unqualified.
|
||||
let then_val_vector_type = then_val.get_type().unqualified().dyncast_vector().expect("vector type");
|
||||
let then_val_element_type = then_val_vector_type.get_element_type();
|
||||
let then_val_element_size = then_val_element_type.get_size();
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
pub fn get_fn<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, instance: Instance<'tcx>) -> Function<'gcc> {
|
||||
let tcx = cx.tcx();
|
||||
|
||||
assert!(!instance.substs.needs_infer());
|
||||
assert!(!instance.substs.has_infer());
|
||||
assert!(!instance.substs.has_escaping_bound_vars());
|
||||
|
||||
let sym = tcx.symbol_name(instance).name;
|
||||
|
@ -1,17 +1,15 @@
|
||||
use gccjit::LValue;
|
||||
use gccjit::{RValue, Type, ToRValue};
|
||||
use rustc_codegen_ssa::mir::place::PlaceRef;
|
||||
use rustc_codegen_ssa::traits::{
|
||||
BaseTypeMethods,
|
||||
ConstMethods,
|
||||
DerivedTypeMethods,
|
||||
MiscMethods,
|
||||
StaticMethods,
|
||||
};
|
||||
use rustc_middle::mir::Mutability;
|
||||
use rustc_middle::ty::layout::{TyAndLayout, LayoutOf};
|
||||
use rustc_middle::ty::layout::{LayoutOf};
|
||||
use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc, Scalar};
|
||||
use rustc_target::abi::{self, HasDataLayout, Pointer, Size};
|
||||
use rustc_target::abi::{self, HasDataLayout, Pointer};
|
||||
|
||||
use crate::consts::const_alloc_to_gcc;
|
||||
use crate::context::CodegenCx;
|
||||
@ -73,6 +71,11 @@ fn const_undef(&self, typ: Type<'gcc>) -> RValue<'gcc> {
|
||||
}
|
||||
}
|
||||
|
||||
fn const_poison(&self, typ: Type<'gcc>) -> RValue<'gcc> {
|
||||
// No distinction between undef and poison.
|
||||
self.const_undef(typ)
|
||||
}
|
||||
|
||||
fn const_int(&self, typ: Type<'gcc>, int: i64) -> RValue<'gcc> {
|
||||
self.gcc_int(typ, int)
|
||||
}
|
||||
@ -105,6 +108,10 @@ fn const_u64(&self, i: u64) -> RValue<'gcc> {
|
||||
self.const_uint(self.type_u64(), i)
|
||||
}
|
||||
|
||||
fn const_u128(&self, i: u128) -> RValue<'gcc> {
|
||||
self.const_uint_big(self.type_u128(), i)
|
||||
}
|
||||
|
||||
fn const_usize(&self, i: u64) -> RValue<'gcc> {
|
||||
let bit_size = self.data_layout().pointer_size.bits();
|
||||
if bit_size < 64 {
|
||||
@ -235,28 +242,26 @@ fn const_data_from_alloc(&self, alloc: ConstAllocation<'tcx>) -> Self::Value {
|
||||
const_alloc_to_gcc(self, alloc)
|
||||
}
|
||||
|
||||
fn from_const_alloc(&self, layout: TyAndLayout<'tcx>, alloc: ConstAllocation<'tcx>, offset: Size) -> PlaceRef<'tcx, RValue<'gcc>> {
|
||||
assert_eq!(alloc.inner().align, layout.align.abi);
|
||||
let ty = self.type_ptr_to(layout.gcc_type(self));
|
||||
let value =
|
||||
if layout.size == Size::ZERO {
|
||||
let value = self.const_usize(alloc.inner().align.bytes());
|
||||
self.const_bitcast(value, ty)
|
||||
}
|
||||
else {
|
||||
let init = const_alloc_to_gcc(self, alloc);
|
||||
let base_addr = self.static_addr_of(init, alloc.inner().align, None);
|
||||
|
||||
let array = self.const_bitcast(base_addr, self.type_i8p());
|
||||
let value = self.context.new_array_access(None, array, self.const_usize(offset.bytes())).get_address(None);
|
||||
self.const_bitcast(value, ty)
|
||||
};
|
||||
PlaceRef::new_sized(value, layout)
|
||||
}
|
||||
|
||||
fn const_ptrcast(&self, val: RValue<'gcc>, ty: Type<'gcc>) -> RValue<'gcc> {
|
||||
self.context.new_cast(None, val, ty)
|
||||
}
|
||||
|
||||
fn const_bitcast(&self, value: RValue<'gcc>, typ: Type<'gcc>) -> RValue<'gcc> {
|
||||
if value.get_type() == self.bool_type.make_pointer() {
|
||||
if let Some(pointee) = typ.get_pointee() {
|
||||
if pointee.dyncast_vector().is_some() {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
}
|
||||
// NOTE: since bitcast makes a value non-constant, don't bitcast if not necessary as some
|
||||
// SIMD builtins require a constant value.
|
||||
self.bitcast_if_needed(value, typ)
|
||||
}
|
||||
|
||||
fn const_ptr_byte_offset(&self, base_addr: Self::Value, offset: abi::Size) -> Self::Value {
|
||||
self.context.new_array_access(None, base_addr, self.const_usize(offset.bytes())).get_address(None)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait SignType<'gcc, 'tcx> {
|
||||
|
@ -1,6 +1,6 @@
|
||||
#[cfg(feature = "master")]
|
||||
use gccjit::{FnAttribute, VarAttribute, Visibility};
|
||||
use gccjit::{Function, GlobalKind, LValue, RValue, ToRValue, Type};
|
||||
use gccjit::{Function, GlobalKind, LValue, RValue, ToRValue};
|
||||
use rustc_codegen_ssa::traits::{BaseTypeMethods, ConstMethods, DerivedTypeMethods, StaticMethods};
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
|
||||
@ -16,21 +16,6 @@
|
||||
use crate::errors::InvalidMinimumAlignment;
|
||||
use crate::type_of::LayoutGccExt;
|
||||
|
||||
impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
||||
pub fn const_bitcast(&self, value: RValue<'gcc>, typ: Type<'gcc>) -> RValue<'gcc> {
|
||||
if value.get_type() == self.bool_type.make_pointer() {
|
||||
if let Some(pointee) = typ.get_pointee() {
|
||||
if pointee.dyncast_vector().is_some() {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
}
|
||||
// NOTE: since bitcast makes a value non-constant, don't bitcast if not necessary as some
|
||||
// SIMD builtins require a constant value.
|
||||
self.bitcast_if_needed(value, typ)
|
||||
}
|
||||
}
|
||||
|
||||
fn set_global_alignment<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, gv: LValue<'gcc>, mut align: Align) {
|
||||
// The target may require greater alignment for globals than the type does.
|
||||
// Note: GCC and Clang also allow `__attribute__((aligned))` on variables,
|
||||
@ -39,7 +24,7 @@ fn set_global_alignment<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, gv: LValue<'gcc>
|
||||
match Align::from_bits(min) {
|
||||
Ok(min) => align = align.max(min),
|
||||
Err(err) => {
|
||||
cx.sess().emit_err(InvalidMinimumAlignment { err });
|
||||
cx.sess().emit_err(InvalidMinimumAlignment { err: err.to_string() });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -477,7 +477,7 @@ impl<'gcc, 'tcx> LayoutOfHelpers<'tcx> for CodegenCx<'gcc, 'tcx> {
|
||||
#[inline]
|
||||
fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {
|
||||
if let LayoutError::SizeOverflow(_) = err {
|
||||
self.sess().emit_fatal(respan(span, err))
|
||||
self.sess().emit_fatal(respan(span, err.into_diagnostic()))
|
||||
} else {
|
||||
span_bug!(span, "failed to get layout for `{}`: {}", ty, err)
|
||||
}
|
||||
@ -499,21 +499,12 @@ fn handle_fn_abi_err(
|
||||
} else {
|
||||
match fn_abi_request {
|
||||
FnAbiRequest::OfFnPtr { sig, extra_args } => {
|
||||
span_bug!(
|
||||
span,
|
||||
"`fn_abi_of_fn_ptr({}, {:?})` failed: {}",
|
||||
sig,
|
||||
extra_args,
|
||||
err
|
||||
);
|
||||
span_bug!(span, "`fn_abi_of_fn_ptr({sig}, {extra_args:?})` failed: {err:?}");
|
||||
}
|
||||
FnAbiRequest::OfInstance { instance, extra_args } => {
|
||||
span_bug!(
|
||||
span,
|
||||
"`fn_abi_of_instance({}, {:?})` failed: {}",
|
||||
instance,
|
||||
extra_args,
|
||||
err
|
||||
"`fn_abi_of_instance({instance}, {extra_args:?})` failed: {err:?}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -132,7 +132,7 @@ fn declare_raw_fn<'gcc>(cx: &CodegenCx<'gcc, '_>, name: &str, _callconv: () /*ll
|
||||
pub fn mangle_name(name: &str) -> String {
|
||||
name.replace(|char: char| {
|
||||
if !char.is_alphanumeric() && char != '_' {
|
||||
debug_assert!("$.".contains(char), "Unsupported char in function name: {}", char);
|
||||
debug_assert!("$.*".contains(char), "Unsupported char in function name {}: {}", name, char);
|
||||
true
|
||||
}
|
||||
else {
|
||||
|
@ -227,3 +227,12 @@ pub(crate) struct UnwindingInlineAsm {
|
||||
pub(crate) struct InvalidMinimumAlignment {
|
||||
pub err: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_gcc_tied_target_features)]
|
||||
#[help]
|
||||
pub(crate) struct TiedTargetFeatures {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub features: String,
|
||||
}
|
||||
|
@ -3016,6 +3016,8 @@
|
||||
"llvm.nvvm.div.rz.ftz.f" => "__nvvm_div_rz_ftz_f",
|
||||
"llvm.nvvm.ex2.approx.d" => "__nvvm_ex2_approx_d",
|
||||
"llvm.nvvm.ex2.approx.f" => "__nvvm_ex2_approx_f",
|
||||
"llvm.nvvm.ex2.approx.f16" => "__nvvm_ex2_approx_f16",
|
||||
"llvm.nvvm.ex2.approx.f16x2" => "__nvvm_ex2_approx_f16x2",
|
||||
"llvm.nvvm.ex2.approx.ftz.f" => "__nvvm_ex2_approx_ftz_f",
|
||||
"llvm.nvvm.f2bf16.rn" => "__nvvm_f2bf16_rn",
|
||||
"llvm.nvvm.f2bf16.rn.relu" => "__nvvm_f2bf16_rn_relu",
|
||||
@ -3077,6 +3079,8 @@
|
||||
"llvm.nvvm.fma.rn.bf16x2" => "__nvvm_fma_rn_bf16x2",
|
||||
"llvm.nvvm.fma.rn.d" => "__nvvm_fma_rn_d",
|
||||
"llvm.nvvm.fma.rn.f" => "__nvvm_fma_rn_f",
|
||||
"llvm.nvvm.fma.rn.f16" => "__nvvm_fma_rn_f16",
|
||||
"llvm.nvvm.fma.rn.f16x2" => "__nvvm_fma_rn_f16x2",
|
||||
"llvm.nvvm.fma.rn.ftz.f" => "__nvvm_fma_rn_ftz_f",
|
||||
"llvm.nvvm.fma.rn.relu.bf16" => "__nvvm_fma_rn_relu_bf16",
|
||||
"llvm.nvvm.fma.rn.relu.bf16x2" => "__nvvm_fma_rn_relu_bf16x2",
|
||||
@ -3090,6 +3094,8 @@
|
||||
"llvm.nvvm.fmax.bf16x2" => "__nvvm_fmax_bf16x2",
|
||||
"llvm.nvvm.fmax.d" => "__nvvm_fmax_d",
|
||||
"llvm.nvvm.fmax.f" => "__nvvm_fmax_f",
|
||||
"llvm.nvvm.fmax.f16" => "__nvvm_fmax_f16",
|
||||
"llvm.nvvm.fmax.f16x2" => "__nvvm_fmax_f16x2",
|
||||
"llvm.nvvm.fmax.ftz.f" => "__nvvm_fmax_ftz_f",
|
||||
"llvm.nvvm.fmax.ftz.nan.f" => "__nvvm_fmax_ftz_nan_f",
|
||||
"llvm.nvvm.fmax.ftz.nan.xorsign.abs.f" => "__nvvm_fmax_ftz_nan_xorsign_abs_f",
|
||||
@ -3107,6 +3113,8 @@
|
||||
"llvm.nvvm.fmin.bf16x2" => "__nvvm_fmin_bf16x2",
|
||||
"llvm.nvvm.fmin.d" => "__nvvm_fmin_d",
|
||||
"llvm.nvvm.fmin.f" => "__nvvm_fmin_f",
|
||||
"llvm.nvvm.fmin.f16" => "__nvvm_fmin_f16",
|
||||
"llvm.nvvm.fmin.f16x2" => "__nvvm_fmin_f16x2",
|
||||
"llvm.nvvm.fmin.ftz.f" => "__nvvm_fmin_ftz_f",
|
||||
"llvm.nvvm.fmin.ftz.nan.f" => "__nvvm_fmin_ftz_nan_f",
|
||||
"llvm.nvvm.fmin.ftz.nan.xorsign.abs.f" => "__nvvm_fmin_ftz_nan_xorsign_abs_f",
|
||||
|
@ -79,6 +79,8 @@ fn get_simple_intrinsic<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, name: Symbol) ->
|
||||
sym::nearbyintf64 => "nearbyint",
|
||||
sym::roundf32 => "roundf",
|
||||
sym::roundf64 => "round",
|
||||
sym::roundevenf32 => "roundevenf",
|
||||
sym::roundevenf64 => "roundeven",
|
||||
sym::abort => "abort",
|
||||
_ => return None,
|
||||
};
|
||||
@ -111,7 +113,7 @@ fn codegen_intrinsic_call(&mut self, instance: Instance<'tcx>, fn_abi: &FnAbi<'t
|
||||
_ if simple.is_some() => {
|
||||
// FIXME(antoyo): remove this cast when the API supports function.
|
||||
let func = unsafe { std::mem::transmute(simple.expect("simple")) };
|
||||
self.call(self.type_void(), None, func, &args.iter().map(|arg| arg.immediate()).collect::<Vec<_>>(), None)
|
||||
self.call(self.type_void(), None, None, func, &args.iter().map(|arg| arg.immediate()).collect::<Vec<_>>(), None)
|
||||
},
|
||||
sym::likely => {
|
||||
self.expect(args[0].immediate(), true)
|
||||
@ -352,7 +354,7 @@ fn codegen_intrinsic_call(&mut self, instance: Instance<'tcx>, fn_abi: &FnAbi<'t
|
||||
fn abort(&mut self) {
|
||||
let func = self.context.get_builtin_function("abort");
|
||||
let func: RValue<'gcc> = unsafe { std::mem::transmute(func) };
|
||||
self.call(self.type_void(), None, func, &[], None);
|
||||
self.call(self.type_void(), None, None, func, &[], None);
|
||||
}
|
||||
|
||||
fn assume(&mut self, value: Self::Value) {
|
||||
@ -1044,7 +1046,7 @@ fn saturating_sub(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>, signed: bool,
|
||||
|
||||
fn try_intrinsic<'a, 'b, 'gcc, 'tcx>(bx: &'b mut Builder<'a, 'gcc, 'tcx>, try_func: RValue<'gcc>, data: RValue<'gcc>, _catch_func: RValue<'gcc>, dest: RValue<'gcc>) {
|
||||
if bx.sess().panic_strategy() == PanicStrategy::Abort {
|
||||
bx.call(bx.type_void(), None, try_func, &[data], None);
|
||||
bx.call(bx.type_void(), None, None, try_func, &[data], None);
|
||||
// Return 0 unconditionally from the intrinsic call;
|
||||
// we can never unwind.
|
||||
let ret_align = bx.tcx.data_layout.i32_align.abi;
|
||||
@ -1113,21 +1115,21 @@ fn codegen_gnu_try<'gcc>(bx: &mut Builder<'_, 'gcc, '_>, try_func: RValue<'gcc>,
|
||||
let zero = bx.cx.context.new_rvalue_zero(bx.int_type);
|
||||
let ptr = bx.cx.context.new_call(None, eh_pointer_builtin, &[zero]);
|
||||
let catch_ty = bx.type_func(&[bx.type_i8p(), bx.type_i8p()], bx.type_void());
|
||||
bx.call(catch_ty, None, catch_func, &[data, ptr], None);
|
||||
bx.call(catch_ty, None, None, catch_func, &[data, ptr], None);
|
||||
bx.ret(bx.const_i32(1));
|
||||
|
||||
// NOTE: the blocks must be filled before adding the try/catch, otherwise gcc will not
|
||||
// generate a try/catch.
|
||||
// FIXME(antoyo): add a check in the libgccjit API to prevent this.
|
||||
bx.switch_to_block(current_block);
|
||||
bx.invoke(try_func_ty, None, try_func, &[data], then, catch, None);
|
||||
bx.invoke(try_func_ty, None, None, try_func, &[data], then, catch, None);
|
||||
});
|
||||
|
||||
let func = unsafe { std::mem::transmute(func) };
|
||||
|
||||
// Note that no invoke is used here because by definition this function
|
||||
// can't panic (that's what it's catching).
|
||||
let ret = bx.call(llty, None, func, &[try_func, data, catch_func], None);
|
||||
let ret = bx.call(llty, None, None, func, &[try_func, data, catch_func], None);
|
||||
let i32_align = bx.tcx().data_layout.i32_align.abi;
|
||||
bx.store(ret, dest, i32_align);
|
||||
}
|
||||
|
@ -165,10 +165,15 @@ macro_rules! require_simd {
|
||||
InvalidMonomorphizationReturnIntegerType { span, name, ret_ty, out_ty }
|
||||
);
|
||||
|
||||
let arg1 = args[0].immediate();
|
||||
// NOTE: we get different vector types for the same vector type and libgccjit doesn't
|
||||
// compare them as equal, so bitcast.
|
||||
// FIXME(antoyo): allow comparing vector types as equal in libgccjit.
|
||||
let arg2 = bx.context.new_bitcast(None, args[1].immediate(), arg1.get_type());
|
||||
return Ok(compare_simd_types(
|
||||
bx,
|
||||
args[0].immediate(),
|
||||
args[1].immediate(),
|
||||
arg1,
|
||||
arg2,
|
||||
in_elem,
|
||||
llret_ty,
|
||||
cmp_op,
|
||||
@ -341,7 +346,8 @@ macro_rules! arith_binary {
|
||||
// endian and MSB-first for big endian.
|
||||
|
||||
let vector = args[0].immediate();
|
||||
let vector_type = vector.get_type().dyncast_vector().expect("vector type");
|
||||
// TODO(antoyo): dyncast_vector should not require a call to unqualified.
|
||||
let vector_type = vector.get_type().unqualified().dyncast_vector().expect("vector type");
|
||||
let elem_type = vector_type.get_element_type();
|
||||
|
||||
let expected_int_bits = in_len.max(8);
|
||||
@ -848,7 +854,8 @@ macro_rules! arith_unary {
|
||||
(true, true) => {
|
||||
// Algorithm from: https://codereview.stackexchange.com/questions/115869/saturated-signed-addition
|
||||
// TODO(antoyo): improve using conditional operators if possible.
|
||||
let arg_type = lhs.get_type();
|
||||
// TODO(antoyo): dyncast_vector should not require a call to unqualified.
|
||||
let arg_type = lhs.get_type().unqualified();
|
||||
// TODO(antoyo): convert lhs and rhs to unsigned.
|
||||
let sum = lhs + rhs;
|
||||
let vector_type = arg_type.dyncast_vector().expect("vector type");
|
||||
@ -878,7 +885,8 @@ macro_rules! arith_unary {
|
||||
res & cmp
|
||||
},
|
||||
(true, false) => {
|
||||
let arg_type = lhs.get_type();
|
||||
// TODO(antoyo): dyncast_vector should not require a call to unqualified.
|
||||
let arg_type = lhs.get_type().unqualified();
|
||||
// TODO(antoyo): this uses the same algorithm from saturating add, but add the
|
||||
// negative of the right operand. Find a proper subtraction algorithm.
|
||||
let rhs = bx.context.new_unary_op(None, UnaryOp::Minus, arg_type, rhs);
|
||||
|
11
src/lib.rs
11
src/lib.rs
@ -27,6 +27,7 @@
|
||||
extern crate rustc_codegen_ssa;
|
||||
extern crate rustc_data_structures;
|
||||
extern crate rustc_errors;
|
||||
extern crate rustc_fluent_macro;
|
||||
extern crate rustc_hir;
|
||||
extern crate rustc_macros;
|
||||
extern crate rustc_metadata;
|
||||
@ -74,20 +75,20 @@
|
||||
use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule};
|
||||
use rustc_codegen_ssa::target_features::supported_target_features;
|
||||
use rustc_codegen_ssa::traits::{CodegenBackend, ExtraBackendMethods, ModuleBufferMethods, ThinBufferMethods, WriteBackendMethods};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_errors::{DiagnosticMessage, ErrorGuaranteed, Handler, SubdiagnosticMessage};
|
||||
use rustc_macros::fluent_messages;
|
||||
use rustc_fluent_macro::fluent_messages;
|
||||
use rustc_metadata::EncodedMetadata;
|
||||
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_middle::ty::query::Providers;
|
||||
use rustc_session::config::{Lto, OptLevel, OutputFilenames};
|
||||
use rustc_session::Session;
|
||||
use rustc_span::Symbol;
|
||||
use rustc_span::fatal_error::FatalError;
|
||||
use tempfile::TempDir;
|
||||
|
||||
fluent_messages! { "../locales/en-US.ftl" }
|
||||
fluent_messages! { "../messages.ftl" }
|
||||
|
||||
pub struct PrintOnPanic<F: Fn() -> String>(pub F);
|
||||
|
||||
@ -138,7 +139,7 @@ fn codegen_crate<'tcx>(&self, tcx: TyCtxt<'tcx>, metadata: EncodedMetadata, need
|
||||
Box::new(res)
|
||||
}
|
||||
|
||||
fn join_codegen(&self, ongoing_codegen: Box<dyn Any>, sess: &Session, _outputs: &OutputFilenames) -> Result<(CodegenResults, FxHashMap<WorkProductId, WorkProduct>), ErrorGuaranteed> {
|
||||
fn join_codegen(&self, ongoing_codegen: Box<dyn Any>, sess: &Session, _outputs: &OutputFilenames) -> Result<(CodegenResults, FxIndexMap<WorkProductId, WorkProduct>), ErrorGuaranteed> {
|
||||
let (codegen_results, work_products) = ongoing_codegen
|
||||
.downcast::<rustc_codegen_ssa::back::write::OngoingCodegen<GccCodegenBackend>>()
|
||||
.expect("Expected GccCodegenBackend's OngoingCodegen, found Box<Any>")
|
||||
|
@ -31,7 +31,7 @@ fn predefine_static(&self, def_id: DefId, _linkage: Linkage, visibility: Visibil
|
||||
|
||||
#[cfg_attr(not(feature="master"), allow(unused_variables))]
|
||||
fn predefine_fn(&self, instance: Instance<'tcx>, linkage: Linkage, visibility: Visibility, symbol_name: &str) {
|
||||
assert!(!instance.substs.needs_infer());
|
||||
assert!(!instance.substs.has_infer());
|
||||
|
||||
let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty());
|
||||
self.linkage.set(base::linkage_to_gcc(linkage));
|
||||
|
12
src/type_.rs
12
src/type_.rs
@ -280,16 +280,4 @@ pub fn struct_fields<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, layout: TyAndLayout
|
||||
}
|
||||
|
||||
impl<'gcc, 'tcx> TypeMembershipMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
||||
fn set_type_metadata(&self, _function: RValue<'gcc>, _typeid: String) {
|
||||
// Unsupported.
|
||||
}
|
||||
|
||||
fn typeid_metadata(&self, _typeid: String) -> RValue<'gcc> {
|
||||
// Unsupported.
|
||||
self.context.new_rvalue_from_int(self.int_type, 0)
|
||||
}
|
||||
|
||||
fn set_kcfi_type_metadata(&self, _function: RValue<'gcc>, _kcfi_typeid: u32) {
|
||||
// Unsupported.
|
||||
}
|
||||
}
|
||||
|
@ -159,8 +159,7 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
|
||||
fn is_gcc_immediate(&self) -> bool {
|
||||
match self.abi {
|
||||
Abi::Scalar(_) | Abi::Vector { .. } => true,
|
||||
Abi::ScalarPair(..) => false,
|
||||
Abi::Uninhabited | Abi::Aggregate { .. } => self.is_zst(),
|
||||
Abi::ScalarPair(..) | Abi::Uninhabited | Abi::Aggregate { .. } => false,
|
||||
}
|
||||
}
|
||||
|
||||
@ -384,8 +383,8 @@ fn reg_backend_type(&self, _ty: &Reg) -> Type<'gcc> {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
fn fn_decl_backend_type(&self, _fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Type<'gcc> {
|
||||
// FIXME(antoyo): return correct type.
|
||||
self.type_void()
|
||||
fn fn_decl_backend_type(&self, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Type<'gcc> {
|
||||
let (return_type, param_types, variadic, _) = fn_abi.gcc_type(self);
|
||||
self.context.new_function_pointer_type(None, return_type, ¶m_types, variadic)
|
||||
}
|
||||
}
|
||||
|
8
test.sh
8
test.sh
@ -214,12 +214,14 @@ function setup_rustc() {
|
||||
rm config.toml || true
|
||||
|
||||
cat > config.toml <<EOF
|
||||
changelog-seen = 2
|
||||
|
||||
[rust]
|
||||
codegen-backends = []
|
||||
deny-warnings = false
|
||||
|
||||
[build]
|
||||
cargo = "$(which cargo)"
|
||||
cargo = "$(rustup which cargo)"
|
||||
local-rebuild = true
|
||||
rustc = "$HOME/.rustup/toolchains/$rust_toolchain-$TARGET_TRIPLE/bin/rustc"
|
||||
|
||||
@ -237,7 +239,7 @@ EOF
|
||||
function asm_tests() {
|
||||
setup_rustc
|
||||
|
||||
echo "[TEST] rustc test suite"
|
||||
echo "[TEST] rustc asm test suite"
|
||||
RUSTC_ARGS="-Zpanic-abort-tests -Csymbol-mangling-version=v0 -Zcodegen-backend="$(pwd)"/../target/"$CHANNEL"/librustc_codegen_gcc."$dylib_ext" --sysroot "$(pwd)"/../build_sysroot/sysroot -Cpanic=abort"
|
||||
COMPILETEST_FORCE_STAGE0=1 ./x.py test --run always --stage 0 tests/assembly/asm --rustc-args "$RUSTC_ARGS"
|
||||
}
|
||||
@ -338,6 +340,8 @@ function test_rustc() {
|
||||
for test in $(rg -i --files-with-matches "//(\[\w+\])?~|// error-pattern:|// build-fail|// run-fail|-Cllvm-args" tests/ui); do
|
||||
rm $test
|
||||
done
|
||||
rm tests/ui/consts/const_cmp_type_id.rs
|
||||
rm tests/ui/consts/issue-73976-monomorphic.rs
|
||||
|
||||
git checkout -- tests/ui/issues/auxiliary/issue-3136-a.rs # contains //~ERROR, but shouldn't be removed
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user