Commit Graph

86 Commits

Author SHA1 Message Date
Matthias Krüger
67762ffe35
Rollup merge of #90833 - tmiasko:optimization-remarks, r=nikic
Emit LLVM optimization remarks when enabled with `-Cremark`

The default diagnostic handler considers all remarks to be disabled by
default unless configured otherwise through LLVM internal flags:
`-pass-remarks`, `-pass-remarks-missed`, and `-pass-remarks-analysis`.
This behaviour makes `-Cremark` ineffective on its own.

Fix this by configuring a custom diagnostic handler that enables
optimization remarks based on the value of `-Cremark` option. With
`-Cremark=all` enabling all remarks.

Fixes #90924.

r? `@nikic`
2021-11-28 23:45:17 +01:00
Benjamin A. Bjørnseth
bb9dee95ed add rustc option for using LLVM stack smash protection
LLVM has built-in heuristics for adding stack canaries to functions. These
heuristics can be selected with LLVM function attributes. This patch adds a
rustc option `-Z stack-protector={none,basic,strong,all}` which controls the use
of these attributes. This gives rustc the same stack smash protection support as
clang offers through options `-fno-stack-protector`, `-fstack-protector`,
`-fstack-protector-strong`, and `-fstack-protector-all`. The protection this can
offer is demonstrated in test/ui/abi/stack-protector.rs. This fills a gap in the
current list of rustc exploit
mitigations (https://doc.rust-lang.org/rustc/exploit-mitigations.html),
originally discussed in #15179.

Stack smash protection adds runtime overhead and is therefore still off by
default, but now users have the option to trade performance for security as they
see fit. An example use case is adding Rust code in an existing C/C++ code base
compiled with stack smash protection. Without the ability to add stack smash
protection to the Rust code, the code base artifacts could be exploitable in
ways not possible if the code base remained pure C/C++.

Stack smash protection support is present in LLVM for almost all the current
tier 1/tier 2 targets: see
test/assembly/stack-protector/stack-protector-target-support.rs. The one
exception is nvptx64-nvidia-cuda. This patch follows clang's example, and adds a
warning message printed if stack smash protection is used with this target (see
test/ui/stack-protector/warn-stack-protector-unsupported.rs). Support for tier 3
targets has not been checked.

Since the heuristics are applied at the LLVM level, the heuristics are expected
to add stack smash protection to a fraction of functions comparable to C/C++.
Some experiments demonstrating how Rust code is affected by the different
heuristics can be found in
test/assembly/stack-protector/stack-protector-heuristics-effect.rs. There is
potential for better heuristics using Rust-specific safety information. For
example it might be reasonable to skip stack smash protection in functions which
transitively only use safe Rust code, or which uses only a subset of functions
the user declares safe (such as anything under `std.*`). Such alternative
heuristics could be added at a later point.

LLVM also offers a "safestack" sanitizer as an alternative way to guard against
stack smashing (see #26612). This could possibly also be included as a
stack-protection heuristic. An alternative is to add it as a sanitizer (#39699).
This is what clang does: safestack is exposed with option
`-fsanitize=safe-stack`.

The options are only supported by the LLVM backend, but as with other codegen
options it is visible in the main codegen option help menu. The heuristic names
"basic", "strong", and "all" are hopefully sufficiently generic to be usable in
other backends as well.

Reviewed-by: Nikita Popov <nikic@php.net>

Extra commits during review:

- [address-review] make the stack-protector option unstable

- [address-review] reduce detail level of stack-protector option help text

- [address-review] correct grammar in comment

- [address-review] use compiler flag to avoid merging functions in test

- [address-review] specify min LLVM version in fortanix stack-protector test

  Only for Fortanix test, since this target specifically requests the
  `--x86-experimental-lvi-inline-asm-hardening` flag.

- [address-review] specify required LLVM components in stack-protector tests

- move stack protector option enum closer to other similar option enums

- rustc_interface/tests: sort debug option list in tracking hash test

- add an explicit `none` stack-protector option

Revert "set LLVM requirements for all stack protector support test revisions"

This reverts commit a49b74f92a4e7d701d6f6cf63d207a8aff2e0f68.
2021-11-22 20:06:22 +01:00
Josh Stone
023cc968e1 Make LLVMRustGetOrInsertGlobal always return a GlobalVariable
`Module::getOrInsertGlobal` returns a `Constant*`, which is a super
class of `GlobalVariable`, but if the given type doesn't match an
existing declaration, it returns a bitcast of that global instead.
This causes UB when we pass that to `LLVMGetVisibility` which
unconditionally casts the opaque argument to a `GlobalValue*`.

Instead, we can do our own get-or-insert without worrying whether
existing types match exactly. It's not relevant when we're just trying
to get/set the linkage and visibility, and if types are needed we can
bitcast or error nicely from `rustc_codegen_llvm` instead.
2021-11-19 19:33:29 -08:00
Tomasz Miąsko
8fa45295f4 Recognize machine optimization remarks 2021-11-16 08:19:20 +01:00
Tomasz Miąsko
6846674c75 Emit LLVM optimization remarks when enabled with -Cremark
The default diagnostic handler considers all remarks to be disabled by
default unless configured otherwise through LLVM internal flags:
`-pass-remarks`, `-pass-remarks-missed`, and `-pass-remarks-analysis`.
This behaviour makes `-Cremark` ineffective on its own.

Fix this by configuring a custom diagnostic handler that enables
optimization remarks based on the value of `-Cremark` option. With
`-Cremark=all` enabling all remarks.
2021-11-16 08:19:20 +01:00
Krasimir Georgiev
d9f2d5f0e9 PassWrapper: additional sanitizer update to match clang
This happened later in the stream than the other changes, but the fix is
overlapping. Fix taken from a55c4ec1cee7683d9095327d9d33e7137ec25292 in
LLVM.
2021-11-11 09:05:21 -05:00
Augie Fackler
d440ce6a9f Didn't mean to invert this boolean. 2021-11-09 10:18:13 -05:00
Augie Fackler
6234a56949 rustc_llvm: update PassWrapper for recent LLVM
Now AddressSanitizerOptions is a struct, but at least the change was
tiny.

r? nikic
2021-11-09 10:18:13 -05:00
Tomasz Miąsko
5a09e12135 Initialize LLVM time trace profiler on each code generation thread
In https://reviews.llvm.org/D71059 LLVM 11, the time trace profiler was
extended to support multiple threads.

`timeTraceProfilerInitialize` creates a thread local profiler instance.
When a thread finishes `timeTraceProfilerFinishThread` moves a thread
local instance into a global collection of instances. Finally when all
codegen work is complete `timeTraceProfilerWrite` writes data from the
current thread local instance and the instances in global collection
of instances.

Previously, the profiler was intialized on a single thread only. Since
this thread performs no code generation on its own, the resulting
profile was empty.

Update LLVM codegen to initialize & finish time trace profiler on each
code generation thread.
2021-11-05 17:47:11 +01:00
Matthias Krüger
2f67647606
Rollup merge of #89581 - jblazquez:master, r=Mark-Simulacrum
Add -Z no-unique-section-names to reduce ELF header bloat.

This change adds a new compiler flag that can help reduce the size of ELF binaries that contain many functions.

By default, when enabling function sections (which is the default for most targets), the LLVM backend will generate different section names for each function. For example, a function `func` would generate a section called `.text.func`. Normally this is fine because the linker will merge all those sections into a single one in the binary. However, starting with [LLVM 12](https://github.com/llvm/llvm-project/commit/ee5d1a04), the backend will also generate unique section names for exception handling, resulting in thousands of `.gcc_except_table.*` sections ending up in the final binary because some linkers like LLD don't currently merge or strip these EH sections (see discussion [here](https://reviews.llvm.org/D83655)). This can bloat the ELF headers and string table significantly in binaries that contain many functions.

The new option is analogous to Clang's `-fno-unique-section-names`, and instructs LLVM to generate the same `.text` and `.gcc_except_table` section for each function, resulting in a smaller final binary.

The motivation to add this new option was because we have a binary that ended up with so many ELF sections (over 65,000) that it broke some existing ELF tools, which couldn't handle so many sections.

Here's our old binary:

```
$ readelf --sections old.elf | head -1
There are 71746 section headers, starting at offset 0x2a246508:

$ readelf --sections old.elf | grep shstrtab
  [71742] .shstrtab      STRTAB          0000000000000000 2977204c ad44bb 00      0   0  1
```

That's an 11MB+ string table. Here's the new binary using this option:

```
$ readelf --sections new.elf | head -1
There are 43 section headers, starting at offset 0x29143ca8:

$ readelf --sections new.elf | grep shstrtab
  [40] .shstrtab         STRTAB          0000000000000000 29143acc 0001db 00      0   0  1
```

The whole binary size went down by over 20MB, which is quite significant.
2021-10-25 22:59:46 +02:00
Josh Stone
e9f545b9a9 Update the minimum external LLVM to 12 2021-10-22 10:50:07 -07:00
Josh Stone
65150af1b4 Update the minimum external LLVM to 11 2021-10-22 09:22:18 -07:00
Krasimir Georgiev
e3c3f4a09c RustWrapper: adapt for an LLVM API change
No functional changes intended.

The LLVM commit
89b57061f7
moved TargetRegistry.(h|cpp) from Support to MC.
This adapts RustWrapper accordingly.
2021-10-18 09:48:47 +02:00
Javier Blazquez
4ed846ad4d Add -Z no-unique-section-names to reduce ELF header bloat.
This change adds a new compiler flag that can help reduce the size of
ELF binaries that contain many functions.

By default, when enabling function sections (which is the default for most
targets), the LLVM backend will generate different section names for each
function. For example, a function "func" would generate a section called
".text.func". Normally this is fine because the linker will merge all those
sections into a single one in the binary. However, starting with LLVM 12
(llvm/llvm-project@ee5d1a0), the backend will
also generate unique section names for exception handling, resulting in
thousands of ".gcc_except_table.*" sections ending up in the final binary
because some linkers don't currently merge or strip these EH sections.
This can bloat the ELF headers and string table significantly in
binaries that contain many functions.

The new option is analogous to Clang's -fno-unique-section-names, and
instructs LLVM to generate the same ".text" and ".gcc_except_table"
section for each function, resulting in smaller object files and
potentially a smaller final binary.
2021-10-11 12:09:32 -07:00
Jubilee
6c17601a2e
Rollup merge of #89025 - ricobbe:raw-dylib-link-ordinal, r=michaelwoerister
Implement `#[link_ordinal(n)]`

Allows the use of `#[link_ordinal(n)]` with `#[link(kind = "raw-dylib")]`, allowing Rust to link against DLLs that export symbols by ordinal rather than by name.  As long as the ordinal matches, the name of the function in Rust is not required to match the name of the corresponding function in the exporting DLL.

Part of #58713.
2021-10-07 20:26:11 -07:00
Jubilee
6c2d4bf3f7
Rollup merge of #87918 - mikebenfield:pr-afdo, r=nikic
Enable AutoFDO.

This largely involves implementing the options debug-info-for-profiling
and profile-sample-use and forwarding them on to LLVM.

AutoFDO can be used on x86-64 Linux like this:
rustc -O -Clink-arg='Wl,--no-rosegment' -Cdebug-info-for-profiling main.rs -o main
perf record -b ./main
create_llvm_prof --binary=main --out=code.prof
rustc -O -Cprofile-sample-use=code.prof main.rs -o main2

Now `main2` will have feedback directed optimization applied to it.

The create_llvm_prof tool can be obtained from this github repository:
https://github.com/google/autofdo

The option -Clink-arg='Wl,--no-rosegment' is necessary to avoid lld
putting an extra RO segment before the executable code, which would make
the binary silently incompatible with create_llvm_prof.
2021-10-07 20:26:09 -07:00
Michael Benfield
a17193dbb9 Enable AutoFDO.
This largely involves implementing the options debug-info-for-profiling
and profile-sample-use and forwarding them on to LLVM.

AutoFDO can be used on x86-64 Linux like this:
rustc -O -Cdebug-info-for-profiling main.rs -o main
perf record -b ./main
create_llvm_prof --binary=main --out=code.prof
rustc -O -Cprofile-sample-use=code.prof main.rs -o main2

Now `main2` will have feedback directed optimization applied to it.

The create_llvm_prof tool can be obtained from this github repository:
https://github.com/google/autofdo

Fixes #64892.
2021-10-06 19:36:52 +00:00
Krasimir Georgiev
67a82e20cf RustWrapper: adapt for LLVM API change of fatal_error_handler_t
No functional changes intended.

The LLVM commit
e463b69736
changed an argument of fatal_error_handler_t from std::string to char*.
This adapts RustWrapper accordingly.
2021-10-05 16:31:36 +02:00
Augie Fackler
12c3f50a90 PassWrapper: handle function rename from upstream D36850
thinLTOResolvePrevailingInModule became thinLTOFinalizeInModule and
gained the ability to propagate noRecurse and noUnwind function
attributes. I ran codegen tests with it both on and off, as the upstream
patch uses it in both modes, and the tests pass both ways. Given that,
it seemed reasonable to go ahead and let the propagation be enabled in
rustc, and see what happens. See https://reviews.llvm.org/D36850 for
more examples of how the new version of the function gets used.
2021-09-27 18:11:21 -04:00
Nikita Popov
074bbc6b87 Use correct pipeline for LTO at O0
Unlike the pre-link piplines, the LTO pipelines do support O0,
and using them is required to avoid leaving behind undefined
references for the linker.
2021-09-25 11:24:23 +02:00
the8472
1deef1f75d
Rollup merge of #89041 - sticnarf:sticnarf/fat-lto-dwarf, r=nagisa
Work around invalid DWARF bugs for fat LTO

This PR applies the same workaround in #46772 to fat LTO.

It seems to fix the bug reported in https://github.com/rust-lang/rust/issues/66118#issuecomment-917434036.
2021-09-22 19:03:21 +02:00
Richard Cobbe
142f6c0b07 Implement #[link_ordinal] attribute in the context of #[link(kind = "raw-dylib")]. 2021-09-20 14:50:35 -07:00
Yilin Chen
d5de680e20 Work around invalid DWARF bugs for fat LTO
Signed-off-by: Yilin Chen <sticnarf@gmail.com>
2021-09-17 23:19:38 +08:00
John Paul Adrian Glaubitz
fa27d50caa compiler/rustc_llvm: Enable M68k LLVM target 2021-09-17 15:07:14 +00:00
Augie Fackler
bc4d8af123 PassWrapper: these two lines shouldn't have been ifdef'd 2021-09-16 15:04:18 -04:00
Augie Fackler
a97f89aeb4 PassWrapper: handle separate Module*SanitizerPass
Change ab41eef9aca3 in LLVM split MemorySanitizerPass into
MemorySanitizerPass for functions and ModuleMemorySanitizerPass for
modules. There's a related change for ThreadSanitizerPass, and in here
since we're using a ModulePassManager I only add the module flavor of
the pass on LLVM 14.

r? @nikic cc @nagisa
2021-09-16 11:49:02 -04:00
Augie Fackler
4d045406d1 RustWrapper: remove some uses of AttrBuilder
Turns out we can also use Attribute::get*() methods here, and avoid the
AttrBuilder and an extra helper method here.
2021-09-08 10:47:41 -04:00
Augie Fackler
484b79b950 RustWrapper: just use the *AtIndex funcs directly
Otherwise we're kind of reimplementing the inverse of the well-named
methods, and that's not a direction we want to go.
2021-09-07 16:15:02 -04:00
Augie Fackler
532bb80f7f RustWrapper: avoid deleted unclear attribute methods
These were deleted in https://reviews.llvm.org/D108614, and in C++ I
definitely see the argument for their removal. I didn't try and
propagate the changes up into higher layers of rustc in this change
because my initial goal was to get rustc working against LLVM HEAD
promptly, but I'm happy to follow up with some refactoring to make the
API on the Rust side match the LLVM API more directly (though the way
the enum works in Rust makes the API less scary IMO).

r? @nagisa cc @nikic
2021-09-07 15:30:42 -04:00
Augie Fackler
027db5d036 RustWrapper: adapt to LLVM change 0f45c16f2caa
The above-mentioned commit (part of the LLVM 14 development cycle)
removes a method that rustc uses somewhat extensively. We mostly switch
to lower-level methods that exist in all versions of LLVM we use, so no
new ifdef logic is required in most cases.
2021-08-26 10:40:27 -04:00
Guillaume Gomez
2638d27ba5
Rollup merge of #88164 - durin42:llvm-14-san-opts, r=nikic
PassWrapper: adapt for LLVM 14 changes

These API changes appear to have all taken place in
https://reviews.llvm.org/D105007, which moved HWAddressSanitizerPass and
AddressSanitizerPass to only accept their options type as a ctor
argument instead of the sequence of bools etc. This required a couple of
parameter additions, which I made match the default prior to the
mentioned upstream LLVM change.

This patch restores rustc to building (though not quite passing all
tests, I've mailed other patches for those issues) against LLVM HEAD.
2021-08-22 20:52:53 +02:00
Augie Fackler
c4e6185385 PassWrapper: adapt for LLVM 14 changes
These API changes appear to have all taken place in
https://reviews.llvm.org/D105007, which moved HWAddressSanitizerPass and
AddressSanitizerPass to only accept their options type as a ctor
argument instead of the sequence of bools etc. This required a couple of
parameter additions, which I made match the default prior to the
mentioned upstream LLVM change.

This patch restores rustc to building (though not quite passing all
tests, I've mailed other patches for those issues) against LLVM HEAD.
2021-08-19 12:44:54 -04:00
Nikita Popov
621f5146c3 Handle SrcMgr diagnostics
This is how InlineAsm diagnostics with source information are
reported now. Previously a separate InlineAsm diagnostic handler
was used.
2021-08-16 18:28:17 +02:00
bors
2d10c2a330 Auto merge of #87798 - durin42:llvm-14, r=nikic
PassWrapper: handle move of OptimizationLevel class out of PassBuilder

This is the first build break of the LLVM 14 cycle, and was caused by
https://reviews.llvm.org/D107025. Mercifully an easy fix.
2021-08-08 04:33:22 +00:00
Augie Fackler
482f1901b0 PassWrapper: handle move of OptimizationLevel class out of PassBuilder
This is the first build break of the LLVM 14 cycle, and was caused by
https://reviews.llvm.org/D107025. Mercifully an easy fix.
2021-08-06 18:08:04 -04:00
Josh Stone
183d79cc09 Prepare call/invoke for opaque pointers
Rather than relying on `getPointerElementType()` from LLVM function
pointers, we now pass the function type explicitly when building `call`
or `invoke` instructions.
2021-08-05 10:58:55 -07:00
Tomasz Miąsko
8e0df32ad6 Replace LLVMConstInBoundsGEP with LLVMConstInBoundsGEP2*
A custom reimplementation of LLVMConstInBoundsGEP2 is used, since the
LLVM contains a declaration of LLVMConstInBoundsGEP2 but not the
implementation.
2021-08-04 15:51:30 +02:00
Nikita Popov
33e9a6b565 Pass type when creating atomic load
Instead of determining it from the pointer type, explicitly pass
the type to load.
2021-07-09 22:00:19 +02:00
Richard Cobbe
6aa45b71b1 Add first cut of functionality for #58713: support for #[link(kind = "raw-dylib")].
This does not yet support #[link_name] attributes on functions, the #[link_ordinal]
attribute, #[link(kind = "raw-dylib")] on extern blocks in bin crates, or
stdcall functions on 32-bit x86.
2021-06-04 18:01:35 -07:00
Alex Crichton
0e0338744d rustc: Store metadata-in-rlibs in object files
This commit updates how rustc compiler metadata is stored in rlibs.
Previously metadata was stored as a raw file that has the same format as
`--emit metadata`. After this commit, however, the metadata is encoded
into a small object file which has one section which is the contents of
the metadata.

The motivation for this commit is to fix a common case where #83730
arises. The problem is that when rustc crates a `dylib` crate type it
needs to include entire rlib files into the dylib, so it passes
`--whole-archive` (or the equivalent) to the linker. The problem with
this, though, is that the linker will attempt to read all files in the
archive. If the metadata file were left as-is (today) then the linker
would generate an error saying it can't read the file. The previous
solution was to alter the rlib just before linking, creating a new
archive in a temporary directory which has the metadata file removed.

This problem from before this commit is now removed if the metadata file
is stored in an object file that the linker can read. The only caveat we
have to take care of is to ensure that the linker never actually
includes the contents of the object file into the final output. We apply
similar tricks as the `.llvmbc` bytecode sections to do this.

This involved changing the metadata loading code a bit, namely updating
some of the LLVM C APIs used to use non-deprecated ones and fiddling
with the lifetimes a bit to get everything to work out. Otherwise though
this isn't intended to be a functional change really, only that metadata
is stored differently in archives now.

This should end up fixing #83730 because by default dylibs will no
longer have their rlib dependencies "altered" meaning that
split-debuginfo will continue to have valid paths pointing at the
original rlibs. (note that we still "alter" rlibs if LTO is enabled to
remove Rust object files and we also "alter" for the #[link(cfg)]
feature, but that's rarely used).

Closes #83730
2021-06-04 10:05:20 -07:00
bors
fc81ad22c4 Auto merge of #85416 - durin42:llvm-catchup-may-2021, r=nagisa
PassWrapper: update for LLVM change D102093

In https://reviews.llvm.org/D102093 lots of things stopped taking the
DebugLogging boolean parameter. Mercifully we appear to always set
DebugPassManager to false, so I don't think we're losing anything by not
passing this parameter.
2021-05-21 11:21:06 +00:00
Augie Fackler
445658ba6d PassWrapper: update for LLVM change D102093
In https://reviews.llvm.org/D102093 lots of things stopped taking the
DebugLogging boolean parameter. Mercifully we appear to always set
DebugPassManager to false, so I don't think we're losing anything by not
passing this parameter.
2021-05-17 14:14:34 -04:00
Nikita Popov
c2b15a6b64 Support -C passes in NewPM
And report an error if parsing the additional pass pipeline fails.
Threading through the error accounts for most of the changes here.
2021-05-08 10:58:08 +02:00
Nikita Popov
db140de8f2 Explicitly register GCOV profiling pass as well 2021-05-08 10:58:08 +02:00
Nikita Popov
5ecbe7fcf8 Explicitly register instrprof pass
Don't use "passes" for this purpose, explicitly insert it into
the correct place in the pipeline instead.
2021-05-08 10:58:08 +02:00
Fangrui Song
0142d1cb97 Replace llvm::sys::fs::F_None with llvm::sys::fs::OF_None
The former is deprecated.
OF_None has been available in LLVM since 2018-06.
2021-04-29 15:25:17 -07:00
Augie Fackler
fc2a74c640 RustWrapper: work around unification of diagnostic handlers
This lets me build against llvm/main as of March 23rd, 2021. I'm not
entirely sure this is _correct_, but it appears to be functionally
identical to what was done in LLVM: existing callsites of
setInlineAsmDiagnosticHandler were moved to SetDiagnosticHandler() on
the context object, which we already set up in both places that we
called setInlineAsmDiagnosticHandler().
2021-04-22 15:46:47 -04:00
Simonas Kazlauskas
487e27350a Don't set fast(-math) for certain simd ops
`fast-math` implies things like functions not being able to accept as an
argument or return as a result, say, `inf` which made these functions
confusingly named or behaving incorrectly, depending on how you
interpret it. Since the time when these intrinsics have been implemented
the intrinsics user's (stdsimd) approach has changed significantly and
so now it is required that these intrinsics operate normally rather than
in "whatever" way.

Fixes #84268
2021-04-17 23:33:10 +03:00
Matt Ickstadt
e258a5ba6e Categorize and explain target features support 2021-04-09 10:16:04 -05:00
Simonas Kazlauskas
2f000a78bf Manually set dso_local when its valid to do so
This should have no real effect in most cases, as e.g. `hidden`
visibility already implies `dso_local` (or at least LLVM IR does not
preserve the `dso_local` setting if the item is already `hidden`), but
it should fix `-Crelocation-model=static` and improve codegen in
executables.

Note that this PR does not exhaustively port the logic in [clang]. Only
the obviously correct portion and what is necessary to fix a regression
from LLVM 12 that relates to `-Crelocation_model=static`.

Fixes #83335

[clang]: 3001d080c8/clang/lib/CodeGen/CodeGenModule.cpp (L945-L1039)
2021-04-03 00:00:29 +03:00