Merge from rustc
This commit is contained in:
commit
869827fd86
747 changed files with 18672 additions and 10001 deletions
15
.github/workflows/ci.yml
vendored
15
.github/workflows/ci.yml
vendored
|
|
@ -193,8 +193,9 @@ jobs:
|
|||
os: ubuntu-20.04-8core-32gb
|
||||
env: {}
|
||||
- name: dist-aarch64-linux
|
||||
env:
|
||||
CODEGEN_BACKENDS: "llvm,cranelift"
|
||||
os: ubuntu-20.04-8core-32gb
|
||||
env: {}
|
||||
- name: dist-android
|
||||
os: ubuntu-20.04-8core-32gb
|
||||
env: {}
|
||||
|
|
@ -244,15 +245,18 @@ jobs:
|
|||
os: ubuntu-20.04-8core-32gb
|
||||
env: {}
|
||||
- name: dist-x86_64-linux
|
||||
env:
|
||||
CODEGEN_BACKENDS: "llvm,cranelift"
|
||||
os: ubuntu-20.04-16core-64gb
|
||||
env: {}
|
||||
- name: dist-x86_64-linux-alt
|
||||
env:
|
||||
IMAGE: dist-x86_64-linux
|
||||
CODEGEN_BACKENDS: "llvm,cranelift"
|
||||
os: ubuntu-20.04-16core-64gb
|
||||
- name: dist-x86_64-musl
|
||||
env:
|
||||
CODEGEN_BACKENDS: "llvm,cranelift"
|
||||
os: ubuntu-20.04-8core-32gb
|
||||
env: {}
|
||||
- name: dist-x86_64-netbsd
|
||||
os: ubuntu-20.04-8core-32gb
|
||||
env: {}
|
||||
|
|
@ -316,6 +320,7 @@ jobs:
|
|||
NO_DEBUG_ASSERTIONS: 1
|
||||
NO_OVERFLOW_CHECKS: 1
|
||||
DIST_REQUIRE_ALL_TOOLS: 1
|
||||
CODEGEN_BACKENDS: "llvm,cranelift"
|
||||
os: macos-13
|
||||
- name: dist-apple-various
|
||||
env:
|
||||
|
|
@ -377,6 +382,7 @@ jobs:
|
|||
- name: x86_64-msvc-ext
|
||||
env:
|
||||
SCRIPT: python x.py --stage 2 test src/tools/cargotest src/tools/cargo && src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh x.py /tmp/toolstate/toolstates.json windows
|
||||
HOST_TARGET: x86_64-pc-windows-msvc
|
||||
RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --enable-lld --save-toolstates=/tmp/toolstate/toolstates.json"
|
||||
DEPLOY_TOOLSTATES_JSON: toolstates-windows.json
|
||||
os: windows-2019-8core-32gb
|
||||
|
|
@ -554,8 +560,9 @@ jobs:
|
|||
matrix:
|
||||
include:
|
||||
- name: dist-x86_64-linux
|
||||
env:
|
||||
CODEGEN_BACKENDS: "llvm,cranelift"
|
||||
os: ubuntu-20.04-16core-64gb
|
||||
env: {}
|
||||
timeout-minutes: 600
|
||||
runs-on: "${{ matrix.os }}"
|
||||
steps:
|
||||
|
|
|
|||
14
Cargo.lock
14
Cargo.lock
|
|
@ -1011,6 +1011,17 @@ dependencies = [
|
|||
"syn 2.0.29",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derivative"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive_builder"
|
||||
version = "0.12.0"
|
||||
|
|
@ -4054,7 +4065,6 @@ dependencies = [
|
|||
"rustc_hir_analysis",
|
||||
"rustc_hir_typeck",
|
||||
"rustc_incremental",
|
||||
"rustc_index",
|
||||
"rustc_lint",
|
||||
"rustc_macros",
|
||||
"rustc_metadata",
|
||||
|
|
@ -4413,7 +4423,6 @@ version = "0.0.0"
|
|||
dependencies = [
|
||||
"field-offset",
|
||||
"measureme",
|
||||
"memoffset",
|
||||
"rustc-rayon-core",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
|
|
@ -4669,6 +4678,7 @@ name = "rustc_type_ir"
|
|||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"derivative",
|
||||
"rustc_data_structures",
|
||||
"rustc_index",
|
||||
"rustc_macros",
|
||||
|
|
|
|||
|
|
@ -4,16 +4,21 @@ version = "0.0.0"
|
|||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
rustc_driver = { path = "../rustc_driver" }
|
||||
rustc_driver_impl = { path = "../rustc_driver_impl" }
|
||||
# tidy-alphabetical-start
|
||||
|
||||
# Make sure rustc_codegen_ssa ends up in the sysroot, because this
|
||||
# crate is intended to be used by codegen backends, which may not be in-tree.
|
||||
rustc_codegen_ssa = { path = "../rustc_codegen_ssa" }
|
||||
|
||||
rustc_driver = { path = "../rustc_driver" }
|
||||
rustc_driver_impl = { path = "../rustc_driver_impl" }
|
||||
|
||||
# Make sure rustc_smir ends up in the sysroot, because this
|
||||
# crate is intended to be used by stable MIR consumers, which are not in-tree
|
||||
# crate is intended to be used by stable MIR consumers, which are not in-tree.
|
||||
rustc_smir = { path = "../rustc_smir" }
|
||||
|
||||
stable_mir = { path = "../stable_mir" }
|
||||
# tidy-alphabetical-end
|
||||
|
||||
[dependencies.jemalloc-sys]
|
||||
version = "0.5.0"
|
||||
|
|
@ -21,7 +26,9 @@ optional = true
|
|||
features = ['unprefixed_malloc_on_supported_platforms']
|
||||
|
||||
[features]
|
||||
# tidy-alphabetical-start
|
||||
jemalloc = ['jemalloc-sys']
|
||||
llvm = ['rustc_driver_impl/llvm']
|
||||
max_level_info = ['rustc_driver_impl/max_level_info']
|
||||
rustc_use_parallel_compiler = ['rustc_driver_impl/rustc_use_parallel_compiler']
|
||||
# tidy-alphabetical-end
|
||||
|
|
|
|||
|
|
@ -4,18 +4,20 @@ version = "0.0.0"
|
|||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
# tidy-alphabetical-start
|
||||
bitflags = "1.2.1"
|
||||
tracing = "0.1"
|
||||
rand = { version = "0.8.4", default-features = false, optional = true }
|
||||
rand_xoshiro = { version = "0.6.0", optional = true }
|
||||
rustc_data_structures = { path = "../rustc_data_structures", optional = true }
|
||||
rustc_index = { path = "../rustc_index", default-features = false }
|
||||
rustc_macros = { path = "../rustc_macros", optional = true }
|
||||
rustc_serialize = { path = "../rustc_serialize", optional = true }
|
||||
tracing = "0.1"
|
||||
# tidy-alphabetical-end
|
||||
|
||||
[features]
|
||||
# tidy-alphabetical-start
|
||||
default = ["nightly", "randomize"]
|
||||
randomize = ["rand", "rand_xoshiro", "nightly"]
|
||||
# rust-analyzer depends on this crate and we therefore require it to built on a stable toolchain
|
||||
# without depending on rustc_data_structures, rustc_macros and rustc_serialize
|
||||
nightly = [
|
||||
|
|
@ -24,3 +26,5 @@ nightly = [
|
|||
"rustc_macros",
|
||||
"rustc_serialize",
|
||||
]
|
||||
randomize = ["rand", "rand_xoshiro", "nightly"]
|
||||
# tidy-alphabetical-end
|
||||
|
|
|
|||
|
|
@ -539,6 +539,7 @@ pub trait LayoutCalculator {
|
|||
// Align the maximum variant size to the largest alignment.
|
||||
size = size.align_to(align.abi);
|
||||
|
||||
// FIXME(oli-obk): deduplicate and harden these checks
|
||||
if size.bytes() >= dl.obj_size_bound() {
|
||||
return None;
|
||||
}
|
||||
|
|
@ -1103,6 +1104,10 @@ fn univariant<
|
|||
inverse_memory_index.into_iter().map(|it| it.index() as u32).collect()
|
||||
};
|
||||
let size = min_size.align_to(align.abi);
|
||||
// FIXME(oli-obk): deduplicate and harden these checks
|
||||
if size.bytes() >= dl.obj_size_bound() {
|
||||
return None;
|
||||
}
|
||||
let mut layout_of_single_non_zst_field = None;
|
||||
let mut abi = Abi::Aggregate { sized };
|
||||
// Try to make this a Scalar/ScalarPair.
|
||||
|
|
|
|||
|
|
@ -4,4 +4,6 @@ version = "0.0.0"
|
|||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
# tidy-alphabetical-start
|
||||
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
|
||||
# tidy-alphabetical-end
|
||||
|
|
|
|||
|
|
@ -3,9 +3,8 @@ name = "rustc_ast"
|
|||
version = "0.0.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
|
||||
[dependencies]
|
||||
# tidy-alphabetical-start
|
||||
bitflags = "1.2.1"
|
||||
memchr = "2.5.0"
|
||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
|
|
@ -14,8 +13,9 @@ rustc_lexer = { path = "../rustc_lexer" }
|
|||
rustc_macros = { path = "../rustc_macros" }
|
||||
rustc_serialize = { path = "../rustc_serialize" }
|
||||
rustc_span = { path = "../rustc_span" }
|
||||
# depends on Mutability and Movability, which could be uplifted into a common crate.
|
||||
# For Mutability and Movability, which could be uplifted into a common crate.
|
||||
rustc_type_ir = { path = "../rustc_type_ir" }
|
||||
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
|
||||
thin-vec = "0.2.12"
|
||||
tracing = "0.1"
|
||||
# tidy-alphabetical-end
|
||||
|
|
|
|||
|
|
@ -1235,7 +1235,7 @@ impl Expr {
|
|||
ExprKind::Closure(..) => ExprPrecedence::Closure,
|
||||
ExprKind::Block(..) => ExprPrecedence::Block,
|
||||
ExprKind::TryBlock(..) => ExprPrecedence::TryBlock,
|
||||
ExprKind::Async(..) => ExprPrecedence::Async,
|
||||
ExprKind::Gen(..) => ExprPrecedence::Gen,
|
||||
ExprKind::Await(..) => ExprPrecedence::Await,
|
||||
ExprKind::Assign(..) => ExprPrecedence::Assign,
|
||||
ExprKind::AssignOp(..) => ExprPrecedence::AssignOp,
|
||||
|
|
@ -1405,11 +1405,9 @@ pub enum ExprKind {
|
|||
Closure(Box<Closure>),
|
||||
/// A block (`'label: { ... }`).
|
||||
Block(P<Block>, Option<Label>),
|
||||
/// An async block (`async move { ... }`).
|
||||
///
|
||||
/// The async block used to have a `NodeId`, which was removed in favor of
|
||||
/// using the parent `NodeId` of the parent `Expr`.
|
||||
Async(CaptureBy, P<Block>),
|
||||
/// An `async` block (`async move { ... }`),
|
||||
/// or a `gen` block (`gen move { ... }`)
|
||||
Gen(CaptureBy, P<Block>, GenBlockKind),
|
||||
/// An await expression (`my_future.await`). Span is of await keyword.
|
||||
Await(P<Expr>, Span),
|
||||
|
||||
|
|
@ -1499,6 +1497,28 @@ pub enum ExprKind {
|
|||
Err,
|
||||
}
|
||||
|
||||
/// Used to differentiate between `async {}` blocks and `gen {}` blocks.
|
||||
#[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq)]
|
||||
pub enum GenBlockKind {
|
||||
Async,
|
||||
Gen,
|
||||
}
|
||||
|
||||
impl fmt::Display for GenBlockKind {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.modifier().fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl GenBlockKind {
|
||||
pub fn modifier(&self) -> &'static str {
|
||||
match self {
|
||||
GenBlockKind::Async => "async",
|
||||
GenBlockKind::Gen => "gen",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The explicit `Self` type in a "qualified path". The actual
|
||||
/// path, including the trait and the associated item, is stored
|
||||
/// separately. `position` represents the index of the associated
|
||||
|
|
@ -2363,6 +2383,12 @@ pub enum Async {
|
|||
No,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Encodable, Decodable, Debug)]
|
||||
pub enum Gen {
|
||||
Yes { span: Span, closure_id: NodeId, return_impl_trait_id: NodeId },
|
||||
No,
|
||||
}
|
||||
|
||||
impl Async {
|
||||
pub fn is_async(self) -> bool {
|
||||
matches!(self, Async::Yes { .. })
|
||||
|
|
|
|||
|
|
@ -1418,7 +1418,7 @@ pub fn noop_visit_expr<T: MutVisitor>(
|
|||
vis.visit_block(blk);
|
||||
visit_opt(label, |label| vis.visit_label(label));
|
||||
}
|
||||
ExprKind::Async(_capture_by, body) => {
|
||||
ExprKind::Gen(_capture_by, body, _) => {
|
||||
vis.visit_block(body);
|
||||
}
|
||||
ExprKind::Await(expr, await_kw_span) => {
|
||||
|
|
|
|||
|
|
@ -197,6 +197,7 @@ pub fn ident_can_begin_expr(name: Symbol, span: Span, is_raw: bool) -> bool {
|
|||
kw::Continue,
|
||||
kw::False,
|
||||
kw::For,
|
||||
kw::Gen,
|
||||
kw::If,
|
||||
kw::Let,
|
||||
kw::Loop,
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<&ast::Expr> {
|
|||
Closure(closure) => {
|
||||
expr = &closure.body;
|
||||
}
|
||||
Async(..) | Block(..) | ForLoop(..) | If(..) | Loop(..) | Match(..) | Struct(..)
|
||||
Gen(..) | Block(..) | ForLoop(..) | If(..) | Loop(..) | Match(..) | Struct(..)
|
||||
| TryBlock(..) | While(..) => break Some(expr),
|
||||
_ => break None,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -285,7 +285,7 @@ pub enum ExprPrecedence {
|
|||
Block,
|
||||
TryBlock,
|
||||
Struct,
|
||||
Async,
|
||||
Gen,
|
||||
Await,
|
||||
Err,
|
||||
}
|
||||
|
|
@ -351,7 +351,7 @@ impl ExprPrecedence {
|
|||
| ExprPrecedence::ConstBlock
|
||||
| ExprPrecedence::Block
|
||||
| ExprPrecedence::TryBlock
|
||||
| ExprPrecedence::Async
|
||||
| ExprPrecedence::Gen
|
||||
| ExprPrecedence::Struct
|
||||
| ExprPrecedence::Err => PREC_PAREN,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -872,7 +872,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
|
|||
walk_list!(visitor, visit_label, opt_label);
|
||||
visitor.visit_block(block);
|
||||
}
|
||||
ExprKind::Async(_, body) => {
|
||||
ExprKind::Gen(_, body, _) => {
|
||||
visitor.visit_block(body);
|
||||
}
|
||||
ExprKind::Await(expr, _) => visitor.visit_expr(expr),
|
||||
|
|
|
|||
|
|
@ -7,18 +7,20 @@ edition = "2021"
|
|||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
# tidy-alphabetical-start
|
||||
rustc_ast = { path = "../rustc_ast" }
|
||||
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
|
||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
rustc_errors = { path = "../rustc_errors" }
|
||||
rustc_hir = { path = "../rustc_hir" }
|
||||
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
|
||||
rustc_hir = { path = "../rustc_hir" }
|
||||
rustc_index = { path = "../rustc_index" }
|
||||
rustc_middle = { path = "../rustc_middle" }
|
||||
rustc_macros = { path = "../rustc_macros" }
|
||||
rustc_middle = { path = "../rustc_middle" }
|
||||
rustc_session = { path = "../rustc_session" }
|
||||
rustc_span = { path = "../rustc_span" }
|
||||
rustc_target = { path = "../rustc_target" }
|
||||
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
|
||||
thin-vec = "0.2.12"
|
||||
tracing = "0.1"
|
||||
# tidy-alphabetical-end
|
||||
|
|
|
|||
|
|
@ -183,7 +183,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
self.arena.alloc_from_iter(arms.iter().map(|x| self.lower_arm(x))),
|
||||
hir::MatchSource::Normal,
|
||||
),
|
||||
ExprKind::Async(capture_clause, block) => self.make_async_expr(
|
||||
ExprKind::Gen(capture_clause, block, GenBlockKind::Async) => self.make_async_expr(
|
||||
*capture_clause,
|
||||
e.id,
|
||||
None,
|
||||
|
|
@ -317,6 +317,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
rest,
|
||||
)
|
||||
}
|
||||
ExprKind::Gen(capture_clause, block, GenBlockKind::Gen) => self.make_gen_expr(
|
||||
*capture_clause,
|
||||
e.id,
|
||||
None,
|
||||
e.span,
|
||||
hir::CoroutineSource::Block,
|
||||
|this| this.with_new_scopes(|this| this.lower_block_expr(block)),
|
||||
),
|
||||
ExprKind::Yield(opt_expr) => self.lower_expr_yield(e.span, opt_expr.as_deref()),
|
||||
ExprKind::Err => hir::ExprKind::Err(
|
||||
self.tcx.sess.delay_span_bug(e.span, "lowered ExprKind::Err"),
|
||||
|
|
@ -598,7 +606,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
closure_node_id: NodeId,
|
||||
ret_ty: Option<hir::FnRetTy<'hir>>,
|
||||
span: Span,
|
||||
async_gen_kind: hir::CoroutineSource,
|
||||
async_coroutine_source: hir::CoroutineSource,
|
||||
body: impl FnOnce(&mut Self) -> hir::Expr<'hir>,
|
||||
) -> hir::ExprKind<'hir> {
|
||||
let output = ret_ty.unwrap_or_else(|| hir::FnRetTy::DefaultReturn(self.lower_span(span)));
|
||||
|
|
@ -637,7 +645,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let params = arena_vec![self; param];
|
||||
|
||||
let body = self.lower_body(move |this| {
|
||||
this.coroutine_kind = Some(hir::CoroutineKind::Async(async_gen_kind));
|
||||
this.coroutine_kind = Some(hir::CoroutineKind::Async(async_coroutine_source));
|
||||
|
||||
let old_ctx = this.task_context;
|
||||
this.task_context = Some(task_context_hid);
|
||||
|
|
@ -661,6 +669,57 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
}))
|
||||
}
|
||||
|
||||
/// Lower a `gen` construct to a generator that implements `Iterator`.
|
||||
///
|
||||
/// This results in:
|
||||
///
|
||||
/// ```text
|
||||
/// static move? |()| -> () {
|
||||
/// <body>
|
||||
/// }
|
||||
/// ```
|
||||
pub(super) fn make_gen_expr(
|
||||
&mut self,
|
||||
capture_clause: CaptureBy,
|
||||
closure_node_id: NodeId,
|
||||
_yield_ty: Option<hir::FnRetTy<'hir>>,
|
||||
span: Span,
|
||||
coroutine_source: hir::CoroutineSource,
|
||||
body: impl FnOnce(&mut Self) -> hir::Expr<'hir>,
|
||||
) -> hir::ExprKind<'hir> {
|
||||
let output = hir::FnRetTy::DefaultReturn(self.lower_span(span));
|
||||
|
||||
// The closure/generator `FnDecl` takes a single (resume) argument of type `input_ty`.
|
||||
let fn_decl = self.arena.alloc(hir::FnDecl {
|
||||
inputs: &[],
|
||||
output,
|
||||
c_variadic: false,
|
||||
implicit_self: hir::ImplicitSelfKind::None,
|
||||
lifetime_elision_allowed: false,
|
||||
});
|
||||
|
||||
let body = self.lower_body(move |this| {
|
||||
this.coroutine_kind = Some(hir::CoroutineKind::Gen(coroutine_source));
|
||||
|
||||
let res = body(this);
|
||||
(&[], res)
|
||||
});
|
||||
|
||||
// `static |()| -> () { body }`:
|
||||
hir::ExprKind::Closure(self.arena.alloc(hir::Closure {
|
||||
def_id: self.local_def_id(closure_node_id),
|
||||
binder: hir::ClosureBinder::Default,
|
||||
capture_clause,
|
||||
bound_generic_params: &[],
|
||||
fn_decl,
|
||||
body,
|
||||
fn_decl_span: self.lower_span(span),
|
||||
fn_arg_span: None,
|
||||
movability: Some(Movability::Movable),
|
||||
constness: hir::Constness::NotConst,
|
||||
}))
|
||||
}
|
||||
|
||||
/// Forwards a possible `#[track_caller]` annotation from `outer_hir_id` to
|
||||
/// `inner_hir_id` in case the `async_fn_track_caller` feature is enabled.
|
||||
pub(super) fn maybe_forward_track_caller(
|
||||
|
|
@ -712,7 +771,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let full_span = expr.span.to(await_kw_span);
|
||||
match self.coroutine_kind {
|
||||
Some(hir::CoroutineKind::Async(_)) => {}
|
||||
Some(hir::CoroutineKind::Coroutine) | None => {
|
||||
Some(hir::CoroutineKind::Coroutine) | Some(hir::CoroutineKind::Gen(_)) | None => {
|
||||
self.tcx.sess.emit_err(AwaitOnlyInAsyncFnAndBlocks {
|
||||
await_kw_span,
|
||||
item_span: self.current_item,
|
||||
|
|
@ -936,8 +995,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
}
|
||||
Some(movability)
|
||||
}
|
||||
Some(hir::CoroutineKind::Async(_)) => {
|
||||
panic!("non-`async` closure body turned `async` during lowering");
|
||||
Some(hir::CoroutineKind::Gen(_)) | Some(hir::CoroutineKind::Async(_)) => {
|
||||
panic!("non-`async`/`gen` closure body turned `async`/`gen` during lowering");
|
||||
}
|
||||
None => {
|
||||
if movability == Movability::Static {
|
||||
|
|
@ -1445,11 +1504,22 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
|
||||
fn lower_expr_yield(&mut self, span: Span, opt_expr: Option<&Expr>) -> hir::ExprKind<'hir> {
|
||||
match self.coroutine_kind {
|
||||
Some(hir::CoroutineKind::Coroutine) => {}
|
||||
Some(hir::CoroutineKind::Gen(_)) => {}
|
||||
Some(hir::CoroutineKind::Async(_)) => {
|
||||
self.tcx.sess.emit_err(AsyncCoroutinesNotSupported { span });
|
||||
}
|
||||
None => self.coroutine_kind = Some(hir::CoroutineKind::Coroutine),
|
||||
Some(hir::CoroutineKind::Coroutine) | None => {
|
||||
if !self.tcx.features().coroutines {
|
||||
rustc_session::parse::feature_err(
|
||||
&self.tcx.sess.parse_sess,
|
||||
sym::coroutines,
|
||||
span,
|
||||
"yield syntax is experimental",
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
self.coroutine_kind = Some(hir::CoroutineKind::Coroutine)
|
||||
}
|
||||
}
|
||||
|
||||
let expr =
|
||||
|
|
|
|||
|
|
@ -988,12 +988,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
&mut self,
|
||||
f: impl FnOnce(&mut Self) -> (&'hir [hir::Param<'hir>], hir::Expr<'hir>),
|
||||
) -> hir::BodyId {
|
||||
let prev_gen_kind = self.coroutine_kind.take();
|
||||
let prev_coroutine_kind = self.coroutine_kind.take();
|
||||
let task_context = self.task_context.take();
|
||||
let (parameters, result) = f(self);
|
||||
let body_id = self.record_body(parameters, result);
|
||||
self.task_context = task_context;
|
||||
self.coroutine_kind = prev_gen_kind;
|
||||
self.coroutine_kind = prev_coroutine_kind;
|
||||
body_id
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1742,14 +1742,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
}
|
||||
|
||||
fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> &'hir [Ident] {
|
||||
// Skip the `...` (`CVarArgs`) trailing arguments from the AST,
|
||||
// as they are not explicit in HIR/Ty function signatures.
|
||||
// (instead, the `c_variadic` flag is set to `true`)
|
||||
let mut inputs = &decl.inputs[..];
|
||||
if decl.c_variadic() {
|
||||
inputs = &inputs[..inputs.len() - 1];
|
||||
}
|
||||
self.arena.alloc_from_iter(inputs.iter().map(|param| match param.pat.kind {
|
||||
self.arena.alloc_from_iter(decl.inputs.iter().map(|param| match param.pat.kind {
|
||||
PatKind::Ident(_, ident, _) => self.lower_ident(ident),
|
||||
_ => Ident::new(kw::Empty, self.lower_span(param.pat.span)),
|
||||
}))
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ version = "0.0.0"
|
|||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
# tidy-alphabetical-start
|
||||
itertools = "0.10.1"
|
||||
rustc_ast = { path = "../rustc_ast" }
|
||||
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
|
||||
|
|
@ -11,11 +12,12 @@ rustc_attr = { path = "../rustc_attr" }
|
|||
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
rustc_errors = { path = "../rustc_errors" }
|
||||
rustc_feature = { path = "../rustc_feature" }
|
||||
rustc_macros = { path = "../rustc_macros" }
|
||||
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
|
||||
rustc_macros = { path = "../rustc_macros" }
|
||||
rustc_parse = { path = "../rustc_parse" }
|
||||
rustc_session = { path = "../rustc_session" }
|
||||
rustc_span = { path = "../rustc_span" }
|
||||
rustc_target = { path = "../rustc_target" }
|
||||
thin-vec = "0.2.12"
|
||||
tracing = "0.1"
|
||||
# tidy-alphabetical-end
|
||||
|
|
|
|||
|
|
@ -42,6 +42,10 @@ ast_passes_const_and_async = functions cannot be both `const` and `async`
|
|||
.async = `async` because of this
|
||||
.label = {""}
|
||||
|
||||
ast_passes_const_and_c_variadic = functions cannot be both `const` and C-variadic
|
||||
.const = `const` because of this
|
||||
.variadic = C-variadic because of this
|
||||
|
||||
ast_passes_const_without_body =
|
||||
free constant item without body
|
||||
.suggestion = provide a definition for the constant
|
||||
|
|
|
|||
|
|
@ -482,9 +482,36 @@ impl<'a> AstValidator<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Reject C-variadic type unless the function is foreign,
|
||||
/// or free and `unsafe extern "C"` semantically.
|
||||
/// Reject invalid C-variadic types.
|
||||
///
|
||||
/// C-variadics must be:
|
||||
/// - Non-const
|
||||
/// - Either foreign, or free and `unsafe extern "C"` semantically
|
||||
fn check_c_variadic_type(&self, fk: FnKind<'a>) {
|
||||
let variadic_spans: Vec<_> = fk
|
||||
.decl()
|
||||
.inputs
|
||||
.iter()
|
||||
.filter(|arg| matches!(arg.ty.kind, TyKind::CVarArgs))
|
||||
.map(|arg| arg.span)
|
||||
.collect();
|
||||
|
||||
if variadic_spans.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(header) = fk.header() {
|
||||
if let Const::Yes(const_span) = header.constness {
|
||||
let mut spans = variadic_spans.clone();
|
||||
spans.push(const_span);
|
||||
self.err_handler().emit_err(errors::ConstAndCVariadic {
|
||||
spans,
|
||||
const_span,
|
||||
variadic_spans: variadic_spans.clone(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
match (fk.ctxt(), fk.header()) {
|
||||
(Some(FnCtxt::Foreign), _) => return,
|
||||
(Some(FnCtxt::Free), Some(header)) => match header.ext {
|
||||
|
|
@ -499,11 +526,7 @@ impl<'a> AstValidator<'a> {
|
|||
_ => {}
|
||||
};
|
||||
|
||||
for Param { ty, span, .. } in &fk.decl().inputs {
|
||||
if let TyKind::CVarArgs = ty.kind {
|
||||
self.err_handler().emit_err(errors::BadCVariadic { span: *span });
|
||||
}
|
||||
}
|
||||
self.err_handler().emit_err(errors::BadCVariadic { span: variadic_spans });
|
||||
}
|
||||
|
||||
fn check_item_named(&self, ident: Ident, kind: &str) {
|
||||
|
|
|
|||
|
|
@ -271,7 +271,7 @@ pub struct ExternItemAscii {
|
|||
#[diag(ast_passes_bad_c_variadic)]
|
||||
pub struct BadCVariadic {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub span: Vec<Span>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
|
|
@ -583,6 +583,17 @@ pub struct ConstAndAsync {
|
|||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes_const_and_c_variadic)]
|
||||
pub struct ConstAndCVariadic {
|
||||
#[primary_span]
|
||||
pub spans: Vec<Span>,
|
||||
#[label(ast_passes_const)]
|
||||
pub const_span: Span,
|
||||
#[label(ast_passes_variadic)]
|
||||
pub variadic_spans: Vec<Span>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes_pattern_in_foreign, code = "E0130")]
|
||||
pub struct PatternInForeign {
|
||||
|
|
|
|||
|
|
@ -554,7 +554,12 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
|
|||
"consider removing `for<...>`"
|
||||
);
|
||||
gate_all!(more_qualified_paths, "usage of qualified paths in this context is experimental");
|
||||
gate_all!(coroutines, "yield syntax is experimental");
|
||||
for &span in spans.get(&sym::yield_expr).iter().copied().flatten() {
|
||||
if !span.at_least_rust_2024() {
|
||||
gate_feature_post!(&visitor, coroutines, span, "yield syntax is experimental");
|
||||
}
|
||||
}
|
||||
gate_all!(gen_blocks, "gen blocks are experimental");
|
||||
gate_all!(raw_ref_op, "raw address of syntax is experimental");
|
||||
gate_all!(const_trait_impl, "const trait impls are experimental");
|
||||
gate_all!(
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ name = "rustc_ast_pretty"
|
|||
version = "0.0.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
|
||||
[dependencies]
|
||||
# tidy-alphabetical-start
|
||||
rustc_ast = { path = "../rustc_ast" }
|
||||
rustc_span = { path = "../rustc_span" }
|
||||
thin-vec = "0.2.12"
|
||||
# tidy-alphabetical-end
|
||||
|
|
|
|||
|
|
@ -445,8 +445,8 @@ impl<'a> State<'a> {
|
|||
self.ibox(0);
|
||||
self.print_block_with_attrs(blk, attrs);
|
||||
}
|
||||
ast::ExprKind::Async(capture_clause, blk) => {
|
||||
self.word_nbsp("async");
|
||||
ast::ExprKind::Gen(capture_clause, blk, kind) => {
|
||||
self.word_nbsp(kind.modifier());
|
||||
self.print_capture_clause(*capture_clause);
|
||||
// cbox/ibox in analogy to the `ExprKind::Block` arm above
|
||||
self.cbox(0);
|
||||
|
|
|
|||
|
|
@ -3,9 +3,8 @@ name = "rustc_attr"
|
|||
version = "0.0.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
|
||||
[dependencies]
|
||||
# tidy-alphabetical-start
|
||||
rustc_ast = { path = "../rustc_ast" }
|
||||
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
|
||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
|
|
@ -17,3 +16,4 @@ rustc_macros = { path = "../rustc_macros" }
|
|||
rustc_serialize = { path = "../rustc_serialize" }
|
||||
rustc_session = { path = "../rustc_session" }
|
||||
rustc_span = { path = "../rustc_span" }
|
||||
# tidy-alphabetical-end
|
||||
|
|
|
|||
|
|
@ -10,10 +10,9 @@ use rustc_session::config::ExpectedValues;
|
|||
use rustc_session::lint::builtin::UNEXPECTED_CFGS;
|
||||
use rustc_session::lint::BuiltinLintDiagnostics;
|
||||
use rustc_session::parse::{feature_err, ParseSess};
|
||||
use rustc_session::Session;
|
||||
use rustc_session::{RustcVersion, Session};
|
||||
use rustc_span::hygiene::Transparency;
|
||||
use rustc_span::{symbol::sym, symbol::Symbol, Span};
|
||||
use std::fmt::{self, Display};
|
||||
use std::num::NonZeroU32;
|
||||
|
||||
use crate::session_diagnostics::{self, IncorrectReprFormatGenericCause};
|
||||
|
|
@ -24,8 +23,6 @@ use crate::session_diagnostics::{self, IncorrectReprFormatGenericCause};
|
|||
/// For more, see [this pull request](https://github.com/rust-lang/rust/pull/100591).
|
||||
pub const VERSION_PLACEHOLDER: &str = "CURRENT_RUSTC_VERSION";
|
||||
|
||||
pub const CURRENT_RUSTC_VERSION: &str = env!("CFG_RELEASE");
|
||||
|
||||
pub fn is_builtin_attr(attr: &Attribute) -> bool {
|
||||
attr.is_doc_comment() || attr.ident().is_some_and(|ident| is_builtin_attr_name(ident.name))
|
||||
}
|
||||
|
|
@ -142,7 +139,7 @@ pub enum StabilityLevel {
|
|||
/// `#[stable]`
|
||||
Stable {
|
||||
/// Rust release which stabilized this feature.
|
||||
since: Since,
|
||||
since: StableSince,
|
||||
/// Is this item allowed to be referred to on stable, despite being contained in unstable
|
||||
/// modules?
|
||||
allowed_through_unstable_modules: bool,
|
||||
|
|
@ -152,8 +149,8 @@ pub enum StabilityLevel {
|
|||
/// Rust release in which a feature is stabilized.
|
||||
#[derive(Encodable, Decodable, PartialEq, Copy, Clone, Debug, Eq, Hash)]
|
||||
#[derive(HashStable_Generic)]
|
||||
pub enum Since {
|
||||
Version(Version),
|
||||
pub enum StableSince {
|
||||
Version(RustcVersion),
|
||||
/// Stabilized in the upcoming version, whatever number that is.
|
||||
Current,
|
||||
/// Failed to parse a stabilization version.
|
||||
|
|
@ -381,16 +378,16 @@ fn parse_stability(sess: &Session, attr: &Attribute) -> Option<(Symbol, Stabilit
|
|||
|
||||
let since = if let Some(since) = since {
|
||||
if since.as_str() == VERSION_PLACEHOLDER {
|
||||
Since::Current
|
||||
} else if let Some(version) = parse_version(since.as_str(), false) {
|
||||
Since::Version(version)
|
||||
StableSince::Current
|
||||
} else if let Some(version) = parse_version(since) {
|
||||
StableSince::Version(version)
|
||||
} else {
|
||||
sess.emit_err(session_diagnostics::InvalidSince { span: attr.span });
|
||||
Since::Err
|
||||
StableSince::Err
|
||||
}
|
||||
} else {
|
||||
sess.emit_err(session_diagnostics::MissingSince { span: attr.span });
|
||||
Since::Err
|
||||
StableSince::Err
|
||||
};
|
||||
|
||||
match feature {
|
||||
|
|
@ -567,31 +564,20 @@ fn gate_cfg(gated_cfg: &GatedCfg, cfg_span: Span, sess: &ParseSess, features: &F
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Encodable, Decodable, Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[derive(HashStable_Generic)]
|
||||
pub struct Version {
|
||||
pub major: u16,
|
||||
pub minor: u16,
|
||||
pub patch: u16,
|
||||
}
|
||||
|
||||
fn parse_version(s: &str, allow_appendix: bool) -> Option<Version> {
|
||||
let mut components = s.split('-');
|
||||
/// Parse a rustc version number written inside string literal in an attribute,
|
||||
/// like appears in `since = "1.0.0"`. Suffixes like "-dev" and "-nightly" are
|
||||
/// not accepted in this position, unlike when parsing CFG_RELEASE.
|
||||
fn parse_version(s: Symbol) -> Option<RustcVersion> {
|
||||
let mut components = s.as_str().split('-');
|
||||
let d = components.next()?;
|
||||
if !allow_appendix && components.next().is_some() {
|
||||
if components.next().is_some() {
|
||||
return None;
|
||||
}
|
||||
let mut digits = d.splitn(3, '.');
|
||||
let major = digits.next()?.parse().ok()?;
|
||||
let minor = digits.next()?.parse().ok()?;
|
||||
let patch = digits.next().unwrap_or("0").parse().ok()?;
|
||||
Some(Version { major, minor, patch })
|
||||
}
|
||||
|
||||
impl Display for Version {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(formatter, "{}.{}.{}", self.major, self.minor, self.patch)
|
||||
}
|
||||
Some(RustcVersion { major, minor, patch })
|
||||
}
|
||||
|
||||
/// Evaluate a cfg-like condition (with `any` and `all`), using `eval` to
|
||||
|
|
@ -623,17 +609,16 @@ pub fn eval_condition(
|
|||
return false;
|
||||
}
|
||||
};
|
||||
let Some(min_version) = parse_version(min_version.as_str(), false) else {
|
||||
let Some(min_version) = parse_version(*min_version) else {
|
||||
sess.emit_warning(session_diagnostics::UnknownVersionLiteral { span: *span });
|
||||
return false;
|
||||
};
|
||||
let rustc_version = parse_version(CURRENT_RUSTC_VERSION, true).unwrap();
|
||||
|
||||
// See https://github.com/rust-lang/rust/issues/64796#issuecomment-640851454 for details
|
||||
if sess.assume_incomplete_release {
|
||||
rustc_version > min_version
|
||||
RustcVersion::CURRENT > min_version
|
||||
} else {
|
||||
rustc_version >= min_version
|
||||
RustcVersion::CURRENT >= min_version
|
||||
}
|
||||
}
|
||||
ast::MetaItemKind::List(mis) => {
|
||||
|
|
@ -735,17 +720,49 @@ pub fn eval_condition(
|
|||
|
||||
#[derive(Copy, Debug, Encodable, Decodable, Clone, HashStable_Generic)]
|
||||
pub struct Deprecation {
|
||||
pub since: Option<Symbol>,
|
||||
pub since: DeprecatedSince,
|
||||
/// The note to issue a reason.
|
||||
pub note: Option<Symbol>,
|
||||
/// A text snippet used to completely replace any use of the deprecated item in an expression.
|
||||
///
|
||||
/// This is currently unstable.
|
||||
pub suggestion: Option<Symbol>,
|
||||
}
|
||||
|
||||
/// Whether to treat the since attribute as being a Rust version identifier
|
||||
/// (rather than an opaque string).
|
||||
pub is_since_rustc_version: bool,
|
||||
/// Release in which an API is deprecated.
|
||||
#[derive(Copy, Debug, Encodable, Decodable, Clone, HashStable_Generic)]
|
||||
pub enum DeprecatedSince {
|
||||
RustcVersion(RustcVersion),
|
||||
/// Deprecated in the future ("to be determined").
|
||||
Future,
|
||||
/// `feature(staged_api)` is off. Deprecation versions outside the standard
|
||||
/// library are allowed to be arbitrary strings, for better or worse.
|
||||
NonStandard(Symbol),
|
||||
/// Deprecation version is unspecified but optional.
|
||||
Unspecified,
|
||||
/// Failed to parse a deprecation version, or the deprecation version is
|
||||
/// unspecified and required. An error has already been emitted.
|
||||
Err,
|
||||
}
|
||||
|
||||
impl Deprecation {
|
||||
/// Whether an item marked with #[deprecated(since = "X")] is currently
|
||||
/// deprecated (i.e., whether X is not greater than the current rustc
|
||||
/// version).
|
||||
pub fn is_in_effect(&self) -> bool {
|
||||
match self.since {
|
||||
DeprecatedSince::RustcVersion(since) => since <= RustcVersion::CURRENT,
|
||||
DeprecatedSince::Future => false,
|
||||
// The `since` field doesn't have semantic purpose without `#![staged_api]`.
|
||||
DeprecatedSince::NonStandard(_) => true,
|
||||
// Assume deprecation is in effect if "since" field is absent or invalid.
|
||||
DeprecatedSince::Unspecified | DeprecatedSince::Err => true,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_since_rustc_version(&self) -> bool {
|
||||
matches!(self.since, DeprecatedSince::RustcVersion(_))
|
||||
}
|
||||
}
|
||||
|
||||
/// Finds the deprecation attribute. `None` if none exists.
|
||||
|
|
@ -854,22 +871,30 @@ pub fn find_deprecation(
|
|||
}
|
||||
}
|
||||
|
||||
if is_rustc {
|
||||
if since.is_none() {
|
||||
sess.emit_err(session_diagnostics::MissingSince { span: attr.span });
|
||||
continue;
|
||||
let since = if let Some(since) = since {
|
||||
if since.as_str() == "TBD" {
|
||||
DeprecatedSince::Future
|
||||
} else if !is_rustc {
|
||||
DeprecatedSince::NonStandard(since)
|
||||
} else if let Some(version) = parse_version(since) {
|
||||
DeprecatedSince::RustcVersion(version)
|
||||
} else {
|
||||
sess.emit_err(session_diagnostics::InvalidSince { span: attr.span });
|
||||
DeprecatedSince::Err
|
||||
}
|
||||
} else if is_rustc {
|
||||
sess.emit_err(session_diagnostics::MissingSince { span: attr.span });
|
||||
DeprecatedSince::Err
|
||||
} else {
|
||||
DeprecatedSince::Unspecified
|
||||
};
|
||||
|
||||
if note.is_none() {
|
||||
sess.emit_err(session_diagnostics::MissingNote { span: attr.span });
|
||||
continue;
|
||||
}
|
||||
if is_rustc && note.is_none() {
|
||||
sess.emit_err(session_diagnostics::MissingNote { span: attr.span });
|
||||
continue;
|
||||
}
|
||||
|
||||
depr = Some((
|
||||
Deprecation { since, note, suggestion, is_since_rustc_version: is_rustc },
|
||||
attr.span,
|
||||
));
|
||||
depr = Some((Deprecation { since, note, suggestion }, attr.span));
|
||||
}
|
||||
|
||||
depr
|
||||
|
|
|
|||
|
|
@ -27,6 +27,6 @@ pub use StabilityLevel::*;
|
|||
|
||||
pub use rustc_ast::attr::*;
|
||||
|
||||
pub(crate) use rustc_ast::HashStableContext;
|
||||
pub(crate) use rustc_session::HashStableContext;
|
||||
|
||||
fluent_messages! { "../messages.ftl" }
|
||||
|
|
|
|||
|
|
@ -4,11 +4,15 @@ version = "0.0.0"
|
|||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
# tidy-alphabetical-start
|
||||
icu_list = "1.2"
|
||||
icu_locid = "1.2"
|
||||
icu_provider = "1.2"
|
||||
icu_provider_adapters = "1.2"
|
||||
zerovec = "0.9.4"
|
||||
# tidy-alphabetical-end
|
||||
|
||||
[features]
|
||||
# tidy-alphabetical-start
|
||||
rustc_use_parallel_compiler = ['icu_provider/sync']
|
||||
# tidy-alphabetical-end
|
||||
|
|
|
|||
|
|
@ -3,19 +3,16 @@ name = "rustc_borrowck"
|
|||
version = "0.0.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
|
||||
[dependencies]
|
||||
# tidy-alphabetical-start
|
||||
either = "1.5.0"
|
||||
itertools = "0.10.1"
|
||||
tracing = "0.1"
|
||||
polonius-engine = "0.13.0"
|
||||
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
|
||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
rustc_errors = { path = "../rustc_errors" }
|
||||
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
|
||||
rustc_graphviz = { path = "../rustc_graphviz" }
|
||||
rustc_hir = { path = "../rustc_hir" }
|
||||
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
|
||||
rustc_index = { path = "../rustc_index" }
|
||||
rustc_infer = { path = "../rustc_infer" }
|
||||
rustc_lexer = { path = "../rustc_lexer" }
|
||||
|
|
@ -24,7 +21,10 @@ rustc_middle = { path = "../rustc_middle" }
|
|||
rustc_mir_dataflow = { path = "../rustc_mir_dataflow" }
|
||||
rustc_serialize = { path = "../rustc_serialize" }
|
||||
rustc_session = { path = "../rustc_session" }
|
||||
rustc_span = { path = "../rustc_span" }
|
||||
rustc_target = { path = "../rustc_target" }
|
||||
rustc_trait_selection = { path = "../rustc_trait_selection" }
|
||||
rustc_traits = { path = "../rustc_traits" }
|
||||
rustc_span = { path = "../rustc_span" }
|
||||
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
|
||||
tracing = "0.1"
|
||||
# tidy-alphabetical-end
|
||||
|
|
|
|||
|
|
@ -373,11 +373,12 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
|||
span: Span,
|
||||
yield_span: Span,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
let coroutine_kind = self.body.coroutine.as_ref().unwrap().coroutine_kind;
|
||||
let mut err = struct_span_err!(
|
||||
self,
|
||||
span,
|
||||
E0626,
|
||||
"borrow may still be in use when coroutine yields",
|
||||
"borrow may still be in use when {coroutine_kind:#} yields",
|
||||
);
|
||||
err.span_label(yield_span, "possible yield occurs here");
|
||||
err
|
||||
|
|
|
|||
|
|
@ -2491,11 +2491,17 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
|
||||
let (sugg_span, suggestion) = match tcx.sess.source_map().span_to_snippet(args_span) {
|
||||
Ok(string) => {
|
||||
if string.starts_with("async ") {
|
||||
let pos = args_span.lo() + BytePos(6);
|
||||
(args_span.with_lo(pos).with_hi(pos), "move ")
|
||||
} else if string.starts_with("async|") {
|
||||
let pos = args_span.lo() + BytePos(5);
|
||||
let coro_prefix = if string.starts_with("async") {
|
||||
// `async` is 5 chars long. Not using `.len()` to avoid the cast from `usize` to `u32`
|
||||
Some(5)
|
||||
} else if string.starts_with("gen") {
|
||||
// `gen` is 3 chars long
|
||||
Some(3)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
if let Some(n) = coro_prefix {
|
||||
let pos = args_span.lo() + BytePos(n);
|
||||
(args_span.with_lo(pos).with_hi(pos), " move")
|
||||
} else {
|
||||
(args_span.shrink_to_lo(), "move ")
|
||||
|
|
@ -2505,6 +2511,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
};
|
||||
let kind = match use_span.coroutine_kind() {
|
||||
Some(coroutine_kind) => match coroutine_kind {
|
||||
CoroutineKind::Gen(kind) => match kind {
|
||||
CoroutineSource::Block => "gen block",
|
||||
CoroutineSource::Closure => "gen closure",
|
||||
_ => bug!("gen block/closure expected, but gen function found."),
|
||||
},
|
||||
CoroutineKind::Async(async_kind) => match async_kind {
|
||||
CoroutineSource::Block => "async block",
|
||||
CoroutineSource::Closure => "async closure",
|
||||
|
|
|
|||
|
|
@ -698,6 +698,20 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
|||
" of async function"
|
||||
}
|
||||
},
|
||||
Some(hir::CoroutineKind::Gen(gen)) => match gen {
|
||||
hir::CoroutineSource::Block => " of gen block",
|
||||
hir::CoroutineSource::Closure => " of gen closure",
|
||||
hir::CoroutineSource::Fn => {
|
||||
let parent_item =
|
||||
hir.get_by_def_id(hir.get_parent_item(mir_hir_id).def_id);
|
||||
let output = &parent_item
|
||||
.fn_decl()
|
||||
.expect("coroutine lowered from gen fn should be in fn")
|
||||
.output;
|
||||
span = output.span();
|
||||
" of gen function"
|
||||
}
|
||||
},
|
||||
Some(hir::CoroutineKind::Coroutine) => " of coroutine",
|
||||
None => " of closure",
|
||||
};
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ use rustc_data_structures::graph::WithSuccessors;
|
|||
use rustc_index::bit_set::{HybridBitSet, SparseBitMatrix};
|
||||
use rustc_index::interval::IntervalSet;
|
||||
use rustc_infer::infer::canonical::QueryRegionConstraints;
|
||||
use rustc_infer::infer::outlives::for_liveness;
|
||||
use rustc_middle::mir::{BasicBlock, Body, ConstraintCategory, Local, Location};
|
||||
use rustc_middle::traits::query::DropckOutlivesResult;
|
||||
use rustc_middle::ty::{RegionVid, Ty, TyCtxt, TypeVisitable, TypeVisitableExt};
|
||||
|
|
@ -601,34 +602,36 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
|
|||
values::location_set_str(elements, live_at.iter()),
|
||||
);
|
||||
|
||||
let tcx = typeck.tcx();
|
||||
let borrowck_context = &mut typeck.borrowck_context;
|
||||
|
||||
// When using `-Zpolonius=next`, we want to record the loans that flow into this value's
|
||||
// regions as being live at the given `live_at` points: this will be used to compute the
|
||||
// location where a loan goes out of scope.
|
||||
let num_loans = borrowck_context.borrow_set.len();
|
||||
let mut value_loans = HybridBitSet::new_empty(num_loans);
|
||||
let num_loans = typeck.borrowck_context.borrow_set.len();
|
||||
let value_loans = &mut HybridBitSet::new_empty(num_loans);
|
||||
|
||||
tcx.for_each_free_region(&value, |live_region| {
|
||||
let live_region_vid = borrowck_context.universal_regions.to_region_vid(live_region);
|
||||
value.visit_with(&mut for_liveness::FreeRegionsVisitor {
|
||||
tcx: typeck.tcx(),
|
||||
param_env: typeck.param_env,
|
||||
op: |r| {
|
||||
let live_region_vid = typeck.borrowck_context.universal_regions.to_region_vid(r);
|
||||
|
||||
borrowck_context
|
||||
.constraints
|
||||
.liveness_constraints
|
||||
.add_elements(live_region_vid, live_at);
|
||||
typeck
|
||||
.borrowck_context
|
||||
.constraints
|
||||
.liveness_constraints
|
||||
.add_elements(live_region_vid, live_at);
|
||||
|
||||
// There can only be inflowing loans for this region when we are using
|
||||
// `-Zpolonius=next`.
|
||||
if let Some(inflowing) = inflowing_loans.row(live_region_vid) {
|
||||
value_loans.union(inflowing);
|
||||
}
|
||||
// There can only be inflowing loans for this region when we are using
|
||||
// `-Zpolonius=next`.
|
||||
if let Some(inflowing) = inflowing_loans.row(live_region_vid) {
|
||||
value_loans.union(inflowing);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
// Record the loans reaching the value.
|
||||
if !value_loans.is_empty() {
|
||||
for point in live_at.iter() {
|
||||
borrowck_context.live_loans.union_row(point, &value_loans);
|
||||
typeck.borrowck_context.live_loans.union_row(point, value_loans);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -188,11 +188,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
|
|||
&mut borrowck_context,
|
||||
);
|
||||
|
||||
// FIXME(-Ztrait-solver=next): A bit dubious that we're only registering
|
||||
// predefined opaques in the typeck root.
|
||||
if infcx.next_trait_solver() && !infcx.tcx.is_typeck_child(body.source.def_id()) {
|
||||
checker.register_predefined_opaques_in_new_solver();
|
||||
}
|
||||
checker.check_user_type_annotations();
|
||||
|
||||
let mut verifier = TypeVerifier::new(&mut checker, promoted);
|
||||
verifier.visit_body(&body);
|
||||
|
|
@ -1021,7 +1017,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
borrowck_context,
|
||||
reported_errors: Default::default(),
|
||||
};
|
||||
checker.check_user_type_annotations();
|
||||
|
||||
// FIXME(-Ztrait-solver=next): A bit dubious that we're only registering
|
||||
// predefined opaques in the typeck root.
|
||||
if infcx.next_trait_solver() && !infcx.tcx.is_typeck_child(body.source.def_id()) {
|
||||
checker.register_predefined_opaques_in_new_solver();
|
||||
}
|
||||
|
||||
checker
|
||||
}
|
||||
|
||||
|
|
@ -1640,7 +1642,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
}
|
||||
TerminatorKind::UnwindTerminate(_) => {
|
||||
if !is_cleanup {
|
||||
span_mirbug!(self, block_data, "abort on non-cleanup block!")
|
||||
span_mirbug!(self, block_data, "terminate on non-cleanup block!")
|
||||
}
|
||||
}
|
||||
TerminatorKind::Return => {
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ edition = "2021"
|
|||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
# tidy-alphabetical-start
|
||||
rustc_ast = { path = "../rustc_ast" }
|
||||
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
|
||||
rustc_attr = { path = "../rustc_attr" }
|
||||
|
|
@ -14,16 +15,17 @@ rustc_data_structures = { path = "../rustc_data_structures" }
|
|||
rustc_errors = { path = "../rustc_errors" }
|
||||
rustc_expand = { path = "../rustc_expand" }
|
||||
rustc_feature = { path = "../rustc_feature" }
|
||||
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
|
||||
rustc_index = { path = "../rustc_index" }
|
||||
rustc_lexer = { path = "../rustc_lexer" }
|
||||
rustc_lint_defs = { path = "../rustc_lint_defs" }
|
||||
rustc_macros = { path = "../rustc_macros" }
|
||||
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
|
||||
rustc_parse_format = { path = "../rustc_parse_format" }
|
||||
rustc_parse = { path = "../rustc_parse" }
|
||||
rustc_parse_format = { path = "../rustc_parse_format" }
|
||||
rustc_session = { path = "../rustc_session" }
|
||||
rustc_span = { path = "../rustc_span" }
|
||||
rustc_target = { path = "../rustc_target" }
|
||||
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
|
||||
thin-vec = "0.2.12"
|
||||
tracing = "0.1"
|
||||
# tidy-alphabetical-end
|
||||
|
|
|
|||
|
|
@ -294,7 +294,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
|
|||
// sync with the `rfc-2011-nicer-assert-messages/all-expr-kinds.rs` test.
|
||||
ExprKind::Assign(_, _, _)
|
||||
| ExprKind::AssignOp(_, _, _)
|
||||
| ExprKind::Async(_, _)
|
||||
| ExprKind::Gen(_, _, _)
|
||||
| ExprKind::Await(_, _)
|
||||
| ExprKind::Block(_, _)
|
||||
| ExprKind::Break(_, _)
|
||||
|
|
|
|||
|
|
@ -45,18 +45,18 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|||
|
||||
[[package]]
|
||||
name = "cranelift-bforest"
|
||||
version = "0.101.1"
|
||||
version = "0.101.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c1512c3bb6b13018e7109fc3ac964bc87b329eaf3a77825d337558d0c7f6f1be"
|
||||
checksum = "f773437307980ac0f424bf9b9a5d0cd21a0f17248c6860c9a65bec8b5975f3fe"
|
||||
dependencies = [
|
||||
"cranelift-entity",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen"
|
||||
version = "0.101.1"
|
||||
version = "0.101.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "16cb8fb9220a6ea7a226705a273ab905309ee546267bdf34948d57932d7f0396"
|
||||
checksum = "443c2ac50e97fb7de1a0f862753fce3f27215558811a6fcee508eb0c3747fa79"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"cranelift-bforest",
|
||||
|
|
@ -75,39 +75,39 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cranelift-codegen-meta"
|
||||
version = "0.101.1"
|
||||
version = "0.101.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab3a8d3b0d4745b183da5ea0792b13d79f5c23d6e69ac04761728e2532b56649"
|
||||
checksum = "c5b174c411480c79ce0793c55042fa51bec27e486381d103a53cab3b480cb2db"
|
||||
dependencies = [
|
||||
"cranelift-codegen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen-shared"
|
||||
version = "0.101.1"
|
||||
version = "0.101.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "524141c8e68f2abc2043de4c2b31f6d9dd42432738c246431d0572a1422a4a84"
|
||||
checksum = "73fa0151a528066a369de6debeea4d4b23a32aba68b5add8c46d3dc8091ff434"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-control"
|
||||
version = "0.101.1"
|
||||
version = "0.101.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "97513b57c961c713789a03886a57b43e14ebcd204cbaa8ae50ca6c70a8e716b3"
|
||||
checksum = "b8adf1e6398493c9bea1190e37d28a0eb0eca5fddbc80e01e506cda34db92b1f"
|
||||
dependencies = [
|
||||
"arbitrary",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-entity"
|
||||
version = "0.101.1"
|
||||
version = "0.101.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3f23d3cf3afa7e45f239702612c76d87964f652a55e28d13ed6d7e20f3479dd"
|
||||
checksum = "4917e2ed3bb5fe87d0ed88395ca6d644018d119a034faedd1f3e1f2c33cd52b2"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-frontend"
|
||||
version = "0.101.1"
|
||||
version = "0.101.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "554cd4947ec9209b58bf9ae5bf83581b5ddf9128bd967208e334b504a57db54e"
|
||||
checksum = "9aaadf1e7cf28886bbf046eaf7ef538997bc8a7e020e578ea4957b39da87d5a1"
|
||||
dependencies = [
|
||||
"cranelift-codegen",
|
||||
"log",
|
||||
|
|
@ -117,15 +117,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cranelift-isle"
|
||||
version = "0.101.1"
|
||||
version = "0.101.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c1892a439696b6413cb54083806f5fd9fc431768b8de74864b3d9e8b93b124f"
|
||||
checksum = "a67fda31b9d69eaa1c49a2081939454c45857596a9d45af6744680541c628b4c"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-jit"
|
||||
version = "0.101.1"
|
||||
version = "0.101.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32209252fb38acaf1662ccd0397907bbe0e92bdb13b6ddbfd2f74e437f83e685"
|
||||
checksum = "d6bf32710628e7ff298739f1ed80a0bfdafc0c6a3e284c4540b23f18e8889d4b"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cranelift-codegen",
|
||||
|
|
@ -143,9 +143,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cranelift-module"
|
||||
version = "0.101.1"
|
||||
version = "0.101.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf42656f5f6df7bfafc4dd7b63a1888b0627c07b43b2cb9aa54e13843fed39eb"
|
||||
checksum = "4d693e93a0fbf56b4bc93cffe6b107c2e52f070e1111950505fc8c83ac440b9d"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cranelift-codegen",
|
||||
|
|
@ -154,9 +154,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cranelift-native"
|
||||
version = "0.101.1"
|
||||
version = "0.101.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e0c2d3badd4b9690865f5bb68a71fa94de592fa2df3f3d11a5a062c60c0a107a"
|
||||
checksum = "76fb52ba71be98312f35e798d9e98e45ab2586f27584231bf7c644fa9501e8af"
|
||||
dependencies = [
|
||||
"cranelift-codegen",
|
||||
"libc",
|
||||
|
|
@ -165,9 +165,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cranelift-object"
|
||||
version = "0.101.1"
|
||||
version = "0.101.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "88eca54bbecea3170035168357306e9c779d4a63d8bf036c9e16bd21fdaa69b5"
|
||||
checksum = "2551b2e185022b89e9efa5e04c0f17f679b86ef73d9f7feabc48b608ff23120d"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cranelift-codegen",
|
||||
|
|
@ -362,9 +362,9 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
|||
|
||||
[[package]]
|
||||
name = "target-lexicon"
|
||||
version = "0.12.5"
|
||||
version = "0.12.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9410d0f6853b1d94f0e519fb95df60f29d2c1eff2d921ffdf01a4c8a3b54f12d"
|
||||
checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
|
|
@ -374,9 +374,9 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
|||
|
||||
[[package]]
|
||||
name = "wasmtime-jit-icache-coherence"
|
||||
version = "14.0.1"
|
||||
version = "14.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9aaf2fa8fd2d6b65abae9b92edfe69254cc5d6b166e342364036c3e347de8da9"
|
||||
checksum = "0980a96b16abbdaf829858d2389697b1d6cfc6a903873fd74b7e47a6b1045584"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
|
|
|
|||
|
|
@ -8,12 +8,12 @@ crate-type = ["dylib"]
|
|||
|
||||
[dependencies]
|
||||
# These have to be in sync with each other
|
||||
cranelift-codegen = { version = "0.101.1", features = ["unwind", "all-arch"] }
|
||||
cranelift-frontend = { version = "0.101.1" }
|
||||
cranelift-module = { version = "0.101.1" }
|
||||
cranelift-native = { version = "0.101.1" }
|
||||
cranelift-jit = { version = "0.101.1", optional = true }
|
||||
cranelift-object = { version = "0.101.1" }
|
||||
cranelift-codegen = { version = "0.101.2", default-features = false, features = ["std", "unwind", "all-arch"] }
|
||||
cranelift-frontend = { version = "0.101.2" }
|
||||
cranelift-module = { version = "0.101.2" }
|
||||
cranelift-native = { version = "0.101.2" }
|
||||
cranelift-jit = { version = "0.101.2", optional = true }
|
||||
cranelift-object = { version = "0.101.2" }
|
||||
target-lexicon = "0.12.0"
|
||||
gimli = { version = "0.28", default-features = false, features = ["write"]}
|
||||
object = { version = "0.32", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] }
|
||||
|
|
@ -35,9 +35,9 @@ smallvec = "1.8.1"
|
|||
|
||||
[features]
|
||||
# Enable features not ready to be enabled when compiling as part of rustc
|
||||
unstable-features = ["jit", "inline_asm"]
|
||||
unstable-features = ["jit", "inline_asm_sym"]
|
||||
jit = ["cranelift-jit", "libloading"]
|
||||
inline_asm = []
|
||||
inline_asm_sym = []
|
||||
|
||||
[package.metadata.rust-analyzer]
|
||||
rustc_private = true
|
||||
|
|
|
|||
|
|
@ -40,22 +40,6 @@ version = "0.2.15"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56fc6cf8dc8c4158eed8649f9b8b0ea1518eb62b544fe9490d66fa0b349eafe9"
|
||||
|
||||
[[package]]
|
||||
name = "auxv"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e50430f9beb8effb02399fa81c76eeaa26b05e4f03b09285cad8d079c1af5a3d"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"gcc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.79"
|
||||
|
|
@ -388,7 +372,6 @@ dependencies = [
|
|||
name = "std_detect"
|
||||
version = "0.1.5"
|
||||
dependencies = [
|
||||
"auxv",
|
||||
"cfg-if",
|
||||
"compiler_builtins",
|
||||
"cupid",
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
[toolchain]
|
||||
channel = "nightly-2023-10-21"
|
||||
channel = "nightly-2023-10-29"
|
||||
components = ["rust-src", "rustc-dev", "llvm-tools"]
|
||||
|
|
|
|||
|
|
@ -4,7 +4,9 @@ set -e
|
|||
# Compiletest expects all standard library paths to start with /rustc/FAKE_PREFIX.
|
||||
# CG_CLIF_STDLIB_REMAP_PATH_PREFIX will cause cg_clif's build system to pass
|
||||
# --remap-path-prefix to handle this.
|
||||
CG_CLIF_STDLIB_REMAP_PATH_PREFIX=/rustc/FAKE_PREFIX ./y.sh build
|
||||
# CG_CLIF_FORCE_GNU_AS will force usage of as instead of the LLVM backend of rustc as we
|
||||
# the LLVM backend isn't compiled in here.
|
||||
CG_CLIF_FORCE_GNU_AS=1 CG_CLIF_STDLIB_REMAP_PATH_PREFIX=/rustc/FAKE_PREFIX ./y.sh build
|
||||
|
||||
echo "[SETUP] Rust fork"
|
||||
git clone https://github.com/rust-lang/rust.git || true
|
||||
|
|
|
|||
|
|
@ -11,5 +11,7 @@ rm -r compiler/rustc_codegen_cranelift/{Cargo.*,src}
|
|||
cp ../Cargo.* compiler/rustc_codegen_cranelift/
|
||||
cp -r ../src compiler/rustc_codegen_cranelift/src
|
||||
|
||||
./x.py build --stage 1 library/std
|
||||
# CG_CLIF_FORCE_GNU_AS will force usage of as instead of the LLVM backend of rustc as we
|
||||
# the LLVM backend isn't compiled in here.
|
||||
CG_CLIF_FORCE_GNU_AS=1 ./x.py build --stage 1 library/std
|
||||
popd
|
||||
|
|
|
|||
|
|
@ -766,7 +766,7 @@ fn codegen_stmt<'tcx>(
|
|||
NullOp::SizeOf => layout.size.bytes(),
|
||||
NullOp::AlignOf => layout.align.abi.bytes(),
|
||||
NullOp::OffsetOf(fields) => {
|
||||
layout.offset_of_subfield(fx, fields.iter().map(|f| f.index())).bytes()
|
||||
layout.offset_of_subfield(fx, fields.iter()).bytes()
|
||||
}
|
||||
};
|
||||
let val = CValue::by_val(
|
||||
|
|
|
|||
|
|
@ -430,47 +430,11 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
// Note: must be kept in sync with get_caller_location from cg_ssa
|
||||
pub(crate) fn get_caller_location(&mut self, mut source_info: mir::SourceInfo) -> CValue<'tcx> {
|
||||
let span_to_caller_location = |fx: &mut FunctionCx<'_, '_, 'tcx>, span: Span| {
|
||||
use rustc_session::RemapFileNameExt;
|
||||
let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span);
|
||||
let caller = fx.tcx.sess.source_map().lookup_char_pos(topmost.lo());
|
||||
let const_loc = fx.tcx.const_caller_location((
|
||||
rustc_span::symbol::Symbol::intern(
|
||||
&caller.file.name.for_codegen(&fx.tcx.sess).to_string_lossy(),
|
||||
),
|
||||
caller.line as u32,
|
||||
caller.col_display as u32 + 1,
|
||||
));
|
||||
crate::constant::codegen_const_value(fx, const_loc, fx.tcx.caller_location_ty())
|
||||
};
|
||||
|
||||
// Walk up the `SourceScope`s, in case some of them are from MIR inlining.
|
||||
// If so, the starting `source_info.span` is in the innermost inlined
|
||||
// function, and will be replaced with outer callsite spans as long
|
||||
// as the inlined functions were `#[track_caller]`.
|
||||
loop {
|
||||
let scope_data = &self.mir.source_scopes[source_info.scope];
|
||||
|
||||
if let Some((callee, callsite_span)) = scope_data.inlined {
|
||||
// Stop inside the most nested non-`#[track_caller]` function,
|
||||
// before ever reaching its caller (which is irrelevant).
|
||||
if !callee.def.requires_caller_location(self.tcx) {
|
||||
return span_to_caller_location(self, source_info.span);
|
||||
}
|
||||
source_info.span = callsite_span;
|
||||
}
|
||||
|
||||
// Skip past all of the parents with `inlined: None`.
|
||||
match scope_data.inlined_parent_scope {
|
||||
Some(parent) => source_info.scope = parent,
|
||||
None => break,
|
||||
}
|
||||
}
|
||||
|
||||
// No inlined `SourceScope`s, or all of them were `#[track_caller]`.
|
||||
self.caller_location.unwrap_or_else(|| span_to_caller_location(self, source_info.span))
|
||||
pub(crate) fn get_caller_location(&mut self, source_info: mir::SourceInfo) -> CValue<'tcx> {
|
||||
self.mir.caller_location_span(source_info, self.caller_location, self.tcx, |span| {
|
||||
let const_loc = self.tcx.span_as_caller_location(span);
|
||||
crate::constant::codegen_const_value(self, const_loc, self.tcx.caller_location_ty())
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn anonymous_str(&mut self, msg: &str) -> Value {
|
||||
|
|
|
|||
|
|
@ -46,6 +46,13 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String,
|
|||
global_asm.push_str(&string);
|
||||
}
|
||||
InlineAsmOperand::SymFn { anon_const } => {
|
||||
if cfg!(not(feature = "inline_asm_sym")) {
|
||||
tcx.sess.span_err(
|
||||
item.span,
|
||||
"asm! and global_asm! sym operands are not yet supported",
|
||||
);
|
||||
}
|
||||
|
||||
let ty = tcx.typeck_body(anon_const.body).node_type(anon_const.hir_id);
|
||||
let instance = match ty.kind() {
|
||||
&ty::FnDef(def_id, args) => Instance::new(def_id, args),
|
||||
|
|
@ -57,6 +64,13 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String,
|
|||
global_asm.push_str(symbol.name);
|
||||
}
|
||||
InlineAsmOperand::SymStatic { path: _, def_id } => {
|
||||
if cfg!(not(feature = "inline_asm_sym")) {
|
||||
tcx.sess.span_err(
|
||||
item.span,
|
||||
"asm! and global_asm! sym operands are not yet supported",
|
||||
);
|
||||
}
|
||||
|
||||
let instance = Instance::mono(tcx, def_id).polymorphize(tcx);
|
||||
let symbol = tcx.symbol_name(instance);
|
||||
global_asm.push_str(symbol.name);
|
||||
|
|
@ -81,22 +95,23 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String,
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn asm_supported(tcx: TyCtxt<'_>) -> bool {
|
||||
cfg!(feature = "inline_asm") && !tcx.sess.target.is_like_windows
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct GlobalAsmConfig {
|
||||
asm_enabled: bool,
|
||||
assembler: PathBuf,
|
||||
target: String,
|
||||
pub(crate) output_filenames: Arc<OutputFilenames>,
|
||||
}
|
||||
|
||||
impl GlobalAsmConfig {
|
||||
pub(crate) fn new(tcx: TyCtxt<'_>) -> Self {
|
||||
GlobalAsmConfig {
|
||||
asm_enabled: asm_supported(tcx),
|
||||
assembler: crate::toolchain::get_toolchain_binary(tcx.sess, "as"),
|
||||
target: match &tcx.sess.opts.target_triple {
|
||||
rustc_target::spec::TargetTriple::TargetTriple(triple) => triple.clone(),
|
||||
rustc_target::spec::TargetTriple::TargetJson { path_for_rustdoc, .. } => {
|
||||
path_for_rustdoc.to_str().unwrap().to_owned()
|
||||
}
|
||||
},
|
||||
output_filenames: tcx.output_filenames(()).clone(),
|
||||
}
|
||||
}
|
||||
|
|
@ -111,21 +126,6 @@ pub(crate) fn compile_global_asm(
|
|||
return Ok(None);
|
||||
}
|
||||
|
||||
if !config.asm_enabled {
|
||||
if global_asm.contains("__rust_probestack") {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
if cfg!(not(feature = "inline_asm")) {
|
||||
return Err(
|
||||
"asm! and global_asm! support is disabled while compiling rustc_codegen_cranelift"
|
||||
.to_owned(),
|
||||
);
|
||||
} else {
|
||||
return Err("asm! and global_asm! are not yet supported on Windows".to_owned());
|
||||
}
|
||||
}
|
||||
|
||||
// Remove all LLVM style comments
|
||||
let mut global_asm = global_asm
|
||||
.lines()
|
||||
|
|
@ -134,20 +134,67 @@ pub(crate) fn compile_global_asm(
|
|||
.join("\n");
|
||||
global_asm.push('\n');
|
||||
|
||||
let output_object_file = config.output_filenames.temp_path(OutputType::Object, Some(cgu_name));
|
||||
let global_asm_object_file = add_file_stem_postfix(
|
||||
config.output_filenames.temp_path(OutputType::Object, Some(cgu_name)),
|
||||
".asm",
|
||||
);
|
||||
|
||||
// Assemble `global_asm`
|
||||
let global_asm_object_file = add_file_stem_postfix(output_object_file, ".asm");
|
||||
let mut child = Command::new(&config.assembler)
|
||||
.arg("-o")
|
||||
.arg(&global_asm_object_file)
|
||||
.stdin(Stdio::piped())
|
||||
.spawn()
|
||||
.expect("Failed to spawn `as`.");
|
||||
child.stdin.take().unwrap().write_all(global_asm.as_bytes()).unwrap();
|
||||
let status = child.wait().expect("Failed to wait for `as`.");
|
||||
if !status.success() {
|
||||
return Err(format!("Failed to assemble `{}`", global_asm));
|
||||
if option_env!("CG_CLIF_FORCE_GNU_AS").is_some() {
|
||||
let mut child = Command::new(&config.assembler)
|
||||
.arg("-o")
|
||||
.arg(&global_asm_object_file)
|
||||
.stdin(Stdio::piped())
|
||||
.spawn()
|
||||
.expect("Failed to spawn `as`.");
|
||||
child.stdin.take().unwrap().write_all(global_asm.as_bytes()).unwrap();
|
||||
let status = child.wait().expect("Failed to wait for `as`.");
|
||||
if !status.success() {
|
||||
return Err(format!("Failed to assemble `{}`", global_asm));
|
||||
}
|
||||
} else {
|
||||
let mut child = Command::new(std::env::current_exe().unwrap())
|
||||
.arg("--target")
|
||||
.arg(&config.target)
|
||||
.arg("--crate-type")
|
||||
.arg("staticlib")
|
||||
.arg("--emit")
|
||||
.arg("obj")
|
||||
.arg("-o")
|
||||
.arg(&global_asm_object_file)
|
||||
.arg("-")
|
||||
.arg("-Abad_asm_style")
|
||||
.arg("-Zcodegen-backend=llvm")
|
||||
.stdin(Stdio::piped())
|
||||
.spawn()
|
||||
.expect("Failed to spawn `as`.");
|
||||
let mut stdin = child.stdin.take().unwrap();
|
||||
stdin
|
||||
.write_all(
|
||||
br####"
|
||||
#![feature(decl_macro, no_core, rustc_attrs)]
|
||||
#![allow(internal_features)]
|
||||
#![no_core]
|
||||
#[rustc_builtin_macro]
|
||||
#[rustc_macro_transparency = "semitransparent"]
|
||||
macro global_asm() { /* compiler built-in */ }
|
||||
global_asm!(r###"
|
||||
"####,
|
||||
)
|
||||
.unwrap();
|
||||
stdin.write_all(global_asm.as_bytes()).unwrap();
|
||||
stdin
|
||||
.write_all(
|
||||
br####"
|
||||
"###);
|
||||
"####,
|
||||
)
|
||||
.unwrap();
|
||||
std::mem::drop(stdin);
|
||||
let status = child.wait().expect("Failed to wait for `as`.");
|
||||
if !status.success() {
|
||||
return Err(format!("Failed to assemble `{}`", global_asm));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Some(global_asm_object_file))
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ use rustc_span::sym;
|
|||
use rustc_target::asm::*;
|
||||
use target_lexicon::BinaryFormat;
|
||||
|
||||
use crate::global_asm::asm_supported;
|
||||
use crate::prelude::*;
|
||||
|
||||
enum CInlineAsmOperand<'tcx> {
|
||||
|
|
@ -45,208 +44,11 @@ pub(crate) fn codegen_inline_asm<'tcx>(
|
|||
) {
|
||||
// FIXME add .eh_frame unwind info directives
|
||||
|
||||
if !asm_supported(fx.tcx) {
|
||||
if template.is_empty() {
|
||||
let destination_block = fx.get_block(destination.unwrap());
|
||||
fx.bcx.ins().jump(destination_block, &[]);
|
||||
return;
|
||||
}
|
||||
|
||||
// Used by panic_abort
|
||||
if template[0] == InlineAsmTemplatePiece::String("int $$0x29".to_string()) {
|
||||
fx.bcx.ins().trap(TrapCode::User(1));
|
||||
return;
|
||||
}
|
||||
|
||||
// Used by stdarch
|
||||
if template[0] == InlineAsmTemplatePiece::String("mov ".to_string())
|
||||
&& matches!(
|
||||
template[1],
|
||||
InlineAsmTemplatePiece::Placeholder {
|
||||
operand_idx: 0,
|
||||
modifier: Some('r'),
|
||||
span: _
|
||||
}
|
||||
)
|
||||
&& template[2] == InlineAsmTemplatePiece::String(", rbx".to_string())
|
||||
&& template[3] == InlineAsmTemplatePiece::String("\n".to_string())
|
||||
&& template[4] == InlineAsmTemplatePiece::String("cpuid".to_string())
|
||||
&& template[5] == InlineAsmTemplatePiece::String("\n".to_string())
|
||||
&& template[6] == InlineAsmTemplatePiece::String("xchg ".to_string())
|
||||
&& matches!(
|
||||
template[7],
|
||||
InlineAsmTemplatePiece::Placeholder {
|
||||
operand_idx: 0,
|
||||
modifier: Some('r'),
|
||||
span: _
|
||||
}
|
||||
)
|
||||
&& template[8] == InlineAsmTemplatePiece::String(", rbx".to_string())
|
||||
{
|
||||
assert_eq!(operands.len(), 4);
|
||||
let (leaf, eax_place) = match operands[1] {
|
||||
InlineAsmOperand::InOut {
|
||||
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::ax)),
|
||||
late: _,
|
||||
ref in_value,
|
||||
out_place: Some(out_place),
|
||||
} => (
|
||||
crate::base::codegen_operand(fx, in_value).load_scalar(fx),
|
||||
crate::base::codegen_place(fx, out_place),
|
||||
),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let ebx_place = match operands[0] {
|
||||
InlineAsmOperand::Out {
|
||||
reg:
|
||||
InlineAsmRegOrRegClass::RegClass(InlineAsmRegClass::X86(
|
||||
X86InlineAsmRegClass::reg,
|
||||
)),
|
||||
late: _,
|
||||
place: Some(place),
|
||||
} => crate::base::codegen_place(fx, place),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let (sub_leaf, ecx_place) = match operands[2] {
|
||||
InlineAsmOperand::InOut {
|
||||
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::cx)),
|
||||
late: _,
|
||||
ref in_value,
|
||||
out_place: Some(out_place),
|
||||
} => (
|
||||
crate::base::codegen_operand(fx, in_value).load_scalar(fx),
|
||||
crate::base::codegen_place(fx, out_place),
|
||||
),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let edx_place = match operands[3] {
|
||||
InlineAsmOperand::Out {
|
||||
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::dx)),
|
||||
late: _,
|
||||
place: Some(place),
|
||||
} => crate::base::codegen_place(fx, place),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let (eax, ebx, ecx, edx) = crate::intrinsics::codegen_cpuid_call(fx, leaf, sub_leaf);
|
||||
|
||||
eax_place.write_cvalue(fx, CValue::by_val(eax, fx.layout_of(fx.tcx.types.u32)));
|
||||
ebx_place.write_cvalue(fx, CValue::by_val(ebx, fx.layout_of(fx.tcx.types.u32)));
|
||||
ecx_place.write_cvalue(fx, CValue::by_val(ecx, fx.layout_of(fx.tcx.types.u32)));
|
||||
edx_place.write_cvalue(fx, CValue::by_val(edx, fx.layout_of(fx.tcx.types.u32)));
|
||||
let destination_block = fx.get_block(destination.unwrap());
|
||||
fx.bcx.ins().jump(destination_block, &[]);
|
||||
return;
|
||||
}
|
||||
|
||||
// Used by compiler-builtins
|
||||
if fx.tcx.symbol_name(fx.instance).name.starts_with("___chkstk") {
|
||||
// ___chkstk, ___chkstk_ms and __alloca are only used on Windows
|
||||
crate::trap::trap_unimplemented(fx, "Stack probes are not supported");
|
||||
return;
|
||||
} else if fx.tcx.symbol_name(fx.instance).name == "__alloca" {
|
||||
crate::trap::trap_unimplemented(fx, "Alloca is not supported");
|
||||
return;
|
||||
}
|
||||
|
||||
// Used by core::hint::spin_loop()
|
||||
if template[0]
|
||||
== InlineAsmTemplatePiece::String(".insn i 0x0F, 0, x0, x0, 0x010".to_string())
|
||||
&& template.len() == 1
|
||||
{
|
||||
let destination_block = fx.get_block(destination.unwrap());
|
||||
fx.bcx.ins().jump(destination_block, &[]);
|
||||
return;
|
||||
}
|
||||
|
||||
// Used by measureme
|
||||
if template[0] == InlineAsmTemplatePiece::String("xor %eax, %eax".to_string())
|
||||
&& template[1] == InlineAsmTemplatePiece::String("\n".to_string())
|
||||
&& template[2] == InlineAsmTemplatePiece::String("mov %rbx, ".to_string())
|
||||
&& matches!(
|
||||
template[3],
|
||||
InlineAsmTemplatePiece::Placeholder {
|
||||
operand_idx: 0,
|
||||
modifier: Some('r'),
|
||||
span: _
|
||||
}
|
||||
)
|
||||
&& template[4] == InlineAsmTemplatePiece::String("\n".to_string())
|
||||
&& template[5] == InlineAsmTemplatePiece::String("cpuid".to_string())
|
||||
&& template[6] == InlineAsmTemplatePiece::String("\n".to_string())
|
||||
&& template[7] == InlineAsmTemplatePiece::String("mov ".to_string())
|
||||
&& matches!(
|
||||
template[8],
|
||||
InlineAsmTemplatePiece::Placeholder {
|
||||
operand_idx: 0,
|
||||
modifier: Some('r'),
|
||||
span: _
|
||||
}
|
||||
)
|
||||
&& template[9] == InlineAsmTemplatePiece::String(", %rbx".to_string())
|
||||
{
|
||||
let destination_block = fx.get_block(destination.unwrap());
|
||||
fx.bcx.ins().jump(destination_block, &[]);
|
||||
return;
|
||||
} else if template[0] == InlineAsmTemplatePiece::String("rdpmc".to_string()) {
|
||||
// Return zero dummy values for all performance counters
|
||||
match operands[0] {
|
||||
InlineAsmOperand::In {
|
||||
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::cx)),
|
||||
value: _,
|
||||
} => {}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let lo = match operands[1] {
|
||||
InlineAsmOperand::Out {
|
||||
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::ax)),
|
||||
late: true,
|
||||
place: Some(place),
|
||||
} => crate::base::codegen_place(fx, place),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let hi = match operands[2] {
|
||||
InlineAsmOperand::Out {
|
||||
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::dx)),
|
||||
late: true,
|
||||
place: Some(place),
|
||||
} => crate::base::codegen_place(fx, place),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let u32_layout = fx.layout_of(fx.tcx.types.u32);
|
||||
let zero = fx.bcx.ins().iconst(types::I32, 0);
|
||||
lo.write_cvalue(fx, CValue::by_val(zero, u32_layout));
|
||||
hi.write_cvalue(fx, CValue::by_val(zero, u32_layout));
|
||||
|
||||
let destination_block = fx.get_block(destination.unwrap());
|
||||
fx.bcx.ins().jump(destination_block, &[]);
|
||||
return;
|
||||
} else if template[0] == InlineAsmTemplatePiece::String("lock xadd ".to_string())
|
||||
&& matches!(
|
||||
template[1],
|
||||
InlineAsmTemplatePiece::Placeholder { operand_idx: 1, modifier: None, span: _ }
|
||||
)
|
||||
&& template[2] == InlineAsmTemplatePiece::String(", (".to_string())
|
||||
&& matches!(
|
||||
template[3],
|
||||
InlineAsmTemplatePiece::Placeholder { operand_idx: 0, modifier: None, span: _ }
|
||||
)
|
||||
&& template[4] == InlineAsmTemplatePiece::String(")".to_string())
|
||||
{
|
||||
let destination_block = fx.get_block(destination.unwrap());
|
||||
fx.bcx.ins().jump(destination_block, &[]);
|
||||
return;
|
||||
}
|
||||
|
||||
if cfg!(not(feature = "inline_asm")) {
|
||||
fx.tcx.sess.span_err(
|
||||
span,
|
||||
"asm! and global_asm! support is disabled while compiling rustc_codegen_cranelift",
|
||||
);
|
||||
} else {
|
||||
fx.tcx.sess.span_err(span, "asm! and global_asm! are not yet supported on Windows");
|
||||
}
|
||||
// Used by panic_abort on Windows, but uses a syntax which only happens to work with
|
||||
// asm!() by accident and breaks with the GNU assembler as well as global_asm!() for
|
||||
// the LLVM backend.
|
||||
if template[0] == InlineAsmTemplatePiece::String("int $$0x29".to_string()) {
|
||||
fx.bcx.ins().trap(TrapCode::User(1));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -280,6 +82,12 @@ pub(crate) fn codegen_inline_asm<'tcx>(
|
|||
CInlineAsmOperand::Const { value }
|
||||
}
|
||||
InlineAsmOperand::SymFn { ref value } => {
|
||||
if cfg!(not(feature = "inline_asm_sym")) {
|
||||
fx.tcx
|
||||
.sess
|
||||
.span_err(span, "asm! and global_asm! sym operands are not yet supported");
|
||||
}
|
||||
|
||||
let const_ = fx.monomorphize(value.const_);
|
||||
if let ty::FnDef(def_id, args) = *const_.ty().kind() {
|
||||
let instance = ty::Instance::resolve_for_fn_ptr(
|
||||
|
|
|
|||
|
|
@ -1,74 +0,0 @@
|
|||
//! Emulation of a subset of the cpuid x86 instruction.
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
/// Emulates a subset of the cpuid x86 instruction.
|
||||
///
|
||||
/// This emulates an intel cpu with sse and sse2 support, but which doesn't support anything else.
|
||||
pub(crate) fn codegen_cpuid_call<'tcx>(
|
||||
fx: &mut FunctionCx<'_, '_, 'tcx>,
|
||||
leaf: Value,
|
||||
_sub_leaf: Value,
|
||||
) -> (Value, Value, Value, Value) {
|
||||
let leaf_0 = fx.bcx.create_block();
|
||||
let leaf_1 = fx.bcx.create_block();
|
||||
let leaf_7 = fx.bcx.create_block();
|
||||
let leaf_8000_0000 = fx.bcx.create_block();
|
||||
let leaf_8000_0001 = fx.bcx.create_block();
|
||||
let unsupported_leaf = fx.bcx.create_block();
|
||||
|
||||
let dest = fx.bcx.create_block();
|
||||
let eax = fx.bcx.append_block_param(dest, types::I32);
|
||||
let ebx = fx.bcx.append_block_param(dest, types::I32);
|
||||
let ecx = fx.bcx.append_block_param(dest, types::I32);
|
||||
let edx = fx.bcx.append_block_param(dest, types::I32);
|
||||
|
||||
let mut switch = cranelift_frontend::Switch::new();
|
||||
switch.set_entry(0, leaf_0);
|
||||
switch.set_entry(1, leaf_1);
|
||||
switch.set_entry(7, leaf_7);
|
||||
switch.set_entry(0x8000_0000, leaf_8000_0000);
|
||||
switch.set_entry(0x8000_0001, leaf_8000_0001);
|
||||
switch.emit(&mut fx.bcx, leaf, unsupported_leaf);
|
||||
|
||||
fx.bcx.switch_to_block(leaf_0);
|
||||
let max_basic_leaf = fx.bcx.ins().iconst(types::I32, 1);
|
||||
let vend0 = fx.bcx.ins().iconst(types::I32, i64::from(u32::from_le_bytes(*b"Genu")));
|
||||
let vend2 = fx.bcx.ins().iconst(types::I32, i64::from(u32::from_le_bytes(*b"ineI")));
|
||||
let vend1 = fx.bcx.ins().iconst(types::I32, i64::from(u32::from_le_bytes(*b"ntel")));
|
||||
fx.bcx.ins().jump(dest, &[max_basic_leaf, vend0, vend1, vend2]);
|
||||
|
||||
fx.bcx.switch_to_block(leaf_1);
|
||||
let cpu_signature = fx.bcx.ins().iconst(types::I32, 0);
|
||||
let additional_information = fx.bcx.ins().iconst(types::I32, 0);
|
||||
let ecx_features = fx.bcx.ins().iconst(types::I32, 0);
|
||||
let edx_features = fx.bcx.ins().iconst(types::I32, 1 << 25 /* sse */ | 1 << 26 /* sse2 */);
|
||||
fx.bcx.ins().jump(dest, &[cpu_signature, additional_information, ecx_features, edx_features]);
|
||||
|
||||
fx.bcx.switch_to_block(leaf_7);
|
||||
// This leaf technically has subleaves, but we just return zero for all subleaves.
|
||||
let zero = fx.bcx.ins().iconst(types::I32, 0);
|
||||
fx.bcx.ins().jump(dest, &[zero, zero, zero, zero]);
|
||||
|
||||
fx.bcx.switch_to_block(leaf_8000_0000);
|
||||
let extended_max_basic_leaf = fx.bcx.ins().iconst(types::I32, 0);
|
||||
let zero = fx.bcx.ins().iconst(types::I32, 0);
|
||||
fx.bcx.ins().jump(dest, &[extended_max_basic_leaf, zero, zero, zero]);
|
||||
|
||||
fx.bcx.switch_to_block(leaf_8000_0001);
|
||||
let zero = fx.bcx.ins().iconst(types::I32, 0);
|
||||
let proc_info_ecx = fx.bcx.ins().iconst(types::I32, 0);
|
||||
let proc_info_edx = fx.bcx.ins().iconst(types::I32, 0);
|
||||
fx.bcx.ins().jump(dest, &[zero, zero, proc_info_ecx, proc_info_edx]);
|
||||
|
||||
fx.bcx.switch_to_block(unsupported_leaf);
|
||||
crate::trap::trap_unimplemented(
|
||||
fx,
|
||||
"__cpuid_count arch intrinsic doesn't yet support specified leaf",
|
||||
);
|
||||
|
||||
fx.bcx.switch_to_block(dest);
|
||||
fx.bcx.ins().nop();
|
||||
|
||||
(eax, ebx, ecx, edx)
|
||||
}
|
||||
|
|
@ -32,41 +32,6 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
|
|||
ret.write_cvalue(fx, CValue::by_val(res, fx.layout_of(fx.tcx.types.i64)));
|
||||
}
|
||||
|
||||
// Used by `_mm_movemask_epi8` and `_mm256_movemask_epi8`
|
||||
"llvm.x86.sse2.pmovmskb.128"
|
||||
| "llvm.x86.avx2.pmovmskb"
|
||||
| "llvm.x86.sse.movmsk.ps"
|
||||
| "llvm.x86.sse2.movmsk.pd" => {
|
||||
intrinsic_args!(fx, args => (a); intrinsic);
|
||||
|
||||
let (lane_count, lane_ty) = a.layout().ty.simd_size_and_type(fx.tcx);
|
||||
let lane_ty = fx.clif_type(lane_ty).unwrap();
|
||||
assert!(lane_count <= 32);
|
||||
|
||||
let mut res = fx.bcx.ins().iconst(types::I32, 0);
|
||||
|
||||
for lane in (0..lane_count).rev() {
|
||||
let a_lane = a.value_lane(fx, lane).load_scalar(fx);
|
||||
|
||||
// cast float to int
|
||||
let a_lane = match lane_ty {
|
||||
types::F32 => codegen_bitcast(fx, types::I32, a_lane),
|
||||
types::F64 => codegen_bitcast(fx, types::I64, a_lane),
|
||||
_ => a_lane,
|
||||
};
|
||||
|
||||
// extract sign bit of an int
|
||||
let a_lane_sign = fx.bcx.ins().ushr_imm(a_lane, i64::from(lane_ty.bits() - 1));
|
||||
|
||||
// shift sign bit into result
|
||||
let a_lane_sign = clif_intcast(fx, a_lane_sign, types::I32, false);
|
||||
res = fx.bcx.ins().ishl_imm(res, 1);
|
||||
res = fx.bcx.ins().bor(res, a_lane_sign);
|
||||
}
|
||||
|
||||
let res = CValue::by_val(res, fx.layout_of(fx.tcx.types.i32));
|
||||
ret.write_cvalue(fx, res);
|
||||
}
|
||||
"llvm.x86.sse.cmp.ps" | "llvm.x86.sse2.cmp.pd" => {
|
||||
let (x, y, kind) = match args {
|
||||
[x, y, kind] => (x, y, kind),
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ macro_rules! intrinsic_args {
|
|||
}
|
||||
}
|
||||
|
||||
mod cpuid;
|
||||
mod llvm;
|
||||
mod llvm_aarch64;
|
||||
mod llvm_x86;
|
||||
|
|
@ -25,7 +24,6 @@ use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
|
|||
use rustc_middle::ty::GenericArgsRef;
|
||||
use rustc_span::symbol::{kw, sym, Symbol};
|
||||
|
||||
pub(crate) use self::cpuid::codegen_cpuid_call;
|
||||
pub(crate) use self::llvm::codegen_llvm_intrinsic_call;
|
||||
use crate::prelude::*;
|
||||
|
||||
|
|
|
|||
|
|
@ -19,9 +19,8 @@ jobs:
|
|||
fail-fast: false
|
||||
matrix:
|
||||
libgccjit_version:
|
||||
- { gcc: "libgccjit.so", extra: "", env_extra: "", artifacts_branch: "master" }
|
||||
- { gcc: "libgccjit_without_int128.so", extra: "", env_extra: "", artifacts_branch: "master-without-128bit-integers" }
|
||||
- { gcc: "libgccjit12.so", extra: "--no-default-features", env_extra: "TEST_FLAGS='-Cpanic=abort -Zpanic-abort-tests'", artifacts_branch: "gcc12" }
|
||||
- { gcc: "libgccjit.so", artifacts_branch: "master" }
|
||||
- { gcc: "libgccjit_without_int128.so", artifacts_branch: "master-without-128bit-integers" }
|
||||
commands: [
|
||||
"--mini-tests",
|
||||
"--std-tests",
|
||||
|
|
@ -33,27 +32,16 @@ jobs:
|
|||
"--extended-regex-tests",
|
||||
"--test-successful-rustc --nb-parts 2 --current-part 0",
|
||||
"--test-successful-rustc --nb-parts 2 --current-part 1",
|
||||
"--test-failing-rustc",
|
||||
]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
repository: llvm/llvm-project
|
||||
path: llvm
|
||||
|
||||
- name: Install packages
|
||||
# `llvm-14-tools` is needed to install the `FileCheck` binary which is used for asm tests.
|
||||
run: sudo apt-get install ninja-build ripgrep llvm-14-tools
|
||||
|
||||
- name: Install libgccjit12
|
||||
if: matrix.libgccjit_version.gcc == 'libgccjit12.so'
|
||||
run: sudo apt-get install libgccjit-12-dev
|
||||
|
||||
- name: Download artifact
|
||||
if: matrix.libgccjit_version.gcc != 'libgccjit12.so'
|
||||
uses: dawidd6/action-download-artifact@v2
|
||||
with:
|
||||
workflow: main.yml
|
||||
|
|
@ -65,11 +53,6 @@ jobs:
|
|||
search_artifacts: true # Because, instead, the action only check the last job ran and that won't work since we want multiple artifacts.
|
||||
|
||||
- name: Setup path to libgccjit
|
||||
if: matrix.libgccjit_version.gcc == 'libgccjit12.so'
|
||||
run: echo /usr/lib/gcc/x86_64-linux-gnu/12 > gcc_path
|
||||
|
||||
- name: Setup path to libgccjit
|
||||
if: matrix.libgccjit_version.gcc != 'libgccjit12.so'
|
||||
run: |
|
||||
sudo dpkg --force-overwrite -i gcc-13/gcc-13.deb
|
||||
echo /usr/lib/ > gcc_path
|
||||
|
|
@ -80,9 +63,6 @@ jobs:
|
|||
echo "LD_LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV
|
||||
echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV
|
||||
|
||||
- name: Set RUST_COMPILER_RT_ROOT
|
||||
run: echo "RUST_COMPILER_RT_ROOT="${{ env.workspace }}/llvm/compiler-rt >> $GITHUB_ENV
|
||||
|
||||
- name: Cache cargo installed crates
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
|
|
@ -119,8 +99,8 @@ jobs:
|
|||
- name: Build
|
||||
run: |
|
||||
./y.sh prepare --only-libcore
|
||||
${{ matrix.libgccjit_version.env_extra }} ./y.sh build ${{ matrix.libgccjit_version.extra }}
|
||||
${{ matrix.libgccjit_version.env_extra }} cargo test ${{ matrix.libgccjit_version.extra }}
|
||||
./y.sh build
|
||||
cargo test
|
||||
./clean_all.sh
|
||||
|
||||
- name: Prepare dependencies
|
||||
|
|
@ -136,16 +116,12 @@ jobs:
|
|||
command: build
|
||||
args: --release
|
||||
|
||||
- name: Add more failing tests for GCC 12
|
||||
if: ${{ matrix.libgccjit_version.gcc == 'libgccjit12.so' }}
|
||||
run: cat failing-ui-tests12.txt >> failing-ui-tests.txt
|
||||
|
||||
- name: Add more failing tests because the sysroot is not compiled with LTO
|
||||
run: cat failing-non-lto-tests.txt >> failing-ui-tests.txt
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
${{ matrix.libgccjit_version.env_extra }} ./test.sh --release --clean --build-sysroot ${{ matrix.commands }} ${{ matrix.libgccjit_version.extra }}
|
||||
./test.sh --release --clean --build-sysroot ${{ matrix.commands }}
|
||||
|
||||
duplicates:
|
||||
runs-on: ubuntu-latest
|
||||
|
|
|
|||
129
compiler/rustc_codegen_gcc/.github/workflows/failures.yml
vendored
Normal file
129
compiler/rustc_codegen_gcc/.github/workflows/failures.yml
vendored
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
# TODO: refactor to avoid duplication with the ci.yml file.
|
||||
name: Failures
|
||||
|
||||
on:
|
||||
- pull_request
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
# Enable backtraces for easier debugging
|
||||
RUST_BACKTRACE: 1
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
libgccjit_version:
|
||||
- gcc: "libgccjit.so"
|
||||
artifacts_branch: "master"
|
||||
- gcc: "libgccjit_without_int128.so"
|
||||
artifacts_branch: "master-without-128bit-integers"
|
||||
- gcc: "libgccjit12.so"
|
||||
artifacts_branch: "gcc12"
|
||||
extra: "--no-default-features"
|
||||
# FIXME(antoyo): we need to set GCC_EXEC_PREFIX so that the linker can find the linker plugin.
|
||||
# Not sure why it's not found otherwise.
|
||||
env_extra: "TEST_FLAGS='-Cpanic=abort -Zpanic-abort-tests' GCC_EXEC_PREFIX=/usr/lib/gcc/"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Install packages
|
||||
run: sudo apt-get install ninja-build ripgrep
|
||||
|
||||
- name: Install libgccjit12
|
||||
if: matrix.libgccjit_version.gcc == 'libgccjit12.so'
|
||||
run: sudo apt-get install libgccjit-12-dev
|
||||
|
||||
- name: Setup path to libgccjit
|
||||
if: matrix.libgccjit_version.gcc == 'libgccjit12.so'
|
||||
run: echo /usr/lib/gcc/x86_64-linux-gnu/12 > gcc_path
|
||||
|
||||
- name: Download artifact
|
||||
if: matrix.libgccjit_version.gcc != 'libgccjit12.so'
|
||||
uses: dawidd6/action-download-artifact@v2
|
||||
with:
|
||||
workflow: main.yml
|
||||
name: gcc-13
|
||||
path: gcc-13
|
||||
repo: antoyo/gcc
|
||||
branch: ${{ matrix.libgccjit_version.artifacts_branch }}
|
||||
event: push
|
||||
search_artifacts: true # Because, instead, the action only check the last job ran and that won't work since we want multiple artifacts.
|
||||
|
||||
- name: Setup path to libgccjit
|
||||
if: matrix.libgccjit_version.gcc != 'libgccjit12.so'
|
||||
run: |
|
||||
sudo dpkg --force-overwrite -i gcc-13/gcc-13.deb
|
||||
echo /usr/lib/ > gcc_path
|
||||
|
||||
- name: Set env
|
||||
run: |
|
||||
echo "LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV
|
||||
echo "LD_LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV
|
||||
echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV
|
||||
|
||||
- name: Cache cargo installed crates
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.cargo/bin
|
||||
key: cargo-installed-crates2-ubuntu-latest
|
||||
|
||||
- name: Cache cargo registry
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.cargo/registry
|
||||
key: ${{ runner.os }}-cargo-registry2-${{ hashFiles('**/Cargo.lock') }}
|
||||
|
||||
- name: Cache cargo index
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.cargo/git
|
||||
key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }}
|
||||
|
||||
- name: Cache cargo target dir
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: target
|
||||
key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain') }}
|
||||
|
||||
#- name: Cache rust repository
|
||||
#uses: actions/cache@v3
|
||||
#id: cache-rust-repository
|
||||
#with:
|
||||
#path: rust
|
||||
#key: ${{ runner.os }}-packages-${{ hashFiles('rust/.git/HEAD') }}
|
||||
|
||||
- name: Git config
|
||||
run: |
|
||||
git config --global user.email "user@example.com"
|
||||
git config --global user.name "User"
|
||||
|
||||
- name: Prepare dependencies
|
||||
if: matrix.libgccjit_version.gcc == 'libgccjit12.so'
|
||||
run: ./y.sh prepare --libgccjit12-patches
|
||||
|
||||
- name: Prepare dependencies
|
||||
if: matrix.libgccjit_version.gcc != 'libgccjit12.so'
|
||||
run: ./y.sh prepare
|
||||
|
||||
# Compile is a separate step, as the actions-rs/cargo action supports error annotations
|
||||
- name: Compile
|
||||
uses: actions-rs/cargo@v1.0.3
|
||||
with:
|
||||
command: build
|
||||
args: --release
|
||||
|
||||
- name: Add more failing tests because the sysroot is not compiled with LTO
|
||||
run: cat failing-non-lto-tests.txt >> failing-ui-tests.txt
|
||||
|
||||
- name: Run tests
|
||||
id: tests
|
||||
run: |
|
||||
${{ matrix.libgccjit_version.env_extra }} ./test.sh --release --clean --build-sysroot --test-failing-rustc ${{ matrix.libgccjit_version.extra }} | tee output_log
|
||||
rg --text "test result" output_log >> $GITHUB_STEP_SUMMARY
|
||||
115
compiler/rustc_codegen_gcc/.github/workflows/gcc12.yml
vendored
Normal file
115
compiler/rustc_codegen_gcc/.github/workflows/gcc12.yml
vendored
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
name: CI libgccjit 12
|
||||
|
||||
on:
|
||||
- push
|
||||
- pull_request
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
# Enable backtraces for easier debugging
|
||||
RUST_BACKTRACE: 1
|
||||
TEST_FLAGS: "-Cpanic=abort -Zpanic-abort-tests"
|
||||
# FIXME(antoyo): we need to set GCC_EXEC_PREFIX so that the linker can find the linker plugin.
|
||||
# Not sure why it's not found otherwise.
|
||||
GCC_EXEC_PREFIX: /usr/lib/gcc/
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
commands: [
|
||||
"--mini-tests",
|
||||
"--std-tests",
|
||||
# FIXME: re-enable asm tests when GCC can emit in the right syntax.
|
||||
# "--asm-tests",
|
||||
"--test-libcore",
|
||||
"--extended-rand-tests",
|
||||
"--extended-regex-example-tests",
|
||||
"--extended-regex-tests",
|
||||
"--test-successful-rustc --nb-parts 2 --current-part 0",
|
||||
"--test-successful-rustc --nb-parts 2 --current-part 1",
|
||||
]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Install packages
|
||||
# `llvm-14-tools` is needed to install the `FileCheck` binary which is used for asm tests.
|
||||
run: sudo apt-get install ninja-build ripgrep llvm-14-tools libgccjit-12-dev
|
||||
|
||||
- name: Setup path to libgccjit
|
||||
run: echo /usr/lib/gcc/x86_64-linux-gnu/12 > gcc_path
|
||||
|
||||
- name: Set env
|
||||
run: |
|
||||
echo "LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV
|
||||
echo "LD_LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV
|
||||
echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV
|
||||
|
||||
- name: Cache cargo installed crates
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.cargo/bin
|
||||
key: cargo-installed-crates2-ubuntu-latest
|
||||
|
||||
- name: Cache cargo registry
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.cargo/registry
|
||||
key: ${{ runner.os }}-cargo-registry2-${{ hashFiles('**/Cargo.lock') }}
|
||||
|
||||
- name: Cache cargo index
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.cargo/git
|
||||
key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }}
|
||||
|
||||
- name: Cache cargo target dir
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: target
|
||||
key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain') }}
|
||||
|
||||
#- name: Cache rust repository
|
||||
## We only clone the rust repository for rustc tests
|
||||
#if: ${{ contains(matrix.commands, 'rustc') }}
|
||||
#uses: actions/cache@v3
|
||||
#id: cache-rust-repository
|
||||
#with:
|
||||
#path: rust
|
||||
#key: ${{ runner.os }}-packages-${{ hashFiles('rust/.git/HEAD') }}
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
./y.sh prepare --only-libcore --libgccjit12-patches
|
||||
./y.sh build --no-default-features --sysroot-panic-abort
|
||||
cargo test --no-default-features
|
||||
./clean_all.sh
|
||||
|
||||
- name: Prepare dependencies
|
||||
run: |
|
||||
git config --global user.email "user@example.com"
|
||||
git config --global user.name "User"
|
||||
./y.sh prepare --libgccjit12-patches
|
||||
|
||||
# Compile is a separate step, as the actions-rs/cargo action supports error annotations
|
||||
- name: Compile
|
||||
uses: actions-rs/cargo@v1.0.3
|
||||
with:
|
||||
command: build
|
||||
args: --release
|
||||
|
||||
- name: Add more failing tests for GCC 12
|
||||
run: cat failing-ui-tests12.txt >> failing-ui-tests.txt
|
||||
|
||||
- name: Add more failing tests because the sysroot is not compiled with LTO
|
||||
run: cat failing-non-lto-tests.txt >> failing-ui-tests.txt
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
./test.sh --release --clean --build-sysroot ${{ matrix.commands }} --no-default-features
|
||||
139
compiler/rustc_codegen_gcc/.github/workflows/m68k.yml
vendored
Normal file
139
compiler/rustc_codegen_gcc/.github/workflows/m68k.yml
vendored
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
# TODO: check if qemu-user-static-binfmt is needed (perhaps to run some tests since it probably calls exec).
|
||||
|
||||
name: m68k CI
|
||||
|
||||
on:
|
||||
- push
|
||||
- pull_request
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
# Enable backtraces for easier debugging
|
||||
RUST_BACKTRACE: 1
|
||||
# TODO: remove when confish.sh is removed.
|
||||
OVERWRITE_TARGET_TRIPLE: m68k-unknown-linux-gnu
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
commands: [
|
||||
"--mini-tests",
|
||||
"--std-tests",
|
||||
# TODO(antoyo): fix those on m68k.
|
||||
#"--test-libcore",
|
||||
#"--extended-rand-tests",
|
||||
#"--extended-regex-example-tests",
|
||||
#"--extended-regex-tests",
|
||||
#"--test-successful-rustc --nb-parts 2 --current-part 0",
|
||||
#"--test-successful-rustc --nb-parts 2 --current-part 1",
|
||||
#"--test-failing-rustc",
|
||||
]
|
||||
|
||||
steps:
|
||||
- name: Install packages
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install qemu qemu-user-static
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Download GCC artifact
|
||||
uses: dawidd6/action-download-artifact@v2
|
||||
with:
|
||||
workflow: m68k.yml
|
||||
name: gcc-m68k-13
|
||||
repo: cross-cg-gcc-tools/cross-gcc
|
||||
branch: master
|
||||
event: push
|
||||
|
||||
- name: Download VM artifact
|
||||
uses: dawidd6/action-download-artifact@v2
|
||||
with:
|
||||
workflow: m68k.yml
|
||||
name: debian-m68k
|
||||
repo: cross-cg-gcc-tools/vms
|
||||
branch: master
|
||||
event: push
|
||||
|
||||
- name: Setup path to libgccjit
|
||||
run: |
|
||||
sudo dpkg -i gcc-m68k-13.deb
|
||||
echo /usr/lib/ > gcc_path
|
||||
|
||||
- name: Set env
|
||||
run: |
|
||||
echo "LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV
|
||||
echo "LD_LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV
|
||||
echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV
|
||||
|
||||
- name: Cache cargo installed crates
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.cargo/bin
|
||||
key: cargo-installed-crates2-ubuntu-latest
|
||||
|
||||
#- name: Cache cargo registry
|
||||
#uses: actions/cache@v3
|
||||
#with:
|
||||
#path: ~/.cargo/registry
|
||||
#key: ${{ runner.os }}-cargo-registry2-${{ hashFiles('**/Cargo.lock') }}
|
||||
|
||||
#- name: Cache cargo index
|
||||
#uses: actions/cache@v3
|
||||
#with:
|
||||
#path: ~/.cargo/git
|
||||
#key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }}
|
||||
|
||||
- name: Cache cargo target dir
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: target
|
||||
key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain') }}
|
||||
|
||||
#- name: Cache rust repository
|
||||
## We only clone the rust repository for rustc tests
|
||||
#if: ${{ contains(matrix.commands, 'rustc') }}
|
||||
#uses: actions/cache@v3
|
||||
#id: cache-rust-repository
|
||||
#with:
|
||||
#path: rust
|
||||
#key: ${{ runner.os }}-packages-${{ hashFiles('rust/.git/HEAD') }}
|
||||
|
||||
- name: Prepare VM
|
||||
run: |
|
||||
mkdir vm
|
||||
sudo mount debian-m68k.img vm
|
||||
sudo cp $(which qemu-m68k-static) vm/usr/bin/
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
./y.sh prepare --only-libcore --cross
|
||||
./y.sh build --target-triple m68k-unknown-linux-gnu
|
||||
CG_GCC_TEST_TARGET=m68k-unknown-linux-gnu cargo test
|
||||
./clean_all.sh
|
||||
|
||||
- name: Prepare dependencies
|
||||
run: |
|
||||
git config --global user.email "user@example.com"
|
||||
git config --global user.name "User"
|
||||
./y.sh prepare --cross
|
||||
|
||||
# Compile is a separate step, as the actions-rs/cargo action supports error annotations
|
||||
- name: Compile
|
||||
uses: actions-rs/cargo@v1.0.3
|
||||
with:
|
||||
command: build
|
||||
args: --release
|
||||
|
||||
- name: Add more failing tests because the sysroot is not compiled with LTO
|
||||
run: cat failing-non-lto-tests.txt >> failing-ui-tests.txt
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
./test.sh --release --clean --build-sysroot ${{ matrix.commands }}
|
||||
|
|
@ -26,11 +26,6 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
repository: llvm/llvm-project
|
||||
path: llvm
|
||||
|
||||
- name: Install packages
|
||||
run: sudo apt-get install ninja-build ripgrep
|
||||
|
||||
|
|
@ -56,9 +51,6 @@ jobs:
|
|||
echo "LD_LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV
|
||||
echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV
|
||||
|
||||
- name: Set RUST_COMPILER_RT_ROOT
|
||||
run: echo "RUST_COMPILER_RT_ROOT="${{ env.workspace }}/llvm/compiler-rt >> $GITHUB_ENV
|
||||
|
||||
- name: Cache cargo installed crates
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
|
|
|
|||
|
|
@ -26,11 +26,6 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
repository: llvm/llvm-project
|
||||
path: llvm
|
||||
|
||||
- name: Install packages
|
||||
run: sudo apt-get install ninja-build ripgrep
|
||||
|
||||
|
|
@ -70,9 +65,6 @@ jobs:
|
|||
echo "LD_LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV
|
||||
echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV
|
||||
|
||||
- name: Set RUST_COMPILER_RT_ROOT
|
||||
run: echo "RUST_COMPILER_RT_ROOT="${{ env.workspace }}/llvm/compiler-rt >> $GITHUB_ENV
|
||||
|
||||
- name: Cache cargo installed crates
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
|
|
|
|||
10
compiler/rustc_codegen_gcc/.ignore
Normal file
10
compiler/rustc_codegen_gcc/.ignore
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
!/build_sysroot/sysroot_src
|
||||
!/simple-raytracer
|
||||
!/regex
|
||||
!/rand
|
||||
!/test-backend
|
||||
!/gcc_path
|
||||
!/benchmarks
|
||||
!*gimple*
|
||||
!*asm*
|
||||
!.github
|
||||
|
|
@ -74,7 +74,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "gccjit"
|
||||
version = "1.0.0"
|
||||
source = "git+https://github.com/antoyo/gccjit.rs#0b158c68bf7e46732869d90550a98e886dee8858"
|
||||
source = "git+https://github.com/antoyo/gccjit.rs#c52a218f5529321285b4489e5562a00e5428e033"
|
||||
dependencies = [
|
||||
"gccjit_sys",
|
||||
]
|
||||
|
|
@ -82,7 +82,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "gccjit_sys"
|
||||
version = "0.0.1"
|
||||
source = "git+https://github.com/antoyo/gccjit.rs#0b158c68bf7e46732869d90550a98e886dee8858"
|
||||
source = "git+https://github.com/antoyo/gccjit.rs#c52a218f5529321285b4489e5562a00e5428e033"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -55,13 +55,6 @@ $ make check-jit RUNTESTFLAGS="-v -v -v jit.exp=jit.dg/test-asm.cc"
|
|||
$ dirname $(readlink -f `find . -name libgccjit.so`) > gcc_path
|
||||
```
|
||||
|
||||
You also need to set RUST_COMPILER_RT_ROOT:
|
||||
|
||||
```bash
|
||||
$ git clone https://github.com/llvm/llvm-project llvm --depth 1 --single-branch
|
||||
$ export RUST_COMPILER_RT_ROOT="$PWD/llvm/compiler-rt"
|
||||
```
|
||||
|
||||
Then you can run commands like this:
|
||||
|
||||
```bash
|
||||
|
|
@ -91,9 +84,17 @@ $ CHANNEL="release" $CG_GCCJIT_DIR/cargo.sh run
|
|||
|
||||
If you compiled cg_gccjit in debug mode (aka you didn't pass `--release` to `./test.sh`) you should use `CHANNEL="debug"` instead or omit `CHANNEL="release"` completely.
|
||||
|
||||
### LTO
|
||||
|
||||
To use LTO, you need to set the variable `FAT_LTO=1` and `EMBED_LTO_BITCODE=1` in addition to setting `lto = "fat"` in the `Cargo.toml`.
|
||||
Don't set `FAT_LTO` when compiling the sysroot, though: only set `EMBED_LTO_BITCODE=1`.
|
||||
|
||||
Failing to set `EMBED_LTO_BITCODE` will give you the following error:
|
||||
|
||||
```
|
||||
error: failed to copy bitcode to object file: No such file or directory (os error 2)
|
||||
```
|
||||
|
||||
### Rustc
|
||||
|
||||
> You should prefer using the Cargo method.
|
||||
|
|
@ -286,6 +287,16 @@ git checkout sync_branch_name
|
|||
git merge master
|
||||
```
|
||||
|
||||
To send the changes to the rust repo:
|
||||
|
||||
```bash
|
||||
cd ../rust
|
||||
git pull origin master
|
||||
git checkout -b subtree-update_cg_gcc_YYYY-MM-DD
|
||||
PATH="$HOME/bin:$PATH" ~/bin/git-subtree pull --prefix=compiler/rustc_codegen_gcc/ https://github.com/rust-lang/rustc_codegen_gcc.git master
|
||||
git push
|
||||
```
|
||||
|
||||
TODO: write a script that does the above.
|
||||
|
||||
https://rust-lang.zulipchat.com/#narrow/stream/301329-t-devtools/topic/subtree.20madness/near/258877725
|
||||
|
|
@ -303,16 +314,25 @@ generate it in [gimple.md](./doc/gimple.md).
|
|||
|
||||
#### 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).
|
||||
* Follow the instructions on [this repo](https://github.com/cross-cg-gcc-tools/cross-gcc).
|
||||
|
||||
#### 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'`.
|
||||
* Run `./y.sh prepare --cross` so that the sysroot is patched for the cross-compiling case.
|
||||
* Set the path to the cross-compiling libgccjit in `gcc_path`.
|
||||
* Comment the line: `context.add_command_line_option("-masm=intel");` in src/base.rs.
|
||||
* (might not be necessary) Disable the compilation of libstd.so (and possibly libcore.so?): Remove dylib from build_sysroot/sysroot_src/library/std/Cargo.toml.
|
||||
* Make sure you have the linker for your target (for instance `m68k-unknown-linux-gnu-gcc`) in your `$PATH`. Currently, the linker name is hardcoded as being `$TARGET-gcc`. Specify the target when building the sysroot: `./y.sh build --target-triple m68k-unknown-linux-gnu`.
|
||||
* Build your project by specifying the target: `OVERWRITE_TARGET_TRIPLE=m68k-unknown-linux-gnu ../cargo.sh build --target m68k-unknown-linux-gnu`.
|
||||
|
||||
If the target is not yet supported by the Rust compiler, create a [target specification file](https://docs.rust-embedded.org/embedonomicon/custom-target.html) (note that the `arch` specified in this file must be supported by the rust compiler).
|
||||
Then, you can use it the following way:
|
||||
|
||||
* Add the target specification file using `--target` as an **absolute** path to build the sysroot: `./y.sh build --target-triple m68k-unknown-linux-gnu --target $(pwd)/m68k-unknown-linux-gnu.json`
|
||||
* Build your project by specifying the target specification file: `OVERWRITE_TARGET_TRIPLE=m68k-unknown-linux-gnu ../cargo.sh build --target path/to/m68k-unknown-linux-gnu.json`.
|
||||
|
||||
If you get the following error:
|
||||
|
||||
```
|
||||
/usr/bin/ld: unrecognised emulation mode: m68kelf
|
||||
```
|
||||
|
||||
Make sure you set `gcc_path` to the install directory.
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ if [[ "$1" == "--release" ]]; then
|
|||
RUSTFLAGS="$RUSTFLAGS -Zmir-opt-level=3" cargo build --target $TARGET_TRIPLE --release
|
||||
else
|
||||
sysroot_channel='debug'
|
||||
cargo build --target $TARGET_TRIPLE --features compiler_builtins/c
|
||||
cargo build --target $TARGET_TRIPLE
|
||||
fi
|
||||
|
||||
# Copy files to sysroot
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use crate::config::set_config;
|
||||
use crate::config::{set_config, ConfigInfo};
|
||||
use crate::utils::{
|
||||
get_gcc_path, run_command, run_command_with_env, run_command_with_output_and_env, walk_dir,
|
||||
get_gcc_path, run_command, run_command_with_output_and_env, walk_dir,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
use std::ffi::OsStr;
|
||||
|
|
@ -11,7 +11,8 @@ use std::path::Path;
|
|||
struct BuildArg {
|
||||
codegen_release_channel: bool,
|
||||
sysroot_release_channel: bool,
|
||||
features: Vec<String>,
|
||||
sysroot_panic_abort: bool,
|
||||
flags: Vec<String>,
|
||||
gcc_path: String,
|
||||
}
|
||||
|
||||
|
|
@ -30,12 +31,15 @@ impl BuildArg {
|
|||
"--release" => build_arg.codegen_release_channel = true,
|
||||
"--release-sysroot" => build_arg.sysroot_release_channel = true,
|
||||
"--no-default-features" => {
|
||||
build_arg.features.push("--no-default-features".to_string());
|
||||
build_arg.flags.push("--no-default-features".to_string());
|
||||
}
|
||||
"--sysroot-panic-abort" => {
|
||||
build_arg.sysroot_panic_abort = true;
|
||||
},
|
||||
"--features" => {
|
||||
if let Some(arg) = args.next() {
|
||||
build_arg.features.push("--features".to_string());
|
||||
build_arg.features.push(arg.as_str().into());
|
||||
build_arg.flags.push("--features".to_string());
|
||||
build_arg.flags.push(arg.as_str().into());
|
||||
} else {
|
||||
return Err(
|
||||
"Expected a value after `--features`, found nothing".to_string()
|
||||
|
|
@ -46,6 +50,24 @@ impl BuildArg {
|
|||
Self::usage();
|
||||
return Ok(None);
|
||||
}
|
||||
"--target-triple" => {
|
||||
if args.next().is_some() {
|
||||
// Handled in config.rs.
|
||||
} else {
|
||||
return Err(
|
||||
"Expected a value after `--target-triple`, found nothing".to_string()
|
||||
);
|
||||
}
|
||||
}
|
||||
"--target" => {
|
||||
if args.next().is_some() {
|
||||
// Handled in config.rs.
|
||||
} else {
|
||||
return Err(
|
||||
"Expected a value after `--target`, found nothing".to_string()
|
||||
);
|
||||
}
|
||||
}
|
||||
arg => return Err(format!("Unknown argument `{}`", arg)),
|
||||
}
|
||||
}
|
||||
|
|
@ -59,8 +81,10 @@ impl BuildArg {
|
|||
|
||||
--release : Build codegen in release mode
|
||||
--release-sysroot : Build sysroot in release mode
|
||||
--sysroot-panic-abort : Build the sysroot without unwinding support.
|
||||
--no-default-features : Add `--no-default-features` flag
|
||||
--features [arg] : Add a new feature [arg]
|
||||
--target-triple [arg] : Set the target triple to [arg]
|
||||
--help : Show this help
|
||||
"#
|
||||
)
|
||||
|
|
@ -69,8 +93,8 @@ impl BuildArg {
|
|||
|
||||
fn build_sysroot(
|
||||
env: &mut HashMap<String, String>,
|
||||
release_mode: bool,
|
||||
target_triple: &str,
|
||||
args: &BuildArg,
|
||||
config: &ConfigInfo,
|
||||
) -> Result<(), String> {
|
||||
std::env::set_current_dir("build_sysroot")
|
||||
.map_err(|error| format!("Failed to go to `build_sysroot` directory: {:?}", error))?;
|
||||
|
|
@ -119,21 +143,24 @@ fn build_sysroot(
|
|||
let _ = fs::remove_dir_all("sysroot");
|
||||
|
||||
// Builds libs
|
||||
let channel = if release_mode {
|
||||
let rustflags = env
|
||||
.get("RUSTFLAGS")
|
||||
.cloned()
|
||||
.unwrap_or_default();
|
||||
env.insert(
|
||||
"RUSTFLAGS".to_string(),
|
||||
format!("{} -Zmir-opt-level=3", rustflags),
|
||||
);
|
||||
let mut rustflags = env
|
||||
.get("RUSTFLAGS")
|
||||
.cloned()
|
||||
.unwrap_or_default();
|
||||
if args.sysroot_panic_abort {
|
||||
rustflags.push_str(" -Cpanic=abort -Zpanic-abort-tests");
|
||||
}
|
||||
env.insert(
|
||||
"RUSTFLAGS".to_string(),
|
||||
format!("{} -Zmir-opt-level=3", rustflags),
|
||||
);
|
||||
let channel = if args.sysroot_release_channel {
|
||||
run_command_with_output_and_env(
|
||||
&[
|
||||
&"cargo",
|
||||
&"build",
|
||||
&"--target",
|
||||
&target_triple,
|
||||
&config.target,
|
||||
&"--release",
|
||||
],
|
||||
None,
|
||||
|
|
@ -146,9 +173,7 @@ fn build_sysroot(
|
|||
&"cargo",
|
||||
&"build",
|
||||
&"--target",
|
||||
&target_triple,
|
||||
&"--features",
|
||||
&"compiler_builtins/c",
|
||||
&config.target,
|
||||
],
|
||||
None,
|
||||
Some(env),
|
||||
|
|
@ -157,14 +182,14 @@ fn build_sysroot(
|
|||
};
|
||||
|
||||
// Copy files to sysroot
|
||||
let sysroot_path = format!("sysroot/lib/rustlib/{}/lib/", target_triple);
|
||||
let sysroot_path = format!("sysroot/lib/rustlib/{}/lib/", config.target_triple);
|
||||
fs::create_dir_all(&sysroot_path)
|
||||
.map_err(|error| format!("Failed to create directory `{}`: {:?}", sysroot_path, error))?;
|
||||
let copier = |dir_to_copy: &Path| {
|
||||
run_command(&[&"cp", &"-r", &dir_to_copy, &sysroot_path], None).map(|_| ())
|
||||
};
|
||||
walk_dir(
|
||||
&format!("target/{}/{}/deps", target_triple, channel),
|
||||
&format!("target/{}/{}/deps", config.target_triple, channel),
|
||||
copier,
|
||||
copier,
|
||||
)?;
|
||||
|
|
@ -175,16 +200,6 @@ fn build_sysroot(
|
|||
fn build_codegen(args: &BuildArg) -> Result<(), String> {
|
||||
let mut env = HashMap::new();
|
||||
|
||||
let current_dir =
|
||||
std::env::current_dir().map_err(|error| format!("`current_dir` failed: {:?}", error))?;
|
||||
if let Ok(rt_root) = std::env::var("RUST_COMPILER_RT_ROOT") {
|
||||
env.insert("RUST_COMPILER_RT_ROOT".to_string(), rt_root);
|
||||
} else {
|
||||
env.insert(
|
||||
"RUST_COMPILER_RT_ROOT".to_string(),
|
||||
format!("{}", current_dir.join("llvm/compiler-rt").display()),
|
||||
);
|
||||
}
|
||||
env.insert("LD_LIBRARY_PATH".to_string(), args.gcc_path.clone());
|
||||
env.insert("LIBRARY_PATH".to_string(), args.gcc_path.clone());
|
||||
|
||||
|
|
@ -196,11 +211,11 @@ fn build_codegen(args: &BuildArg) -> Result<(), String> {
|
|||
} else {
|
||||
env.insert("CHANNEL".to_string(), "debug".to_string());
|
||||
}
|
||||
let ref_features = args.features.iter().map(|s| s.as_str()).collect::<Vec<_>>();
|
||||
for feature in &ref_features {
|
||||
command.push(feature);
|
||||
let flags = args.flags.iter().map(|s| s.as_str()).collect::<Vec<_>>();
|
||||
for flag in &flags {
|
||||
command.push(flag);
|
||||
}
|
||||
run_command_with_env(&command, None, Some(&env))?;
|
||||
run_command_with_output_and_env(&command, None, Some(&env))?;
|
||||
|
||||
let config = set_config(&mut env, &[], Some(&args.gcc_path))?;
|
||||
|
||||
|
|
@ -217,8 +232,8 @@ fn build_codegen(args: &BuildArg) -> Result<(), String> {
|
|||
println!("[BUILD] sysroot");
|
||||
build_sysroot(
|
||||
&mut env,
|
||||
args.sysroot_release_channel,
|
||||
&config.target_triple,
|
||||
args,
|
||||
&config,
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ use std::collections::HashMap;
|
|||
use std::env as std_env;
|
||||
|
||||
pub struct ConfigInfo {
|
||||
pub target: String,
|
||||
pub target_triple: String,
|
||||
pub rustc_command: Vec<String>,
|
||||
pub run_wrapper: Option<&'static str>,
|
||||
}
|
||||
|
||||
// Returns the beginning for the command line of rustc.
|
||||
|
|
@ -30,22 +30,46 @@ pub fn set_config(
|
|||
};
|
||||
let host_triple = get_rustc_host_triple()?;
|
||||
let mut linker = None;
|
||||
let mut target_triple = host_triple.as_str();
|
||||
let mut run_wrapper = None;
|
||||
// FIXME: handle this with a command line flag?
|
||||
// let mut target_triple = "m68k-unknown-linux-gnu";
|
||||
let mut target_triple = host_triple.clone();
|
||||
let mut target = target_triple.clone();
|
||||
|
||||
// We skip binary name and the command.
|
||||
let mut args = std::env::args().skip(2);
|
||||
|
||||
let mut set_target_triple = false;
|
||||
let mut set_target = false;
|
||||
while let Some(arg) = args.next() {
|
||||
match arg.as_str() {
|
||||
"--target-triple" => {
|
||||
if let Some(arg) = args.next() {
|
||||
target_triple = arg;
|
||||
set_target_triple = true;
|
||||
} else {
|
||||
return Err(
|
||||
"Expected a value after `--target-triple`, found nothing".to_string()
|
||||
);
|
||||
}
|
||||
},
|
||||
"--target" => {
|
||||
if let Some(arg) = args.next() {
|
||||
target = arg;
|
||||
set_target = true;
|
||||
} else {
|
||||
return Err(
|
||||
"Expected a value after `--target`, found nothing".to_string()
|
||||
);
|
||||
}
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
if set_target_triple && !set_target {
|
||||
target = target_triple.clone();
|
||||
}
|
||||
|
||||
if host_triple != target_triple {
|
||||
if target_triple == "m68k-unknown-linux-gnu" {
|
||||
target_triple = "mips-unknown-linux-gnu";
|
||||
linker = Some("-Clinker=m68k-linux-gcc");
|
||||
} else if target_triple == "aarch64-unknown-linux-gnu" {
|
||||
// We are cross-compiling for aarch64. Use the correct linker and run tests in qemu.
|
||||
linker = Some("-Clinker=aarch64-linux-gnu-gcc");
|
||||
run_wrapper = Some("qemu-aarch64 -L /usr/aarch64-linux-gnu");
|
||||
} else {
|
||||
return Err(format!("unknown non-native platform `{}`", target_triple));
|
||||
}
|
||||
linker = Some(format!("-Clinker={}-gcc", target_triple));
|
||||
}
|
||||
let current_dir =
|
||||
std_env::current_dir().map_err(|error| format!("`current_dir` failed: {:?}", error))?;
|
||||
|
|
@ -118,8 +142,8 @@ pub fn set_config(
|
|||
"target/out".to_string(),
|
||||
]);
|
||||
Ok(ConfigInfo {
|
||||
target_triple: target_triple.to_string(),
|
||||
target,
|
||||
target_triple,
|
||||
rustc_command,
|
||||
run_wrapper,
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ mod build;
|
|||
mod config;
|
||||
mod prepare;
|
||||
mod rustc_info;
|
||||
mod test;
|
||||
mod utils;
|
||||
|
||||
macro_rules! arg_error {
|
||||
|
|
@ -23,6 +24,7 @@ Available commands for build_system:
|
|||
|
||||
prepare : Run prepare command
|
||||
build : Run build command
|
||||
test : Run test command
|
||||
--help : Show this message"
|
||||
);
|
||||
}
|
||||
|
|
@ -30,6 +32,7 @@ Available commands for build_system:
|
|||
pub enum Command {
|
||||
Prepare,
|
||||
Build,
|
||||
Test,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
|
@ -40,6 +43,7 @@ fn main() {
|
|||
let command = match env::args().nth(1).as_deref() {
|
||||
Some("prepare") => Command::Prepare,
|
||||
Some("build") => Command::Build,
|
||||
Some("test") => Command::Test,
|
||||
Some("--help") => {
|
||||
usage();
|
||||
process::exit(0);
|
||||
|
|
@ -55,6 +59,7 @@ fn main() {
|
|||
if let Err(e) = match command {
|
||||
Command::Prepare => prepare::run(),
|
||||
Command::Build => build::run(),
|
||||
Command::Test => test::run(),
|
||||
} {
|
||||
eprintln!("Command failed to run: {e:?}");
|
||||
process::exit(1);
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use crate::utils::{cargo_install, git_clone, run_command, run_command_with_outpu
|
|||
use std::fs;
|
||||
use std::path::Path;
|
||||
|
||||
fn prepare_libcore(sysroot_path: &Path) -> Result<(), String> {
|
||||
fn prepare_libcore(sysroot_path: &Path, libgccjit12_patches: bool, cross_compile: bool) -> Result<(), String> {
|
||||
let rustc_path = match get_rustc_path() {
|
||||
Some(path) => path,
|
||||
None => return Err("`rustc` path not found".to_string()),
|
||||
|
|
@ -87,6 +87,22 @@ fn prepare_libcore(sysroot_path: &Path) -> Result<(), String> {
|
|||
Ok(())
|
||||
},
|
||||
)?;
|
||||
if cross_compile {
|
||||
walk_dir("cross_patches", |_| Ok(()), |file_path: &Path| {
|
||||
patches.push(file_path.to_path_buf());
|
||||
Ok(())
|
||||
})?;
|
||||
}
|
||||
if libgccjit12_patches {
|
||||
walk_dir(
|
||||
"patches/libgccjit12",
|
||||
|_| Ok(()),
|
||||
|file_path: &Path| {
|
||||
patches.push(file_path.to_path_buf());
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
}
|
||||
patches.sort();
|
||||
for file_path in patches {
|
||||
println!("[GIT] apply `{}`", file_path.display());
|
||||
|
|
@ -156,16 +172,22 @@ where
|
|||
}
|
||||
|
||||
struct PrepareArg {
|
||||
cross_compile: bool,
|
||||
only_libcore: bool,
|
||||
libgccjit12_patches: bool,
|
||||
}
|
||||
|
||||
impl PrepareArg {
|
||||
fn new() -> Result<Option<Self>, String> {
|
||||
let mut only_libcore = false;
|
||||
let mut cross_compile = false;
|
||||
let mut libgccjit12_patches = false;
|
||||
|
||||
for arg in std::env::args().skip(2) {
|
||||
match arg.as_str() {
|
||||
"--only-libcore" => only_libcore = true,
|
||||
"--cross" => cross_compile = true,
|
||||
"--libgccjit12-patches" => libgccjit12_patches = true,
|
||||
"--help" => {
|
||||
Self::usage();
|
||||
return Ok(None);
|
||||
|
|
@ -173,7 +195,11 @@ impl PrepareArg {
|
|||
a => return Err(format!("Unknown argument `{a}`")),
|
||||
}
|
||||
}
|
||||
Ok(Some(Self { only_libcore }))
|
||||
Ok(Some(Self {
|
||||
cross_compile,
|
||||
only_libcore,
|
||||
libgccjit12_patches,
|
||||
}))
|
||||
}
|
||||
|
||||
fn usage() {
|
||||
|
|
@ -181,8 +207,10 @@ impl PrepareArg {
|
|||
r#"
|
||||
`prepare` command help:
|
||||
|
||||
--only-libcore : Only setup libcore and don't clone other repositories
|
||||
--help : Show this help
|
||||
--only-libcore : Only setup libcore and don't clone other repositories
|
||||
--cross : Apply the patches needed to do cross-compilation
|
||||
--libgccjit12-patches : Apply patches needed for libgccjit12
|
||||
--help : Show this help
|
||||
"#
|
||||
)
|
||||
}
|
||||
|
|
@ -194,7 +222,7 @@ pub fn run() -> Result<(), String> {
|
|||
None => return Ok(()),
|
||||
};
|
||||
let sysroot_path = Path::new("build_sysroot");
|
||||
prepare_libcore(sysroot_path)?;
|
||||
prepare_libcore(sysroot_path, args.libgccjit12_patches, args.cross_compile)?;
|
||||
|
||||
if !args.only_libcore {
|
||||
cargo_install("hyperfine")?;
|
||||
|
|
|
|||
15
compiler/rustc_codegen_gcc/build_system/src/test.rs
Normal file
15
compiler/rustc_codegen_gcc/build_system/src/test.rs
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
use crate::utils::run_command_with_output;
|
||||
|
||||
fn get_args<'a>(args: &mut Vec<&'a dyn AsRef<std::ffi::OsStr>>, extra_args: &'a Vec<String>) {
|
||||
for extra_arg in extra_args {
|
||||
args.push(extra_arg);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run() -> Result<(), String> {
|
||||
let mut args: Vec<&dyn AsRef<std::ffi::OsStr>> = vec![&"bash", &"test.sh"];
|
||||
let extra_args = std::env::args().skip(2).collect::<Vec<_>>();
|
||||
get_args(&mut args, &extra_args);
|
||||
let current_dir = std::env::current_dir().map_err(|error| format!("`current_dir` failed: {:?}", error))?;
|
||||
run_command_with_output(args.as_slice(), Some(¤t_dir))
|
||||
}
|
||||
|
|
@ -12,7 +12,7 @@ TOOLCHAIN=$(cat rust-toolchain | grep channel | sed 's/channel = "\(.*\)"/\1/')
|
|||
|
||||
popd >/dev/null
|
||||
|
||||
if [[ $(rustc -V) != $(rustc +${TOOLCHAIN} -V) ]]; then
|
||||
if [[ $(${RUSTC} -V) != $(${RUSTC} +${TOOLCHAIN} -V) ]]; then
|
||||
echo "rustc_codegen_gcc is build for $(rustc +${TOOLCHAIN} -V) but the default rustc version is $(rustc -V)."
|
||||
echo "Using $(rustc +${TOOLCHAIN} -V)."
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -4,38 +4,43 @@ export CARGO_INCREMENTAL=0
|
|||
|
||||
if [ -f ./gcc_path ]; then
|
||||
export GCC_PATH=$(cat gcc_path)
|
||||
elif (( $use_system_gcc == 1 )); then
|
||||
echo 'Using system GCC'
|
||||
else
|
||||
echo 'Please put the path to your custom build of libgccjit in the file `gcc_path`, see Readme.md for details'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -z "$RUSTC" ]]; then
|
||||
export RUSTC="rustc"
|
||||
fi
|
||||
|
||||
unamestr=`uname`
|
||||
if [[ "$unamestr" == 'Linux' ]]; then
|
||||
dylib_ext='so'
|
||||
dylib_ext='so'
|
||||
elif [[ "$unamestr" == 'Darwin' ]]; then
|
||||
dylib_ext='dylib'
|
||||
dylib_ext='dylib'
|
||||
else
|
||||
echo "Unsupported os"
|
||||
exit 1
|
||||
echo "Unsupported os"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
HOST_TRIPLE=$(rustc -vV | grep host | cut -d: -f2 | tr -d " ")
|
||||
TARGET_TRIPLE=$HOST_TRIPLE
|
||||
#TARGET_TRIPLE="m68k-unknown-linux-gnu"
|
||||
# TODO: remove $OVERWRITE_TARGET_TRIPLE when config.sh is removed.
|
||||
TARGET_TRIPLE="${OVERWRITE_TARGET_TRIPLE:-$HOST_TRIPLE}"
|
||||
|
||||
linker=''
|
||||
RUN_WRAPPER=''
|
||||
if [[ "$HOST_TRIPLE" != "$TARGET_TRIPLE" ]]; 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'
|
||||
else
|
||||
echo "Unknown non-native platform"
|
||||
fi
|
||||
RUN_WRAPPER=run_in_vm
|
||||
if [[ "$TARGET_TRIPLE" == "m68k-unknown-linux-gnu" ]]; then
|
||||
linker='-Clinker=m68k-unknown-linux-gnu-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'
|
||||
else
|
||||
echo "Unknown non-native platform"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Since we don't support ThinLTO, disable LTO completely when not trying to do LTO.
|
||||
|
|
@ -45,19 +50,32 @@ if [[ ! -v FAT_LTO ]]; then
|
|||
disable_lto_flags='-Clto=off'
|
||||
fi
|
||||
|
||||
export RUSTFLAGS="$CG_RUSTFLAGS $linker -Csymbol-mangling-version=v0 -Cdebuginfo=2 $disable_lto_flags -Zcodegen-backend=$(pwd)/target/${CHANNEL:-debug}/librustc_codegen_gcc.$dylib_ext --sysroot $(pwd)/build_sysroot/sysroot $TEST_FLAGS"
|
||||
if [[ -z "$BUILTIN_BACKEND" ]]; then
|
||||
export RUSTFLAGS="$CG_RUSTFLAGS $linker -Csymbol-mangling-version=v0 -Cdebuginfo=2 $disable_lto_flags -Zcodegen-backend=$(pwd)/target/${CHANNEL:-debug}/librustc_codegen_gcc.$dylib_ext --sysroot $(pwd)/build_sysroot/sysroot $TEST_FLAGS"
|
||||
else
|
||||
export RUSTFLAGS="$CG_RUSTFLAGS $linker -Csymbol-mangling-version=v0 -Cdebuginfo=2 $disable_lto_flags -Zcodegen-backend=gcc $TEST_FLAGS -Cpanic=abort"
|
||||
fi
|
||||
|
||||
# FIXME(antoyo): remove once the atomic shim is gone
|
||||
if [[ unamestr == 'Darwin' ]]; then
|
||||
export RUSTFLAGS="$RUSTFLAGS -Clink-arg=-undefined -Clink-arg=dynamic_lookup"
|
||||
export RUSTFLAGS="$RUSTFLAGS -Clink-arg=-undefined -Clink-arg=dynamic_lookup"
|
||||
fi
|
||||
|
||||
RUSTC="rustc $RUSTFLAGS -L crate=target/out --out-dir target/out"
|
||||
if [[ -z "$cargo_target_dir" ]]; then
|
||||
RUST_CMD="$RUSTC $RUSTFLAGS -L crate=target/out --out-dir target/out"
|
||||
cargo_target_dir="target/out"
|
||||
else
|
||||
RUST_CMD="$RUSTC $RUSTFLAGS -L crate=$cargo_target_dir --out-dir $cargo_target_dir"
|
||||
fi
|
||||
export RUSTC_LOG=warn # display metadata load errors
|
||||
|
||||
export LD_LIBRARY_PATH="$(pwd)/target/out:$(pwd)/build_sysroot/sysroot/lib/rustlib/$TARGET_TRIPLE/lib:$GCC_PATH"
|
||||
export LD_LIBRARY_PATH="$(pwd)/target/out:$(pwd)/build_sysroot/sysroot/lib/rustlib/$TARGET_TRIPLE/lib"
|
||||
if [[ ! -z "$:$GCC_PATH" ]]; then
|
||||
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$GCC_PATH"
|
||||
fi
|
||||
|
||||
export DYLD_LIBRARY_PATH=$LD_LIBRARY_PATH
|
||||
# NOTE: To avoid the -fno-inline errors, use /opt/gcc/bin/gcc instead of cc.
|
||||
# To do so, add a symlink for cc to /opt/gcc/bin/gcc in our PATH.
|
||||
# Another option would be to add the following Rust flag: -Clinker=/opt/gcc/bin/gcc
|
||||
export PATH="/opt/gcc/bin:$PATH"
|
||||
export PATH="/opt/gcc/bin:/opt/m68k-unknown-linux-gnu/bin:$PATH"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
From 966beefe08be6045bfcca26079b76a7a80413080 Mon Sep 17 00:00:00 2001
|
||||
From: None <none@example.com>
|
||||
Date: Thu, 28 Sep 2023 17:37:38 -0400
|
||||
Subject: [PATCH] Disable libstd and libtest dylib
|
||||
|
||||
---
|
||||
library/std/Cargo.toml | 2 +-
|
||||
library/test/Cargo.toml | 2 +-
|
||||
2 files changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
|
||||
index 5b21355..cb0c49b 100644
|
||||
--- a/library/std/Cargo.toml
|
||||
+++ b/library/std/Cargo.toml
|
||||
@@ -9,7 +9,7 @@ description = "The Rust Standard Library"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
-crate-type = ["dylib", "rlib"]
|
||||
+crate-type = ["rlib"]
|
||||
|
||||
[dependencies]
|
||||
alloc = { path = "../alloc", public = true }
|
||||
diff --git a/library/test/Cargo.toml b/library/test/Cargo.toml
|
||||
index 91a1abd..a58c160 100644
|
||||
--- a/library/test/Cargo.toml
|
||||
+++ b/library/test/Cargo.toml
|
||||
@@ -4,7 +4,7 @@ version = "0.0.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
-crate-type = ["dylib", "rlib"]
|
||||
+crate-type = ["rlib"]
|
||||
|
||||
[dependencies]
|
||||
getopts = { version = "0.2.21", features = ['rustc-dep-of-std'] }
|
||||
--
|
||||
2.42.0
|
||||
|
||||
5
compiler/rustc_codegen_gcc/doc/tests.md
Normal file
5
compiler/rustc_codegen_gcc/doc/tests.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# Tests
|
||||
|
||||
## Show the rustc command for UI tests
|
||||
|
||||
Add ` --test-args "--verbose"` to `./x.py test`.
|
||||
|
|
@ -9,6 +9,7 @@
|
|||
// add fast paths for low alignment values.
|
||||
#[cfg(any(target_arch = "x86",
|
||||
target_arch = "arm",
|
||||
target_arch = "m68k",
|
||||
target_arch = "mips",
|
||||
target_arch = "mips32r6",
|
||||
target_arch = "powerpc",
|
||||
|
|
|
|||
|
|
@ -152,7 +152,8 @@ fn main() {
|
|||
let slice = &[0, 1] as &[i32];
|
||||
let slice_ptr = slice as *const [i32] as *const i32;
|
||||
|
||||
assert_eq!(slice_ptr as usize % 4, 0);
|
||||
let align = intrinsics::min_align_of::<*const i32>();
|
||||
assert_eq!(slice_ptr as usize % align, 0);
|
||||
|
||||
//return;
|
||||
|
||||
|
|
@ -186,7 +187,10 @@ fn main() {
|
|||
let a: &dyn SomeTrait = &"abc\0";
|
||||
a.object_safe();
|
||||
|
||||
#[cfg(target_arch="x86_64")]
|
||||
assert_eq!(intrinsics::size_of_val(a) as u8, 16);
|
||||
#[cfg(target_arch="m68k")]
|
||||
assert_eq!(intrinsics::size_of_val(a) as u8, 8);
|
||||
assert_eq!(intrinsics::size_of_val(&0u32) as u8, 4);
|
||||
|
||||
assert_eq!(intrinsics::min_align_of::<u16>() as u8, 2);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#![feature(core_intrinsics, coroutines, coroutine_trait, is_sorted)]
|
||||
|
||||
#[cfg(feature="master")]
|
||||
#[cfg(target_arch="x86_64")]
|
||||
use std::arch::x86_64::*;
|
||||
use std::io::Write;
|
||||
use std::ops::Coroutine;
|
||||
|
|
@ -95,6 +96,7 @@ fn main() {
|
|||
|
||||
println!("{:?}", std::intrinsics::caller_location());
|
||||
|
||||
#[cfg(target_arch="x86_64")]
|
||||
#[cfg(feature="master")]
|
||||
unsafe {
|
||||
test_simd();
|
||||
|
|
@ -108,6 +110,7 @@ fn main() {
|
|||
}
|
||||
|
||||
#[cfg(feature="master")]
|
||||
#[cfg(target_arch="x86_64")]
|
||||
#[target_feature(enable = "sse2")]
|
||||
unsafe fn test_simd() {
|
||||
let x = _mm_setzero_si128();
|
||||
|
|
@ -136,6 +139,7 @@ unsafe fn test_simd() {
|
|||
}
|
||||
|
||||
#[cfg(feature="master")]
|
||||
#[cfg(target_arch="x86_64")]
|
||||
#[target_feature(enable = "sse2")]
|
||||
unsafe fn test_mm_slli_si128() {
|
||||
#[rustfmt::skip]
|
||||
|
|
@ -164,6 +168,7 @@ unsafe fn test_mm_slli_si128() {
|
|||
|
||||
|
||||
#[cfg(feature="master")]
|
||||
#[cfg(target_arch="x86_64")]
|
||||
#[target_feature(enable = "sse2")]
|
||||
unsafe fn test_mm_movemask_epi8() {
|
||||
#[rustfmt::skip]
|
||||
|
|
@ -178,6 +183,7 @@ unsafe fn test_mm_movemask_epi8() {
|
|||
}
|
||||
|
||||
#[cfg(feature="master")]
|
||||
#[cfg(target_arch="x86_64")]
|
||||
#[target_feature(enable = "avx2")]
|
||||
unsafe fn test_mm256_movemask_epi8() {
|
||||
let a = _mm256_set1_epi8(-1);
|
||||
|
|
@ -187,6 +193,7 @@ unsafe fn test_mm256_movemask_epi8() {
|
|||
}
|
||||
|
||||
#[cfg(feature="master")]
|
||||
#[cfg(target_arch="x86_64")]
|
||||
#[target_feature(enable = "sse2")]
|
||||
unsafe fn test_mm_add_epi8() {
|
||||
let a = _mm_setr_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
|
||||
|
|
@ -203,6 +210,7 @@ unsafe fn test_mm_add_epi8() {
|
|||
}
|
||||
|
||||
#[cfg(feature="master")]
|
||||
#[cfg(target_arch="x86_64")]
|
||||
#[target_feature(enable = "sse2")]
|
||||
unsafe fn test_mm_add_pd() {
|
||||
let a = _mm_setr_pd(1.0, 2.0);
|
||||
|
|
@ -212,6 +220,7 @@ unsafe fn test_mm_add_pd() {
|
|||
}
|
||||
|
||||
#[cfg(feature="master")]
|
||||
#[cfg(target_arch="x86_64")]
|
||||
fn assert_eq_m128i(x: std::arch::x86_64::__m128i, y: std::arch::x86_64::__m128i) {
|
||||
unsafe {
|
||||
assert_eq!(std::mem::transmute::<_, [u8; 16]>(x), std::mem::transmute::<_, [u8; 16]>(y));
|
||||
|
|
@ -219,6 +228,7 @@ fn assert_eq_m128i(x: std::arch::x86_64::__m128i, y: std::arch::x86_64::__m128i)
|
|||
}
|
||||
|
||||
#[cfg(feature="master")]
|
||||
#[cfg(target_arch="x86_64")]
|
||||
#[target_feature(enable = "sse2")]
|
||||
pub unsafe fn assert_eq_m128d(a: __m128d, b: __m128d) {
|
||||
if _mm_movemask_pd(_mm_cmpeq_pd(a, b)) != 0b11 {
|
||||
|
|
@ -227,6 +237,7 @@ pub unsafe fn assert_eq_m128d(a: __m128d, b: __m128d) {
|
|||
}
|
||||
|
||||
#[cfg(feature="master")]
|
||||
#[cfg(target_arch="x86_64")]
|
||||
#[target_feature(enable = "sse2")]
|
||||
unsafe fn test_mm_cvtsi128_si64() {
|
||||
let r = _mm_cvtsi128_si64(std::mem::transmute::<[i64; 2], _>([5, 0]));
|
||||
|
|
@ -234,6 +245,7 @@ unsafe fn test_mm_cvtsi128_si64() {
|
|||
}
|
||||
|
||||
#[cfg(feature="master")]
|
||||
#[cfg(target_arch="x86_64")]
|
||||
#[target_feature(enable = "sse4.1")]
|
||||
unsafe fn test_mm_cvtepi8_epi16() {
|
||||
let a = _mm_set1_epi8(10);
|
||||
|
|
@ -247,6 +259,7 @@ unsafe fn test_mm_cvtepi8_epi16() {
|
|||
}
|
||||
|
||||
#[cfg(feature="master")]
|
||||
#[cfg(target_arch="x86_64")]
|
||||
#[target_feature(enable = "sse4.1")]
|
||||
unsafe fn test_mm_extract_epi8() {
|
||||
#[rustfmt::skip]
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ tests/ui/lto/lto-many-codegen-units.rs
|
|||
tests/ui/lto/issue-100772.rs
|
||||
tests/ui/lto/lto-rustc-loads-linker-plugin.rs
|
||||
tests/ui/panic-runtime/lto-unwind.rs
|
||||
tests/ui/sanitize/issue-111184-generator-witness.rs
|
||||
tests/ui/sanitize/issue-111184-coroutine-witness.rs
|
||||
tests/ui/sepcomp/sepcomp-lib-lto.rs
|
||||
tests/ui/lto/lto-opt-level-s.rs
|
||||
tests/ui/lto/lto-opt-level-z.rs
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@ tests/ui/cfg/cfg-panic-abort.rs
|
|||
tests/ui/drop/dynamic-drop-async.rs
|
||||
tests/ui/drop/repeat-drop.rs
|
||||
tests/ui/fmt/format-args-capture.rs
|
||||
tests/ui/generator/panic-drops-resume.rs
|
||||
tests/ui/generator/panic-drops.rs
|
||||
tests/ui/coroutine/panic-drops-resume.rs
|
||||
tests/ui/coroutine/panic-drops.rs
|
||||
tests/ui/intrinsics/panic-uninitialized-zeroed.rs
|
||||
tests/ui/iterators/iter-sum-overflow-debug.rs
|
||||
tests/ui/iterators/iter-sum-overflow-overflow-checks.rs
|
||||
|
|
@ -53,7 +53,7 @@ tests/ui/simd/issue-89193.rs
|
|||
tests/ui/statics/issue-91050-1.rs
|
||||
tests/ui/statics/issue-91050-2.rs
|
||||
tests/ui/alloc-error/default-alloc-error-hook.rs
|
||||
tests/ui/generator/panic-safe.rs
|
||||
tests/ui/coroutine/panic-safe.rs
|
||||
tests/ui/issues/issue-14875.rs
|
||||
tests/ui/issues/issue-29948.rs
|
||||
tests/ui/panics/nested_panic_caught.rs
|
||||
|
|
@ -70,4 +70,5 @@ tests/ui/lto/lto-thin-rustc-loads-linker-plugin.rs
|
|||
tests/ui/lto/all-crates.rs
|
||||
tests/ui/async-await/deep-futures-are-freeze.rs
|
||||
tests/ui/closures/capture-unsized-by-ref.rs
|
||||
tests/ui/generator/resume-after-return.rs
|
||||
tests/ui/coroutine/resume-after-return.rs
|
||||
tests/ui/macros/rfc-2011-nicer-assert-messages/all-expr-kinds.rs
|
||||
|
|
|
|||
|
|
@ -19,22 +19,22 @@ tests/ui/simd/intrinsic/generic-reduction-pass.rs
|
|||
tests/ui/simd/intrinsic/generic-select-pass.rs
|
||||
tests/ui/simd/intrinsic/inlining-issue67557-ice.rs
|
||||
tests/ui/simd/intrinsic/inlining-issue67557.rs
|
||||
tests/ui/simd/monomorphize-shuffle-index.rs
|
||||
tests/ui/simd/shuffle.rs
|
||||
tests/ui/simd/simd-bitmask.rs
|
||||
tests/ui/generator/resume-after-return.rs
|
||||
tests/ui/iterators/iter-step-overflow-debug.rs
|
||||
tests/ui/macros/rfc-2011-nicer-assert-messages/all-expr-kinds.rs
|
||||
tests/ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs
|
||||
tests/ui/privacy/reachable-unnameable-items.rs
|
||||
tests/ui/rfc-1937-termination-trait/termination-trait-in-test.rs
|
||||
tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-in-test.rs
|
||||
tests/ui/async-await/async-fn-size-moved-locals.rs
|
||||
tests/ui/async-await/async-fn-size-uninit-locals.rs
|
||||
tests/ui/cfg/cfg-panic.rs
|
||||
tests/ui/generator/size-moved-locals.rs
|
||||
tests/ui/coroutine/size-moved-locals.rs
|
||||
tests/ui/macros/rfc-2011-nicer-assert-messages/all-not-available-cases.rs
|
||||
tests/ui/simd/intrinsic/generic-gather-pass.rs
|
||||
tests/ui/simd/issue-85915-simd-ptrs.rs
|
||||
tests/ui/issues/issue-68010-large-zst-consts.rs
|
||||
tests/ui/rust-2018/proc-macro-crate-in-paths.rs
|
||||
tests/ui/target-feature/missing-plusminus.rs
|
||||
tests/ui/sse2.rs
|
||||
tests/ui/codegen/issue-79865-llvm-miscompile.rs
|
||||
tests/ui/intrinsics/intrinsics-integer.rs
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
From 7bcd24ec6d4a96121874cb1ae5a23ea274aeff34 Mon Sep 17 00:00:00 2001
|
||||
From: None <none@example.com>
|
||||
Date: Thu, 19 Oct 2023 13:12:51 -0400
|
||||
Subject: [PATCH] [core] Disable portable-simd test
|
||||
|
||||
---
|
||||
library/core/tests/lib.rs | 2 --
|
||||
1 file changed, 2 deletions(-)
|
||||
|
||||
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
|
||||
index 5814ed4..194ad4c 100644
|
||||
--- a/library/core/tests/lib.rs
|
||||
+++ b/library/core/tests/lib.rs
|
||||
@@ -90,7 +90,6 @@
|
||||
#![feature(unwrap_infallible)]
|
||||
#![feature(pointer_byte_offsets)]
|
||||
#![feature(pointer_is_aligned)]
|
||||
-#![feature(portable_simd)]
|
||||
#![feature(ptr_metadata)]
|
||||
#![feature(lazy_cell)]
|
||||
#![feature(unsized_tuple_coercion)]
|
||||
@@ -157,7 +156,6 @@ mod pin;
|
||||
mod pin_macro;
|
||||
mod ptr;
|
||||
mod result;
|
||||
-mod simd;
|
||||
mod slice;
|
||||
mod str;
|
||||
mod str_lossy;
|
||||
--
|
||||
2.42.0
|
||||
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
[toolchain]
|
||||
channel = "nightly-2023-10-08"
|
||||
channel = "nightly-2023-10-21"
|
||||
components = ["rust-src", "rustc-dev", "llvm-tools-preview"]
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
#[cfg(feature = "master")]
|
||||
use gccjit::FnAttribute;
|
||||
use gccjit::{ToLValue, ToRValue, Type};
|
||||
use rustc_codegen_ssa::traits::{AbiBuilderMethods, BaseTypeMethods};
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
|
|
@ -96,14 +98,23 @@ impl GccType for Reg {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct FnAbiGcc<'gcc> {
|
||||
pub return_type: Type<'gcc>,
|
||||
pub arguments_type: Vec<Type<'gcc>>,
|
||||
pub is_c_variadic: bool,
|
||||
pub on_stack_param_indices: FxHashSet<usize>,
|
||||
#[cfg(feature = "master")]
|
||||
pub fn_attributes: Vec<FnAttribute<'gcc>>,
|
||||
}
|
||||
|
||||
pub trait FnAbiGccExt<'gcc, 'tcx> {
|
||||
// TODO(antoyo): return a function pointer type instead?
|
||||
fn gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> (Type<'gcc>, Vec<Type<'gcc>>, bool, FxHashSet<usize>);
|
||||
fn gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> FnAbiGcc<'gcc>;
|
||||
fn ptr_to_gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc>;
|
||||
}
|
||||
|
||||
impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
|
||||
fn gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> (Type<'gcc>, Vec<Type<'gcc>>, bool, FxHashSet<usize>) {
|
||||
fn gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> FnAbiGcc<'gcc> {
|
||||
let mut on_stack_param_indices = FxHashSet::default();
|
||||
|
||||
// This capacity calculation is approximate.
|
||||
|
|
@ -111,7 +122,7 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
|
|||
self.args.len() + if let PassMode::Indirect { .. } = self.ret.mode { 1 } else { 0 }
|
||||
);
|
||||
|
||||
let return_ty =
|
||||
let return_type =
|
||||
match self.ret.mode {
|
||||
PassMode::Ignore => cx.type_void(),
|
||||
PassMode::Direct(_) | PassMode::Pair(..) => self.ret.layout.immediate_gcc_type(cx),
|
||||
|
|
@ -121,19 +132,24 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
|
|||
cx.type_void()
|
||||
}
|
||||
};
|
||||
#[cfg(feature = "master")]
|
||||
let mut non_null_args = Vec::new();
|
||||
|
||||
#[cfg(feature = "master")]
|
||||
let apply_attrs = |ty: Type<'gcc>, attrs: &ArgAttributes| {
|
||||
if cx.sess().opts.optimize != config::OptLevel::No
|
||||
&& attrs.regular.contains(rustc_target::abi::call::ArgAttribute::NoAlias)
|
||||
{
|
||||
ty.make_restrict()
|
||||
} else {
|
||||
ty
|
||||
let mut apply_attrs = |mut ty: Type<'gcc>, attrs: &ArgAttributes, arg_index: usize| {
|
||||
if cx.sess().opts.optimize == config::OptLevel::No {
|
||||
return ty;
|
||||
}
|
||||
if attrs.regular.contains(rustc_target::abi::call::ArgAttribute::NoAlias) {
|
||||
ty = ty.make_restrict()
|
||||
}
|
||||
if attrs.regular.contains(rustc_target::abi::call::ArgAttribute::NonNull) {
|
||||
non_null_args.push(arg_index as i32 + 1);
|
||||
}
|
||||
ty
|
||||
};
|
||||
#[cfg(not(feature = "master"))]
|
||||
let apply_attrs = |ty: Type<'gcc>, _attrs: &ArgAttributes| {
|
||||
let apply_attrs = |ty: Type<'gcc>, _attrs: &ArgAttributes, _arg_index: usize| {
|
||||
ty
|
||||
};
|
||||
|
||||
|
|
@ -141,8 +157,9 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
|
|||
let arg_ty = match arg.mode {
|
||||
PassMode::Ignore => continue,
|
||||
PassMode::Pair(a, b) => {
|
||||
argument_tys.push(apply_attrs(arg.layout.scalar_pair_element_gcc_type(cx, 0), &a));
|
||||
argument_tys.push(apply_attrs(arg.layout.scalar_pair_element_gcc_type(cx, 1), &b));
|
||||
let arg_pos = argument_tys.len();
|
||||
argument_tys.push(apply_attrs(arg.layout.scalar_pair_element_gcc_type(cx, 0), &a, arg_pos));
|
||||
argument_tys.push(apply_attrs(arg.layout.scalar_pair_element_gcc_type(cx, 1), &b, arg_pos + 1));
|
||||
continue;
|
||||
}
|
||||
PassMode::Cast { ref cast, pad_i32 } => {
|
||||
|
|
@ -151,31 +168,53 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
|
|||
argument_tys.push(Reg::i32().gcc_type(cx));
|
||||
}
|
||||
let ty = cast.gcc_type(cx);
|
||||
apply_attrs(ty, &cast.attrs)
|
||||
apply_attrs(ty, &cast.attrs, argument_tys.len())
|
||||
}
|
||||
PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: true } => {
|
||||
// This is a "byval" argument, so we don't apply the `restrict` attribute on it.
|
||||
on_stack_param_indices.insert(argument_tys.len());
|
||||
arg.memory_ty(cx)
|
||||
},
|
||||
PassMode::Direct(attrs) => apply_attrs(arg.layout.immediate_gcc_type(cx), &attrs),
|
||||
PassMode::Direct(attrs) => apply_attrs(arg.layout.immediate_gcc_type(cx), &attrs, argument_tys.len()),
|
||||
PassMode::Indirect { attrs, meta_attrs: None, on_stack: false } => {
|
||||
apply_attrs(cx.type_ptr_to(arg.memory_ty(cx)), &attrs)
|
||||
apply_attrs(cx.type_ptr_to(arg.memory_ty(cx)), &attrs, argument_tys.len())
|
||||
}
|
||||
PassMode::Indirect { attrs, meta_attrs: Some(meta_attrs), on_stack } => {
|
||||
assert!(!on_stack);
|
||||
apply_attrs(apply_attrs(cx.type_ptr_to(arg.memory_ty(cx)), &attrs), &meta_attrs)
|
||||
let ty = apply_attrs(cx.type_ptr_to(arg.memory_ty(cx)), &attrs, argument_tys.len());
|
||||
apply_attrs(ty, &meta_attrs, argument_tys.len())
|
||||
}
|
||||
};
|
||||
argument_tys.push(arg_ty);
|
||||
}
|
||||
|
||||
(return_ty, argument_tys, self.c_variadic, on_stack_param_indices)
|
||||
#[cfg(feature = "master")]
|
||||
let fn_attrs = if non_null_args.is_empty() {
|
||||
Vec::new()
|
||||
} else {
|
||||
vec![FnAttribute::NonNull(non_null_args)]
|
||||
};
|
||||
|
||||
FnAbiGcc {
|
||||
return_type,
|
||||
arguments_type: argument_tys,
|
||||
is_c_variadic: self.c_variadic,
|
||||
on_stack_param_indices,
|
||||
#[cfg(feature = "master")]
|
||||
fn_attributes: fn_attrs,
|
||||
}
|
||||
}
|
||||
|
||||
fn ptr_to_gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc> {
|
||||
let (return_type, params, variadic, on_stack_param_indices) = self.gcc_type(cx);
|
||||
let pointer_type = cx.context.new_function_pointer_type(None, return_type, ¶ms, variadic);
|
||||
// FIXME(antoyo): Should we do something with `FnAbiGcc::fn_attributes`?
|
||||
let FnAbiGcc {
|
||||
return_type,
|
||||
arguments_type,
|
||||
is_c_variadic,
|
||||
on_stack_param_indices,
|
||||
..
|
||||
} = self.gcc_type(cx);
|
||||
let pointer_type = cx.context.new_function_pointer_type(None, return_type, &arguments_type, is_c_variadic);
|
||||
cx.on_stack_params.borrow_mut().insert(pointer_type.dyncast_function_ptr_type().expect("function ptr type"), on_stack_param_indices);
|
||||
pointer_type
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,6 +53,9 @@ pub fn from_fn_attrs<'gcc, 'tcx>(
|
|||
codegen_fn_attrs.inline
|
||||
};
|
||||
if let Some(attr) = inline_attr(cx, inline) {
|
||||
if let FnAttribute::AlwaysInline = attr {
|
||||
func.add_attribute(FnAttribute::Inline);
|
||||
}
|
||||
func.add_attribute(attr);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -98,10 +98,11 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, target_info: Lock
|
|||
.map(|string| &string[1..])
|
||||
.collect();
|
||||
|
||||
// TODO(antoyo): only set on x86 platforms.
|
||||
context.add_command_line_option("-masm=intel");
|
||||
if tcx.sess.target.arch == "x86" || tcx.sess.target.arch == "x86_64" {
|
||||
context.add_command_line_option("-masm=intel");
|
||||
}
|
||||
|
||||
if !disabled_features.contains("avx") {
|
||||
if !disabled_features.contains("avx") && tcx.sess.target.arch == "x86_64" {
|
||||
// NOTE: we always enable AVX because the equivalent of llvm.x86.sse2.cmp.pd in GCC for
|
||||
// SSE2 is multiple builtins, so we use the AVX __builtin_ia32_cmppd instead.
|
||||
// FIXME(antoyo): use the proper builtins for llvm.x86.sse2.cmp.pd and similar.
|
||||
|
|
|
|||
|
|
@ -751,9 +751,8 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
|
|||
loaded_value.to_rvalue()
|
||||
}
|
||||
|
||||
fn volatile_load(&mut self, _ty: Type<'gcc>, ptr: RValue<'gcc>) -> RValue<'gcc> {
|
||||
// TODO(antoyo): use ty.
|
||||
let ptr = self.context.new_cast(None, ptr, ptr.get_type().make_volatile());
|
||||
fn volatile_load(&mut self, ty: Type<'gcc>, ptr: RValue<'gcc>) -> RValue<'gcc> {
|
||||
let ptr = self.context.new_cast(None, ptr, ty.make_volatile().make_pointer());
|
||||
ptr.dereference(None).to_rvalue()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -424,35 +424,35 @@ impl<'gcc, 'tcx> TypeReflection<'gcc, 'tcx> for Type<'gcc> {
|
|||
}
|
||||
|
||||
fn is_i8(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool {
|
||||
self.unqualified() == cx.i8_type
|
||||
self.is_compatible_with(cx.i8_type)
|
||||
}
|
||||
|
||||
fn is_u8(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool {
|
||||
self.unqualified() == cx.u8_type
|
||||
self.is_compatible_with(cx.u8_type)
|
||||
}
|
||||
|
||||
fn is_i16(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool {
|
||||
self.unqualified() == cx.i16_type
|
||||
self.is_compatible_with(cx.i16_type)
|
||||
}
|
||||
|
||||
fn is_u16(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool {
|
||||
self.unqualified() == cx.u16_type
|
||||
self.is_compatible_with(cx.u16_type)
|
||||
}
|
||||
|
||||
fn is_i32(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool {
|
||||
self.unqualified() == cx.i32_type
|
||||
self.is_compatible_with(cx.i32_type)
|
||||
}
|
||||
|
||||
fn is_u32(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool {
|
||||
self.unqualified() == cx.u32_type
|
||||
self.is_compatible_with(cx.u32_type)
|
||||
}
|
||||
|
||||
fn is_i64(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool {
|
||||
self.unqualified() == cx.i64_type
|
||||
self.is_compatible_with(cx.i64_type)
|
||||
}
|
||||
|
||||
fn is_u64(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool {
|
||||
self.unqualified() == cx.u64_type
|
||||
self.is_compatible_with(cx.u64_type)
|
||||
}
|
||||
|
||||
fn is_i128(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool {
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ use rustc_target::abi::{call::FnAbi, HasDataLayout, PointeeInfo, Size, TargetDat
|
|||
use rustc_target::spec::{HasTargetSpec, Target, TlsModel};
|
||||
|
||||
use crate::callee::get_fn;
|
||||
use crate::common::SignType;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct FuncSig<'gcc> {
|
||||
|
|
@ -129,29 +130,57 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
|||
pub fn new(context: &'gcc Context<'gcc>, codegen_unit: &'tcx CodegenUnit<'tcx>, tcx: TyCtxt<'tcx>, supports_128bit_integers: bool) -> Self {
|
||||
let check_overflow = tcx.sess.overflow_checks();
|
||||
|
||||
let i8_type = context.new_c_type(CType::Int8t);
|
||||
let i16_type = context.new_c_type(CType::Int16t);
|
||||
let i32_type = context.new_c_type(CType::Int32t);
|
||||
let i64_type = context.new_c_type(CType::Int64t);
|
||||
let u8_type = context.new_c_type(CType::UInt8t);
|
||||
let u16_type = context.new_c_type(CType::UInt16t);
|
||||
let u32_type = context.new_c_type(CType::UInt32t);
|
||||
let u64_type = context.new_c_type(CType::UInt64t);
|
||||
let create_type = |ctype, rust_type| {
|
||||
let layout = tcx.layout_of(ParamEnv::reveal_all().and(rust_type)).unwrap();
|
||||
let align = layout.align.abi.bytes();
|
||||
#[cfg(feature="master")]
|
||||
{
|
||||
context.new_c_type(ctype).get_aligned(align)
|
||||
}
|
||||
#[cfg(not(feature="master"))]
|
||||
{
|
||||
// Since libgccjit 12 doesn't contain the fix to compare aligned integer types,
|
||||
// only align u128 and i128.
|
||||
if layout.ty.int_size_and_signed(tcx).0.bytes() == 16 {
|
||||
context.new_c_type(ctype).get_aligned(align)
|
||||
}
|
||||
else {
|
||||
context.new_c_type(ctype)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let i8_type = create_type(CType::Int8t, tcx.types.i8);
|
||||
let i16_type = create_type(CType::Int16t, tcx.types.i16);
|
||||
let i32_type = create_type(CType::Int32t, tcx.types.i32);
|
||||
let i64_type = create_type(CType::Int64t, tcx.types.i64);
|
||||
let u8_type = create_type(CType::UInt8t, tcx.types.u8);
|
||||
let u16_type = create_type(CType::UInt16t, tcx.types.u16);
|
||||
let u32_type = create_type(CType::UInt32t, tcx.types.u32);
|
||||
let u64_type = create_type(CType::UInt64t, tcx.types.u64);
|
||||
|
||||
let (i128_type, u128_type) =
|
||||
if supports_128bit_integers {
|
||||
let i128_type = context.new_c_type(CType::Int128t).get_aligned(8); // TODO(antoyo): should the alignment be hard-coded?;
|
||||
let u128_type = context.new_c_type(CType::UInt128t).get_aligned(8); // TODO(antoyo): should the alignment be hard-coded?;
|
||||
let i128_type = create_type(CType::Int128t, tcx.types.i128);
|
||||
let u128_type = create_type(CType::UInt128t, tcx.types.u128);
|
||||
(i128_type, u128_type)
|
||||
}
|
||||
else {
|
||||
let i128_type = context.new_array_type(None, i64_type, 2);
|
||||
let u128_type = context.new_array_type(None, u64_type, 2);
|
||||
/*let layout = tcx.layout_of(ParamEnv::reveal_all().and(tcx.types.i128)).unwrap();
|
||||
let i128_align = layout.align.abi.bytes();
|
||||
let layout = tcx.layout_of(ParamEnv::reveal_all().and(tcx.types.u128)).unwrap();
|
||||
let u128_align = layout.align.abi.bytes();*/
|
||||
|
||||
// TODO(antoyo): re-enable the alignment when libgccjit fixed the issue in
|
||||
// gcc_jit_context_new_array_constructor (it should not use reinterpret_cast).
|
||||
let i128_type = context.new_array_type(None, i64_type, 2)/*.get_aligned(i128_align)*/;
|
||||
let u128_type = context.new_array_type(None, u64_type, 2)/*.get_aligned(u128_align)*/;
|
||||
(i128_type, u128_type)
|
||||
};
|
||||
|
||||
let tls_model = to_gcc_tls_mode(tcx.sess.tls_model());
|
||||
|
||||
// TODO(antoyo): set alignment on those types as well.
|
||||
let float_type = context.new_type::<f32>();
|
||||
let double_type = context.new_type::<f64>();
|
||||
|
||||
|
|
@ -167,14 +196,10 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
|||
let ulonglong_type = context.new_c_type(CType::ULongLong);
|
||||
let sizet_type = context.new_c_type(CType::SizeT);
|
||||
|
||||
let isize_type = context.new_c_type(CType::LongLong);
|
||||
let usize_type = context.new_c_type(CType::ULongLong);
|
||||
let usize_type = sizet_type;
|
||||
let isize_type = usize_type;
|
||||
let bool_type = context.new_type::<bool>();
|
||||
|
||||
// TODO(antoyo): only have those assertions on x86_64.
|
||||
assert_eq!(isize_type.get_size(), i64_type.get_size());
|
||||
assert_eq!(usize_type.get_size(), u64_type.get_size());
|
||||
|
||||
let mut functions = FxHashMap::default();
|
||||
let builtins = [
|
||||
"__builtin_unreachable", "abort", "__builtin_expect", "__builtin_add_overflow", "__builtin_mul_overflow",
|
||||
|
|
@ -192,7 +217,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
|||
functions.insert(builtin.to_string(), context.get_builtin_function(builtin));
|
||||
}
|
||||
|
||||
Self {
|
||||
let mut cx = Self {
|
||||
check_overflow,
|
||||
codegen_unit,
|
||||
context,
|
||||
|
|
@ -254,7 +279,10 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
|||
pointee_infos: Default::default(),
|
||||
structs_as_pointer: Default::default(),
|
||||
cleanup_blocks: Default::default(),
|
||||
}
|
||||
};
|
||||
// TODO(antoyo): instead of doing this, add SsizeT to libgccjit.
|
||||
cx.isize_type = usize_type.to_signed(&cx);
|
||||
cx
|
||||
}
|
||||
|
||||
pub fn rvalue_as_function(&self, value: RValue<'gcc>) -> Function<'gcc> {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use rustc_middle::ty::Ty;
|
|||
use rustc_span::Symbol;
|
||||
use rustc_target::abi::call::FnAbi;
|
||||
|
||||
use crate::abi::FnAbiGccExt;
|
||||
use crate::abi::{FnAbiGcc, FnAbiGccExt};
|
||||
use crate::context::CodegenCx;
|
||||
use crate::intrinsic::llvm;
|
||||
|
||||
|
|
@ -80,9 +80,20 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
|||
}
|
||||
|
||||
pub fn declare_fn(&self, name: &str, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Function<'gcc> {
|
||||
let (return_type, params, variadic, on_stack_param_indices) = fn_abi.gcc_type(self);
|
||||
let func = declare_raw_fn(self, name, () /*fn_abi.llvm_cconv()*/, return_type, ¶ms, variadic);
|
||||
let FnAbiGcc {
|
||||
return_type,
|
||||
arguments_type,
|
||||
is_c_variadic,
|
||||
on_stack_param_indices,
|
||||
#[cfg(feature="master")]
|
||||
fn_attributes,
|
||||
} = fn_abi.gcc_type(self);
|
||||
let func = declare_raw_fn(self, name, () /*fn_abi.llvm_cconv()*/, return_type, &arguments_type, is_c_variadic);
|
||||
self.on_stack_function_params.borrow_mut().insert(func, on_stack_param_indices);
|
||||
#[cfg(feature="master")]
|
||||
for fn_attr in fn_attributes {
|
||||
func.add_attribute(fn_attr);
|
||||
}
|
||||
func
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -198,9 +198,16 @@ pub fn check_tied_features(sess: &Session, features: &FxHashMap<&str, bool>) ->
|
|||
None
|
||||
}
|
||||
|
||||
fn arch_to_gcc(name: &str) -> &str {
|
||||
match name {
|
||||
"M68020" => "68020",
|
||||
_ => name,
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_native(name: &str) -> &str {
|
||||
if name != "native" {
|
||||
return name;
|
||||
return arch_to_gcc(name);
|
||||
}
|
||||
|
||||
#[cfg(feature="master")]
|
||||
|
|
|
|||
|
|
@ -7,7 +7,9 @@ use std::convert::TryFrom;
|
|||
use gccjit::{ComparisonOp, FunctionType, RValue, ToRValue, Type, UnaryOp, BinaryOp};
|
||||
use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
|
||||
use rustc_codegen_ssa::traits::{BackendTypes, BaseTypeMethods, BuilderMethods, OverflowOp};
|
||||
use rustc_middle::ty::Ty;
|
||||
use rustc_middle::ty::{ParamEnv, Ty};
|
||||
use rustc_target::abi::{Endian, call::{ArgAbi, ArgAttributes, Conv, FnAbi, PassMode}};
|
||||
use rustc_target::spec;
|
||||
|
||||
use crate::builder::ToGccComp;
|
||||
use crate::{builder::Builder, common::{SignType, TypeReflection}, context::CodegenCx};
|
||||
|
|
@ -37,11 +39,10 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
}
|
||||
else {
|
||||
let element_type = typ.dyncast_array().expect("element type");
|
||||
let values = [
|
||||
self.from_low_high_rvalues(typ,
|
||||
self.cx.context.new_unary_op(None, UnaryOp::BitwiseNegate, element_type, self.low(a)),
|
||||
self.cx.context.new_unary_op(None, UnaryOp::BitwiseNegate, element_type, self.high(a)),
|
||||
];
|
||||
self.cx.context.new_array_constructor(None, typ, &values)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -100,7 +101,6 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
let condition = self.gcc_icmp(IntPredicate::IntNE, self.gcc_and(b, sixty_four), zero);
|
||||
self.llbb().end_with_conditional(None, condition, then_block, else_block);
|
||||
|
||||
// TODO(antoyo): take endianness into account.
|
||||
let shift_value = self.gcc_sub(b, sixty_four);
|
||||
let high = self.high(a);
|
||||
let sign =
|
||||
|
|
@ -110,11 +110,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
else {
|
||||
zero
|
||||
};
|
||||
let values = [
|
||||
high >> shift_value,
|
||||
sign,
|
||||
];
|
||||
let array_value = self.context.new_array_constructor(None, a_type, &values);
|
||||
let array_value = self.from_low_high_rvalues(a_type, high >> shift_value, sign);
|
||||
then_block.add_assignment(None, result, array_value);
|
||||
then_block.end_with_jump(None, after_block);
|
||||
|
||||
|
|
@ -130,11 +126,10 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
let casted_low = self.context.new_cast(None, self.low(a), unsigned_type);
|
||||
let shifted_low = casted_low >> self.context.new_cast(None, b, unsigned_type);
|
||||
let shifted_low = self.context.new_cast(None, shifted_low, native_int_type);
|
||||
let values = [
|
||||
let array_value = self.from_low_high_rvalues(a_type,
|
||||
(high << shift_value) | shifted_low,
|
||||
high >> b,
|
||||
];
|
||||
let array_value = self.context.new_array_constructor(None, a_type, &values);
|
||||
);
|
||||
actual_else_block.add_assignment(None, result, array_value);
|
||||
actual_else_block.end_with_jump(None, after_block);
|
||||
|
||||
|
|
@ -314,18 +309,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
_ => unreachable!(),
|
||||
},
|
||||
};
|
||||
let a_type = lhs.get_type();
|
||||
let b_type = rhs.get_type();
|
||||
let param_a = self.context.new_parameter(None, a_type, "a");
|
||||
let param_b = self.context.new_parameter(None, b_type, "b");
|
||||
let result_field = self.context.new_field(None, a_type, "result");
|
||||
let overflow_field = self.context.new_field(None, self.bool_type, "overflow");
|
||||
let return_type = self.context.new_struct_type(None, "result_overflow", &[result_field, overflow_field]);
|
||||
let func = self.context.new_function(None, FunctionType::Extern, return_type.as_type(), &[param_a, param_b], func_name, false);
|
||||
let result = self.context.new_call(None, func, &[lhs, rhs]);
|
||||
let overflow = result.access_field(None, overflow_field);
|
||||
let int_result = result.access_field(None, result_field);
|
||||
return (int_result, overflow);
|
||||
return self.operation_with_overflow(func_name, lhs, rhs);
|
||||
},
|
||||
_ => {
|
||||
match oop {
|
||||
|
|
@ -350,6 +334,54 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
(res.dereference(None).to_rvalue(), overflow)
|
||||
}
|
||||
|
||||
pub fn operation_with_overflow(&self, func_name: &str, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) {
|
||||
let a_type = lhs.get_type();
|
||||
let b_type = rhs.get_type();
|
||||
let param_a = self.context.new_parameter(None, a_type, "a");
|
||||
let param_b = self.context.new_parameter(None, b_type, "b");
|
||||
let result_field = self.context.new_field(None, a_type, "result");
|
||||
let overflow_field = self.context.new_field(None, self.bool_type, "overflow");
|
||||
|
||||
let ret_ty = Ty::new_tup(self.tcx, &[self.tcx.types.i128, self.tcx.types.bool]);
|
||||
let layout = self.tcx.layout_of(ParamEnv::reveal_all().and(ret_ty)).unwrap();
|
||||
|
||||
let arg_abi = ArgAbi {
|
||||
layout,
|
||||
mode: PassMode::Direct(ArgAttributes::new()),
|
||||
};
|
||||
let mut fn_abi = FnAbi {
|
||||
args: vec![arg_abi.clone(), arg_abi.clone()].into_boxed_slice(),
|
||||
ret: arg_abi,
|
||||
c_variadic: false,
|
||||
fixed_count: 2,
|
||||
conv: Conv::C,
|
||||
can_unwind: false,
|
||||
};
|
||||
fn_abi.adjust_for_foreign_abi(self.cx, spec::abi::Abi::C {
|
||||
unwind: false,
|
||||
}).unwrap();
|
||||
|
||||
let indirect = matches!(fn_abi.ret.mode, PassMode::Indirect { .. });
|
||||
|
||||
let return_type = self.context.new_struct_type(None, "result_overflow", &[result_field, overflow_field]);
|
||||
let result =
|
||||
if indirect {
|
||||
let return_value = self.current_func().new_local(None, return_type.as_type(), "return_value");
|
||||
let return_param_type = return_type.as_type().make_pointer();
|
||||
let return_param = self.context.new_parameter(None, return_param_type, "return_value");
|
||||
let func = self.context.new_function(None, FunctionType::Extern, self.type_void(), &[return_param, param_a, param_b], func_name, false);
|
||||
self.llbb().add_eval(None, self.context.new_call(None, func, &[return_value.get_address(None), lhs, rhs]));
|
||||
return_value.to_rvalue()
|
||||
}
|
||||
else {
|
||||
let func = self.context.new_function(None, FunctionType::Extern, return_type.as_type(), &[param_a, param_b], func_name, false);
|
||||
self.context.new_call(None, func, &[lhs, rhs])
|
||||
};
|
||||
let overflow = result.access_field(None, overflow_field);
|
||||
let int_result = result.access_field(None, result_field);
|
||||
return (int_result, overflow);
|
||||
}
|
||||
|
||||
pub fn gcc_icmp(&mut self, op: IntPredicate, mut lhs: RValue<'gcc>, mut rhs: RValue<'gcc>) -> RValue<'gcc> {
|
||||
let a_type = lhs.get_type();
|
||||
let b_type = rhs.get_type();
|
||||
|
|
@ -415,6 +447,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
IntPredicate::IntNE => {
|
||||
return self.context.new_comparison(None, ComparisonOp::NotEquals, cmp, self.context.new_rvalue_one(self.int_type));
|
||||
},
|
||||
// TODO(antoyo): cast to u128 for unsigned comparison. See below.
|
||||
IntPredicate::IntUGT => (ComparisonOp::Equals, 2),
|
||||
IntPredicate::IntUGE => (ComparisonOp::GreaterThanEquals, 1),
|
||||
IntPredicate::IntULT => (ComparisonOp::Equals, 0),
|
||||
|
|
@ -444,6 +477,18 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
rhs = self.context.new_cast(None, rhs, a_type);
|
||||
}
|
||||
}
|
||||
match op {
|
||||
IntPredicate::IntUGT | IntPredicate::IntUGE | IntPredicate::IntULT | IntPredicate::IntULE => {
|
||||
if !a_type.is_vector() {
|
||||
let unsigned_type = a_type.to_unsigned(&self.cx);
|
||||
lhs = self.context.new_cast(None, lhs, unsigned_type);
|
||||
rhs = self.context.new_cast(None, rhs, unsigned_type);
|
||||
}
|
||||
},
|
||||
// TODO(antoyo): we probably need to handle signed comparison for unsigned
|
||||
// integers.
|
||||
_ => (),
|
||||
}
|
||||
self.context.new_comparison(None, op.to_gcc_comparison(), lhs, rhs)
|
||||
}
|
||||
}
|
||||
|
|
@ -455,11 +500,10 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
a ^ b
|
||||
}
|
||||
else {
|
||||
let values = [
|
||||
self.from_low_high_rvalues(a_type,
|
||||
self.low(a) ^ self.low(b),
|
||||
self.high(a) ^ self.high(b),
|
||||
];
|
||||
self.context.new_array_constructor(None, a_type, &values)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -505,12 +549,10 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
let condition = self.gcc_icmp(IntPredicate::IntNE, self.gcc_and(b, sixty_four), zero);
|
||||
self.llbb().end_with_conditional(None, condition, then_block, else_block);
|
||||
|
||||
// TODO(antoyo): take endianness into account.
|
||||
let values = [
|
||||
let array_value = self.from_low_high_rvalues(a_type,
|
||||
zero,
|
||||
self.low(a) << (b - sixty_four),
|
||||
];
|
||||
let array_value = self.context.new_array_constructor(None, a_type, &values);
|
||||
);
|
||||
then_block.add_assignment(None, result, array_value);
|
||||
then_block.end_with_jump(None, after_block);
|
||||
|
||||
|
|
@ -521,16 +563,16 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
b0_block.end_with_jump(None, after_block);
|
||||
|
||||
// NOTE: cast low to its unsigned type in order to perform a logical right shift.
|
||||
// TODO(antoyo): adjust this ^ comment.
|
||||
let unsigned_type = native_int_type.to_unsigned(&self.cx);
|
||||
let casted_low = self.context.new_cast(None, self.low(a), unsigned_type);
|
||||
let shift_value = self.context.new_cast(None, sixty_four - b, unsigned_type);
|
||||
let high_low = self.context.new_cast(None, casted_low >> shift_value, native_int_type);
|
||||
let values = [
|
||||
|
||||
let array_value = self.from_low_high_rvalues(a_type,
|
||||
self.low(a) << b,
|
||||
(self.high(a) << b) | high_low,
|
||||
];
|
||||
|
||||
let array_value = self.context.new_array_constructor(None, a_type, &values);
|
||||
);
|
||||
actual_else_block.add_assignment(None, result, array_value);
|
||||
actual_else_block.end_with_jump(None, after_block);
|
||||
|
||||
|
|
@ -546,16 +588,16 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
let arg_type = arg.get_type();
|
||||
if !self.is_native_int_type(arg_type) {
|
||||
let native_int_type = arg_type.dyncast_array().expect("get element type");
|
||||
let lsb = self.context.new_array_access(None, arg, self.context.new_rvalue_from_int(self.int_type, 0)).to_rvalue();
|
||||
let lsb = self.low(arg);
|
||||
let swapped_lsb = self.gcc_bswap(lsb, width / 2);
|
||||
let swapped_lsb = self.context.new_cast(None, swapped_lsb, native_int_type);
|
||||
let msb = self.context.new_array_access(None, arg, self.context.new_rvalue_from_int(self.int_type, 1)).to_rvalue();
|
||||
let msb = self.high(arg);
|
||||
let swapped_msb = self.gcc_bswap(msb, width / 2);
|
||||
let swapped_msb = self.context.new_cast(None, swapped_msb, native_int_type);
|
||||
|
||||
// NOTE: we also need to swap the two elements here, in addition to swapping inside
|
||||
// the elements themselves like done above.
|
||||
return self.context.new_array_constructor(None, arg_type, &[swapped_msb, swapped_lsb]);
|
||||
return self.from_low_high_rvalues(arg_type, swapped_msb, swapped_lsb);
|
||||
}
|
||||
|
||||
// TODO(antoyo): check if it's faster to use string literals and a
|
||||
|
|
@ -659,11 +701,10 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
|||
else {
|
||||
assert!(!a_native && !b_native, "both types should either be native or non-native for or operation");
|
||||
let native_int_type = a_type.dyncast_array().expect("get element type");
|
||||
let values = [
|
||||
self.from_low_high_rvalues(a_type,
|
||||
self.context.new_binary_op(None, operation, native_int_type, self.low(a), self.low(b)),
|
||||
self.context.new_binary_op(None, operation, native_int_type, self.high(a), self.high(b)),
|
||||
];
|
||||
self.context.new_array_constructor(None, a_type, &values)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -687,11 +728,10 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
|||
let zero = self.context.new_rvalue_zero(value_type);
|
||||
let is_negative = self.context.new_comparison(None, ComparisonOp::LessThan, value, zero);
|
||||
let is_negative = self.gcc_int_cast(is_negative, dest_element_type);
|
||||
let values = [
|
||||
self.from_low_high_rvalues(dest_typ,
|
||||
self.context.new_cast(None, value, dest_element_type),
|
||||
self.context.new_unary_op(None, UnaryOp::Minus, dest_element_type, is_negative),
|
||||
];
|
||||
self.context.new_array_constructor(None, dest_typ, &values)
|
||||
)
|
||||
}
|
||||
else {
|
||||
// Since u128 and i128 are the only types that can be unsupported, we know the type of
|
||||
|
|
@ -769,20 +809,47 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
|||
}
|
||||
|
||||
fn high(&self, value: RValue<'gcc>) -> RValue<'gcc> {
|
||||
self.context.new_array_access(None, value, self.context.new_rvalue_from_int(self.int_type, 1))
|
||||
let index =
|
||||
match self.sess().target.options.endian {
|
||||
Endian::Little => 1,
|
||||
Endian::Big => 0,
|
||||
};
|
||||
self.context.new_array_access(None, value, self.context.new_rvalue_from_int(self.int_type, index))
|
||||
.to_rvalue()
|
||||
}
|
||||
|
||||
fn low(&self, value: RValue<'gcc>) -> RValue<'gcc> {
|
||||
self.context.new_array_access(None, value, self.context.new_rvalue_from_int(self.int_type, 0))
|
||||
let index =
|
||||
match self.sess().target.options.endian {
|
||||
Endian::Little => 0,
|
||||
Endian::Big => 1,
|
||||
};
|
||||
self.context.new_array_access(None, value, self.context.new_rvalue_from_int(self.int_type, index))
|
||||
.to_rvalue()
|
||||
}
|
||||
|
||||
fn from_low_high_rvalues(&self, typ: Type<'gcc>, low: RValue<'gcc>, high: RValue<'gcc>) -> RValue<'gcc> {
|
||||
let (first, last) =
|
||||
match self.sess().target.options.endian {
|
||||
Endian::Little => (low, high),
|
||||
Endian::Big => (high, low),
|
||||
};
|
||||
|
||||
let values = [first, last];
|
||||
self.context.new_array_constructor(None, typ, &values)
|
||||
}
|
||||
|
||||
fn from_low_high(&self, typ: Type<'gcc>, low: i64, high: i64) -> RValue<'gcc> {
|
||||
let (first, last) =
|
||||
match self.sess().target.options.endian {
|
||||
Endian::Little => (low, high),
|
||||
Endian::Big => (high, low),
|
||||
};
|
||||
|
||||
let native_int_type = typ.dyncast_array().expect("get element type");
|
||||
let values = [
|
||||
self.context.new_rvalue_from_long(native_int_type, low),
|
||||
self.context.new_rvalue_from_long(native_int_type, high),
|
||||
self.context.new_rvalue_from_long(native_int_type, first),
|
||||
self.context.new_rvalue_from_long(native_int_type, last),
|
||||
];
|
||||
self.context.new_array_constructor(None, typ, &values)
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -432,15 +432,21 @@ pub fn ignore_arg_cast(func_name: &str, index: usize, args_len: usize) -> bool {
|
|||
|
||||
#[cfg(not(feature="master"))]
|
||||
pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function<'gcc> {
|
||||
match name {
|
||||
"llvm.x86.xgetbv" | "llvm.x86.sse2.pause" => {
|
||||
let gcc_name = "__builtin_trap";
|
||||
let func = cx.context.get_builtin_function(gcc_name);
|
||||
cx.functions.borrow_mut().insert(gcc_name.to_string(), func);
|
||||
return func;
|
||||
},
|
||||
_ => unimplemented!("unsupported LLVM intrinsic {}", name),
|
||||
}
|
||||
let gcc_name =
|
||||
match name {
|
||||
"llvm.x86.sse2.pause" => {
|
||||
// NOTE: pause is only a hint, so we use a dummy built-in because target built-ins
|
||||
// are not supported in libgccjit 12.
|
||||
"__builtin_inff"
|
||||
},
|
||||
"llvm.x86.xgetbv" => {
|
||||
"__builtin_trap"
|
||||
},
|
||||
_ => unimplemented!("unsupported LLVM intrinsic {}", name),
|
||||
};
|
||||
let func = cx.context.get_builtin_function(gcc_name);
|
||||
cx.functions.borrow_mut().insert(gcc_name.to_string(), func);
|
||||
return func;
|
||||
}
|
||||
|
||||
#[cfg(feature="master")]
|
||||
|
|
|
|||
|
|
@ -4,7 +4,9 @@ mod simd;
|
|||
#[cfg(feature="master")]
|
||||
use std::iter;
|
||||
|
||||
use gccjit::{ComparisonOp, Function, RValue, ToRValue, Type, UnaryOp, FunctionType};
|
||||
#[cfg(feature="master")]
|
||||
use gccjit::FunctionType;
|
||||
use gccjit::{ComparisonOp, Function, RValue, ToRValue, Type, UnaryOp};
|
||||
use rustc_codegen_ssa::MemFlags;
|
||||
use rustc_codegen_ssa::base::wants_msvc_seh;
|
||||
use rustc_codegen_ssa::common::IntPredicate;
|
||||
|
|
@ -143,11 +145,15 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
|
|||
|
||||
sym::volatile_load | sym::unaligned_volatile_load => {
|
||||
let tp_ty = fn_args.type_at(0);
|
||||
let mut ptr = args[0].immediate();
|
||||
if let PassMode::Cast { cast: ty, .. } = &fn_abi.ret.mode {
|
||||
ptr = self.pointercast(ptr, self.type_ptr_to(ty.gcc_type(self)));
|
||||
}
|
||||
let load = self.volatile_load(ptr.get_type(), ptr);
|
||||
let ptr = args[0].immediate();
|
||||
let load =
|
||||
if let PassMode::Cast { cast: ty, pad_i32: _ } = &fn_abi.ret.mode {
|
||||
let gcc_ty = ty.gcc_type(self);
|
||||
self.volatile_load(gcc_ty, ptr)
|
||||
}
|
||||
else {
|
||||
self.volatile_load(self.layout_of(tp_ty).gcc_type(self), ptr)
|
||||
};
|
||||
// TODO(antoyo): set alignment.
|
||||
self.to_immediate(load, self.layout_of(tp_ty))
|
||||
}
|
||||
|
|
@ -819,75 +825,58 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
value
|
||||
};
|
||||
|
||||
if value_type.is_u128(&self.cx) {
|
||||
// TODO(antoyo): implement in the normal algorithm below to have a more efficient
|
||||
// implementation (that does not require a call to __popcountdi2).
|
||||
let popcount = self.context.get_builtin_function("__builtin_popcountll");
|
||||
// only break apart 128-bit ints if they're not natively supported
|
||||
// TODO(antoyo): remove this if/when native 128-bit integers land in libgccjit
|
||||
if value_type.is_u128(&self.cx) && !self.cx.supports_128bit_integers {
|
||||
let sixty_four = self.gcc_int(value_type, 64);
|
||||
let right_shift = self.gcc_lshr(value, sixty_four);
|
||||
let high = self.gcc_int_cast(right_shift, self.cx.ulonglong_type);
|
||||
let high = self.context.new_call(None, popcount, &[high]);
|
||||
let high = self.pop_count(high);
|
||||
let low = self.gcc_int_cast(value, self.cx.ulonglong_type);
|
||||
let low = self.context.new_call(None, popcount, &[low]);
|
||||
let low = self.pop_count(low);
|
||||
let res = high + low;
|
||||
return self.gcc_int_cast(res, result_type);
|
||||
}
|
||||
|
||||
// First step.
|
||||
let mask = self.context.new_rvalue_from_long(value_type, 0x5555555555555555);
|
||||
let left = value & mask;
|
||||
let shifted = value >> self.context.new_rvalue_from_int(value_type, 1);
|
||||
let right = shifted & mask;
|
||||
let value = left + right;
|
||||
// Use Wenger's algorithm for population count, gcc's seems to play better with it
|
||||
// for (int counter = 0; value != 0; counter++) {
|
||||
// value &= value - 1;
|
||||
// }
|
||||
let func = self.current_func.borrow().expect("func");
|
||||
let loop_head = func.new_block("head");
|
||||
let loop_body = func.new_block("body");
|
||||
let loop_tail = func.new_block("tail");
|
||||
|
||||
// Second step.
|
||||
let mask = self.context.new_rvalue_from_long(value_type, 0x3333333333333333);
|
||||
let left = value & mask;
|
||||
let shifted = value >> self.context.new_rvalue_from_int(value_type, 2);
|
||||
let right = shifted & mask;
|
||||
let value = left + right;
|
||||
let counter_type = self.int_type;
|
||||
let counter = self.current_func().new_local(None, counter_type, "popcount_counter");
|
||||
let val = self.current_func().new_local(None, value_type, "popcount_value");
|
||||
let zero = self.gcc_zero(counter_type);
|
||||
self.llbb().add_assignment(None, counter, zero);
|
||||
self.llbb().add_assignment(None, val, value);
|
||||
self.br(loop_head);
|
||||
|
||||
// Third step.
|
||||
let mask = self.context.new_rvalue_from_long(value_type, 0x0F0F0F0F0F0F0F0F);
|
||||
let left = value & mask;
|
||||
let shifted = value >> self.context.new_rvalue_from_int(value_type, 4);
|
||||
let right = shifted & mask;
|
||||
let value = left + right;
|
||||
// check if value isn't zero
|
||||
self.switch_to_block(loop_head);
|
||||
let zero = self.gcc_zero(value_type);
|
||||
let cond = self.gcc_icmp(IntPredicate::IntNE, val.to_rvalue(), zero);
|
||||
self.cond_br(cond, loop_body, loop_tail);
|
||||
|
||||
if value_type.is_u8(&self.cx) {
|
||||
return self.context.new_cast(None, value, result_type);
|
||||
}
|
||||
// val &= val - 1;
|
||||
self.switch_to_block(loop_body);
|
||||
let one = self.gcc_int(value_type, 1);
|
||||
let sub = self.gcc_sub(val.to_rvalue(), one);
|
||||
let op = self.gcc_and(val.to_rvalue(), sub);
|
||||
loop_body.add_assignment(None, val, op);
|
||||
|
||||
// Fourth step.
|
||||
let mask = self.context.new_rvalue_from_long(value_type, 0x00FF00FF00FF00FF);
|
||||
let left = value & mask;
|
||||
let shifted = value >> self.context.new_rvalue_from_int(value_type, 8);
|
||||
let right = shifted & mask;
|
||||
let value = left + right;
|
||||
// counter += 1
|
||||
let one = self.gcc_int(counter_type, 1);
|
||||
let op = self.gcc_add(counter.to_rvalue(), one);
|
||||
loop_body.add_assignment(None, counter, op);
|
||||
self.br(loop_head);
|
||||
|
||||
if value_type.is_u16(&self.cx) {
|
||||
return self.context.new_cast(None, value, result_type);
|
||||
}
|
||||
|
||||
// Fifth step.
|
||||
let mask = self.context.new_rvalue_from_long(value_type, 0x0000FFFF0000FFFF);
|
||||
let left = value & mask;
|
||||
let shifted = value >> self.context.new_rvalue_from_int(value_type, 16);
|
||||
let right = shifted & mask;
|
||||
let value = left + right;
|
||||
|
||||
if value_type.is_u32(&self.cx) {
|
||||
return self.context.new_cast(None, value, result_type);
|
||||
}
|
||||
|
||||
// Sixth step.
|
||||
let mask = self.context.new_rvalue_from_long(value_type, 0x00000000FFFFFFFF);
|
||||
let left = value & mask;
|
||||
let shifted = value >> self.context.new_rvalue_from_int(value_type, 32);
|
||||
let right = shifted & mask;
|
||||
let value = left + right;
|
||||
|
||||
self.context.new_cast(None, value, result_type)
|
||||
// end of loop
|
||||
self.switch_to_block(loop_tail);
|
||||
self.gcc_int_cast(counter.to_rvalue(), result_type)
|
||||
}
|
||||
|
||||
// Algorithm from: https://blog.regehr.org/archives/1063
|
||||
|
|
@ -947,15 +936,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
128 => "__rust_i128_addo",
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let param_a = self.context.new_parameter(None, result_type, "a");
|
||||
let param_b = self.context.new_parameter(None, result_type, "b");
|
||||
let result_field = self.context.new_field(None, result_type, "result");
|
||||
let overflow_field = self.context.new_field(None, self.bool_type, "overflow");
|
||||
let return_type = self.context.new_struct_type(None, "result_overflow", &[result_field, overflow_field]);
|
||||
let func = self.context.new_function(None, FunctionType::Extern, return_type.as_type(), &[param_a, param_b], func_name, false);
|
||||
let result = self.context.new_call(None, func, &[lhs, rhs]);
|
||||
let overflow = result.access_field(None, overflow_field);
|
||||
let int_result = result.access_field(None, result_field);
|
||||
let (int_result, overflow) = self.operation_with_overflow(func_name, lhs, rhs);
|
||||
self.llbb().add_assignment(None, res, int_result);
|
||||
overflow
|
||||
};
|
||||
|
|
@ -1017,15 +998,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
128 => "__rust_i128_subo",
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let param_a = self.context.new_parameter(None, result_type, "a");
|
||||
let param_b = self.context.new_parameter(None, result_type, "b");
|
||||
let result_field = self.context.new_field(None, result_type, "result");
|
||||
let overflow_field = self.context.new_field(None, self.bool_type, "overflow");
|
||||
let return_type = self.context.new_struct_type(None, "result_overflow", &[result_field, overflow_field]);
|
||||
let func = self.context.new_function(None, FunctionType::Extern, return_type.as_type(), &[param_a, param_b], func_name, false);
|
||||
let result = self.context.new_call(None, func, &[lhs, rhs]);
|
||||
let overflow = result.access_field(None, overflow_field);
|
||||
let int_result = result.access_field(None, result_field);
|
||||
let (int_result, overflow) = self.operation_with_overflow(func_name, lhs, rhs);
|
||||
self.llbb().add_assignment(None, res, int_result);
|
||||
overflow
|
||||
};
|
||||
|
|
@ -1197,7 +1170,7 @@ fn get_rust_try_fn<'a, 'gcc, 'tcx>(cx: &'a CodegenCx<'gcc, 'tcx>, codegen: &mut
|
|||
#[cfg(feature="master")]
|
||||
fn gen_fn<'a, 'gcc, 'tcx>(cx: &'a CodegenCx<'gcc, 'tcx>, name: &str, rust_fn_sig: ty::PolyFnSig<'tcx>, codegen: &mut dyn FnMut(Builder<'a, 'gcc, 'tcx>)) -> (Type<'gcc>, Function<'gcc>) {
|
||||
let fn_abi = cx.fn_abi_of_fn_ptr(rust_fn_sig, ty::List::empty());
|
||||
let (typ, _, _, _) = fn_abi.gcc_type(cx);
|
||||
let return_type = fn_abi.gcc_type(cx).return_type;
|
||||
// FIXME(eddyb) find a nicer way to do this.
|
||||
cx.linkage.set(FunctionType::Internal);
|
||||
let func = cx.declare_fn(name, fn_abi);
|
||||
|
|
@ -1207,5 +1180,5 @@ fn gen_fn<'a, 'gcc, 'tcx>(cx: &'a CodegenCx<'gcc, 'tcx>, name: &str, rust_fn_sig
|
|||
let block = Builder::append_block(cx, func_val, "entry-block");
|
||||
let bx = Builder::build(cx, block);
|
||||
codegen(bx);
|
||||
(typ, func)
|
||||
(return_type, func)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
* TODO(antoyo): remove the patches.
|
||||
*/
|
||||
|
||||
#![cfg_attr(not(bootstrap), allow(internal_features))]
|
||||
#![cfg_attr(not(bootstrap), doc(rust_logo))]
|
||||
#![cfg_attr(not(bootstrap), feature(rustdoc_internals))]
|
||||
#![feature(
|
||||
|
|
@ -251,8 +252,9 @@ impl ExtraBackendMethods for GccCodegenBackend {
|
|||
temp_dir: None,
|
||||
};
|
||||
|
||||
// TODO(antoyo): only set for x86.
|
||||
mods.context.add_command_line_option("-masm=intel");
|
||||
if tcx.sess.target.arch == "x86" || tcx.sess.target.arch == "x86_64" {
|
||||
mods.context.add_command_line_option("-masm=intel");
|
||||
}
|
||||
unsafe { allocator::codegen(tcx, &mut mods, module_name, kind, alloc_error_handler_kind); }
|
||||
mods
|
||||
}
|
||||
|
|
|
|||
|
|
@ -119,11 +119,11 @@ impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
|||
}
|
||||
|
||||
fn type_f32(&self) -> Type<'gcc> {
|
||||
self.context.new_type::<f32>()
|
||||
self.float_type
|
||||
}
|
||||
|
||||
fn type_f64(&self) -> Type<'gcc> {
|
||||
self.context.new_type::<f64>()
|
||||
self.double_type
|
||||
}
|
||||
|
||||
fn type_func(&self, params: &[Type<'gcc>], return_type: Type<'gcc>) -> Type<'gcc> {
|
||||
|
|
@ -216,17 +216,17 @@ impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
|||
value.get_type()
|
||||
}
|
||||
|
||||
fn type_array(&self, ty: Type<'gcc>, len: u64) -> Type<'gcc> {
|
||||
// TODO: remove this as well?
|
||||
/*if let Some(struct_type) = ty.is_struct() {
|
||||
#[cfg_attr(feature="master", allow(unused_mut))]
|
||||
fn type_array(&self, ty: Type<'gcc>, mut len: u64) -> Type<'gcc> {
|
||||
#[cfg(not(feature="master"))]
|
||||
if let Some(struct_type) = ty.is_struct() {
|
||||
if struct_type.get_field_count() == 0 {
|
||||
// NOTE: since gccjit only supports i32 for the array size and libcore's tests uses a
|
||||
// size of usize::MAX in test_binary_search, we workaround this by setting the size to
|
||||
// zero for ZSTs.
|
||||
// FIXME(antoyo): fix gccjit API.
|
||||
len = 0;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
self.context.new_array_type(None, ty, len)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
|
|||
use rustc_target::abi::{self, Abi, Align, F32, F64, FieldsShape, Int, Integer, Pointer, PointeeInfo, Size, TyAbiInterface, Variants};
|
||||
use rustc_target::abi::call::{CastTarget, FnAbi, Reg};
|
||||
|
||||
use crate::abi::{FnAbiGccExt, GccType};
|
||||
use crate::abi::{FnAbiGcc, FnAbiGccExt, GccType};
|
||||
use crate::context::CodegenCx;
|
||||
use crate::type_::struct_fields;
|
||||
|
||||
|
|
@ -372,7 +372,13 @@ impl<'gcc, 'tcx> LayoutTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
|||
}
|
||||
|
||||
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)
|
||||
// FIXME(antoyo): Should we do something with `FnAbiGcc::fn_attributes`?
|
||||
let FnAbiGcc {
|
||||
return_type,
|
||||
arguments_type,
|
||||
is_c_variadic,
|
||||
..
|
||||
} = fn_abi.gcc_type(self);
|
||||
self.context.new_function_pointer_type(None, return_type, &arguments_type, is_c_variadic)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,16 +5,6 @@
|
|||
set -e
|
||||
#set -x
|
||||
|
||||
if [ -f ./gcc_path ]; then
|
||||
export GCC_PATH=$(cat gcc_path)
|
||||
else
|
||||
echo 'Please put the path to your custom build of libgccjit in the file `gcc_path`, see Readme.md for details'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export LD_LIBRARY_PATH="$GCC_PATH"
|
||||
export LIBRARY_PATH="$GCC_PATH"
|
||||
|
||||
flags=
|
||||
gcc_master_branch=1
|
||||
channel="debug"
|
||||
|
|
@ -22,12 +12,18 @@ funcs=()
|
|||
build_only=0
|
||||
nb_parts=0
|
||||
current_part=0
|
||||
use_system_gcc=0
|
||||
use_backend=0
|
||||
cargo_target_dir=""
|
||||
|
||||
export CHANNEL='debug'
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
--release)
|
||||
codegen_channel=release
|
||||
channel="release"
|
||||
export CHANNEL='release'
|
||||
shift
|
||||
;;
|
||||
--release-sysroot)
|
||||
|
|
@ -111,6 +107,22 @@ while [[ $# -gt 0 ]]; do
|
|||
build_only=1
|
||||
shift
|
||||
;;
|
||||
"--use-system-gcc")
|
||||
use_system_gcc=1
|
||||
shift
|
||||
;;
|
||||
"--use-backend")
|
||||
use_backend=1
|
||||
shift
|
||||
export BUILTIN_BACKEND=$1
|
||||
shift
|
||||
;;
|
||||
"--out-dir")
|
||||
shift
|
||||
export CARGO_TARGET_DIR=$1
|
||||
cargo_target_dir=$1
|
||||
shift
|
||||
;;
|
||||
"--nb-parts")
|
||||
shift
|
||||
nb_parts=$1
|
||||
|
|
@ -128,13 +140,25 @@ while [[ $# -gt 0 ]]; do
|
|||
esac
|
||||
done
|
||||
|
||||
if [[ $channel == "release" ]]; then
|
||||
export CHANNEL='release'
|
||||
CARGO_INCREMENTAL=1 cargo rustc --release $flags
|
||||
if [ -f ./gcc_path ]; then
|
||||
export GCC_PATH=$(cat gcc_path)
|
||||
elif (( $use_system_gcc == 1 )); then
|
||||
echo 'Using system GCC'
|
||||
else
|
||||
echo $LD_LIBRARY_PATH
|
||||
export CHANNEL='debug'
|
||||
cargo rustc $flags
|
||||
echo 'Please put the path to your custom build of libgccjit in the file `gcc_path`, see Readme.md for details'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export LD_LIBRARY_PATH="$GCC_PATH"
|
||||
export LIBRARY_PATH="$GCC_PATH"
|
||||
|
||||
if [[ $use_backend == 0 ]]; then
|
||||
if [[ $channel == "release" ]]; then
|
||||
CARGO_INCREMENTAL=1 cargo rustc --release $flags
|
||||
else
|
||||
echo $LD_LIBRARY_PATH
|
||||
cargo rustc $flags
|
||||
fi
|
||||
fi
|
||||
|
||||
if (( $build_only == 1 )); then
|
||||
|
|
@ -145,20 +169,26 @@ fi
|
|||
source config.sh
|
||||
|
||||
function clean() {
|
||||
rm -r target/out || true
|
||||
mkdir -p target/out/gccjit
|
||||
rm -r $cargo_target_dir || true
|
||||
mkdir -p $cargo_target_dir/gccjit
|
||||
}
|
||||
|
||||
function mini_tests() {
|
||||
echo "[BUILD] mini_core"
|
||||
$RUSTC example/mini_core.rs --crate-name mini_core --crate-type lib,dylib --target $TARGET_TRIPLE
|
||||
crate_types="lib,dylib"
|
||||
|
||||
if [[ "$HOST_TRIPLE" != "$TARGET_TRIPLE" ]]; then
|
||||
crate_types="lib"
|
||||
fi
|
||||
|
||||
$RUST_CMD example/mini_core.rs --crate-name mini_core --crate-type $crate_types --target $TARGET_TRIPLE
|
||||
|
||||
echo "[BUILD] example"
|
||||
$RUSTC example/example.rs --crate-type lib --target $TARGET_TRIPLE
|
||||
$RUST_CMD 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
|
||||
$RUST_CMD example/mini_core_hello_world.rs --crate-name mini_core_hello_world --crate-type bin -g --target $TARGET_TRIPLE
|
||||
$RUN_WRAPPER $cargo_target_dir/mini_core_hello_world abc bcd
|
||||
}
|
||||
|
||||
function build_sysroot() {
|
||||
|
|
@ -166,41 +196,61 @@ function build_sysroot() {
|
|||
time ./build_sysroot/build_sysroot.sh $sysroot_channel
|
||||
}
|
||||
|
||||
# TODO(GuillaumeGomez): when rewriting in Rust, refactor with the code in tests/lang_tests_common.rs if possible.
|
||||
function run_in_vm() {
|
||||
vm_parent_dir=${CG_GCC_VM_DIR:-$(pwd)}
|
||||
vm_dir=vm
|
||||
exe=$1
|
||||
exe_filename=$(basename $exe)
|
||||
vm_home_dir=$vm_parent_dir/$vm_dir/home
|
||||
vm_exe_path=$vm_home_dir/$exe_filename
|
||||
inside_vm_exe_path=/home/$exe_filename
|
||||
sudo cp $exe $vm_exe_path
|
||||
|
||||
shift
|
||||
pushd $vm_parent_dir
|
||||
sudo chroot $vm_dir qemu-m68k-static $inside_vm_exe_path $@
|
||||
popd
|
||||
}
|
||||
|
||||
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
|
||||
$RUST_CMD example/arbitrary_self_types_pointers_and_wrappers.rs --crate-name arbitrary_self_types_pointers_and_wrappers --crate-type bin --target $TARGET_TRIPLE
|
||||
$RUN_WRAPPER $cargo_target_dir/arbitrary_self_types_pointers_and_wrappers
|
||||
|
||||
echo "[AOT] alloc_system"
|
||||
$RUSTC example/alloc_system.rs --crate-type lib --target "$TARGET_TRIPLE"
|
||||
$RUST_CMD 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
|
||||
# FIXME: doesn't work on m68k.
|
||||
if [[ "$HOST_TRIPLE" == "$TARGET_TRIPLE" ]]; then
|
||||
echo "[AOT] alloc_example"
|
||||
$RUST_CMD example/alloc_example.rs --crate-type bin --target $TARGET_TRIPLE
|
||||
$RUN_WRAPPER $cargo_target_dir/alloc_example
|
||||
fi
|
||||
|
||||
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)
|
||||
$RUST_CMD example/dst-field-align.rs --crate-name dst_field_align --crate-type bin --target $TARGET_TRIPLE
|
||||
$RUN_WRAPPER $cargo_target_dir/dst_field_align || (echo $?; false)
|
||||
|
||||
echo "[AOT] std_example"
|
||||
std_flags="--cfg feature=\"master\""
|
||||
if (( $gcc_master_branch == 0 )); then
|
||||
std_flags=""
|
||||
fi
|
||||
$RUSTC example/std_example.rs --crate-type bin --target $TARGET_TRIPLE $std_flags
|
||||
$RUN_WRAPPER ./target/out/std_example --target $TARGET_TRIPLE
|
||||
$RUST_CMD example/std_example.rs --crate-type bin --target $TARGET_TRIPLE $std_flags
|
||||
$RUN_WRAPPER $cargo_target_dir/std_example --target $TARGET_TRIPLE
|
||||
|
||||
echo "[AOT] subslice-patterns-const-eval"
|
||||
$RUSTC example/subslice-patterns-const-eval.rs --crate-type bin $TEST_FLAGS --target $TARGET_TRIPLE
|
||||
$RUN_WRAPPER ./target/out/subslice-patterns-const-eval
|
||||
$RUST_CMD example/subslice-patterns-const-eval.rs --crate-type bin $TEST_FLAGS --target $TARGET_TRIPLE
|
||||
$RUN_WRAPPER $cargo_target_dir/subslice-patterns-const-eval
|
||||
|
||||
echo "[AOT] track-caller-attribute"
|
||||
$RUSTC example/track-caller-attribute.rs --crate-type bin $TEST_FLAGS --target $TARGET_TRIPLE
|
||||
$RUN_WRAPPER ./target/out/track-caller-attribute
|
||||
$RUST_CMD example/track-caller-attribute.rs --crate-type bin $TEST_FLAGS --target $TARGET_TRIPLE
|
||||
$RUN_WRAPPER $cargo_target_dir/track-caller-attribute
|
||||
|
||||
echo "[BUILD] mod_bench"
|
||||
$RUSTC example/mod_bench.rs --crate-type bin --target $TARGET_TRIPLE
|
||||
$RUST_CMD example/mod_bench.rs --crate-type bin --target $TARGET_TRIPLE
|
||||
}
|
||||
|
||||
function setup_rustc() {
|
||||
|
|
@ -209,7 +259,7 @@ function setup_rustc() {
|
|||
git clone https://github.com/rust-lang/rust.git || true
|
||||
cd rust
|
||||
git fetch
|
||||
git checkout $(rustc -V | cut -d' ' -f3 | tr -d '(')
|
||||
git checkout $($RUSTC -V | cut -d' ' -f3 | tr -d '(')
|
||||
export RUSTFLAGS=
|
||||
|
||||
rm config.toml || true
|
||||
|
|
@ -225,7 +275,7 @@ verbose-tests = true
|
|||
[build]
|
||||
cargo = "$(rustup which cargo)"
|
||||
local-rebuild = true
|
||||
rustc = "$HOME/.rustup/toolchains/$rust_toolchain-$TARGET_TRIPLE/bin/rustc"
|
||||
rustc = "$HOME/.rustup/toolchains/$rust_toolchain-$HOST_TRIPLE/bin/rustc"
|
||||
|
||||
[target.x86_64-unknown-linux-gnu]
|
||||
llvm-filecheck = "`which FileCheck-10 || which FileCheck-11 || which FileCheck-12 || which FileCheck-13 || which FileCheck-14`"
|
||||
|
|
@ -234,8 +284,8 @@ llvm-filecheck = "`which FileCheck-10 || which FileCheck-11 || which FileCheck-1
|
|||
download-ci-llvm = false
|
||||
EOF
|
||||
|
||||
rustc -V | cut -d' ' -f3 | tr -d '('
|
||||
git checkout $(rustc -V | cut -d' ' -f3 | tr -d '(') tests
|
||||
$RUSTC -V | cut -d' ' -f3 | tr -d '('
|
||||
git checkout $($RUSTC -V | cut -d' ' -f3 | tr -d '(') tests
|
||||
}
|
||||
|
||||
function asm_tests() {
|
||||
|
|
@ -262,17 +312,17 @@ function test_libcore() {
|
|||
#echo "[BENCH COMPILE] mod_bench"
|
||||
|
||||
#COMPILE_MOD_BENCH_INLINE="$RUSTC example/mod_bench.rs --crate-type bin -Zmir-opt-level=3 -O --crate-name mod_bench_inline"
|
||||
#COMPILE_MOD_BENCH_LLVM_0="rustc example/mod_bench.rs --crate-type bin -Copt-level=0 -o target/out/mod_bench_llvm_0 -Cpanic=abort"
|
||||
#COMPILE_MOD_BENCH_LLVM_1="rustc example/mod_bench.rs --crate-type bin -Copt-level=1 -o target/out/mod_bench_llvm_1 -Cpanic=abort"
|
||||
#COMPILE_MOD_BENCH_LLVM_2="rustc example/mod_bench.rs --crate-type bin -Copt-level=2 -o target/out/mod_bench_llvm_2 -Cpanic=abort"
|
||||
#COMPILE_MOD_BENCH_LLVM_3="rustc example/mod_bench.rs --crate-type bin -Copt-level=3 -o target/out/mod_bench_llvm_3 -Cpanic=abort"
|
||||
#COMPILE_MOD_BENCH_LLVM_0="rustc example/mod_bench.rs --crate-type bin -Copt-level=0 -o $cargo_target_dir/mod_bench_llvm_0 -Cpanic=abort"
|
||||
#COMPILE_MOD_BENCH_LLVM_1="rustc example/mod_bench.rs --crate-type bin -Copt-level=1 -o $cargo_target_dir/mod_bench_llvm_1 -Cpanic=abort"
|
||||
#COMPILE_MOD_BENCH_LLVM_2="rustc example/mod_bench.rs --crate-type bin -Copt-level=2 -o $cargo_target_dir/mod_bench_llvm_2 -Cpanic=abort"
|
||||
#COMPILE_MOD_BENCH_LLVM_3="rustc example/mod_bench.rs --crate-type bin -Copt-level=3 -o $cargo_target_dir/mod_bench_llvm_3 -Cpanic=abort"
|
||||
|
||||
## Use 100 runs, because a single compilations doesn't take more than ~150ms, so it isn't very slow
|
||||
#hyperfine --runs ${COMPILE_RUNS:-100} "$COMPILE_MOD_BENCH_INLINE" "$COMPILE_MOD_BENCH_LLVM_0" "$COMPILE_MOD_BENCH_LLVM_1" "$COMPILE_MOD_BENCH_LLVM_2" "$COMPILE_MOD_BENCH_LLVM_3"
|
||||
|
||||
#echo
|
||||
#echo "[BENCH RUN] mod_bench"
|
||||
#hyperfine --runs ${RUN_RUNS:-10} ./target/out/mod_bench{,_inline} ./target/out/mod_bench_llvm_*
|
||||
#hyperfine --runs ${RUN_RUNS:-10} $cargo_target_dir/mod_bench{,_inline} $cargo_target_dir/mod_bench_llvm_*
|
||||
|
||||
function extended_rand_tests() {
|
||||
if (( $gcc_master_branch == 0 )); then
|
||||
|
|
@ -347,10 +397,10 @@ function test_rustc() {
|
|||
|
||||
git checkout -- tests/ui/issues/auxiliary/issue-3136-a.rs # contains //~ERROR, but shouldn't be removed
|
||||
|
||||
rm -r tests/ui/{abi*,extern/,unsized-locals/,proc-macro/,threads-sendsync/,thinlto/,borrowck/,chalkify/bugs/,test*,consts/const-float-bits-reject-conv.rs,consts/issue-miri-1910.rs} || true
|
||||
rm -r tests/ui/{abi*,extern/,unsized-locals/,proc-macro/,threads-sendsync/,borrowck/,test*,consts/issue-miri-1910.rs} || true
|
||||
rm tests/ui/mir/mir_heavy_promoted.rs # this test is oom-killed in the CI.
|
||||
# Tests generating errors.
|
||||
rm tests/ui/consts/const-eval/nonnull_as_ref_ub.rs tests/ui/consts/issue-94675.rs
|
||||
rm tests/ui/consts/issue-94675.rs
|
||||
for test in $(rg --files-with-matches "thread" tests/ui); do
|
||||
rm $test
|
||||
done
|
||||
|
|
@ -393,7 +443,7 @@ function test_rustc() {
|
|||
fi
|
||||
|
||||
echo "[TEST] rustc test suite"
|
||||
COMPILETEST_FORCE_STAGE0=1 ./x.py test --run always --stage 0 tests/ui/ --rustc-args "$RUSTC_ARGS"
|
||||
COMPILETEST_FORCE_STAGE0=1 ./x.py test --run always --stage 0 tests/ui/ --rustc-args "$RUSTC_ARGS" # --target $TARGET_TRIPLE
|
||||
}
|
||||
|
||||
function test_failing_rustc() {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
//! The common code for `tests/lang_tests_*.rs`
|
||||
use std::{
|
||||
env::{self, current_dir},
|
||||
path::PathBuf,
|
||||
path::{Path, PathBuf},
|
||||
process::Command,
|
||||
};
|
||||
|
||||
|
|
@ -23,9 +23,29 @@ pub fn main_inner(profile: Profile) {
|
|||
let gcc_path = include_str!("../gcc_path");
|
||||
let gcc_path = gcc_path.trim();
|
||||
env::set_var("LD_LIBRARY_PATH", gcc_path);
|
||||
|
||||
fn rust_filter(filename: &Path) -> bool {
|
||||
filename.extension().expect("extension").to_str().expect("to_str") == "rs"
|
||||
}
|
||||
|
||||
#[cfg(feature="master")]
|
||||
fn filter(filename: &Path) -> bool {
|
||||
rust_filter(filename)
|
||||
}
|
||||
|
||||
#[cfg(not(feature="master"))]
|
||||
fn filter(filename: &Path) -> bool {
|
||||
if let Some(filename) = filename.to_str() {
|
||||
if filename.ends_with("gep.rs") {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
rust_filter(filename)
|
||||
}
|
||||
|
||||
LangTester::new()
|
||||
.test_dir("tests/run")
|
||||
.test_file_filter(|path| path.extension().expect("extension").to_str().expect("to_str") == "rs")
|
||||
.test_file_filter(filter)
|
||||
.test_extract(|source| {
|
||||
let lines =
|
||||
source.lines()
|
||||
|
|
@ -50,6 +70,19 @@ pub fn main_inner(profile: Profile) {
|
|||
"-o", exe.to_str().expect("to_str"),
|
||||
path.to_str().expect("to_str"),
|
||||
]);
|
||||
|
||||
// TODO(antoyo): find a way to send this via a cli argument.
|
||||
let test_target = std::env::var("CG_GCC_TEST_TARGET");
|
||||
if let Ok(ref target) = test_target {
|
||||
compiler.args(&["--target", &target]);
|
||||
let linker = format!("{}-gcc", target);
|
||||
compiler.args(&[format!("-Clinker={}", linker)]);
|
||||
let mut env_path = std::env::var("PATH").unwrap_or_default();
|
||||
// TODO(antoyo): find a better way to add the PATH necessary locally.
|
||||
env_path = format!("/opt/m68k-unknown-linux-gnu/bin:{}", env_path);
|
||||
compiler.env("PATH", env_path);
|
||||
}
|
||||
|
||||
if let Some(flags) = option_env!("TEST_FLAGS") {
|
||||
for flag in flags.split_whitespace() {
|
||||
compiler.arg(&flag);
|
||||
|
|
@ -65,8 +98,37 @@ pub fn main_inner(profile: Profile) {
|
|||
}
|
||||
}
|
||||
// Test command 2: run `tempdir/x`.
|
||||
let runtime = Command::new(exe);
|
||||
vec![("Compiler", compiler), ("Run-time", runtime)]
|
||||
if test_target.is_ok() {
|
||||
let vm_parent_dir = std::env::var("CG_GCC_VM_DIR")
|
||||
.map(|dir| PathBuf::from(dir))
|
||||
.unwrap_or_else(|_| std::env::current_dir().unwrap());
|
||||
let vm_dir = "vm";
|
||||
let exe_filename = exe.file_name().unwrap();
|
||||
let vm_home_dir = vm_parent_dir.join(vm_dir).join("home");
|
||||
let vm_exe_path = vm_home_dir.join(exe_filename);
|
||||
// FIXME(antoyo): panicking here makes the test pass.
|
||||
let inside_vm_exe_path = PathBuf::from("/home").join(&exe_filename);
|
||||
let mut copy = Command::new("sudo");
|
||||
copy.arg("cp");
|
||||
copy.args(&[&exe, &vm_exe_path]);
|
||||
|
||||
let mut runtime = Command::new("sudo");
|
||||
runtime.args(&["chroot", vm_dir, "qemu-m68k-static"]);
|
||||
runtime.arg(inside_vm_exe_path);
|
||||
runtime.current_dir(vm_parent_dir);
|
||||
vec![
|
||||
("Compiler", compiler),
|
||||
("Copy", copy),
|
||||
("Run-time", runtime),
|
||||
]
|
||||
}
|
||||
else {
|
||||
let runtime = Command::new(exe);
|
||||
vec![
|
||||
("Compiler", compiler),
|
||||
("Run-time", runtime),
|
||||
]
|
||||
}
|
||||
})
|
||||
.run();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,8 +5,10 @@
|
|||
|
||||
#![feature(asm_const)]
|
||||
|
||||
#[cfg(target_arch="x86_64")]
|
||||
use std::arch::{asm, global_asm};
|
||||
|
||||
#[cfg(target_arch="x86_64")]
|
||||
global_asm!(
|
||||
"
|
||||
.global add_asm
|
||||
|
|
@ -20,6 +22,7 @@ extern "C" {
|
|||
fn add_asm(a: i64, b: i64) -> i64;
|
||||
}
|
||||
|
||||
#[cfg(target_arch="x86_64")]
|
||||
pub unsafe fn mem_cpy(dst: *mut u8, src: *const u8, len: usize) {
|
||||
asm!(
|
||||
"rep movsb",
|
||||
|
|
@ -30,7 +33,8 @@ pub unsafe fn mem_cpy(dst: *mut u8, src: *const u8, len: usize) {
|
|||
);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
#[cfg(target_arch="x86_64")]
|
||||
fn asm() {
|
||||
unsafe {
|
||||
asm!("nop");
|
||||
}
|
||||
|
|
@ -173,3 +177,11 @@ fn main() {
|
|||
}
|
||||
assert_eq!(array1, array2);
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch="x86_64"))]
|
||||
fn asm() {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
asm();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,6 +35,6 @@ pub(crate) unsafe auto trait Freeze {}
|
|||
*/
|
||||
|
||||
#[start]
|
||||
fn main(mut argc: isize, _argv: *const *const u8) -> isize {
|
||||
fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
||||
0
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,138 +4,20 @@
|
|||
// stdout: Success
|
||||
// status: signal
|
||||
|
||||
#![allow(internal_features, unused_attributes)]
|
||||
#![feature(auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs)]
|
||||
fn main() {
|
||||
std::panic::set_hook(Box::new(|_| {
|
||||
println!("Success");
|
||||
std::process::abort();
|
||||
}));
|
||||
|
||||
#![no_std]
|
||||
#![no_core]
|
||||
|
||||
/*
|
||||
* Core
|
||||
*/
|
||||
|
||||
// Because we don't have core yet.
|
||||
#[lang = "sized"]
|
||||
pub trait Sized {}
|
||||
|
||||
#[lang = "copy"]
|
||||
trait Copy {
|
||||
}
|
||||
|
||||
impl Copy for isize {}
|
||||
impl Copy for *mut i32 {}
|
||||
impl Copy for usize {}
|
||||
impl Copy for i32 {}
|
||||
impl Copy for u8 {}
|
||||
impl Copy for i8 {}
|
||||
|
||||
#[lang = "receiver"]
|
||||
trait Receiver {
|
||||
}
|
||||
|
||||
#[lang = "freeze"]
|
||||
pub(crate) unsafe auto trait Freeze {}
|
||||
|
||||
#[lang = "panic_location"]
|
||||
struct PanicLocation {
|
||||
file: &'static str,
|
||||
line: u32,
|
||||
column: u32,
|
||||
}
|
||||
|
||||
mod libc {
|
||||
#[link(name = "c")]
|
||||
extern "C" {
|
||||
pub fn puts(s: *const u8) -> i32;
|
||||
pub fn fflush(stream: *mut i32) -> i32;
|
||||
|
||||
pub static stdout: *mut i32;
|
||||
}
|
||||
}
|
||||
|
||||
mod intrinsics {
|
||||
extern "rust-intrinsic" {
|
||||
#[rustc_safe_intrinsic]
|
||||
pub fn abort() -> !;
|
||||
}
|
||||
}
|
||||
|
||||
#[lang = "panic"]
|
||||
#[track_caller]
|
||||
#[no_mangle]
|
||||
pub fn panic(_msg: &'static str) -> ! {
|
||||
unsafe {
|
||||
// Panicking is expected iff overflow checking is enabled.
|
||||
#[cfg(debug_assertions)]
|
||||
libc::puts("Success\0" as *const str as *const u8);
|
||||
libc::fflush(libc::stdout);
|
||||
intrinsics::abort();
|
||||
}
|
||||
}
|
||||
|
||||
#[lang = "add"]
|
||||
trait Add<RHS = Self> {
|
||||
type Output;
|
||||
|
||||
fn add(self, rhs: RHS) -> Self::Output;
|
||||
}
|
||||
|
||||
impl Add for u8 {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: Self) -> Self {
|
||||
self + rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for i8 {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: Self) -> Self {
|
||||
self + rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for i32 {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: Self) -> Self {
|
||||
self + rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for usize {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: Self) -> Self {
|
||||
self + rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for isize {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: Self) -> Self {
|
||||
self + rhs
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Code
|
||||
*/
|
||||
|
||||
#[start]
|
||||
fn main(mut argc: isize, _argv: *const *const u8) -> isize {
|
||||
let int = 9223372036854775807isize;
|
||||
let int = int + argc; // overflow
|
||||
let arg_count = std::env::args().count();
|
||||
let int = isize::MAX;
|
||||
let _int = int + arg_count as isize; // overflow
|
||||
|
||||
// If overflow checking is disabled, we should reach here.
|
||||
#[cfg(not(debug_assertions))]
|
||||
unsafe {
|
||||
libc::puts("Success\0" as *const str as *const u8);
|
||||
libc::fflush(libc::stdout);
|
||||
intrinsics::abort();
|
||||
println!("Success");
|
||||
std::process::abort();
|
||||
}
|
||||
|
||||
int
|
||||
}
|
||||
|
|
|
|||
26
compiler/rustc_codegen_gcc/tests/run/volatile.rs
Normal file
26
compiler/rustc_codegen_gcc/tests/run/volatile.rs
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
// Compiler:
|
||||
//
|
||||
// Run-time:
|
||||
// status: 0
|
||||
|
||||
use std::mem::MaybeUninit;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Struct {
|
||||
pointer: *const (),
|
||||
func: unsafe fn(*const ()),
|
||||
}
|
||||
|
||||
fn func(ptr: *const ()) {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut x = MaybeUninit::<&Struct>::uninit();
|
||||
x.write(&Struct {
|
||||
pointer: std::ptr::null(),
|
||||
func,
|
||||
});
|
||||
let x = unsafe { x.assume_init() };
|
||||
let value = unsafe { (x as *const Struct).read_volatile() };
|
||||
println!("{:?}", value);
|
||||
}
|
||||
|
|
@ -7,18 +7,15 @@ edition = "2021"
|
|||
test = false
|
||||
|
||||
[dependencies]
|
||||
# tidy-alphabetical-start
|
||||
bitflags = "1.0"
|
||||
cstr = "0.2"
|
||||
itertools = "0.10.5"
|
||||
libc = "0.2"
|
||||
measureme = "10.0.0"
|
||||
object = { version = "0.32.0", default-features = false, features = [
|
||||
"std",
|
||||
"read",
|
||||
] }
|
||||
tracing = "0.1"
|
||||
rustc_middle = { path = "../rustc_middle" }
|
||||
object = { version = "0.32.0", default-features = false, features = ["std", "read"] }
|
||||
rustc-demangle = "0.1.21"
|
||||
rustc_ast = { path = "../rustc_ast" }
|
||||
rustc_attr = { path = "../rustc_attr" }
|
||||
rustc_codegen_ssa = { path = "../rustc_codegen_ssa" }
|
||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
|
|
@ -30,12 +27,14 @@ rustc_index = { path = "../rustc_index" }
|
|||
rustc_llvm = { path = "../rustc_llvm" }
|
||||
rustc_macros = { path = "../rustc_macros" }
|
||||
rustc_metadata = { path = "../rustc_metadata" }
|
||||
rustc_middle = { path = "../rustc_middle" }
|
||||
rustc_query_system = { path = "../rustc_query_system" }
|
||||
rustc_session = { path = "../rustc_session" }
|
||||
rustc_span = { path = "../rustc_span" }
|
||||
rustc_symbol_mangling = { path = "../rustc_symbol_mangling" }
|
||||
rustc_target = { path = "../rustc_target" }
|
||||
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
|
||||
rustc_ast = { path = "../rustc_ast" }
|
||||
rustc_span = { path = "../rustc_span" }
|
||||
serde = { version = "1", features = [ "derive" ]}
|
||||
serde_json = "1"
|
||||
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
|
||||
tracing = "0.1"
|
||||
# tidy-alphabetical-end
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ impl<'tcx> FunctionCoverageCollector<'tcx> {
|
|||
// have zero as both of their operands, and will therefore always have
|
||||
// a value of zero. Other expressions that refer to these as operands
|
||||
// can have those operands replaced with `CovTerm::Zero`.
|
||||
let mut zero_expressions = FxIndexSet::default();
|
||||
let mut zero_expressions = ZeroExpressions::default();
|
||||
|
||||
// Simplify a copy of each expression based on lower-numbered expressions,
|
||||
// and then update the set of always-zero expressions if necessary.
|
||||
|
|
@ -131,16 +131,16 @@ impl<'tcx> FunctionCoverageCollector<'tcx> {
|
|||
)
|
||||
};
|
||||
|
||||
// If an operand refers to an expression that is always zero, then
|
||||
// that operand can be replaced with `CovTerm::Zero`.
|
||||
let maybe_set_operand_to_zero = |operand: &mut CovTerm| match *operand {
|
||||
CovTerm::Expression(id) => {
|
||||
// If an operand refers to a counter or expression that is always
|
||||
// zero, then that operand can be replaced with `CovTerm::Zero`.
|
||||
let maybe_set_operand_to_zero = |operand: &mut CovTerm| {
|
||||
if let CovTerm::Expression(id) = *operand {
|
||||
assert_operand_expression_is_lower(id);
|
||||
if zero_expressions.contains(&id) {
|
||||
*operand = CovTerm::Zero;
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
|
||||
if is_zero_term(&self.counters_seen, &zero_expressions, *operand) {
|
||||
*operand = CovTerm::Zero;
|
||||
}
|
||||
};
|
||||
maybe_set_operand_to_zero(&mut lhs);
|
||||
maybe_set_operand_to_zero(&mut rhs);
|
||||
|
|
@ -159,7 +159,7 @@ impl<'tcx> FunctionCoverageCollector<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
ZeroExpressions(zero_expressions)
|
||||
zero_expressions
|
||||
}
|
||||
|
||||
pub(crate) fn into_finished(self) -> FunctionCoverage<'tcx> {
|
||||
|
|
@ -205,19 +205,14 @@ impl<'tcx> FunctionCoverage<'tcx> {
|
|||
// thing on the Rust side unless we're confident we can do much better.
|
||||
// (See `CounterExpressionsMinimizer` in `CoverageMappingWriter.cpp`.)
|
||||
|
||||
let counter_from_operand = |operand: CovTerm| match operand {
|
||||
CovTerm::Expression(id) if self.zero_expressions.contains(id) => Counter::ZERO,
|
||||
_ => Counter::from_term(operand),
|
||||
};
|
||||
|
||||
self.function_coverage_info.expressions.iter().map(move |&Expression { lhs, op, rhs }| {
|
||||
CounterExpression {
|
||||
lhs: counter_from_operand(lhs),
|
||||
lhs: self.counter_for_term(lhs),
|
||||
kind: match op {
|
||||
Op::Add => ExprKind::Add,
|
||||
Op::Subtract => ExprKind::Subtract,
|
||||
},
|
||||
rhs: counter_from_operand(rhs),
|
||||
rhs: self.counter_for_term(rhs),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
@ -227,34 +222,49 @@ impl<'tcx> FunctionCoverage<'tcx> {
|
|||
pub(crate) fn counter_regions(
|
||||
&self,
|
||||
) -> impl Iterator<Item = (Counter, &CodeRegion)> + ExactSizeIterator {
|
||||
// Historically, mappings were stored directly in counter/expression
|
||||
// statements in MIR, and MIR optimizations would sometimes remove them.
|
||||
// That's mostly no longer true, so now we detect cases where that would
|
||||
// have happened, and zero out the corresponding mappings here instead.
|
||||
let counter_for_term = move |term: CovTerm| {
|
||||
let force_to_zero = match term {
|
||||
CovTerm::Counter(id) => !self.counters_seen.contains(id),
|
||||
CovTerm::Expression(id) => self.zero_expressions.contains(id),
|
||||
CovTerm::Zero => false,
|
||||
};
|
||||
if force_to_zero { Counter::ZERO } else { Counter::from_term(term) }
|
||||
};
|
||||
|
||||
self.function_coverage_info.mappings.iter().map(move |mapping| {
|
||||
let &Mapping { term, ref code_region } = mapping;
|
||||
let counter = counter_for_term(term);
|
||||
let counter = self.counter_for_term(term);
|
||||
(counter, code_region)
|
||||
})
|
||||
}
|
||||
|
||||
fn counter_for_term(&self, term: CovTerm) -> Counter {
|
||||
if is_zero_term(&self.counters_seen, &self.zero_expressions, term) {
|
||||
Counter::ZERO
|
||||
} else {
|
||||
Counter::from_term(term)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Set of expression IDs that are known to always evaluate to zero.
|
||||
/// Any mapping or expression operand that refers to these expressions can have
|
||||
/// that reference replaced with a constant zero value.
|
||||
#[derive(Default)]
|
||||
struct ZeroExpressions(FxIndexSet<ExpressionId>);
|
||||
|
||||
impl ZeroExpressions {
|
||||
fn insert(&mut self, id: ExpressionId) {
|
||||
self.0.insert(id);
|
||||
}
|
||||
|
||||
fn contains(&self, id: ExpressionId) -> bool {
|
||||
self.0.contains(&id)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if the given term is known to have a value of zero, taking
|
||||
/// into account knowledge of which counters are unused and which expressions
|
||||
/// are always zero.
|
||||
fn is_zero_term(
|
||||
counters_seen: &BitSet<CounterId>,
|
||||
zero_expressions: &ZeroExpressions,
|
||||
term: CovTerm,
|
||||
) -> bool {
|
||||
match term {
|
||||
CovTerm::Zero => true,
|
||||
CovTerm::Counter(id) => !counters_seen.contains(id),
|
||||
CovTerm::Expression(id) => zero_expressions.contains(id),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -935,9 +935,10 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
}
|
||||
|
||||
macro_rules! require_simd {
|
||||
($ty: expr, $diag: expr) => {
|
||||
require!($ty.is_simd(), $diag)
|
||||
};
|
||||
($ty: expr, $variant:ident) => {{
|
||||
require!($ty.is_simd(), InvalidMonomorphization::$variant { span, name, ty: $ty });
|
||||
$ty.simd_size_and_type(bx.tcx())
|
||||
}};
|
||||
}
|
||||
|
||||
let tcx = bx.tcx();
|
||||
|
|
@ -946,12 +947,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
let arg_tys = sig.inputs();
|
||||
|
||||
if name == sym::simd_select_bitmask {
|
||||
require_simd!(
|
||||
arg_tys[1],
|
||||
InvalidMonomorphization::SimdArgument { span, name, ty: arg_tys[1] }
|
||||
);
|
||||
|
||||
let (len, _) = arg_tys[1].simd_size_and_type(bx.tcx());
|
||||
let (len, _) = require_simd!(arg_tys[1], SimdArgument);
|
||||
|
||||
let expected_int_bits = (len.max(8) - 1).next_power_of_two();
|
||||
let expected_bytes = len / 8 + ((len % 8 > 0) as u64);
|
||||
|
|
@ -988,7 +984,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
}
|
||||
|
||||
// every intrinsic below takes a SIMD vector as its first argument
|
||||
require_simd!(arg_tys[0], InvalidMonomorphization::SimdInput { span, name, ty: arg_tys[0] });
|
||||
let (in_len, in_elem) = require_simd!(arg_tys[0], SimdInput);
|
||||
let in_ty = arg_tys[0];
|
||||
|
||||
let comparison = match name {
|
||||
|
|
@ -1001,11 +997,8 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
_ => None,
|
||||
};
|
||||
|
||||
let (in_len, in_elem) = arg_tys[0].simd_size_and_type(bx.tcx());
|
||||
if let Some(cmp_op) = comparison {
|
||||
require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });
|
||||
|
||||
let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx());
|
||||
let (out_len, out_ty) = require_simd!(ret_ty, SimdReturn);
|
||||
|
||||
require!(
|
||||
in_len == out_len,
|
||||
|
|
@ -1041,8 +1034,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
.unwrap_branch();
|
||||
let n = idx.len() as u64;
|
||||
|
||||
require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });
|
||||
let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx());
|
||||
let (out_len, out_ty) = require_simd!(ret_ty, SimdReturn);
|
||||
require!(
|
||||
out_len == n,
|
||||
InvalidMonomorphization::ReturnLength { span, name, in_len: n, ret_ty, out_len }
|
||||
|
|
@ -1099,8 +1091,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
}),
|
||||
};
|
||||
|
||||
require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });
|
||||
let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx());
|
||||
let (out_len, out_ty) = require_simd!(ret_ty, SimdReturn);
|
||||
require!(
|
||||
out_len == n,
|
||||
InvalidMonomorphization::ReturnLength { span, name, in_len: n, ret_ty, out_len }
|
||||
|
|
@ -1179,11 +1170,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
if name == sym::simd_select {
|
||||
let m_elem_ty = in_elem;
|
||||
let m_len = in_len;
|
||||
require_simd!(
|
||||
arg_tys[1],
|
||||
InvalidMonomorphization::SimdArgument { span, name, ty: arg_tys[1] }
|
||||
);
|
||||
let (v_len, _) = arg_tys[1].simd_size_and_type(bx.tcx());
|
||||
let (v_len, _) = require_simd!(arg_tys[1], SimdArgument);
|
||||
require!(
|
||||
m_len == v_len,
|
||||
InvalidMonomorphization::MismatchedLengths { span, name, m_len, v_len }
|
||||
|
|
@ -1401,20 +1388,16 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
// * M: any integer width is supported, will be truncated to i1
|
||||
|
||||
// All types must be simd vector types
|
||||
require_simd!(in_ty, InvalidMonomorphization::SimdFirst { span, name, ty: in_ty });
|
||||
require_simd!(
|
||||
arg_tys[1],
|
||||
InvalidMonomorphization::SimdSecond { span, name, ty: arg_tys[1] }
|
||||
);
|
||||
require_simd!(
|
||||
arg_tys[2],
|
||||
InvalidMonomorphization::SimdThird { span, name, ty: arg_tys[2] }
|
||||
);
|
||||
require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });
|
||||
|
||||
// The second argument must be a simd vector with an element type that's a pointer
|
||||
// to the element type of the first argument
|
||||
let (_, element_ty0) = require_simd!(in_ty, SimdFirst);
|
||||
let (out_len, element_ty1) = require_simd!(arg_tys[1], SimdSecond);
|
||||
// The element type of the third argument must be a signed integer type of any width:
|
||||
let (out_len2, element_ty2) = require_simd!(arg_tys[2], SimdThird);
|
||||
require_simd!(ret_ty, SimdReturn);
|
||||
|
||||
// Of the same length:
|
||||
let (out_len, _) = arg_tys[1].simd_size_and_type(bx.tcx());
|
||||
let (out_len2, _) = arg_tys[2].simd_size_and_type(bx.tcx());
|
||||
require!(
|
||||
in_len == out_len,
|
||||
InvalidMonomorphization::SecondArgumentLength {
|
||||
|
|
@ -1444,11 +1427,6 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
InvalidMonomorphization::ExpectedReturnType { span, name, in_ty, ret_ty }
|
||||
);
|
||||
|
||||
// The second argument must be a simd vector with an element type that's a pointer
|
||||
// to the element type of the first argument
|
||||
let (_, element_ty0) = arg_tys[0].simd_size_and_type(bx.tcx());
|
||||
let (_, element_ty1) = arg_tys[1].simd_size_and_type(bx.tcx());
|
||||
|
||||
require!(
|
||||
matches!(
|
||||
element_ty1.kind(),
|
||||
|
|
@ -1465,20 +1443,15 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
}
|
||||
);
|
||||
|
||||
// The element type of the third argument must be a signed integer type of any width:
|
||||
let (_, element_ty2) = arg_tys[2].simd_size_and_type(bx.tcx());
|
||||
match element_ty2.kind() {
|
||||
ty::Int(_) => (),
|
||||
_ => {
|
||||
require!(
|
||||
false,
|
||||
InvalidMonomorphization::ThirdArgElementType {
|
||||
span,
|
||||
name,
|
||||
expected_element: element_ty2,
|
||||
third_arg: arg_tys[2]
|
||||
}
|
||||
);
|
||||
return_error!(InvalidMonomorphization::ThirdArgElementType {
|
||||
span,
|
||||
name,
|
||||
expected_element: element_ty2,
|
||||
third_arg: arg_tys[2]
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1527,19 +1500,13 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
// * M: any integer width is supported, will be truncated to i1
|
||||
|
||||
// All types must be simd vector types
|
||||
require_simd!(in_ty, InvalidMonomorphization::SimdFirst { span, name, ty: in_ty });
|
||||
require_simd!(
|
||||
arg_tys[1],
|
||||
InvalidMonomorphization::SimdSecond { span, name, ty: arg_tys[1] }
|
||||
);
|
||||
require_simd!(
|
||||
arg_tys[2],
|
||||
InvalidMonomorphization::SimdThird { span, name, ty: arg_tys[2] }
|
||||
);
|
||||
// The second argument must be a simd vector with an element type that's a pointer
|
||||
// to the element type of the first argument
|
||||
let (_, element_ty0) = require_simd!(in_ty, SimdFirst);
|
||||
let (element_len1, element_ty1) = require_simd!(arg_tys[1], SimdSecond);
|
||||
let (element_len2, element_ty2) = require_simd!(arg_tys[2], SimdThird);
|
||||
|
||||
// Of the same length:
|
||||
let (element_len1, _) = arg_tys[1].simd_size_and_type(bx.tcx());
|
||||
let (element_len2, _) = arg_tys[2].simd_size_and_type(bx.tcx());
|
||||
require!(
|
||||
in_len == element_len1,
|
||||
InvalidMonomorphization::SecondArgumentLength {
|
||||
|
|
@ -1563,12 +1530,6 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
}
|
||||
);
|
||||
|
||||
// The second argument must be a simd vector with an element type that's a pointer
|
||||
// to the element type of the first argument
|
||||
let (_, element_ty0) = arg_tys[0].simd_size_and_type(bx.tcx());
|
||||
let (_, element_ty1) = arg_tys[1].simd_size_and_type(bx.tcx());
|
||||
let (_, element_ty2) = arg_tys[2].simd_size_and_type(bx.tcx());
|
||||
|
||||
require!(
|
||||
matches!(
|
||||
element_ty1.kind(),
|
||||
|
|
@ -1590,15 +1551,12 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
match element_ty2.kind() {
|
||||
ty::Int(_) => (),
|
||||
_ => {
|
||||
require!(
|
||||
false,
|
||||
InvalidMonomorphization::ThirdArgElementType {
|
||||
span,
|
||||
name,
|
||||
expected_element: element_ty2,
|
||||
third_arg: arg_tys[2]
|
||||
}
|
||||
);
|
||||
return_error!(InvalidMonomorphization::ThirdArgElementType {
|
||||
span,
|
||||
name,
|
||||
expected_element: element_ty2,
|
||||
third_arg: arg_tys[2]
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1794,8 +1752,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
bitwise_red!(simd_reduce_any: vector_reduce_or, true);
|
||||
|
||||
if name == sym::simd_cast_ptr {
|
||||
require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });
|
||||
let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx());
|
||||
let (out_len, out_elem) = require_simd!(ret_ty, SimdReturn);
|
||||
require!(
|
||||
in_len == out_len,
|
||||
InvalidMonomorphization::ReturnLengthInputType {
|
||||
|
|
@ -1843,8 +1800,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
}
|
||||
|
||||
if name == sym::simd_expose_addr {
|
||||
require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });
|
||||
let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx());
|
||||
let (out_len, out_elem) = require_simd!(ret_ty, SimdReturn);
|
||||
require!(
|
||||
in_len == out_len,
|
||||
InvalidMonomorphization::ReturnLengthInputType {
|
||||
|
|
@ -1872,8 +1828,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
}
|
||||
|
||||
if name == sym::simd_from_exposed_addr {
|
||||
require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });
|
||||
let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx());
|
||||
let (out_len, out_elem) = require_simd!(ret_ty, SimdReturn);
|
||||
require!(
|
||||
in_len == out_len,
|
||||
InvalidMonomorphization::ReturnLengthInputType {
|
||||
|
|
@ -1901,8 +1856,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
}
|
||||
|
||||
if name == sym::simd_cast || name == sym::simd_as {
|
||||
require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });
|
||||
let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx());
|
||||
let (out_len, out_elem) = require_simd!(ret_ty, SimdReturn);
|
||||
require!(
|
||||
in_len == out_len,
|
||||
InvalidMonomorphization::ReturnLengthInputType {
|
||||
|
|
@ -1989,17 +1943,14 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
}
|
||||
_ => { /* Unsupported. Fallthrough. */ }
|
||||
}
|
||||
require!(
|
||||
false,
|
||||
InvalidMonomorphization::UnsupportedCast {
|
||||
span,
|
||||
name,
|
||||
in_ty,
|
||||
in_elem,
|
||||
ret_ty,
|
||||
out_elem
|
||||
}
|
||||
);
|
||||
return_error!(InvalidMonomorphization::UnsupportedCast {
|
||||
span,
|
||||
name,
|
||||
in_ty,
|
||||
in_elem,
|
||||
ret_ty,
|
||||
out_elem
|
||||
});
|
||||
}
|
||||
macro_rules! arith_binary {
|
||||
($($name: ident: $($($p: ident),* => $call: ident),*;)*) => {
|
||||
|
|
@ -2010,8 +1961,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
})*
|
||||
_ => {},
|
||||
}
|
||||
require!(
|
||||
false,
|
||||
return_error!(
|
||||
InvalidMonomorphization::UnsupportedOperation { span, name, in_ty, in_elem }
|
||||
);
|
||||
})*
|
||||
|
|
@ -2041,8 +1991,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
})*
|
||||
_ => {},
|
||||
}
|
||||
require!(
|
||||
false,
|
||||
return_error!(
|
||||
InvalidMonomorphization::UnsupportedOperation { span, name, in_ty, in_elem }
|
||||
);
|
||||
})*
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue