diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 02:49:42 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 02:49:42 +0000 |
commit | 837b550238aa671a591ccf282dddeab29cadb206 (patch) | |
tree | 914b6b8862bace72bd3245ca184d374b08d8a672 /compiler/rustc_codegen_ssa | |
parent | Adding debian version 1.70.0+dfsg2-1. (diff) | |
download | rustc-837b550238aa671a591ccf282dddeab29cadb206.tar.xz rustc-837b550238aa671a591ccf282dddeab29cadb206.zip |
Merging upstream version 1.71.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_codegen_ssa')
27 files changed, 864 insertions, 433 deletions
diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index c55991e00..0ac12d32b 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -7,15 +7,14 @@ edition = "2021" test = false [dependencies] -ar_archive_writer = "0.1.1" +ar_archive_writer = "0.1.3" bitflags = "1.2.1" cc = "1.0.69" itertools = "0.10.1" tracing = "0.1" -libc = "0.2.50" jobserver = "0.1.22" tempfile = "3.2" -thorin-dwp = "0.4" +thorin-dwp = "0.6" pathdiff = "0.2.0" serde_json = "1.0.59" snap = "1" @@ -29,6 +28,7 @@ rustc_span = { path = "../rustc_span" } rustc_middle = { path = "../rustc_middle" } rustc_type_ir = { path = "../rustc_type_ir" } rustc_attr = { path = "../rustc_attr" } +rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_symbol_mangling = { path = "../rustc_symbol_mangling" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } @@ -42,7 +42,14 @@ rustc_query_system = { path = "../rustc_query_system" } rustc_target = { path = "../rustc_target" } rustc_session = { path = "../rustc_session" } +[target.'cfg(unix)'.dependencies] +libc = "0.2.50" + [dependencies.object] -version = "0.30.1" +version = "0.31.1" default-features = false features = ["read_core", "elf", "macho", "pe", "unaligned", "archive", "write"] + +[target.'cfg(windows)'.dependencies.windows] +version = "0.48.0" +features = ["Win32_Globalization"] diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl index 243be0e1f..9aa2b2e2b 100644 --- a/compiler/rustc_codegen_ssa/messages.ftl +++ b/compiler/rustc_codegen_ssa/messages.ftl @@ -1,293 +1,306 @@ -codegen_ssa_lib_def_write_failure = failed to write lib.def file: {$error} - -codegen_ssa_version_script_write_failure = failed to write version script: {$error} +codegen_ssa_L4Bender_exporting_symbols_unimplemented = exporting symbols not implemented yet for L4Bender -codegen_ssa_symbol_file_write_failure = failed to write symbols file: {$error} +codegen_ssa_add_native_library = failed to add native library {$library_path}: {$error} -codegen_ssa_ld64_unimplemented_modifier = `as-needed` modifier not implemented yet for ld64 +codegen_ssa_apple_sdk_error_sdk_path = failed to get {$sdk_name} SDK path: {$error} -codegen_ssa_linker_unsupported_modifier = `as-needed` modifier not supported for current linker +codegen_ssa_archive_build_failure = + failed to build archive: {$error} -codegen_ssa_L4Bender_exporting_symbols_unimplemented = exporting symbols not implemented yet for L4Bender +codegen_ssa_atomic_compare_exchange = Atomic compare-exchange intrinsic missing failure memory ordering -codegen_ssa_no_natvis_directory = error enumerating natvis directory: {$error} +codegen_ssa_check_installed_visual_studio = please ensure that Visual Studio 2017 or later, or Build Tools for Visual Studio were installed with the Visual C++ option. codegen_ssa_copy_path = could not copy {$from} to {$to}: {$error} codegen_ssa_copy_path_buf = unable to copy {$source_file} to {$output_path}: {$error} +codegen_ssa_create_temp_dir = couldn't create a temp dir: {$error} + +codegen_ssa_erroneous_constant = erroneous constant encountered + +codegen_ssa_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)` + +codegen_ssa_extern_funcs_not_found = some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified + +codegen_ssa_extract_bundled_libs_archive_member = failed to get data from archive member '{$rlib}': {$error} +codegen_ssa_extract_bundled_libs_convert_name = failed to convert name '{$rlib}': {$error} +codegen_ssa_extract_bundled_libs_mmap_file = failed to mmap file '{$rlib}': {$error} +codegen_ssa_extract_bundled_libs_open_file = failed to open file '{$rlib}': {$error} +codegen_ssa_extract_bundled_libs_parse_archive = failed to parse archive '{$rlib}': {$error} +codegen_ssa_extract_bundled_libs_read_entry = failed to read entry '{$rlib}': {$error} +codegen_ssa_extract_bundled_libs_write_file = failed to write file '{$rlib}': {$error} + +codegen_ssa_failed_to_write = failed to write {$path}: {$error} + codegen_ssa_ignoring_emit_path = ignoring emit path because multiple .{$extension} files were produced codegen_ssa_ignoring_output = ignoring -o because multiple .{$extension} files were produced -codegen_ssa_create_temp_dir = couldn't create a temp dir: {$error} +codegen_ssa_illegal_link_ordinal_format = illegal ordinal format in `link_ordinal` + .note = an unsuffixed integer value, e.g., `1`, is expected codegen_ssa_incompatible_linking_modifiers = link modifiers combination `+bundle,+whole-archive` is unstable when generating rlibs -codegen_ssa_add_native_library = failed to add native library {$library_path}: {$error} - -codegen_ssa_multiple_external_func_decl = multiple declarations of external function `{$function}` from library `{$library_name}` have different calling conventions +codegen_ssa_insufficient_vs_code_product = VS Code is a different product, and is not sufficient. -codegen_ssa_rlib_missing_format = could not find formats for rlibs +codegen_ssa_invalid_link_ordinal_nargs = incorrect number of arguments to `#[link_ordinal]` + .note = the attribute requires exactly one argument -codegen_ssa_rlib_only_rmeta_found = could not find rlib for: `{$crate_name}`, found rmeta (metadata) file +codegen_ssa_invalid_monomorphization_basic_float_type = invalid monomorphization of `{$name}` intrinsic: expected basic float type, found `{$ty}` -codegen_ssa_rlib_not_found = could not find rlib for: `{$crate_name}` +codegen_ssa_invalid_monomorphization_basic_integer_type = invalid monomorphization of `{$name}` intrinsic: expected basic integer type, found `{$ty}` -codegen_ssa_rlib_incompatible_dependency_formats = `{$ty1}` and `{$ty2}` do not have equivalent dependency formats (`{$list1}` vs `{$list2}`) +codegen_ssa_invalid_monomorphization_cannot_return = invalid monomorphization of `{$name}` intrinsic: cannot return `{$ret_ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]` -codegen_ssa_linking_failed = linking with `{$linker_path}` failed: {$exit_status} +codegen_ssa_invalid_monomorphization_cast_fat_pointer = invalid monomorphization of `{$name}` intrinsic: cannot cast fat pointer `{$ty}` -codegen_ssa_extern_funcs_not_found = some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified +codegen_ssa_invalid_monomorphization_expected_element_type = invalid monomorphization of `{$name}` intrinsic: expected element type `{$expected_element}` of second argument `{$second_arg}` to be a pointer to the element type `{$in_elem}` of the first argument `{$in_ty}`, found `{$expected_element}` != `{$mutability} {$in_elem}` -codegen_ssa_specify_libraries_to_link = use the `-l` flag to specify native libraries to link +codegen_ssa_invalid_monomorphization_expected_pointer = invalid monomorphization of `{$name}` intrinsic: expected pointer, got `{$ty}` -codegen_ssa_use_cargo_directive = use the `cargo:rustc-link-lib` directive to specify the native libraries to link with Cargo (see https://doc.rust-lang.org/cargo/reference/build-scripts.html#cargorustc-link-libkindname) +codegen_ssa_invalid_monomorphization_expected_return_type = invalid monomorphization of `{$name}` intrinsic: expected return type `{$in_ty}`, found `{$ret_ty}` -codegen_ssa_thorin_read_input_failure = failed to read input file +codegen_ssa_invalid_monomorphization_expected_usize = invalid monomorphization of `{$name}` intrinsic: expected `usize`, got `{$ty}` -codegen_ssa_thorin_parse_input_file_kind = failed to parse input file kind +codegen_ssa_invalid_monomorphization_expected_vector_element_type = invalid monomorphization of `{$name}` intrinsic: expected element type `{$expected_element}` of vector type `{$vector_type}` to be a signed or unsigned integer type -codegen_ssa_thorin_parse_input_object_file = failed to parse input object file +codegen_ssa_invalid_monomorphization_float_to_int_unchecked = invalid monomorphization of `float_to_int_unchecked` intrinsic: expected basic float type, found `{$ty}` -codegen_ssa_thorin_parse_input_archive_file = failed to parse input archive file +codegen_ssa_invalid_monomorphization_floating_point_type = invalid monomorphization of `{$name}` intrinsic: `{$in_ty}` is not a floating-point type -codegen_ssa_thorin_parse_archive_member = failed to parse archive member +codegen_ssa_invalid_monomorphization_floating_point_vector = invalid monomorphization of `{$name}` intrinsic: unsupported element type `{$f_ty}` of floating-point vector `{$in_ty}` -codegen_ssa_thorin_invalid_input_kind = input is not an archive or elf object +codegen_ssa_invalid_monomorphization_inserted_type = invalid monomorphization of `{$name}` intrinsic: expected inserted type `{$in_elem}` (element of input `{$in_ty}`), found `{$out_ty}` -codegen_ssa_thorin_decompress_data = failed to decompress compressed section +codegen_ssa_invalid_monomorphization_invalid_bitmask = invalid monomorphization of `{$name}` intrinsic: invalid bitmask `{$mask_ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]` -codegen_ssa_thorin_section_without_name = section without name at offset {$offset} +codegen_ssa_invalid_monomorphization_mask_type = invalid monomorphization of `{$name}` intrinsic: mask element type is `{$ty}`, expected `i_` -codegen_ssa_thorin_relocation_with_invalid_symbol = relocation with invalid symbol for section `{$section}` at offset {$offset} +codegen_ssa_invalid_monomorphization_mismatched_lengths = invalid monomorphization of `{$name}` intrinsic: mismatched lengths: mask length `{$m_len}` != other vector length `{$v_len}` -codegen_ssa_thorin_multiple_relocations = multiple relocations for section `{$section}` at offset {$offset} +codegen_ssa_invalid_monomorphization_return_element = invalid monomorphization of `{$name}` intrinsic: expected return element type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}` with element type `{$out_ty}` -codegen_ssa_thorin_unsupported_relocation = unsupported relocation for section {$section} at offset {$offset} +codegen_ssa_invalid_monomorphization_return_integer_type = invalid monomorphization of `{$name}` intrinsic: expected return type with integer elements, found `{$ret_ty}` with non-integer `{$out_ty}` -codegen_ssa_thorin_missing_dwo_name = missing path attribute to DWARF object ({$id}) +codegen_ssa_invalid_monomorphization_return_length = invalid monomorphization of `{$name}` intrinsic: expected return type of length {$in_len}, found `{$ret_ty}` with length {$out_len} -codegen_ssa_thorin_no_compilation_units = input object has no compilation units +codegen_ssa_invalid_monomorphization_return_length_input_type = invalid monomorphization of `{$name}` intrinsic: expected return type with length {$in_len} (same as input type `{$in_ty}`), found `{$ret_ty}` with length {$out_len} -codegen_ssa_thorin_no_die = no top-level debugging information entry in compilation/type unit +codegen_ssa_invalid_monomorphization_return_type = invalid monomorphization of `{$name}` intrinsic: expected return type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}` -codegen_ssa_thorin_top_level_die_not_unit = top-level debugging information entry is not a compilation/type unit +codegen_ssa_invalid_monomorphization_second_argument_length = invalid monomorphization of `{$name}` intrinsic: expected second argument with length {$in_len} (same as input type `{$in_ty}`), found `{$arg_ty}` with length {$out_len} -codegen_ssa_thorin_missing_required_section = input object missing required section `{$section}` +codegen_ssa_invalid_monomorphization_shuffle_index_not_constant = invalid monomorphization of `{$name}` intrinsic: shuffle index #{$arg_idx} is not a constant -codegen_ssa_thorin_parse_unit_abbreviations = failed to parse unit abbreviations +codegen_ssa_invalid_monomorphization_shuffle_index_out_of_bounds = invalid monomorphization of `{$name}` intrinsic: shuffle index #{$arg_idx} is out of bounds (limit {$total_len}) -codegen_ssa_thorin_parse_unit_attribute = failed to parse unit attribute +codegen_ssa_invalid_monomorphization_simd_argument = invalid monomorphization of `{$name}` intrinsic: expected SIMD argument type, found non-SIMD `{$ty}` -codegen_ssa_thorin_parse_unit_header = failed to parse unit header +codegen_ssa_invalid_monomorphization_simd_first = invalid monomorphization of `{$name}` intrinsic: expected SIMD first type, found non-SIMD `{$ty}` -codegen_ssa_thorin_parse_unit = failed to parse unit +codegen_ssa_invalid_monomorphization_simd_input = invalid monomorphization of `{$name}` intrinsic: expected SIMD input type, found non-SIMD `{$ty}` -codegen_ssa_thorin_incompatible_index_version = incompatible `{$section}` index version: found version {$actual}, expected version {$format} +codegen_ssa_invalid_monomorphization_simd_return = invalid monomorphization of `{$name}` intrinsic: expected SIMD return type, found non-SIMD `{$ty}` -codegen_ssa_thorin_offset_at_index = read offset at index {$index} of `.debug_str_offsets.dwo` section +codegen_ssa_invalid_monomorphization_simd_second = invalid monomorphization of `{$name}` intrinsic: expected SIMD second type, found non-SIMD `{$ty}` -codegen_ssa_thorin_str_at_offset = read string at offset {$offset} of `.debug_str.dwo` section +codegen_ssa_invalid_monomorphization_simd_shuffle = invalid monomorphization of `{$name}` intrinsic: simd_shuffle index must be an array of `u32`, got `{$ty}` -codegen_ssa_thorin_parse_index = failed to parse `{$section}` index section +codegen_ssa_invalid_monomorphization_simd_third = invalid monomorphization of `{$name}` intrinsic: expected SIMD third type, found non-SIMD `{$ty}` -codegen_ssa_thorin_unit_not_in_index = unit {$unit} from input package is not in its index +codegen_ssa_invalid_monomorphization_third_arg_element_type = invalid monomorphization of `{$name}` intrinsic: expected element type `{$expected_element}` of third argument `{$third_arg}` to be a signed integer type -codegen_ssa_thorin_row_not_in_index = row {$row} found in index's hash table not present in index +codegen_ssa_invalid_monomorphization_third_argument_length = invalid monomorphization of `{$name}` intrinsic: expected third argument with length {$in_len} (same as input type `{$in_ty}`), found `{$arg_ty}` with length {$out_len} -codegen_ssa_thorin_section_not_in_row = section not found in unit's row in index +codegen_ssa_invalid_monomorphization_unrecognized_intrinsic = invalid monomorphization of `{$name}` intrinsic: unrecognized intrinsic `{$name}` -codegen_ssa_thorin_empty_unit = unit {$unit} in input DWARF object with no data +codegen_ssa_invalid_monomorphization_unsupported_cast = invalid monomorphization of `{$name}` intrinsic: unsupported cast from `{$in_ty}` with element `{$in_elem}` to `{$ret_ty}` with element `{$out_elem}` -codegen_ssa_thorin_multiple_debug_info_section = multiple `.debug_info.dwo` sections +codegen_ssa_invalid_monomorphization_unsupported_operation = invalid monomorphization of `{$name}` intrinsic: unsupported operation on `{$in_ty}` with element `{$in_elem}` -codegen_ssa_thorin_multiple_debug_types_section = multiple `.debug_types.dwo` sections in a package +codegen_ssa_invalid_monomorphization_unsupported_symbol = invalid monomorphization of `{$name}` intrinsic: unsupported {$symbol} from `{$in_ty}` with element `{$in_elem}` to `{$ret_ty}` -codegen_ssa_thorin_not_split_unit = regular compilation unit in object (missing dwo identifier) +codegen_ssa_invalid_monomorphization_unsupported_symbol_of_size = invalid monomorphization of `{$name}` intrinsic: unsupported {$symbol} from `{$in_ty}` with element `{$in_elem}` of size `{$size}` to `{$ret_ty}` -codegen_ssa_thorin_duplicate_unit = duplicate split compilation unit ({$unit}) +codegen_ssa_invalid_monomorphization_vector_argument = invalid monomorphization of `{$name}` intrinsic: vector argument `{$in_ty}`'s element type `{$in_elem}`, expected integer element type -codegen_ssa_thorin_missing_referenced_unit = unit {$unit} referenced by executable was not found +codegen_ssa_invalid_no_sanitize = invalid argument for `no_sanitize` + .note = expected one of: `address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow-call-stack`, or `thread` -codegen_ssa_thorin_not_output_object_created = no output object was created from inputs +codegen_ssa_invalid_windows_subsystem = invalid windows subsystem `{$subsystem}`, only `windows` and `console` are allowed -codegen_ssa_thorin_mixed_input_encodings = input objects haved mixed encodings +codegen_ssa_ld64_unimplemented_modifier = `as-needed` modifier not implemented yet for ld64 -codegen_ssa_thorin_io = {$error} -codegen_ssa_thorin_object_read = {$error} -codegen_ssa_thorin_object_write = {$error} -codegen_ssa_thorin_gimli_read = {$error} -codegen_ssa_thorin_gimli_write = {$error} +codegen_ssa_lib_def_write_failure = failed to write lib.def file: {$error} codegen_ssa_link_exe_unexpected_error = `link.exe` returned an unexpected error -codegen_ssa_repair_vs_build_tools = the Visual Studio build tools may need to be repaired using the Visual Studio installer - -codegen_ssa_missing_cpp_build_tool_component = or a necessary component may be missing from the "C++ build tools" workload +codegen_ssa_link_script_unavailable = can only use link script when linking with GNU-like linker -codegen_ssa_select_cpp_build_tool_workload = in the Visual Studio installer, ensure the "C++ build tools" workload is selected +codegen_ssa_link_script_write_failure = failed to write link script to {$path}: {$error} -codegen_ssa_visual_studio_not_installed = you may need to install Visual Studio build tools with the "C++ build tools" workload +codegen_ssa_linker_file_stem = couldn't extract file stem from specified linker codegen_ssa_linker_not_found = linker `{$linker_path}` not found .note = {$error} -codegen_ssa_unable_to_exe_linker = could not exec the linker `{$linker_path}` - .note = {$error} - .command_note = {$command_formatted} +codegen_ssa_linker_unsupported_modifier = `as-needed` modifier not supported for current linker -codegen_ssa_msvc_missing_linker = the msvc targets depend on the msvc linker but `link.exe` was not found +codegen_ssa_linking_failed = linking with `{$linker_path}` failed: {$exit_status} -codegen_ssa_check_installed_visual_studio = please ensure that Visual Studio 2017 or later, or Build Tools for Visual Studio were installed with the Visual C++ option. +codegen_ssa_metadata_object_file_write = error writing metadata object file: {$error} -codegen_ssa_insufficient_vs_code_product = VS Code is a different product, and is not sufficient. +codegen_ssa_missing_cpp_build_tool_component = or a necessary component may be missing from the "C++ build tools" workload -codegen_ssa_processing_dymutil_failed = processing debug info with `dsymutil` failed: {$status} - .note = {$output} +codegen_ssa_missing_memory_ordering = Atomic intrinsic missing memory ordering -codegen_ssa_unable_to_run_dsymutil = unable to run `dsymutil`: {$error} +codegen_ssa_msvc_missing_linker = the msvc targets depend on the msvc linker but `link.exe` was not found -codegen_ssa_stripping_debu_info_failed = stripping debug info with `{$util}` failed: {$status} - .note = {$output} +codegen_ssa_multiple_external_func_decl = multiple declarations of external function `{$function}` from library `{$library_name}` have different calling conventions -codegen_ssa_unable_to_run = unable to run `{$util}`: {$error} +codegen_ssa_multiple_main_functions = entry symbol `main` declared multiple times + .help = did you use `#[no_mangle]` on `fn main`? Use `#[start]` instead -codegen_ssa_linker_file_stem = couldn't extract file stem from specified linker +codegen_ssa_no_natvis_directory = error enumerating natvis directory: {$error} -codegen_ssa_static_library_native_artifacts = Link against the following native artifacts when linking against this static library. The order and any duplication can be significant on some platforms. +codegen_ssa_option_gcc_only = option `-Z gcc-ld` is used even though linker flavor is not gcc -codegen_ssa_link_script_unavailable = can only use link script when linking with GNU-like linker +codegen_ssa_polymorphic_constant_too_generic = codegen encountered polymorphic constant: TooGeneric -codegen_ssa_link_script_write_failure = failed to write link script to {$path}: {$error} +codegen_ssa_processing_dymutil_failed = processing debug info with `dsymutil` failed: {$status} + .note = {$output} -codegen_ssa_failed_to_write = failed to write {$path}: {$error} +codegen_ssa_read_file = failed to read file: {$message} -codegen_ssa_unable_to_write_debugger_visualizer = Unable to write debugger visualizer file `{$path}`: {$error} +codegen_ssa_repair_vs_build_tools = the Visual Studio build tools may need to be repaired using the Visual Studio installer codegen_ssa_rlib_archive_build_failure = failed to build archive from rlib: {$error} -codegen_ssa_option_gcc_only = option `-Z gcc-ld` is used even though linker flavor is not gcc +codegen_ssa_rlib_incompatible_dependency_formats = `{$ty1}` and `{$ty2}` do not have equivalent dependency formats (`{$list1}` vs `{$list2}`) -codegen_ssa_extract_bundled_libs_open_file = failed to open file '{$rlib}': {$error} -codegen_ssa_extract_bundled_libs_mmap_file = failed to mmap file '{$rlib}': {$error} -codegen_ssa_extract_bundled_libs_parse_archive = failed to parse archive '{$rlib}': {$error} -codegen_ssa_extract_bundled_libs_read_entry = failed to read entry '{$rlib}': {$error} -codegen_ssa_extract_bundled_libs_archive_member = failed to get data from archive member '{$rlib}': {$error} -codegen_ssa_extract_bundled_libs_convert_name = failed to convert name '{$rlib}': {$error} -codegen_ssa_extract_bundled_libs_write_file = failed to write file '{$rlib}': {$error} +codegen_ssa_rlib_missing_format = could not find formats for rlibs -codegen_ssa_unsupported_arch = unsupported arch `{$arch}` for os `{$os}` +codegen_ssa_rlib_not_found = could not find rlib for: `{$crate_name}` -codegen_ssa_apple_sdk_error_sdk_path = failed to get {$sdk_name} SDK path: {$error} +codegen_ssa_rlib_only_rmeta_found = could not find rlib for: `{$crate_name}`, found rmeta (metadata) file -codegen_ssa_read_file = failed to read file: {$message} +codegen_ssa_select_cpp_build_tool_workload = in the Visual Studio installer, ensure the "C++ build tools" workload is selected -codegen_ssa_unsupported_link_self_contained = option `-C link-self-contained` is not supported on this target +codegen_ssa_shuffle_indices_evaluation = could not evaluate shuffle_indices at compile time -codegen_ssa_archive_build_failure = - failed to build archive: {$error} +codegen_ssa_specify_libraries_to_link = use the `-l` flag to specify native libraries to link -codegen_ssa_unknown_archive_kind = - Don't know how to build archive of type: {$kind} +codegen_ssa_static_library_native_artifacts = Link against the following native artifacts when linking against this static library. The order and any duplication can be significant on some platforms. -codegen_ssa_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)` +codegen_ssa_stripping_debug_info_failed = stripping debug info with `{$util}` failed: {$status} + .note = {$output} -codegen_ssa_multiple_main_functions = entry symbol `main` declared multiple times - .help = did you use `#[no_mangle]` on `fn main`? Use `#[start]` instead +codegen_ssa_symbol_file_write_failure = failed to write symbols file: {$error} -codegen_ssa_metadata_object_file_write = error writing metadata object file: {$error} +codegen_ssa_target_feature_safe_trait = `#[target_feature(..)]` cannot be applied to safe trait method + .label = cannot be applied to safe trait method + .label_def = not an `unsafe` function -codegen_ssa_invalid_windows_subsystem = invalid windows subsystem `{$subsystem}`, only `windows` and `console` are allowed +codegen_ssa_thorin_decompress_data = failed to decompress compressed section -codegen_ssa_erroneous_constant = erroneous constant encountered +codegen_ssa_thorin_duplicate_unit = duplicate split compilation unit ({$unit}) -codegen_ssa_shuffle_indices_evaluation = could not evaluate shuffle_indices at compile time +codegen_ssa_thorin_empty_unit = unit {$unit} in input DWARF object with no data -codegen_ssa_missing_memory_ordering = Atomic intrinsic missing memory ordering +codegen_ssa_thorin_gimli_read = {$error} +codegen_ssa_thorin_gimli_write = {$error} -codegen_ssa_unknown_atomic_ordering = unknown ordering in atomic intrinsic +codegen_ssa_thorin_incompatible_index_version = incompatible `{$section}` index version: found version {$actual}, expected version {$format} -codegen_ssa_atomic_compare_exchange = Atomic compare-exchange intrinsic missing failure memory ordering +codegen_ssa_thorin_invalid_input_kind = input is not an archive or elf object -codegen_ssa_unknown_atomic_operation = unknown atomic operation +codegen_ssa_thorin_io = {$error} +codegen_ssa_thorin_missing_dwo_name = missing path attribute to DWARF object ({$id}) -codegen_ssa_invalid_monomorphization_basic_integer_type = invalid monomorphization of `{$name}` intrinsic: expected basic integer type, found `{$ty}` +codegen_ssa_thorin_missing_referenced_unit = unit {$unit} referenced by executable was not found -codegen_ssa_invalid_monomorphization_basic_float_type = invalid monomorphization of `{$name}` intrinsic: expected basic float type, found `{$ty}` +codegen_ssa_thorin_missing_required_section = input object missing required section `{$section}` -codegen_ssa_invalid_monomorphization_float_to_int_unchecked = invalid monomorphization of `float_to_int_unchecked` intrinsic: expected basic float type, found `{$ty}` +codegen_ssa_thorin_mixed_input_encodings = input objects haved mixed encodings -codegen_ssa_invalid_monomorphization_floating_point_vector = invalid monomorphization of `{$name}` intrinsic: unsupported element type `{$f_ty}` of floating-point vector `{$in_ty}` +codegen_ssa_thorin_multiple_debug_info_section = multiple `.debug_info.dwo` sections -codegen_ssa_invalid_monomorphization_floating_point_type = invalid monomorphization of `{$name}` intrinsic: `{$in_ty}` is not a floating-point type +codegen_ssa_thorin_multiple_debug_types_section = multiple `.debug_types.dwo` sections in a package -codegen_ssa_invalid_monomorphization_unrecognized_intrinsic = invalid monomorphization of `{$name}` intrinsic: unrecognized intrinsic `{$name}` +codegen_ssa_thorin_multiple_relocations = multiple relocations for section `{$section}` at offset {$offset} -codegen_ssa_invalid_monomorphization_simd_argument = invalid monomorphization of `{$name}` intrinsic: expected SIMD argument type, found non-SIMD `{$ty}` +codegen_ssa_thorin_no_compilation_units = input object has no compilation units -codegen_ssa_invalid_monomorphization_simd_input = invalid monomorphization of `{$name}` intrinsic: expected SIMD input type, found non-SIMD `{$ty}` +codegen_ssa_thorin_no_die = no top-level debugging information entry in compilation/type unit -codegen_ssa_invalid_monomorphization_simd_first = invalid monomorphization of `{$name}` intrinsic: expected SIMD first type, found non-SIMD `{$ty}` +codegen_ssa_thorin_not_output_object_created = no output object was created from inputs -codegen_ssa_invalid_monomorphization_simd_second = invalid monomorphization of `{$name}` intrinsic: expected SIMD second type, found non-SIMD `{$ty}` +codegen_ssa_thorin_not_split_unit = regular compilation unit in object (missing dwo identifier) -codegen_ssa_invalid_monomorphization_simd_third = invalid monomorphization of `{$name}` intrinsic: expected SIMD third type, found non-SIMD `{$ty}` +codegen_ssa_thorin_object_read = {$error} +codegen_ssa_thorin_object_write = {$error} +codegen_ssa_thorin_offset_at_index = read offset at index {$index} of `.debug_str_offsets.dwo` section -codegen_ssa_invalid_monomorphization_simd_return = invalid monomorphization of `{$name}` intrinsic: expected SIMD return type, found non-SIMD `{$ty}` +codegen_ssa_thorin_parse_archive_member = failed to parse archive member -codegen_ssa_invalid_monomorphization_invalid_bitmask = invalid monomorphization of `{$name}` intrinsic: invalid bitmask `{$mask_ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]` +codegen_ssa_thorin_parse_index = failed to parse `{$section}` index section -codegen_ssa_polymorphic_constant_too_generic = codegen encountered polymorphic constant: TooGeneric +codegen_ssa_thorin_parse_input_archive_file = failed to parse input archive file -codegen_ssa_invalid_monomorphization_return_length_input_type = invalid monomorphization of `{$name}` intrinsic: expected return type with length {$in_len} (same as input type `{$in_ty}`), found `{$ret_ty}` with length {$out_len} +codegen_ssa_thorin_parse_input_file_kind = failed to parse input file kind -codegen_ssa_invalid_monomorphization_second_argument_length = invalid monomorphization of `{$name}` intrinsic: expected second argument with length {$in_len} (same as input type `{$in_ty}`), found `{$arg_ty}` with length {$out_len} +codegen_ssa_thorin_parse_input_object_file = failed to parse input object file -codegen_ssa_invalid_monomorphization_third_argument_length = invalid monomorphization of `{$name}` intrinsic: expected third argument with length {$in_len} (same as input type `{$in_ty}`), found `{$arg_ty}` with length {$out_len} +codegen_ssa_thorin_parse_unit = failed to parse unit -codegen_ssa_invalid_monomorphization_return_integer_type = invalid monomorphization of `{$name}` intrinsic: expected return type with integer elements, found `{$ret_ty}` with non-integer `{$out_ty}` +codegen_ssa_thorin_parse_unit_abbreviations = failed to parse unit abbreviations -codegen_ssa_invalid_monomorphization_simd_shuffle = invalid monomorphization of `{$name}` intrinsic: simd_shuffle index must be an array of `u32`, got `{$ty}` +codegen_ssa_thorin_parse_unit_attribute = failed to parse unit attribute -codegen_ssa_invalid_monomorphization_return_length = invalid monomorphization of `{$name}` intrinsic: expected return type of length {$in_len}, found `{$ret_ty}` with length {$out_len} +codegen_ssa_thorin_parse_unit_header = failed to parse unit header -codegen_ssa_invalid_monomorphization_return_element = invalid monomorphization of `{$name}` intrinsic: expected return element type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}` with element type `{$out_ty}` +codegen_ssa_thorin_read_input_failure = failed to read input file -codegen_ssa_invalid_monomorphization_shuffle_index_not_constant = invalid monomorphization of `{$name}` intrinsic: shuffle index #{$arg_idx} is not a constant +codegen_ssa_thorin_relocation_with_invalid_symbol = relocation with invalid symbol for section `{$section}` at offset {$offset} -codegen_ssa_invalid_monomorphization_shuffle_index_out_of_bounds = invalid monomorphization of `{$name}` intrinsic: shuffle index #{$arg_idx} is out of bounds (limit {$total_len}) +codegen_ssa_thorin_row_not_in_index = row {$row} found in index's hash table not present in index -codegen_ssa_invalid_monomorphization_inserted_type = invalid monomorphization of `{$name}` intrinsic: expected inserted type `{$in_elem}` (element of input `{$in_ty}`), found `{$out_ty}` +codegen_ssa_thorin_section_not_in_row = section not found in unit's row in index -codegen_ssa_invalid_monomorphization_return_type = invalid monomorphization of `{$name}` intrinsic: expected return type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}` +codegen_ssa_thorin_section_without_name = section without name at offset {$offset} -codegen_ssa_invalid_monomorphization_expected_return_type = invalid monomorphization of `{$name}` intrinsic: expected return type `{$in_ty}`, found `{$ret_ty}` +codegen_ssa_thorin_str_at_offset = read string at offset {$offset} of `.debug_str.dwo` section -codegen_ssa_invalid_monomorphization_mismatched_lengths = invalid monomorphization of `{$name}` intrinsic: mismatched lengths: mask length `{$m_len}` != other vector length `{$v_len}` +codegen_ssa_thorin_top_level_die_not_unit = top-level debugging information entry is not a compilation/type unit -codegen_ssa_invalid_monomorphization_mask_type = invalid monomorphization of `{$name}` intrinsic: mask element type is `{$ty}`, expected `i_` +codegen_ssa_thorin_unit_not_in_index = unit {$unit} from input package is not in its index -codegen_ssa_invalid_monomorphization_vector_argument = invalid monomorphization of `{$name}` intrinsic: vector argument `{$in_ty}`'s element type `{$in_elem}`, expected integer element type +codegen_ssa_thorin_unsupported_relocation = unsupported relocation for section {$section} at offset {$offset} -codegen_ssa_invalid_monomorphization_cannot_return = invalid monomorphization of `{$name}` intrinsic: cannot return `{$ret_ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]` +codegen_ssa_unable_to_exe_linker = could not exec the linker `{$linker_path}` + .note = {$error} + .command_note = {$command_formatted} -codegen_ssa_invalid_monomorphization_expected_element_type = invalid monomorphization of `{$name}` intrinsic: expected element type `{$expected_element}` of second argument `{$second_arg}` to be a pointer to the element type `{$in_elem}` of the first argument `{$in_ty}`, found `{$expected_element}` != `{$mutability} {$in_elem}` +codegen_ssa_unable_to_run = unable to run `{$util}`: {$error} -codegen_ssa_invalid_monomorphization_third_arg_element_type = invalid monomorphization of `{$name}` intrinsic: expected element type `{$expected_element}` of third argument `{$third_arg}` to be a signed integer type +codegen_ssa_unable_to_run_dsymutil = unable to run `dsymutil`: {$error} -codegen_ssa_invalid_monomorphization_unsupported_symbol_of_size = invalid monomorphization of `{$name}` intrinsic: unsupported {$symbol} from `{$in_ty}` with element `{$in_elem}` of size `{$size}` to `{$ret_ty}` +codegen_ssa_unable_to_write_debugger_visualizer = Unable to write debugger visualizer file `{$path}`: {$error} -codegen_ssa_invalid_monomorphization_unsupported_symbol = invalid monomorphization of `{$name}` intrinsic: unsupported {$symbol} from `{$in_ty}` with element `{$in_elem}` to `{$ret_ty}` +codegen_ssa_unknown_archive_kind = + Don't know how to build archive of type: {$kind} -codegen_ssa_invalid_monomorphization_cast_fat_pointer = invalid monomorphization of `{$name}` intrinsic: cannot cast fat pointer `{$ty}` +codegen_ssa_unknown_atomic_operation = unknown atomic operation -codegen_ssa_invalid_monomorphization_expected_pointer = invalid monomorphization of `{$name}` intrinsic: expected pointer, got `{$ty}` +codegen_ssa_unknown_atomic_ordering = unknown ordering in atomic intrinsic -codegen_ssa_invalid_monomorphization_expected_usize = invalid monomorphization of `{$name}` intrinsic: expected `usize`, got `{$ty}` +codegen_ssa_unsupported_arch = unsupported arch `{$arch}` for os `{$os}` -codegen_ssa_invalid_monomorphization_unsupported_cast = invalid monomorphization of `{$name}` intrinsic: unsupported cast from `{$in_ty}` with element `{$in_elem}` to `{$ret_ty}` with element `{$out_elem}` +codegen_ssa_unsupported_link_self_contained = option `-C link-self-contained` is not supported on this target -codegen_ssa_invalid_monomorphization_unsupported_operation = invalid monomorphization of `{$name}` intrinsic: unsupported operation on `{$in_ty}` with element `{$in_elem}` +codegen_ssa_use_cargo_directive = use the `cargo:rustc-link-lib` directive to specify the native libraries to link with Cargo (see https://doc.rust-lang.org/cargo/reference/build-scripts.html#cargorustc-link-libkindname) -codegen_ssa_invalid_monomorphization_expected_vector_element_type = invalid monomorphization of `{$name}` intrinsic: expected element type `{$expected_element}` of vector type `{$vector_type}` to be a signed or unsigned integer type +codegen_ssa_version_script_write_failure = failed to write version script: {$error} + +codegen_ssa_visual_studio_not_installed = you may need to install Visual Studio build tools with the "C++ build tools" workload diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs index 66ec8f5f5..1c464b3ec 100644 --- a/compiler/rustc_codegen_ssa/src/back/archive.rs +++ b/compiler/rustc_codegen_ssa/src/back/archive.rs @@ -233,6 +233,7 @@ impl<'a> ArArchiveBuilder<'a> { "bsd" => ArchiveKind::Bsd, "darwin" => ArchiveKind::Darwin, "coff" => ArchiveKind::Coff, + "aix_big" => ArchiveKind::AixBig, kind => { self.sess.emit_fatal(UnknownArchiveKind { kind }); } diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index eecfe13bb..8a00c42a0 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -9,6 +9,7 @@ use rustc_fs_util::fix_windows_verbatim_for_gcc; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_metadata::find_native_static_library; use rustc_metadata::fs::{emit_wrapper_file, METADATA_FILENAME}; +use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile; use rustc_middle::middle::dependency_format::Linkage; use rustc_middle::middle::exported_symbols::SymbolExportKind; use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, LdImpl, Strip}; @@ -21,7 +22,6 @@ use rustc_session::utils::NativeLibKind; /// need out of the shared crate context before we get rid of it. use rustc_session::{filesearch, Session}; use rustc_span::symbol::Symbol; -use rustc_span::DebuggerVisualizerFile; use rustc_target::spec::crt_objects::{CrtObjects, LinkSelfContainedDefault}; use rustc_target::spec::{Cc, LinkOutputKind, LinkerFlavor, LinkerFlavorCli, Lld, PanicStrategy}; use rustc_target::spec::{RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo}; @@ -40,7 +40,6 @@ use regex::Regex; use tempfile::Builder as TempFileBuilder; use itertools::Itertools; -use std::borrow::Borrow; use std::cell::OnceCell; use std::collections::BTreeSet; use std::ffi::OsString; @@ -54,7 +53,7 @@ use std::{env, fmt, fs, io, mem, str}; pub fn ensure_removed(diag_handler: &Handler, path: &Path) { if let Err(e) = fs::remove_file(path) { if e.kind() != io::ErrorKind::NotFound { - diag_handler.err(&format!("failed to remove {}: {}", path.display(), e)); + diag_handler.err(format!("failed to remove {}: {}", path.display(), e)); } } } @@ -547,12 +546,40 @@ fn link_staticlib<'a>( ab.build(out_filename); - if !all_native_libs.is_empty() { - if sess.opts.prints.contains(&PrintRequest::NativeStaticLibs) { - print_native_static_libs(sess, &all_native_libs); + let crates = codegen_results.crate_info.used_crates.iter(); + + let fmts = codegen_results + .crate_info + .dependency_formats + .iter() + .find_map(|&(ty, ref list)| if ty == CrateType::Staticlib { Some(list) } else { None }) + .expect("no dependency formats for staticlib"); + + let mut all_rust_dylibs = vec![]; + for &cnum in crates { + match fmts.get(cnum.as_usize() - 1) { + Some(&Linkage::Dynamic) => {} + _ => continue, + } + let crate_name = codegen_results.crate_info.crate_name[&cnum]; + let used_crate_source = &codegen_results.crate_info.used_crate_source[&cnum]; + if let Some((path, _)) = &used_crate_source.dylib { + all_rust_dylibs.push(&**path); + } else { + if used_crate_source.rmeta.is_some() { + sess.emit_fatal(errors::LinkRlibError::OnlyRmetaFound { crate_name }); + } else { + sess.emit_fatal(errors::LinkRlibError::NotFound { crate_name }); + } } } + all_native_libs.extend_from_slice(&codegen_results.crate_info.used_libraries); + + if sess.opts.prints.contains(&PrintRequest::NativeStaticLibs) { + print_native_static_libs(sess, &all_native_libs, &all_rust_dylibs); + } + Ok(()) } @@ -576,17 +603,17 @@ fn link_dwarf_object<'a>( impl<Relocations> ThorinSession<Relocations> { fn alloc_mmap(&self, data: Mmap) -> &Mmap { - (*self.arena_mmap.alloc(data)).borrow() + &*self.arena_mmap.alloc(data) } } impl<Relocations> thorin::Session<Relocations> for ThorinSession<Relocations> { fn alloc_data(&self, data: Vec<u8>) -> &[u8] { - (*self.arena_data.alloc(data)).borrow() + &*self.arena_data.alloc(data) } fn alloc_relocation(&self, data: Relocations) -> &Relocations { - (*self.arena_relocations.alloc(data)).borrow() + &*self.arena_relocations.alloc(data) } fn read_input(&self, path: &Path) -> std::io::Result<&[u8]> { @@ -860,7 +887,7 @@ fn link_natively<'a>( if !prog.status.success() { let mut output = prog.stderr.clone(); output.extend_from_slice(&prog.stdout); - let escaped_output = escape_string(&output); + let escaped_output = escape_linker_output(&output, flavor); // FIXME: Add UI tests for this error. let err = errors::LinkingFailed { linker_path: &linker_path, @@ -1052,6 +1079,83 @@ fn escape_string(s: &[u8]) -> String { } } +#[cfg(not(windows))] +fn escape_linker_output(s: &[u8], _flavour: LinkerFlavor) -> String { + escape_string(s) +} + +/// If the output of the msvc linker is not UTF-8 and the host is Windows, +/// then try to convert the string from the OEM encoding. +#[cfg(windows)] +fn escape_linker_output(s: &[u8], flavour: LinkerFlavor) -> String { + // This only applies to the actual MSVC linker. + if flavour != LinkerFlavor::Msvc(Lld::No) { + return escape_string(s); + } + match str::from_utf8(s) { + Ok(s) => return s.to_owned(), + Err(_) => match win::locale_byte_str_to_string(s, win::oem_code_page()) { + Some(s) => s, + // The string is not UTF-8 and isn't valid for the OEM code page + None => format!("Non-UTF-8 output: {}", s.escape_ascii()), + }, + } +} + +/// Wrappers around the Windows API. +#[cfg(windows)] +mod win { + use windows::Win32::Globalization::{ + GetLocaleInfoEx, MultiByteToWideChar, CP_OEMCP, LOCALE_IUSEUTF8LEGACYOEMCP, + LOCALE_NAME_SYSTEM_DEFAULT, LOCALE_RETURN_NUMBER, MB_ERR_INVALID_CHARS, + }; + + /// Get the Windows system OEM code page. This is most notably the code page + /// used for link.exe's output. + pub fn oem_code_page() -> u32 { + unsafe { + let mut cp: u32 = 0; + // We're using the `LOCALE_RETURN_NUMBER` flag to return a u32. + // But the API requires us to pass the data as though it's a [u16] string. + let len = std::mem::size_of::<u32>() / std::mem::size_of::<u16>(); + let data = std::slice::from_raw_parts_mut(&mut cp as *mut u32 as *mut u16, len); + let len_written = GetLocaleInfoEx( + LOCALE_NAME_SYSTEM_DEFAULT, + LOCALE_IUSEUTF8LEGACYOEMCP | LOCALE_RETURN_NUMBER, + Some(data), + ); + if len_written as usize == len { cp } else { CP_OEMCP } + } + } + /// Try to convert a multi-byte string to a UTF-8 string using the given code page + /// The string does not need to be null terminated. + /// + /// This is implemented as a wrapper around `MultiByteToWideChar`. + /// See <https://learn.microsoft.com/en-us/windows/win32/api/stringapiset/nf-stringapiset-multibytetowidechar> + /// + /// It will fail if the multi-byte string is longer than `i32::MAX` or if it contains + /// any invalid bytes for the expected encoding. + pub fn locale_byte_str_to_string(s: &[u8], code_page: u32) -> Option<String> { + // `MultiByteToWideChar` requires a length to be a "positive integer". + if s.len() > isize::MAX as usize { + return None; + } + // Error if the string is not valid for the expected code page. + let flags = MB_ERR_INVALID_CHARS; + // Call MultiByteToWideChar twice. + // First to calculate the length then to convert the string. + let mut len = unsafe { MultiByteToWideChar(code_page, flags, s, None) }; + if len > 0 { + let mut utf16 = vec![0; len as usize]; + len = unsafe { MultiByteToWideChar(code_page, flags, s, Some(&mut utf16)) }; + if len > 0 { + return utf16.get(..len as usize).map(String::from_utf16_lossy); + } + } + None + } +} + fn add_sanitizer_libraries(sess: &Session, crate_type: CrateType, linker: &mut dyn Linker) { // On macOS the runtimes are distributed as dylibs which should be linked to // both executables and dynamic shared objects. Everywhere else the runtimes @@ -1294,8 +1398,12 @@ enum RlibFlavor { StaticlibBase, } -fn print_native_static_libs(sess: &Session, all_native_libs: &[NativeLib]) { - let lib_args: Vec<_> = all_native_libs +fn print_native_static_libs( + sess: &Session, + all_native_libs: &[NativeLib], + all_rust_dylibs: &[&Path], +) { + let mut lib_args: Vec<_> = all_native_libs .iter() .filter(|l| relevant_lib(sess, l)) .filter_map(|lib| { @@ -1325,11 +1433,46 @@ fn print_native_static_libs(sess: &Session, all_native_libs: &[NativeLib]) { } }) .collect(); + for path in all_rust_dylibs { + // FIXME deduplicate with add_dynamic_crate + + // Just need to tell the linker about where the library lives and + // what its name is + let parent = path.parent(); + if let Some(dir) = parent { + let dir = fix_windows_verbatim_for_gcc(dir); + if sess.target.is_like_msvc { + let mut arg = String::from("/LIBPATH:"); + arg.push_str(&dir.display().to_string()); + lib_args.push(arg); + } else { + lib_args.push("-L".to_owned()); + lib_args.push(dir.display().to_string()); + } + } + let stem = path.file_stem().unwrap().to_str().unwrap(); + // Convert library file-stem into a cc -l argument. + let prefix = if stem.starts_with("lib") && !sess.target.is_like_windows { 3 } else { 0 }; + let lib = &stem[prefix..]; + let path = parent.unwrap_or_else(|| Path::new("")); + if sess.target.is_like_msvc { + // When producing a dll, the MSVC linker may not actually emit a + // `foo.lib` file if the dll doesn't actually export any symbols, so we + // check to see if the file is there and just omit linking to it if it's + // not present. + let name = format!("{}.dll.lib", lib); + if path.join(&name).exists() { + lib_args.push(name); + } + } else { + lib_args.push(format!("-l{}", lib)); + } + } if !lib_args.is_empty() { sess.emit_note(errors::StaticLibraryNativeArtifacts); // Prefix for greppability // Note: This must not be translated as tools are allowed to depend on this exact string. - sess.note_without_error(&format!("native-static-libs: {}", &lib_args.join(" "))); + sess.note_without_error(format!("native-static-libs: {}", &lib_args.join(" "))); } } diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 65dfc325a..cd56f85cc 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -144,7 +144,7 @@ pub fn get_linker<'a>( cmd, sess, target_cpu, - hinted_static: false, + hinted_static: None, is_ld: cc == Cc::No, is_gnu: flavor.is_gnu(), }) as Box<dyn Linker>, @@ -214,7 +214,7 @@ pub struct GccLinker<'a> { cmd: Command, sess: &'a Session, target_cpu: &'a str, - hinted_static: bool, // Keeps track of the current hinting mode. + hinted_static: Option<bool>, // Keeps track of the current hinting mode. // Link as ld is_ld: bool, is_gnu: bool, @@ -275,9 +275,9 @@ impl<'a> GccLinker<'a> { if !self.takes_hints() { return; } - if !self.hinted_static { + if self.hinted_static != Some(true) { self.linker_arg("-Bstatic"); - self.hinted_static = true; + self.hinted_static = Some(true); } } @@ -285,9 +285,9 @@ impl<'a> GccLinker<'a> { if !self.takes_hints() { return; } - if self.hinted_static { + if self.hinted_static != Some(false) { self.linker_arg("-Bdynamic"); - self.hinted_static = false; + self.hinted_static = Some(false); } } @@ -1484,25 +1484,25 @@ impl<'a> L4Bender<'a> { pub struct AixLinker<'a> { cmd: Command, sess: &'a Session, - hinted_static: bool, + hinted_static: Option<bool>, } impl<'a> AixLinker<'a> { pub fn new(cmd: Command, sess: &'a Session) -> AixLinker<'a> { - AixLinker { cmd: cmd, sess: sess, hinted_static: false } + AixLinker { cmd: cmd, sess: sess, hinted_static: None } } fn hint_static(&mut self) { - if !self.hinted_static { + if self.hinted_static != Some(true) { self.cmd.arg("-bstatic"); - self.hinted_static = true; + self.hinted_static = Some(true); } } fn hint_dynamic(&mut self) { - if self.hinted_static { + if self.hinted_static != Some(false) { self.cmd.arg("-bdynamic"); - self.hinted_static = false; + self.hinted_static = Some(false); } } @@ -1631,7 +1631,7 @@ impl<'a> Linker for AixLinker<'a> { } }; if let Err(e) = res { - self.sess.fatal(&format!("failed to write export file: {}", e)); + self.sess.fatal(format!("failed to write export file: {}", e)); } self.cmd.arg(format!("-bE:{}", path.to_str().unwrap())); } diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index d5d843702..ad27b854d 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -12,9 +12,9 @@ use object::{ use snap::write::FrameEncoder; +use object::elf::NT_GNU_PROPERTY_TYPE_0; use rustc_data_structures::memmap::Mmap; -use rustc_data_structures::owned_slice::try_slice_owned; -use rustc_data_structures::sync::MetadataRef; +use rustc_data_structures::owned_slice::{try_slice_owned, OwnedSlice}; use rustc_metadata::fs::METADATA_FILENAME; use rustc_metadata::EncodedMetadata; use rustc_session::cstore::MetadataLoader; @@ -38,7 +38,7 @@ pub struct DefaultMetadataLoader; fn load_metadata_with( path: &Path, f: impl for<'a> FnOnce(&'a [u8]) -> Result<&'a [u8], String>, -) -> Result<MetadataRef, String> { +) -> Result<OwnedSlice, String> { let file = File::open(path).map_err(|e| format!("failed to open file '{}': {}", path.display(), e))?; @@ -48,7 +48,7 @@ fn load_metadata_with( } impl MetadataLoader for DefaultMetadataLoader { - fn get_rlib_metadata(&self, _target: &Target, path: &Path) -> Result<MetadataRef, String> { + fn get_rlib_metadata(&self, _target: &Target, path: &Path) -> Result<OwnedSlice, String> { load_metadata_with(path, |data| { let archive = object::read::archive::ArchiveFile::parse(&*data) .map_err(|e| format!("failed to parse rlib '{}': {}", path.display(), e))?; @@ -68,7 +68,7 @@ impl MetadataLoader for DefaultMetadataLoader { }) } - fn get_dylib_metadata(&self, _target: &Target, path: &Path) -> Result<MetadataRef, String> { + fn get_dylib_metadata(&self, _target: &Target, path: &Path) -> Result<OwnedSlice, String> { load_metadata_with(path, |data| search_for_section(path, data, ".rustc")) } } @@ -93,6 +93,54 @@ pub(super) fn search_for_section<'a>( .map_err(|e| format!("failed to read {} section in '{}': {}", section, path.display(), e)) } +fn add_gnu_property_note( + file: &mut write::Object<'static>, + architecture: Architecture, + binary_format: BinaryFormat, + endianness: Endianness, +) { + // check bti protection + if binary_format != BinaryFormat::Elf + || !matches!(architecture, Architecture::X86_64 | Architecture::Aarch64) + { + return; + } + + let section = file.add_section( + file.segment_name(StandardSegment::Data).to_vec(), + b".note.gnu.property".to_vec(), + SectionKind::Note, + ); + let mut data: Vec<u8> = Vec::new(); + let n_namsz: u32 = 4; // Size of the n_name field + let n_descsz: u32 = 16; // Size of the n_desc field + let n_type: u32 = NT_GNU_PROPERTY_TYPE_0; // Type of note descriptor + let header_values = [n_namsz, n_descsz, n_type]; + header_values.iter().for_each(|v| { + data.extend_from_slice(&match endianness { + Endianness::Little => v.to_le_bytes(), + Endianness::Big => v.to_be_bytes(), + }) + }); + data.extend_from_slice(b"GNU\0"); // Owner of the program property note + let pr_type: u32 = match architecture { + Architecture::X86_64 => 0xc0000002, + Architecture::Aarch64 => 0xc0000000, + _ => unreachable!(), + }; + let pr_datasz: u32 = 4; //size of the pr_data field + let pr_data: u32 = 3; //program property descriptor + let pr_padding: u32 = 0; + let property_values = [pr_type, pr_datasz, pr_data, pr_padding]; + property_values.iter().for_each(|v| { + data.extend_from_slice(&match endianness { + Endianness::Little => v.to_le_bytes(), + Endianness::Big => v.to_be_bytes(), + }) + }); + file.append_section_data(section, &data, 8); +} + pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static>> { let endianness = match sess.target.options.endian { Endian::Little => Endianness::Little, @@ -140,6 +188,11 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static }; let mut file = write::Object::new(binary_format, architecture, endianness); + if sess.target.is_like_osx { + if let Some(build_version) = macho_object_build_version_for_target(&sess.target) { + file.set_macho_build_version(build_version) + } + } let e_flags = match architecture { Architecture::Mips => { let arch = match sess.target.options.cpu.as_ref() { @@ -205,10 +258,38 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static _ => elf::ELFOSABI_NONE, }; let abi_version = 0; + add_gnu_property_note(&mut file, architecture, binary_format, endianness); file.flags = FileFlags::Elf { os_abi, abi_version, e_flags }; Some(file) } +/// Apple's LD, when linking for Mac Catalyst, requires object files to +/// contain information about what they were built for (LC_BUILD_VERSION): +/// the platform (macOS/watchOS etc), minimum OS version, and SDK version. +/// This returns a `MachOBuildVersion` if necessary for the target. +fn macho_object_build_version_for_target( + target: &Target, +) -> Option<object::write::MachOBuildVersion> { + if !target.llvm_target.ends_with("-macabi") { + return None; + } + /// The `object` crate demands "X.Y.Z encoded in nibbles as xxxx.yy.zz" + /// e.g. minOS 14.0 = 0x000E0000, or SDK 16.2 = 0x00100200 + fn pack_version((major, minor): (u32, u32)) -> u32 { + (major << 16) | (minor << 8) + } + + let platform = object::macho::PLATFORM_MACCATALYST; + let min_os = (14, 0); + let sdk = (16, 2); + + let mut build_version = object::write::MachOBuildVersion::default(); + build_version.platform = platform; + build_version.minos = pack_version(min_os); + build_version.sdk = pack_version(sdk); + Some(build_version) +} + pub enum MetadataPosition { First, Last, diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index d0fd3cd76..a8b6030ac 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -2,7 +2,7 @@ use crate::base::allocator_kind_for_codegen; use std::collections::hash_map::Entry::*; -use rustc_ast::expand::allocator::ALLOCATOR_METHODS; +use rustc_ast::expand::allocator::{ALLOCATOR_METHODS, NO_ALLOC_SHIM_IS_UNSTABLE}; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def::DefKind; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LOCAL_CRATE}; @@ -11,7 +11,7 @@ use rustc_middle::middle::exported_symbols::{ metadata_symbol_name, ExportedSymbol, SymbolExportInfo, SymbolExportKind, SymbolExportLevel, }; use rustc_middle::query::LocalCrate; -use rustc_middle::ty::query::{ExternProviders, Providers}; +use rustc_middle::query::{ExternProviders, Providers}; use rustc_middle::ty::subst::{GenericArgKind, SubstsRef}; use rustc_middle::ty::Instance; use rustc_middle::ty::{self, SymbolName, TyCtxt}; @@ -241,6 +241,17 @@ fn exported_symbols_provider_local( used: false, }, )); + + let exported_symbol = + ExportedSymbol::NoDefId(SymbolName::new(tcx, NO_ALLOC_SHIM_IS_UNSTABLE)); + symbols.push(( + exported_symbol, + SymbolExportInfo { + level: SymbolExportLevel::Rust, + kind: SymbolExportKind::Data, + used: false, + }, + )) } if tcx.sess.instrument_coverage() || tcx.sess.opts.cg.profile_generate.enabled() { @@ -333,7 +344,7 @@ fn exported_symbols_provider_local( match *mono_item { MonoItem::Fn(Instance { def: InstanceDef::Item(def), substs }) => { if substs.non_erasable_generics().next().is_some() { - let symbol = ExportedSymbol::Generic(def.did, substs); + let symbol = ExportedSymbol::Generic(def, substs); symbols.push(( symbol, SymbolExportInfo { diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 2dda4cd16..c323372bd 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -872,7 +872,7 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>( let load_from_incr_comp_dir = |output_path: PathBuf, saved_path: &str| { let source_file = in_incr_comp_dir(&incr_comp_session_dir, saved_path); debug!( - "copying pre-existing module `{}` from {:?} to {}", + "copying preexisting module `{}` from {:?} to {}", module.name, source_file, output_path.display() @@ -1821,9 +1821,15 @@ impl SharedEmitterMain { let source = sess .source_map() .new_source_file(FileName::inline_asm_source_code(&buffer), buffer); - let source_span = Span::with_root_ctxt(source.start_pos, source.end_pos); - let spans: Vec<_> = - spans.iter().map(|sp| source_span.from_inner(*sp)).collect(); + let spans: Vec<_> = spans + .iter() + .map(|sp| { + Span::with_root_ctxt( + source.normalized_byte_pos(sp.start as u32), + source.normalized_byte_pos(sp.end as u32), + ) + }) + .collect(); err.span_note(spans, "instantiated into assembly here"); } @@ -1833,7 +1839,7 @@ impl SharedEmitterMain { sess.abort_if_errors(); } Ok(SharedEmitterMessage::Fatal(msg)) => { - sess.fatal(&msg); + sess.fatal(msg); } Err(_) => { break; diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index c5ca7936a..ab7dd1ba8 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -13,32 +13,29 @@ use crate::mir::place::PlaceRef; use crate::traits::*; use crate::{CachedModuleCodegen, CompiledModule, CrateInfo, MemFlags, ModuleCodegen, ModuleKind}; -use rustc_ast::expand::allocator::AllocatorKind; +use rustc_ast::expand::allocator::{global_fn_name, AllocatorKind, ALLOCATOR_METHODS}; use rustc_attr as attr; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry}; - -use rustc_data_structures::sync::par_iter; -#[cfg(parallel_compiler)] -use rustc_data_structures::sync::ParallelIterator; +use rustc_data_structures::sync::par_map; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::lang_items::LangItem; use rustc_metadata::EncodedMetadata; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; +use rustc_middle::middle::debugger_visualizer::{DebuggerVisualizerFile, DebuggerVisualizerType}; use rustc_middle::middle::exported_symbols; use rustc_middle::middle::exported_symbols::SymbolExportKind; use rustc_middle::middle::lang_items; use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem}; +use rustc_middle::query::Providers; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout}; -use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use rustc_session::cgu_reuse_tracker::CguReuse; use rustc_session::config::{self, CrateType, EntryFnType, OutputType}; use rustc_session::Session; use rustc_span::symbol::sym; use rustc_span::Symbol; -use rustc_span::{DebuggerVisualizerFile, DebuggerVisualizerType}; use rustc_target::abi::{Align, FIRST_VARIANT}; use std::collections::BTreeSet; @@ -494,7 +491,7 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( (rust_main, start_ty, vec![arg_argc, arg_argv]) }; - let result = bx.call(start_ty, None, start_fn, &args, None); + let result = bx.call(start_ty, None, None, start_fn, &args, None); let cast = bx.intcast(result, cx.type_int(), true); bx.ret(cast); @@ -689,7 +686,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>( // This likely is a temporary measure. Once we don't have to support the // non-parallel compiler anymore, we can compile CGUs end-to-end in // parallel and get rid of the complicated scheduling logic. - let mut pre_compiled_cgus = if cfg!(parallel_compiler) { + let mut pre_compiled_cgus = if tcx.sess.threads() > 1 { tcx.sess.time("compile_first_CGU_batch", || { // Try to find one CGU to compile per thread. let cgus: Vec<_> = cgu_reuse @@ -702,12 +699,10 @@ pub fn codegen_crate<B: ExtraBackendMethods>( // Compile the found CGUs in parallel. let start_time = Instant::now(); - let pre_compiled_cgus = par_iter(cgus) - .map(|(i, _)| { - let module = backend.compile_codegen_unit(tcx, codegen_units[i].name()); - (i, module) - }) - .collect(); + let pre_compiled_cgus = par_map(cgus, |(i, _)| { + let module = backend.compile_codegen_unit(tcx, codegen_units[i].name()); + (i, module) + }); total_codegen_time += start_time.elapsed(); @@ -914,7 +909,21 @@ impl CrateInfo { missing_weak_lang_items .iter() .map(|item| (format!("{prefix}{item}"), SymbolExportKind::Text)), - ) + ); + if tcx.allocator_kind(()).is_some() { + // At least one crate needs a global allocator. This crate may be placed + // after the crate that defines it in the linker order, in which case some + // linkers return an error. By adding the global allocator shim methods to + // the linked_symbols list, linking the generated symbols.o will ensure that + // circular dependencies involving the global allocator don't lead to linker + // errors. + linked_symbols.extend(ALLOCATOR_METHODS.iter().map(|method| { + ( + format!("{prefix}{}", global_fn_name(method.name).as_str()), + SymbolExportKind::Text, + ) + })); + } }); } diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 8542bab68..d6c230127 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -7,13 +7,14 @@ use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE}; use rustc_hir::{lang_items, weak_lang_items::WEAK_LANG_ITEMS, LangItem}; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc_middle::mir::mono::Linkage; -use rustc_middle::ty::query::Providers; +use rustc_middle::query::Providers; use rustc_middle::ty::{self as ty, TyCtxt}; use rustc_session::{lint, parse::feature_err}; use rustc_span::symbol::Ident; use rustc_span::{sym, Span}; use rustc_target::spec::{abi, SanitizerSet}; +use crate::errors; use crate::target_features::from_target_feature; use crate::{errors::ExpectedUsedSymbol, target_features::check_target_feature_trait_unsafe}; @@ -156,7 +157,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { None => { // Unfortunately, unconditionally using `llvm.used` causes // issues in handling `.init_array` with the gold linker, - // but using `llvm.compiler.used` caused a nontrival amount + // but using `llvm.compiler.used` caused a nontrivial amount // of unintentional ecosystem breakage -- particularly on // Mach-O targets. // @@ -300,7 +301,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { if let Some(val) = attr.value_str() { if val.as_str().bytes().any(|b| b == 0) { let msg = format!("illegal null byte in link_section value: `{}`", &val); - tcx.sess.span_err(attr.span, &msg); + tcx.sess.span_err(attr.span, msg); } else { codegen_fn_attrs.link_section = Some(val); } @@ -334,10 +335,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { codegen_fn_attrs.no_sanitize |= SanitizerSet::HWADDRESS } _ => { - tcx.sess - .struct_span_err(item.span(), "invalid argument for `no_sanitize`") - .note("expected one of: `address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow-call-stack`, or `thread`") - .emit(); + tcx.sess.emit_err(errors::InvalidNoSanitize { span: item.span() }); } } } @@ -594,24 +592,12 @@ fn should_inherit_track_caller(tcx: TyCtxt<'_>, def_id: DefId) -> bool { fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &ast::Attribute) -> Option<u16> { use rustc_ast::{LitIntType, LitKind, MetaItemLit}; - if !tcx.features().raw_dylib && tcx.sess.target.arch == "x86" { - feature_err( - &tcx.sess.parse_sess, - sym::raw_dylib, - attr.span, - "`#[link_ordinal]` is unstable on x86", - ) - .emit(); - } let meta_item_list = attr.meta_item_list(); let meta_item_list = meta_item_list.as_deref(); let sole_meta_list = match meta_item_list { Some([item]) => item.lit(), Some(_) => { - tcx.sess - .struct_span_err(attr.span, "incorrect number of arguments to `#[link_ordinal]`") - .note("the attribute requires exactly one argument") - .emit(); + tcx.sess.emit_err(errors::InvalidLinkOrdinalNargs { span: attr.span }); return None; } _ => None, @@ -636,16 +622,13 @@ fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &ast::Attribute) -> Option<u16> { } else { let msg = format!("ordinal value in `link_ordinal` is too large: `{}`", &ordinal); tcx.sess - .struct_span_err(attr.span, &msg) + .struct_span_err(attr.span, msg) .note("the value may not exceed `u16::MAX`") .emit(); None } } else { - tcx.sess - .struct_span_err(attr.span, "illegal ordinal format in `link_ordinal`") - .note("an unsuffixed integer value, e.g., `1`, is expected") - .emit(); + tcx.sess.emit_err(errors::InvalidLinkOrdinalFormat { span: attr.span }); None } } diff --git a/compiler/rustc_codegen_ssa/src/coverageinfo/ffi.rs b/compiler/rustc_codegen_ssa/src/coverageinfo/ffi.rs index e288760a0..1791ce4b3 100644 --- a/compiler/rustc_codegen_ssa/src/coverageinfo/ffi.rs +++ b/compiler/rustc_codegen_ssa/src/coverageinfo/ffi.rs @@ -1,6 +1,6 @@ use rustc_middle::mir::coverage::{CounterValueReference, MappedExpressionIndex}; -/// Aligns with [llvm::coverage::Counter::CounterKind](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L95) +/// Must match the layout of `LLVMRustCounterKind`. #[derive(Copy, Clone, Debug)] #[repr(C)] pub enum CounterKind { @@ -17,8 +17,10 @@ pub enum CounterKind { /// `instrprof.increment()`) /// * For `CounterKind::Expression`, `id` is the index into the coverage map's array of /// counter expressions. -/// Aligns with [llvm::coverage::Counter](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L102-L103) -/// Important: The Rust struct layout (order and types of fields) must match its C++ counterpart. +/// +/// Corresponds to struct `llvm::coverage::Counter`. +/// +/// Must match the layout of `LLVMRustCounter`. #[derive(Copy, Clone, Debug)] #[repr(C)] pub struct Counter { @@ -59,7 +61,9 @@ impl Counter { } } -/// Aligns with [llvm::coverage::CounterExpression::ExprKind](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L150) +/// Corresponds to enum `llvm::coverage::CounterExpression::ExprKind`. +/// +/// Must match the layout of `LLVMRustCounterExprKind`. #[derive(Copy, Clone, Debug)] #[repr(C)] pub enum ExprKind { @@ -67,9 +71,9 @@ pub enum ExprKind { Add = 1, } -/// Aligns with [llvm::coverage::CounterExpression](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L151-L152) -/// Important: The Rust struct layout (order and types of fields) must match its C++ -/// counterpart. +/// Corresponds to struct `llvm::coverage::CounterExpression`. +/// +/// Must match the layout of `LLVMRustCounterExpression`. #[derive(Copy, Clone, Debug)] #[repr(C)] pub struct CounterExpression { diff --git a/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs b/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs index 1ea130400..e4da3b8de 100644 --- a/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs +++ b/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs @@ -1,6 +1,6 @@ pub use super::ffi::*; -use rustc_index::vec::{IndexSlice, IndexVec}; +use rustc_index::{IndexSlice, IndexVec}; use rustc_middle::mir::coverage::{ CodeRegion, CounterValueReference, ExpressionOperandId, InjectedExpressionId, InjectedExpressionIndex, MappedExpressionIndex, Op, diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index f2469fde3..6297f9134 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -12,7 +12,7 @@ // * `"` is treated as the start of a string. use rustc_data_structures::fx::FxHashSet; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher}; use rustc_hir::def_id::DefId; use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathData}; use rustc_hir::{AsyncGeneratorKind, GeneratorKind, Mutability}; @@ -94,7 +94,7 @@ fn push_debuginfo_type_name<'tcx>( // Computing the layout can still fail here, e.g. if the target architecture // cannot represent the type. See https://github.com/rust-lang/rust/issues/94961. // FIXME: migrate once `rustc_middle::mir::interpret::InterpError` is translatable. - tcx.sess.fatal(&format!("{}", e)); + tcx.sess.fatal(format!("{}", e)); } } } else { @@ -675,8 +675,7 @@ fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: ty::Const<'tcx>, output: &mut S hcx.while_hashing_spans(false, |hcx| { ct.to_valtree().hash_stable(hcx, &mut hasher) }); - let hash: u64 = hasher.finish(); - hash + hasher.finish::<Hash64>() }); if cpp_like_debuginfo(tcx) { diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index 66e7e314f..cf4893b82 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -424,7 +424,7 @@ pub struct UnableToRunDsymutil { } #[derive(Diagnostic)] -#[diag(codegen_ssa_stripping_debu_info_failed)] +#[diag(codegen_ssa_stripping_debug_info_failed)] #[note] pub struct StrippingDebugInfoFailed<'a> { pub util: &'a str, @@ -981,3 +981,37 @@ impl IntoDiagnosticArg for ExpectedPointerMutability { } } } + +#[derive(Diagnostic)] +#[diag(codegen_ssa_invalid_no_sanitize)] +#[note] +pub struct InvalidNoSanitize { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(codegen_ssa_invalid_link_ordinal_nargs)] +#[note] +pub struct InvalidLinkOrdinalNargs { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(codegen_ssa_illegal_link_ordinal_format)] +#[note] +pub struct InvalidLinkOrdinalFormat { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(codegen_ssa_target_feature_safe_trait)] +pub struct TargetFeatureSafeTrait { + #[primary_span] + #[label] + pub span: Span, + #[label(codegen_ssa_label_def)] + pub def: Span, +} diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 0ab12314b..31854c7f4 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -25,20 +25,22 @@ use rustc_ast as ast; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::Lrc; use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; +use rustc_fluent_macro::fluent_messages; use rustc_hir::def_id::CrateNum; -use rustc_macros::fluent_messages; use rustc_middle::dep_graph::WorkProduct; +use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile; use rustc_middle::middle::dependency_format::Dependencies; use rustc_middle::middle::exported_symbols::SymbolExportKind; -use rustc_middle::ty::query::{ExternProviders, Providers}; -use rustc_serialize::opaque::{MemDecoder, MemEncoder}; +use rustc_middle::query::{ExternProviders, Providers}; +use rustc_serialize::opaque::{FileEncoder, MemDecoder}; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use rustc_session::config::{CrateType, OutputFilenames, OutputType, RUST_CGU_EXT}; use rustc_session::cstore::{self, CrateSource}; use rustc_session::utils::NativeLibKind; +use rustc_session::Session; use rustc_span::symbol::Symbol; -use rustc_span::DebuggerVisualizerFile; use std::collections::BTreeSet; +use std::io; use std::path::{Path, PathBuf}; pub mod back; @@ -174,11 +176,11 @@ pub struct CodegenResults { pub crate_info: CrateInfo, } -pub enum CodegenErrors<'a> { +pub enum CodegenErrors { WrongFileType, EmptyVersionNumber, EncodingVersionMismatch { version_array: String, rlink_version: u32 }, - RustcVersionMismatch { rustc_version: String, current_version: &'a str }, + RustcVersionMismatch { rustc_version: String }, } pub fn provide(providers: &mut Providers) { @@ -212,21 +214,23 @@ pub fn looks_like_rust_object_file(filename: &str) -> bool { const RLINK_VERSION: u32 = 1; const RLINK_MAGIC: &[u8] = b"rustlink"; -const RUSTC_VERSION: Option<&str> = option_env!("CFG_VERSION"); - impl CodegenResults { - pub fn serialize_rlink(codegen_results: &CodegenResults) -> Vec<u8> { - let mut encoder = MemEncoder::new(); + pub fn serialize_rlink( + sess: &Session, + rlink_file: &Path, + codegen_results: &CodegenResults, + ) -> Result<usize, io::Error> { + let mut encoder = FileEncoder::new(rlink_file)?; encoder.emit_raw_bytes(RLINK_MAGIC); // `emit_raw_bytes` is used to make sure that the version representation does not depend on // Encoder's inner representation of `u32`. encoder.emit_raw_bytes(&RLINK_VERSION.to_be_bytes()); - encoder.emit_str(RUSTC_VERSION.unwrap()); + encoder.emit_str(sess.cfg_version); Encodable::encode(codegen_results, &mut encoder); encoder.finish() } - pub fn deserialize_rlink<'a>(data: Vec<u8>) -> Result<Self, CodegenErrors<'a>> { + pub fn deserialize_rlink(sess: &Session, data: Vec<u8>) -> Result<Self, CodegenErrors> { // The Decodable machinery is not used here because it panics if the input data is invalid // and because its internal representation may change. if !data.starts_with(RLINK_MAGIC) { @@ -248,11 +252,9 @@ impl CodegenResults { let mut decoder = MemDecoder::new(&data[4..], 0); let rustc_version = decoder.read_str(); - let current_version = RUSTC_VERSION.unwrap(); - if rustc_version != current_version { + if rustc_version != sess.cfg_version { return Err(CodegenErrors::RustcVersionMismatch { rustc_version: rustc_version.to_string(), - current_version, }); } diff --git a/compiler/rustc_codegen_ssa/src/meth.rs b/compiler/rustc_codegen_ssa/src/meth.rs index 2421acab4..a8b935bd6 100644 --- a/compiler/rustc_codegen_ssa/src/meth.rs +++ b/compiler/rustc_codegen_ssa/src/meth.rs @@ -28,8 +28,9 @@ impl<'a, 'tcx> VirtualIndex { if bx.cx().sess().opts.unstable_opts.virtual_function_elimination && bx.cx().sess().lto() == Lto::Fat { - let typeid = - bx.typeid_metadata(typeid_for_trait_ref(bx.tcx(), expect_dyn_trait_in_self(ty))); + let typeid = bx + .typeid_metadata(typeid_for_trait_ref(bx.tcx(), expect_dyn_trait_in_self(ty))) + .unwrap(); let vtable_byte_offset = self.0 * bx.data_layout().pointer_size.bytes(); let func = bx.type_checked_load(llvtable, vtable_byte_offset, typeid); bx.pointercast(func, llty) @@ -67,10 +68,10 @@ impl<'a, 'tcx> VirtualIndex { /// ref of the type. fn expect_dyn_trait_in_self(ty: Ty<'_>) -> ty::PolyExistentialTraitRef<'_> { for arg in ty.peel_refs().walk() { - if let GenericArgKind::Type(ty) = arg.unpack() { - if let ty::Dynamic(data, _, _) = ty.kind() { - return data.principal().expect("expected principal trait object"); - } + if let GenericArgKind::Type(ty) = arg.unpack() + && let ty::Dynamic(data, _, _) = ty.kind() + { + return data.principal().expect("expected principal trait object"); } } diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs index f43f1d64a..22c1f0597 100644 --- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs +++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs @@ -5,7 +5,7 @@ use super::FunctionCx; use crate::traits::*; use rustc_data_structures::graph::dominators::Dominators; use rustc_index::bit_set::BitSet; -use rustc_index::vec::{IndexSlice, IndexVec}; +use rustc_index::{IndexSlice, IndexVec}; use rustc_middle::mir::traversal; use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::{self, Location, TerminatorKind}; @@ -84,7 +84,7 @@ impl DefLocation { struct LocalAnalyzer<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { fx: &'mir FunctionCx<'a, 'tcx, Bx>, - dominators: Dominators<mir::BasicBlock>, + dominators: &'mir Dominators<mir::BasicBlock>, locals: IndexVec<mir::Local, LocalKind>, } @@ -203,7 +203,9 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx> self.assign(local, DefLocation::Body(location)); } - PlaceContext::NonUse(_) | PlaceContext::MutatingUse(MutatingUseContext::Retag) => {} + PlaceContext::NonUse(_) + | PlaceContext::NonMutatingUse(NonMutatingUseContext::PlaceMention) + | PlaceContext::MutatingUse(MutatingUseContext::Retag) => {} PlaceContext::NonMutatingUse( NonMutatingUseContext::Copy | NonMutatingUseContext::Move, diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index dd8697781..3f0b64b11 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -12,7 +12,6 @@ use crate::MemFlags; use rustc_ast as ast; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_hir::lang_items::LangItem; -use rustc_index::vec::Idx; use rustc_middle::mir::{self, AssertKind, SwitchTargets}; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement}; use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; @@ -20,7 +19,6 @@ use rustc_middle::ty::{self, Instance, Ty}; use rustc_session::config::OptLevel; use rustc_span::source_map::Span; use rustc_span::{sym, Symbol}; -use rustc_symbol_mangling::typeid::typeid_for_fnabi; use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode, Reg}; use rustc_target::abi::{self, HasDataLayout, WrappingRange}; use rustc_target::spec::abi::Abi; @@ -164,6 +162,12 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { // do an invoke, otherwise do a call. let fn_ty = bx.fn_decl_backend_type(&fn_abi); + let fn_attrs = if bx.tcx().def_kind(fx.instance.def_id()).has_codegen_attrs() { + Some(bx.tcx().codegen_fn_attrs(fx.instance.def_id())) + } else { + None + }; + if !fn_abi.can_unwind { unwind = mir::UnwindAction::Unreachable; } @@ -191,6 +195,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { }; let invokeret = bx.invoke( fn_ty, + fn_attrs, Some(&fn_abi), fn_ptr, &llargs, @@ -212,7 +217,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { } MergingSucc::False } else { - let llret = bx.call(fn_ty, Some(&fn_abi), fn_ptr, &llargs, self.funclet(fx)); + let llret = bx.call(fn_ty, fn_attrs, Some(&fn_abi), fn_ptr, &llargs, self.funclet(fx)); if fx.mir[self.bb].is_cleanup { // Cleanup is always the cold path. Don't inline // drop glue. Also, when there is a deeply-nested @@ -369,7 +374,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { if self.fn_abi.c_variadic { // The `VaList` "spoofed" argument is just after all the real arguments. let va_list_arg_idx = self.fn_abi.args.len(); - match self.locals[mir::Local::new(1 + va_list_arg_idx)] { + match self.locals[mir::Local::from_usize(1 + va_list_arg_idx)] { LocalRef::Place(va_list) => { bx.va_end(va_list.llval); } @@ -1026,7 +1031,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }); let needs_location = - instance.map_or(false, |i| i.def.requires_caller_location(self.cx.tcx())); + instance.is_some_and(|i| i.def.requires_caller_location(self.cx.tcx())); if needs_location { let mir_args = if let Some(num_untupled) = num_untupled { first_args.len() + num_untupled @@ -1052,48 +1057,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.codegen_argument(bx, location, &mut llargs, last_arg); } - let (is_indirect_call, fn_ptr) = match (llfn, instance) { - (Some(llfn), _) => (true, llfn), - (None, Some(instance)) => (false, bx.get_fn_addr(instance)), - _ => span_bug!(span, "no llfn for call"), + let fn_ptr = match (instance, llfn) { + (Some(instance), None) => bx.get_fn_addr(instance), + (_, Some(llfn)) => llfn, + _ => span_bug!(span, "no instance or llfn for call"), }; - // For backends that support CFI using type membership (i.e., testing whether a given - // pointer is associated with a type identifier). - if bx.tcx().sess.is_sanitizer_cfi_enabled() && is_indirect_call { - // Emit type metadata and checks. - // FIXME(rcvalle): Add support for generalized identifiers. - // FIXME(rcvalle): Create distinct unnamed MDNodes for internal identifiers. - let typeid = typeid_for_fnabi(bx.tcx(), fn_abi); - let typeid_metadata = self.cx.typeid_metadata(typeid); - - // Test whether the function pointer is associated with the type identifier. - let cond = bx.type_test(fn_ptr, typeid_metadata); - let bb_pass = bx.append_sibling_block("type_test.pass"); - let bb_fail = bx.append_sibling_block("type_test.fail"); - bx.cond_br(cond, bb_pass, bb_fail); - - bx.switch_to_block(bb_pass); - let merging_succ = helper.do_call( - self, - bx, - fn_abi, - fn_ptr, - &llargs, - target.as_ref().map(|&target| (ret_dest, target)), - unwind, - &copied_constant_arguments, - false, - ); - assert_eq!(merging_succ, MergingSucc::False); - - bx.switch_to_block(bb_fail); - bx.abort(); - bx.unreachable(); - - return MergingSucc::False; - } - helper.do_call( self, bx, @@ -1287,7 +1256,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { MergingSucc::False } - mir::TerminatorKind::Drop { place, target, unwind } => { + mir::TerminatorKind::Drop { place, target, unwind, replace: _ } => { self.codegen_drop_terminator(helper, bx, place, target, unwind, mergeable_succ()) } @@ -1481,11 +1450,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { ) -> OperandRef<'tcx, Bx::Value> { let tcx = bx.tcx(); - let mut span_to_caller_location = |mut span: Span| { - // Remove `Inlined` marks as they pollute `expansion_cause`. - while span.is_inlined() { - span.remove_mark(); - } + let mut span_to_caller_location = |span: Span| { let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span); let caller = tcx.sess.source_map().lookup_char_pos(topmost.lo()); let const_loc = tcx.const_caller_location(( @@ -1631,7 +1596,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx = Bx::build(self.cx, llbb); let llpersonality = self.cx.eh_personality(); - bx.cleanup_landing_pad(llpersonality); + bx.filter_landing_pad(llpersonality); funclet = None; } @@ -1641,7 +1606,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let (fn_abi, fn_ptr) = common::build_langcall(&bx, None, LangItem::PanicCannotUnwind); let fn_ty = bx.fn_decl_backend_type(&fn_abi); - let llret = bx.call(fn_ty, Some(&fn_abi), fn_ptr, &[], funclet.as_ref()); + let llret = bx.call(fn_ty, None, Some(&fn_abi), fn_ptr, &[], funclet.as_ref()); bx.do_not_inline(llret); bx.unreachable(); diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs index d049bafb8..bba2800fb 100644 --- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs +++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs @@ -1,5 +1,5 @@ use crate::traits::*; -use rustc_index::vec::IndexVec; +use rustc_index::IndexVec; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir; use rustc_middle::ty; @@ -8,7 +8,7 @@ use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf}; use rustc_session::config::DebugInfo; use rustc_span::symbol::{kw, Symbol}; use rustc_span::{BytePos, Span}; -use rustc_target::abi::{Abi, FieldIdx, Size, VariantIdx}; +use rustc_target::abi::{Abi, FieldIdx, FieldsShape, Size, VariantIdx}; use super::operand::{OperandRef, OperandValue}; use super::place::PlaceRef; @@ -41,6 +41,9 @@ pub struct PerLocalVarDebugInfo<'tcx, D> { /// `.place.projection` from `mir::VarDebugInfo`. pub projection: &'tcx ty::List<mir::PlaceElem<'tcx>>, + + /// `references` from `mir::VarDebugInfo`. + pub references: u8, } #[derive(Clone, Copy, Debug)] @@ -80,6 +83,7 @@ trait DebugInfoOffsetLocation<'tcx, Bx> { fn deref(&self, bx: &mut Bx) -> Self; fn layout(&self) -> TyAndLayout<'tcx>; fn project_field(&self, bx: &mut Bx, field: FieldIdx) -> Self; + fn project_constant_index(&self, bx: &mut Bx, offset: u64) -> Self; fn downcast(&self, bx: &mut Bx, variant: VariantIdx) -> Self; } @@ -98,6 +102,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> DebugInfoOffsetLocation<'tcx, Bx> PlaceRef::project_field(*self, bx, field.index()) } + fn project_constant_index(&self, bx: &mut Bx, offset: u64) -> Self { + let lloffset = bx.cx().const_usize(offset); + self.project_index(bx, lloffset) + } + fn downcast(&self, bx: &mut Bx, variant: VariantIdx) -> Self { self.project_downcast(bx, variant) } @@ -120,6 +129,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> DebugInfoOffsetLocation<'tcx, Bx> self.field(bx.cx(), field.index()) } + fn project_constant_index(&self, bx: &mut Bx, index: u64) -> Self { + self.field(bx.cx(), index as usize) + } + fn downcast(&self, bx: &mut Bx, variant: VariantIdx) -> Self { self.for_variant(bx.cx(), variant) } @@ -165,6 +178,18 @@ fn calculate_debuginfo_offset< mir::ProjectionElem::Downcast(_, variant) => { place = place.downcast(bx, variant); } + mir::ProjectionElem::ConstantIndex { + offset: index, + min_length: _, + from_end: false, + } => { + let offset = indirect_offsets.last_mut().unwrap_or(&mut direct_offset); + let FieldsShape::Array { stride, count: _ } = place.layout().fields else { + span_bug!(var.source_info.span, "ConstantIndex on non-array type {:?}", place.layout()) + }; + *offset += stride * index; + place = place.project_constant_index(bx, index); + } _ => { // Sanity check for `can_use_in_debuginfo`. debug_assert!(!elem.can_use_in_debuginfo()); @@ -293,6 +318,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { dbg_var, fragment: None, projection: ty::List::empty(), + references: 0, }) } } else { @@ -358,55 +384,74 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let vars = vars.iter().cloned().chain(fallback_var); for var in vars { - let Some(dbg_var) = var.dbg_var else { continue }; - let Some(dbg_loc) = self.dbg_loc(var.source_info) else { continue }; - - let DebugInfoOffset { direct_offset, indirect_offsets, result: _ } = - calculate_debuginfo_offset(bx, local, &var, base.layout); - - // When targeting MSVC, create extra allocas for arguments instead of pointing multiple - // dbg_var_addr() calls into the same alloca with offsets. MSVC uses CodeView records - // not DWARF and LLVM doesn't support translating the resulting - // [DW_OP_deref, DW_OP_plus_uconst, offset, DW_OP_deref] debug info to CodeView. - // Creating extra allocas on the stack makes the resulting debug info simple enough - // that LLVM can generate correct CodeView records and thus the values appear in the - // debugger. (#83709) - let should_create_individual_allocas = bx.cx().sess().target.is_like_msvc - && self.mir.local_kind(local) == mir::LocalKind::Arg - // LLVM can handle simple things but anything more complex than just a direct - // offset or one indirect offset of 0 is too complex for it to generate CV records - // correctly. - && (direct_offset != Size::ZERO - || !matches!(&indirect_offsets[..], [Size::ZERO] | [])); - - if should_create_individual_allocas { - let DebugInfoOffset { direct_offset: _, indirect_offsets: _, result: place } = - calculate_debuginfo_offset(bx, local, &var, base); - - // Create a variable which will be a pointer to the actual value - let ptr_ty = bx - .tcx() - .mk_ptr(ty::TypeAndMut { mutbl: mir::Mutability::Mut, ty: place.layout.ty }); - let ptr_layout = bx.layout_of(ptr_ty); - let alloca = PlaceRef::alloca(bx, ptr_layout); - bx.set_var_name(alloca.llval, &(var.name.to_string() + ".dbg.spill")); - - // Write the pointer to the variable - bx.store(place.llval, alloca.llval, alloca.align); - - // Point the debug info to `*alloca` for the current variable - bx.dbg_var_addr(dbg_var, dbg_loc, alloca.llval, Size::ZERO, &[Size::ZERO], None); - } else { - bx.dbg_var_addr( - dbg_var, - dbg_loc, - base.llval, - direct_offset, - &indirect_offsets, - None, - ); + self.debug_introduce_local_as_var(bx, local, base, var); + } + } + + fn debug_introduce_local_as_var( + &self, + bx: &mut Bx, + local: mir::Local, + mut base: PlaceRef<'tcx, Bx::Value>, + var: PerLocalVarDebugInfo<'tcx, Bx::DIVariable>, + ) { + let Some(dbg_var) = var.dbg_var else { return }; + let Some(dbg_loc) = self.dbg_loc(var.source_info) else { return }; + + let DebugInfoOffset { mut direct_offset, indirect_offsets, result: _ } = + calculate_debuginfo_offset(bx, local, &var, base.layout); + let mut indirect_offsets = &indirect_offsets[..]; + + // When targeting MSVC, create extra allocas for arguments instead of pointing multiple + // dbg_var_addr() calls into the same alloca with offsets. MSVC uses CodeView records + // not DWARF and LLVM doesn't support translating the resulting + // [DW_OP_deref, DW_OP_plus_uconst, offset, DW_OP_deref] debug info to CodeView. + // Creating extra allocas on the stack makes the resulting debug info simple enough + // that LLVM can generate correct CodeView records and thus the values appear in the + // debugger. (#83709) + let should_create_individual_allocas = bx.cx().sess().target.is_like_msvc + && self.mir.local_kind(local) == mir::LocalKind::Arg + // LLVM can handle simple things but anything more complex than just a direct + // offset or one indirect offset of 0 is too complex for it to generate CV records + // correctly. + && (direct_offset != Size::ZERO || !matches!(indirect_offsets, [Size::ZERO] | [])); + + let create_alloca = |bx: &mut Bx, place: PlaceRef<'tcx, Bx::Value>, refcount| { + // Create a variable which will be a pointer to the actual value + let ptr_ty = bx + .tcx() + .mk_ptr(ty::TypeAndMut { mutbl: mir::Mutability::Mut, ty: place.layout.ty }); + let ptr_layout = bx.layout_of(ptr_ty); + let alloca = PlaceRef::alloca(bx, ptr_layout); + bx.set_var_name(alloca.llval, &format!("{}.ref{}.dbg.spill", var.name, refcount)); + + // Write the pointer to the variable + bx.store(place.llval, alloca.llval, alloca.align); + + // Point the debug info to `*alloca` for the current variable + alloca + }; + + if var.references > 0 { + base = calculate_debuginfo_offset(bx, local, &var, base).result; + + // Point the debug info to `&...&base == alloca` for the current variable + for refcount in 0..var.references { + base = create_alloca(bx, base, refcount); } + + direct_offset = Size::ZERO; + indirect_offsets = &[]; + } else if should_create_individual_allocas { + let place = calculate_debuginfo_offset(bx, local, &var, base).result; + + // Point the debug info to `*alloca` for the current variable + base = create_alloca(bx, place, 0); + direct_offset = Size::ZERO; + indirect_offsets = &[Size::ZERO]; } + + bx.dbg_var_addr(dbg_var, dbg_loc, base.llval, direct_offset, indirect_offsets, None); } pub fn debug_introduce_locals(&self, bx: &mut Bx) { @@ -439,7 +484,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }; let dbg_var = dbg_scope_and_span.map(|(dbg_scope, _, span)| { - let (var_ty, var_kind) = match var.value { + let (mut var_ty, var_kind) = match var.value { mir::VarDebugInfoContents::Place(place) => { let var_ty = self.monomorphized_place_ty(place.as_ref()); let var_kind = if let Some(arg_index) = var.argument_index @@ -476,6 +521,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } }; + for _ in 0..var.references { + var_ty = + bx.tcx().mk_ptr(ty::TypeAndMut { mutbl: mir::Mutability::Mut, ty: var_ty }); + } + self.cx.create_dbg_var(var.name, var_ty, dbg_scope, var_kind, span) }); @@ -487,6 +537,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { dbg_var, fragment: None, projection: place.projection, + references: var.references, }); } mir::VarDebugInfoContents::Const(c) => { @@ -494,6 +545,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let Some(dbg_loc) = self.dbg_loc(var.source_info) else { continue }; if let Ok(operand) = self.eval_mir_constant_to_operand(bx, &c) { + self.set_debug_loc(bx, var.source_info); let base = Self::spill_operand_to_stack( &operand, Some(var.name.to_string()), @@ -539,6 +591,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { Some(fragment_start..fragment_start + fragment_layout.size) }, projection: place.projection, + references: var.references, }); } } diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs index 7af7fc92d..1479242f2 100644 --- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs @@ -135,13 +135,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { .unwrap(); OperandRef::from_const(bx, value, ret_ty).immediate_or_packed_pair(bx) } - sym::offset => { - let ty = substs.type_at(0); - let layout = bx.layout_of(ty); - let ptr = args[0].immediate(); - let offset = args[1].immediate(); - bx.inbounds_gep(bx.backend_type(layout), ptr, &[offset]) - } sym::arith_offset => { let ty = substs.type_at(0); let layout = bx.layout_of(ty); diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index 3dadb33c9..1204c99e5 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -9,7 +9,7 @@ use rustc_target::abi::call::{FnAbi, PassMode}; use std::iter; use rustc_index::bit_set::BitSet; -use rustc_index::vec::IndexVec; +use rustc_index::IndexVec; use self::debuginfo::{FunctionDebugContext, PerLocalVarDebugInfo}; use self::place::PlaceRef; @@ -111,7 +111,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.instance.subst_mir_and_normalize_erasing_regions( self.cx.tcx(), ty::ParamEnv::reveal_all(), - value, + ty::EarlyBinder(value), ) } } @@ -152,7 +152,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( cx: &'a Bx::CodegenCx, instance: Instance<'tcx>, ) { - assert!(!instance.substs.needs_infer()); + assert!(!instance.substs.has_infer()); let llfn = cx.get_fn(instance); @@ -304,7 +304,17 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( bug!("spread argument isn't a tuple?!"); }; - let place = PlaceRef::alloca(bx, bx.layout_of(arg_ty)); + let layout = bx.layout_of(arg_ty); + + // FIXME: support unsized params in "rust-call" ABI + if layout.is_unsized() { + span_bug!( + arg_decl.source_info.span, + "\"rust-call\" ABI does not support unsized params", + ); + } + + let place = PlaceRef::alloca(bx, layout); for i in 0..tupled_arg_tys.len() { let arg = &fx.fn_abi.args[idx]; idx += 1; diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index b37797fef..2301c3ef1 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -2,6 +2,7 @@ use super::place::PlaceRef; use super::{FunctionCx, LocalRef}; use crate::base; +use crate::common::TypeKind; use crate::glue; use crate::traits::*; use crate::MemFlags; @@ -236,19 +237,47 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { }; match (&mut val, field.abi) { - (OperandValue::Immediate(llval), _) => { + ( + OperandValue::Immediate(llval), + Abi::Scalar(_) | Abi::ScalarPair(..) | Abi::Vector { .. }, + ) => { // Bools in union fields needs to be truncated. *llval = bx.to_immediate(*llval, field); // HACK(eddyb) have to bitcast pointers until LLVM removes pointee types. - *llval = bx.bitcast(*llval, bx.cx().immediate_backend_type(field)); + let ty = bx.cx().immediate_backend_type(field); + if bx.type_kind(ty) == TypeKind::Pointer { + *llval = bx.pointercast(*llval, ty); + } } (OperandValue::Pair(a, b), Abi::ScalarPair(a_abi, b_abi)) => { // Bools in union fields needs to be truncated. *a = bx.to_immediate_scalar(*a, a_abi); *b = bx.to_immediate_scalar(*b, b_abi); // HACK(eddyb) have to bitcast pointers until LLVM removes pointee types. - *a = bx.bitcast(*a, bx.cx().scalar_pair_element_backend_type(field, 0, true)); - *b = bx.bitcast(*b, bx.cx().scalar_pair_element_backend_type(field, 1, true)); + let a_ty = bx.cx().scalar_pair_element_backend_type(field, 0, true); + let b_ty = bx.cx().scalar_pair_element_backend_type(field, 1, true); + if bx.type_kind(a_ty) == TypeKind::Pointer { + *a = bx.pointercast(*a, a_ty); + } + if bx.type_kind(b_ty) == TypeKind::Pointer { + *b = bx.pointercast(*b, b_ty); + } + } + // Newtype vector of array, e.g. #[repr(simd)] struct S([i32; 4]); + (OperandValue::Immediate(llval), Abi::Aggregate { sized: true }) => { + assert!(matches!(self.layout.abi, Abi::Vector { .. })); + + let llty = bx.cx().backend_type(self.layout); + let llfield_ty = bx.cx().backend_type(field); + + // Can't bitcast an aggregate, so round trip through memory. + let lltemp = bx.alloca(llfield_ty, field.align.abi); + let llptr = bx.pointercast(lltemp, bx.cx().type_ptr_to(llty)); + bx.store(*llval, llptr, field.align.abi); + *llval = bx.load(llfield_ty, lltemp, field.align.abi); + } + (OperandValue::Immediate(_), Abi::Uninhabited | Abi::Aggregate { sized: false }) => { + bug!() } (OperandValue::Pair(..), _) => bug!(), (OperandValue::Ref(..), _) => bug!(), @@ -373,8 +402,6 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue<V> { indirect_dest: PlaceRef<'tcx, V>, ) { debug!("OperandRef::store_unsized: operand={:?}, indirect_dest={:?}", self, indirect_dest); - let flags = MemFlags::empty(); - // `indirect_dest` must have `*mut T` type. We extract `T` out of it. let unsized_ty = indirect_dest .layout @@ -387,17 +414,23 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue<V> { bug!("store_unsized called with a sized value") }; - // FIXME: choose an appropriate alignment, or use dynamic align somehow - let max_align = Align::from_bits(128).unwrap(); - let min_align = Align::from_bits(8).unwrap(); - - // Allocate an appropriate region on the stack, and copy the value into it - let (llsize, _) = glue::size_and_align_of_dst(bx, unsized_ty, Some(llextra)); - let lldst = bx.byte_array_alloca(llsize, max_align); - bx.memcpy(lldst, max_align, llptr, min_align, llsize, flags); + // Allocate an appropriate region on the stack, and copy the value into it. Since alloca + // doesn't support dynamic alignment, we allocate an extra align - 1 bytes, and align the + // pointer manually. + let (size, align) = glue::size_and_align_of_dst(bx, unsized_ty, Some(llextra)); + let one = bx.const_usize(1); + let align_minus_1 = bx.sub(align, one); + let size_extra = bx.add(size, align_minus_1); + let min_align = Align::ONE; + let alloca = bx.byte_array_alloca(size_extra, min_align); + let address = bx.ptrtoint(alloca, bx.type_isize()); + let neg_address = bx.neg(address); + let offset = bx.and(neg_address, align_minus_1); + let dst = bx.inbounds_gep(bx.type_i8(), alloca, &[offset]); + bx.memcpy(dst, min_align, llptr, min_align, size, MemFlags::empty()); // Store the allocated region and the extra to the indirect place. - let indirect_operand = OperandValue::Pair(lldst, llextra); + let indirect_operand = OperandValue::Pair(dst, llextra); indirect_operand.store(bx, indirect_dest); } } diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index d88226f5d..6e7065713 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -12,6 +12,7 @@ use rustc_middle::mir::Operand; use rustc_middle::ty::cast::{CastTy, IntTy}; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, adjustment::PointerCast, Instance, Ty, TyCtxt}; +use rustc_session::config::OptLevel; use rustc_span::source_map::{Span, DUMMY_SP}; use rustc_target::abi::{self, FIRST_VARIANT}; @@ -231,10 +232,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { (ScalarOrZst::Scalar(in_scalar), ScalarOrZst::Scalar(out_scalar)) if in_scalar.size(self.cx) == out_scalar.size(self.cx) => { + let operand_bty = bx.backend_type(operand.layout); let cast_bty = bx.backend_type(cast); - Some(OperandValue::Immediate( - self.transmute_immediate(bx, imm, in_scalar, out_scalar, cast_bty), - )) + Some(OperandValue::Immediate(self.transmute_immediate( + bx, + imm, + in_scalar, + operand_bty, + out_scalar, + cast_bty, + ))) } _ => None, } @@ -250,11 +257,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { && in_a.size(self.cx) == out_a.size(self.cx) && in_b.size(self.cx) == out_b.size(self.cx) { + let in_a_ibty = bx.scalar_pair_element_backend_type(operand.layout, 0, false); + let in_b_ibty = bx.scalar_pair_element_backend_type(operand.layout, 1, false); let out_a_ibty = bx.scalar_pair_element_backend_type(cast, 0, false); let out_b_ibty = bx.scalar_pair_element_backend_type(cast, 1, false); Some(OperandValue::Pair( - self.transmute_immediate(bx, imm_a, in_a, out_a, out_a_ibty), - self.transmute_immediate(bx, imm_b, in_b, out_b, out_b_ibty), + self.transmute_immediate(bx, imm_a, in_a, in_a_ibty, out_a, out_a_ibty), + self.transmute_immediate(bx, imm_b, in_b, in_b_ibty, out_b, out_b_ibty), )) } else { None @@ -273,6 +282,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx: &mut Bx, mut imm: Bx::Value, from_scalar: abi::Scalar, + from_backend_ty: Bx::Type, to_scalar: abi::Scalar, to_backend_ty: Bx::Type, ) -> Bx::Value { @@ -280,6 +290,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { use abi::Primitive::*; imm = bx.from_immediate(imm); + + // When scalars are passed by value, there's no metadata recording their + // valid ranges. For example, `char`s are passed as just `i32`, with no + // way for LLVM to know that they're 0x10FFFF at most. Thus we assume + // the range of the input value too, not just the output range. + self.assume_scalar_range(bx, imm, from_scalar, from_backend_ty); + imm = match (from_scalar.primitive(), to_scalar.primitive()) { (Int(..) | F32 | F64, Int(..) | F32 | F64) => bx.bitcast(imm, to_backend_ty), (Pointer(..), Pointer(..)) => bx.pointercast(imm, to_backend_ty), @@ -294,10 +311,55 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx.bitcast(int_imm, to_backend_ty) } }; + self.assume_scalar_range(bx, imm, to_scalar, to_backend_ty); imm = bx.to_immediate_scalar(imm, to_scalar); imm } + fn assume_scalar_range( + &self, + bx: &mut Bx, + imm: Bx::Value, + scalar: abi::Scalar, + backend_ty: Bx::Type, + ) { + if matches!(self.cx.sess().opts.optimize, OptLevel::No | OptLevel::Less) + // For now, the critical niches are all over `Int`eger values. + // Should floating-point values or pointers ever get more complex + // niches, then this code will probably want to handle them too. + || !matches!(scalar.primitive(), abi::Primitive::Int(..)) + || scalar.is_always_valid(self.cx) + { + return; + } + + let abi::WrappingRange { start, end } = scalar.valid_range(self.cx); + + if start <= end { + if start > 0 { + let low = bx.const_uint_big(backend_ty, start); + let cmp = bx.icmp(IntPredicate::IntUGE, imm, low); + bx.assume(cmp); + } + + let type_max = scalar.size(self.cx).unsigned_int_max(); + if end < type_max { + let high = bx.const_uint_big(backend_ty, end); + let cmp = bx.icmp(IntPredicate::IntULE, imm, high); + bx.assume(cmp); + } + } else { + let low = bx.const_uint_big(backend_ty, start); + let cmp_low = bx.icmp(IntPredicate::IntUGE, imm, low); + + let high = bx.const_uint_big(backend_ty, end); + let cmp_high = bx.icmp(IntPredicate::IntULE, imm, high); + + let or = bx.or(cmp_low, cmp_high); + bx.assume(or); + } + } + pub fn codegen_rvalue_unsized( &mut self, bx: &mut Bx, @@ -604,13 +666,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } - mir::Rvalue::NullaryOp(null_op, ty) => { + mir::Rvalue::NullaryOp(ref null_op, ty) => { let ty = self.monomorphize(ty); assert!(bx.cx().type_is_sized(ty)); let layout = bx.cx().layout_of(ty); let val = match null_op { mir::NullOp::SizeOf => layout.size.bytes(), mir::NullOp::AlignOf => layout.align.abi.bytes(), + mir::NullOp::OffsetOf(fields) => { + layout.offset_of_subfield(bx.cx(), fields.iter().map(|f| f.index())).bytes() + } }; let val = bx.cx().const_usize(val); let tcx = self.cx.tcx(); @@ -632,7 +697,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let fn_ptr = bx.get_fn_addr(instance); let fn_abi = bx.fn_abi_of_instance(instance, ty::List::empty()); let fn_ty = bx.fn_decl_backend_type(&fn_abi); - bx.call(fn_ty, Some(fn_abi), fn_ptr, &[], None) + let fn_attrs = if bx.tcx().def_kind(instance.def_id()).has_codegen_attrs() { + Some(bx.tcx().codegen_fn_attrs(instance.def_id())) + } else { + None + }; + bx.call(fn_ty, fn_attrs, Some(fn_abi), fn_ptr, &[], None) } else { bx.get_static(def_id) }; @@ -754,8 +824,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { .builtin_deref(true) .unwrap_or_else(|| bug!("deref of non-pointer {:?}", input_ty)) .ty; - let llty = bx.cx().backend_type(bx.cx().layout_of(pointee_type)); - bx.inbounds_gep(llty, lhs, &[rhs]) + let pointee_layout = bx.cx().layout_of(pointee_type); + if pointee_layout.is_zst() { + // `Offset` works in terms of the size of pointee, + // so offsetting a pointer to ZST is a noop. + lhs + } else { + let llty = bx.cx().backend_type(pointee_layout); + bx.inbounds_gep(llty, lhs, &[rhs]) + } } mir::BinOp::Shl => common::build_unchecked_lshift(bx, lhs, rhs), mir::BinOp::Shr => common::build_unchecked_rshift(bx, input_ty, lhs, rhs), diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index 611dd3d1c..c5976a654 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -1,3 +1,4 @@ +use crate::errors; use rustc_ast::ast; use rustc_attr::InstructionSetAttr; use rustc_data_structures::fx::FxHashMap; @@ -7,7 +8,7 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_hir::def_id::LocalDefId; use rustc_hir::def_id::LOCAL_CRATE; -use rustc_middle::ty::query::Providers; +use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; use rustc_session::parse::feature_err; use rustc_session::Session; @@ -172,16 +173,13 @@ const X86_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[ ("avx512dq", Some(sym::avx512_target_feature)), ("avx512er", Some(sym::avx512_target_feature)), ("avx512f", Some(sym::avx512_target_feature)), - ("avx512gfni", Some(sym::avx512_target_feature)), ("avx512ifma", Some(sym::avx512_target_feature)), ("avx512pf", Some(sym::avx512_target_feature)), - ("avx512vaes", Some(sym::avx512_target_feature)), ("avx512vbmi", Some(sym::avx512_target_feature)), ("avx512vbmi2", Some(sym::avx512_target_feature)), ("avx512vl", Some(sym::avx512_target_feature)), ("avx512vnni", Some(sym::avx512_target_feature)), ("avx512vp2intersect", Some(sym::avx512_target_feature)), - ("avx512vpclmulqdq", Some(sym::avx512_target_feature)), ("avx512vpopcntdq", Some(sym::avx512_target_feature)), ("bmi1", None), ("bmi2", None), @@ -252,6 +250,7 @@ const RISCV_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[ ("f", Some(sym::riscv_target_feature)), ("m", Some(sym::riscv_target_feature)), ("relax", Some(sym::riscv_target_feature)), + ("unaligned-scalar-mem", Some(sym::riscv_target_feature)), ("v", Some(sym::riscv_target_feature)), ("zba", Some(sym::riscv_target_feature)), ("zbb", Some(sym::riscv_target_feature)), @@ -369,7 +368,7 @@ pub fn from_target_feature( let Some(feature_gate) = supported_target_features.get(feature) else { let msg = format!("the feature named `{}` is not valid for this target", feature); - let mut err = tcx.sess.struct_span_err(item.span(), &msg); + let mut err = tcx.sess.struct_span_err(item.span(), msg); err.span_label( item.span(), format!("`{}` is not valid for this target", feature), @@ -407,7 +406,7 @@ pub fn from_target_feature( &tcx.sess.parse_sess, feature_gate.unwrap(), item.span(), - &format!("the target feature `{}` is currently unstable", feature), + format!("the target feature `{}` is currently unstable", feature), ) .emit(); } @@ -443,14 +442,10 @@ pub fn check_target_feature_trait_unsafe(tcx: TyCtxt<'_>, id: LocalDefId, attr_s if let DefKind::AssocFn = tcx.def_kind(id) { let parent_id = tcx.local_parent(id); if let DefKind::Trait | DefKind::Impl { of_trait: true } = tcx.def_kind(parent_id) { - tcx.sess - .struct_span_err( - attr_span, - "`#[target_feature(..)]` cannot be applied to safe trait method", - ) - .span_label(attr_span, "cannot be applied to safe trait method") - .span_label(tcx.def_span(id), "not an `unsafe` function") - .emit(); + tcx.sess.emit_err(errors::TargetFeatureSafeTrait { + span: attr_span, + def: tcx.def_span(id), + }); } } } diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs index 64bebe50d..d83bfc740 100644 --- a/compiler/rustc_codegen_ssa/src/traits/backend.rs +++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs @@ -1,3 +1,5 @@ +use std::any::Any; + use super::write::WriteBackendMethods; use super::CodegenObject; use crate::back::write::TargetMachineFactoryFn; @@ -5,11 +7,12 @@ use crate::{CodegenResults, ModuleCodegen}; use rustc_ast::expand::allocator::AllocatorKind; use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::sync::{DynSend, DynSync}; use rustc_errors::ErrorGuaranteed; use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; +use rustc_middle::query::{ExternProviders, Providers}; use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, LayoutOf, TyAndLayout}; -use rustc_middle::ty::query::{ExternProviders, Providers}; use rustc_middle::ty::{Ty, TyCtxt}; use rustc_session::{ config::{self, OutputFilenames, PrintRequest}, @@ -20,10 +23,6 @@ use rustc_span::symbol::Symbol; use rustc_target::abi::call::FnAbi; use rustc_target::spec::Target; -pub use rustc_data_structures::sync::MetadataRef; - -use std::any::Any; - pub trait BackendTypes { type Value: CodegenObject; type Function: CodegenObject; @@ -117,7 +116,9 @@ pub trait CodegenBackend { ) -> Result<(), ErrorGuaranteed>; } -pub trait ExtraBackendMethods: CodegenBackend + WriteBackendMethods + Sized + Send + Sync { +pub trait ExtraBackendMethods: + CodegenBackend + WriteBackendMethods + Sized + Send + Sync + DynSend + DynSync +{ fn codegen_allocator<'tcx>( &self, tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs index 194768d94..853c6934c 100644 --- a/compiler/rustc_codegen_ssa/src/traits/builder.rs +++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs @@ -14,6 +14,7 @@ use crate::mir::operand::OperandRef; use crate::mir::place::PlaceRef; use crate::MemFlags; +use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::ty::layout::{HasParamEnv, TyAndLayout}; use rustc_middle::ty::Ty; use rustc_span::Span; @@ -72,6 +73,7 @@ pub trait BuilderMethods<'a, 'tcx>: fn invoke( &mut self, llty: Self::Type, + fn_attrs: Option<&CodegenFnAttrs>, fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, llfn: Self::Value, args: &[Self::Value], @@ -272,6 +274,7 @@ pub trait BuilderMethods<'a, 'tcx>: // These are used by everyone except msvc fn cleanup_landing_pad(&mut self, pers_fn: Self::Value) -> (Self::Value, Self::Value); + fn filter_landing_pad(&mut self, pers_fn: Self::Value) -> (Self::Value, Self::Value); fn resume(&mut self, exn0: Self::Value, exn1: Self::Value); // These are used only by msvc @@ -321,6 +324,7 @@ pub trait BuilderMethods<'a, 'tcx>: fn call( &mut self, llty: Self::Type, + fn_attrs: Option<&CodegenFnAttrs>, fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, llfn: Self::Value, args: &[Self::Value], diff --git a/compiler/rustc_codegen_ssa/src/traits/type_.rs b/compiler/rustc_codegen_ssa/src/traits/type_.rs index 32905b079..36d986422 100644 --- a/compiler/rustc_codegen_ssa/src/traits/type_.rs +++ b/compiler/rustc_codegen_ssa/src/traits/type_.rs @@ -128,12 +128,16 @@ pub trait LayoutTypeMethods<'tcx>: Backend<'tcx> { ) -> Self::Type; } -// For backends that support CFI using type membership (i.e., testing whether a given pointer is +// For backends that support CFI using type membership (i.e., testing whether a given pointer is // associated with a type identifier). pub trait TypeMembershipMethods<'tcx>: Backend<'tcx> { - fn set_type_metadata(&self, function: Self::Function, typeid: String); - fn typeid_metadata(&self, typeid: String) -> Self::Value; - fn set_kcfi_type_metadata(&self, function: Self::Function, typeid: u32); + fn add_type_metadata(&self, _function: Self::Function, _typeid: String) {} + fn set_type_metadata(&self, _function: Self::Function, _typeid: String) {} + fn typeid_metadata(&self, _typeid: String) -> Option<Self::Value> { + None + } + fn add_kcfi_type_metadata(&self, _function: Self::Function, _typeid: u32) {} + fn set_kcfi_type_metadata(&self, _function: Self::Function, _typeid: u32) {} } pub trait ArgAbiMethods<'tcx>: HasCodegen<'tcx> { |