Skip to content

Prepare call/invoke for opaque pointers #87743

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

Merged
merged 3 commits into from
Aug 7, 2021
Merged

Conversation

cuviper
Copy link
Member

@cuviper cuviper commented Aug 3, 2021

Rather than relying on getPointerElementType() from LLVM function
pointers, we now pass the function type explicitly when building call
or invoke instructions.

@rust-highfive
Copy link
Contributor

r? @jackh726

(rust-highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Aug 3, 2021
@cuviper
Copy link
Member Author

cuviper commented Aug 3, 2021

r? @nikic

@rust-highfive rust-highfive assigned nikic and unassigned jackh726 Aug 3, 2021
fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type {
let args_capacity: usize = self.args.iter().map(|arg|
fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>, decl: bool) -> &'ll Type {
// Ignore extra args when calling C variadic functions.
Copy link
Member

Choose a reason for hiding this comment

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

This comment is very slightly confusing. I think it would be somewhat more comprehensible if it said

Suggested change
// Ignore extra args when calling C variadic functions.
// Ignore variadic args when calling C variadic functions.

Additionally, this says "calling", but the ignoring only happens if decl is true

Copy link
Member

Choose a reason for hiding this comment

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

Finally another thing I find confusing here is that we tell LLVM the function as variadic regardless of decl, so I'm not exactly sure what purpose this serves? Is it intended to remove the VaList style argument?

Copy link
Member

Choose a reason for hiding this comment

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

Say you have fn(i32, i64, ...), and you call it like fn(i32, i64, bool, f32), I think the last two argument types need to be removed to make sure that the function signature at the call site matches the declaration. Maybe always using &self.args[..self.fixed_count] would work too though?

Copy link
Member Author

Choose a reason for hiding this comment

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

So, this variadic thing was the last bit I struggled with, and I'm happy to explore better ways to represent it.

The specific example that tripped when building std was libc::fcntl, which looks like this:

pub fn fcntl(fd: ::c_int, cmd: ::c_int, ...) -> ::c_int;

That turns into LLVM fn(i32, i32, ...) -> i32. The call site for set_cloexec in std passes three args, and the FnAbi::llvm_type from there gave me fn(i32, i32, i32, ...) -> i32 -- having that "extra" arg when its FnAbi was constructed, but still represented as variadic. However, that tripped an assertion:

rustc: [...]/rust/src/llvm-project/llvm/lib/Bitcode/Writer/ValueEnumerator.h:167: unsigned int llvm::ValueEnumerator::getTypeID(llvm::Type*) const: Assertion `I != TypeMap.end() && "Type not in ValueEnumerator!"' failed.

So I used fixed_count to try and get the original declaration type, which seems to work -- giving the same signature as element_type(val_ty(fn_ptr)) would if we didn't care about being opaque.

Maybe always using &self.args[..self.fixed_count] would work too though?

It at least needs to check for c_variadic, because I know that the #[track_caller] argument for &Location is also past the fixed_count. I can try it without considering the new decl parameter though, or outright removing that.

Copy link
Member

Choose a reason for hiding this comment

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

It at least needs to check for c_variadic, because I know that the #[track_caller] argument for &Location is also past the fixed_count.

That seems bad. At least on riscv that will cause the #[track_caller] argument to be handled like a vararg during the abi calculation.

Copy link
Member Author

Choose a reason for hiding this comment

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

At least on riscv that will cause the #[track_caller] argument to be handled like a vararg during the abi calculation.

I looked at that, but it's only called by adjust_for_cabi, which isn't used for Rust/intrinsic ABIs.

Copy link
Member Author

Choose a reason for hiding this comment

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

All tests passed locally without using decl, even with LLVM assertions, so I've removed it.

cuviper added 3 commits August 5, 2021 10:58
Rather than relying on `getPointerElementType()` from LLVM function
pointers, we now pass the function type explicitly when building `call`
or `invoke` instructions.
We can apply the `c_variadic` fix all the time, rather than trying to
distinguish between declarations and any other use.
@cuviper
Copy link
Member Author

cuviper commented Aug 5, 2021

AFAICS the remaining calls to element_type are only for vectors, so I've now strengthened it with a TypeKind check to treat element_type(pointer) as a bug.

@nikic
Copy link
Contributor

nikic commented Aug 7, 2021

@bors r+

@bors
Copy link
Collaborator

bors commented Aug 7, 2021

📌 Commit a292390 has been approved by nikic

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Aug 7, 2021
@bors
Copy link
Collaborator

bors commented Aug 7, 2021

⌛ Testing commit a292390 with merge 574d375...

@bors
Copy link
Collaborator

bors commented Aug 7, 2021

☀️ Test successful - checks-actions
Approved by: nikic
Pushing 574d375 to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Aug 7, 2021
@bors bors merged commit 574d375 into rust-lang:master Aug 7, 2021
@rustbot rustbot added this to the 1.56.0 milestone Aug 7, 2021
Comment on lines 285 to 287
fn fn_ptr_backend_type(&self, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> &'ll Type {
fn_abi.ptr_to_llvm_type(self)
}
Copy link
Member

Choose a reason for hiding this comment

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

I wonder if this method should have this default (or be inlined, but right now there's two callers):

self.type_ptr_to_ext(cx.data_layout().instruction_address_space)

(also type_ptr_to_ext should probably be renamed to type_ptr_to_in_addrspace or something)

@cuviper cuviper deleted the opaque-calls branch September 21, 2021 16:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
merged-by-bors This PR was explicitly merged by bors. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants