Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cg_llvm: Replace some DIBuilder wrappers with LLVM-C API bindings (part 2) #136632

Open
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

Zalathar
Copy link
Contributor

@Zalathar Zalathar commented Feb 6, 2025


This is the next batch of LLVMDIBuilder binding migrations.

This time I also introduced some safe wrapper methods, because I noticed a few cases where I was repeating the same irrelevant/default argument values at multiple call sites.

@Zalathar Zalathar added the A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. label Feb 6, 2025
@rust-log-analyzer

This comment has been minimized.

@Zalathar
Copy link
Contributor Author

Zalathar commented Feb 6, 2025

Looks like I discovered an existing bug by accidentally fixing it.

In #116096, the intent was to tell debuginfo that function ZSTs have a size of 0 bytes and an alignment of 1 byte. But because debuginfo typically handles alignment in bits, the alignment was accidentally set to 1 bit instead.

(It doesn't help that LLVM IR just prints “align” without specifying a unit, so align: 1 looks correct, but isn't. Looking at the implementation in AsmWriter.cpp, it is indeed printing out the alignment in bits.)

matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Feb 7, 2025
…ompiler-errors

Debuginfo for function ZSTs should have alignment of 8 bits, not 1 bit

In rust-lang#116096, function ZSTs were made to have debuginfo that gives them an alignment of “1”. But because alignment in LLVM debuginfo is denoted in *bits*, not bytes, this resulted in an alignment specification of 1 bit instead of 1 byte.

I don't know whether this has any practical consequences, but I noticed that a test started failing when I accidentally fixed the mistake while working on rust-lang#136632, so I extracted the fix (and the test adjustment) to this PR.
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Feb 8, 2025
…ompiler-errors

Debuginfo for function ZSTs should have alignment of 8 bits, not 1 bit

In rust-lang#116096, function ZSTs were made to have debuginfo that gives them an alignment of “1”. But because alignment in LLVM debuginfo is denoted in *bits*, not bytes, this resulted in an alignment specification of 1 bit instead of 1 byte.

I don't know whether this has any practical consequences, but I noticed that a test started failing when I accidentally fixed the mistake while working on rust-lang#136632, so I extracted the fix (and the test adjustment) to this PR.
rust-timer added a commit to rust-lang-ci/rust that referenced this pull request Feb 8, 2025
Rollup merge of rust-lang#136640 - Zalathar:debuginfo-align-bits, r=compiler-errors

Debuginfo for function ZSTs should have alignment of 8 bits, not 1 bit

In rust-lang#116096, function ZSTs were made to have debuginfo that gives them an alignment of “1”. But because alignment in LLVM debuginfo is denoted in *bits*, not bytes, this resulted in an alignment specification of 1 bit instead of 1 byte.

I don't know whether this has any practical consequences, but I noticed that a test started failing when I accidentally fixed the mistake while working on rust-lang#136632, so I extracted the fix (and the test adjustment) to this PR.
@bors
Copy link
Contributor

bors commented Feb 8, 2025

☔ The latest upstream changes (presumably #136728) made this pull request unmergeable. Please resolve the merge conflicts.

@bors bors added the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Feb 8, 2025
@Zalathar
Copy link
Contributor Author

I'll come back to this after #136881 has had a chance to land.

@rustbot rustbot added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Feb 14, 2025
@Zalathar
Copy link
Contributor Author

Rebased after #136640 and #136881.

@rustbot ready

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Feb 14, 2025
@Zalathar
Copy link
Contributor Author

Huh, somehow this never actually got assigned a reviewer.

r? workingjubilee (or reroll)

This is low-priority cleanup, so no particular rush.

(Also this will probably conflict with #137247 at some point.)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is where all the action is, then, since this makes-safe a few things...

@@ -1772,6 +1772,59 @@ unsafe extern "C" {
Scope: &'ll Metadata,
InlinedAt: Option<&'ll Metadata>,
) -> &'ll Metadata;

pub(crate) fn LLVMDIBuilderCreateSubroutineType<'ll>(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

trivially obvious but this can in fact do a UB if we violate it

Suggested change
pub(crate) fn LLVMDIBuilderCreateSubroutineType<'ll>(
/// create debuginfo for subroutine types
/// # Safety
/// - `ParameterTypes` and `NumParameterTypes` must be from the same slice
pub(crate) fn LLVMDIBuilderCreateSubroutineType<'ll>(

Flags: DIFlags, // (optional; default is `DIFlags::FlagZero`)
) -> &'ll Metadata;

pub(crate) fn LLVMDIBuilderCreateUnionType<'ll>(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same comment except for Name and NameLen, Elements and ElementsLen, UniqueId and UniqueIdLen, also please note whether the obvious should be a CStr with or without its nul byte

Comment on lines +1801 to +1819
pub(crate) fn LLVMDIBuilderCreateArrayType<'ll>(
Builder: &DIBuilder<'ll>,
Size: u64,
AlignInBits: u32,
Ty: &'ll Metadata,
Subscripts: *const &'ll Metadata,
NumSubscripts: c_uint,
) -> &'ll Metadata;

pub(crate) fn LLVMDIBuilderCreateBasicType<'ll>(
Builder: &DIBuilder<'ll>,
Name: *const c_uchar,
NameLen: size_t,
SizeInBits: u64,
Encoding: c_uint, // `LLVMDWARFTypeEncoding`
Flags: DIFlags, // (optional; default is `DIFlags::FlagZero`)
) -> &'ll Metadata;

pub(crate) fn LLVMDIBuilderCreatePointerType<'ll>(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same comments

Comment on lines +15 to +17
unsafe {
llvm::LLVMDIBuilderCreateSubroutineType(
self,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, so, it's somewhat hard to audit the safe wrappers if I don't know what safety constraints they are filling. I can guess, but I shouldn't have to. Either there should be safety comments on the wrapper decls or they should be on this block, so that future additions to these functions don't fuck up and change the parts of the code that have to be a certain way.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

like it could be, idk, instead of exhaustively listing param relationships

// SAFETY: this call is safe if we know the DIBuilder is live, which we do because
// we have it by-ref, and the rest is just translating slices to two params

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Feb 24, 2025
@Zalathar
Copy link
Contributor Author

Okay, so, it's somewhat hard to audit the safe wrappers if I don't know what safety constraints they are filling. I can guess, but I shouldn't have to. Either there should be safety comments on the wrapper decls or they should be on this block, so that future additions to these functions don't fuck up and change the parts of the code that have to be a certain way.

The bad news is that somebody has to guess, because LLVM doesn't document its API soundness conditions, and the hundreds of ad-hoc unsafe blocks in cg_llvm don't document their assumptions either.

I'm sympathetic to wanting to make these bindings more auditable (since I had to do my best to “audit” each one while making these changes), but practically speaking I don't think it's realistic for individual bindings/wrappers to have a SAFETY comment more detailed than “please see the general safety remarks in the module docs”.

(With the caveat that those docs mostly don't exist yet!)

At the very least, any safety notes that we do add should probably be honest about how YOLO they actually are, because overconfident safety docs can be worse than no safety docs at all.

@workingjubilee
Copy link
Member

workingjubilee commented Feb 25, 2025

@Zalathar well... I think that saying both the pointer and the len should come from the same slice is a pretty safe bet? 🤔

but yes you are right, please feel free to add this to any list of safety requirements:

/// - lol who knows? even LLVM doesn't

@workingjubilee
Copy link
Member

to rephrase my "I shouldn't have to guess" thing:

we should write down our guesses so we don't have to go through the process of resynthesizing the guesses each time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants