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

cranelift: Add LibCalls to the interpreter #4782

Merged
merged 11 commits into from
Aug 29, 2022

Conversation

afonso360
Copy link
Contributor

@afonso360 afonso360 commented Aug 25, 2022

👋 Hey,

This does not fix any of the issues reported by the fuzzer so far, but I think that is just a coincidence, since at some point it will generate a libcall and we cannot handle those either.

Edit: Actually this may have already been reported, but have returned the same error as #4758 so it wasn't reported separately.

This allows the interpreter to register libcall handlers and invoke them when called.

I switched the fuzzer generated libcall from Udiv to Ishl, reason being that we don't want libcalls that can trap. Both functions have identical signatures so we shouldn't have any input format changes to the fuzzer.

@github-actions github-actions bot added cranelift Issues related to the Cranelift code generator fuzzing Issues related to our fuzzing infrastructure labels Aug 25, 2022
@github-actions
Copy link

Subscribe to Label Action

cc @fitzgen

This issue or pull request has been labeled: "cranelift", "fuzzing"

Thus the following users have been cc'd because of the following labels:

  • fitzgen: fuzzing

To subscribe or unsubscribe from this label, edit the .github/subscribe-to-label.json configuration file.

Learn more.

@jameysharp
Copy link
Contributor

Huh. I was going to suggest that if there are libcalls with undefined behavior on some inputs then we should be limiting what we pass them to ensure that we only use them in ways consistent with the semantics we want. But I went to check how libcalls like UdivI64 or IshlI64 are used, and as far as I can tell, they aren't. We should probably remove them, yeah?

These libcalls are constructed in Rust source:

  • ElfTlsGetAddr
  • ElfTlsGetOffset
  • Memcmp
  • Memcpy
  • Memmove
  • Memset
  • Probestack

While these are constructed in the x64 ISLE rules (but not any other backend?):

  • CeilF32
  • CeilF64
  • FloorF32
  • FloorF64
  • FmaF32
  • FmaF64
  • NearestF32
  • NearestF64
  • TruncF32
  • TruncF64

LibCall::for_inst would construct some other libcalls, but apparently its only use was removed last year in bae4ec6, so I've excluded it from the above lists.

@afonso360
Copy link
Contributor Author

But I went to check how libcalls like UdivI64 or IshlI64 are used, and as far as I can tell, they aren't. We should probably remove them, yeah?

That sounds like a good idea.

While these are constructed in the x64 ISLE rules (but not any other backend?):

Yeah, x86 doesn't have native instructions for these without extensions, so we have to lower them as libcalls if some extensions are disabled. I only know about AArch64 but they have equivalents for these in the base ISA. Not sure about s390x but i assume its the same

We can emit something like CeilF32 or any other really. The only downside being that it puts us in the "Changes fuzzer input do not merge" category. I'm okay with that.

I think the float libcalls don't trap at all.

@afonso360 afonso360 marked this pull request as draft August 26, 2022 14:04
@afonso360
Copy link
Contributor Author

I've changed this in a few ways, and since we are going to change the input of the fuzzer we might as well do it properly and generate multiple libcalls, so we now do that.

I've also removed the unused libcalls and a few accessory bits.

Copy link
Contributor

@jameysharp jameysharp left a comment

Choose a reason for hiding this comment

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

This looks great! I was briefly sad that Opcode::Call handling got so much more complicated, but it all looks like useful complexity to me, so 👍

When we're ready to merge fuzzgen changes, I'm in favor of this one. I do have a couple suggestions, but I'd also merge it as-is.

Comment on lines 62 to 73
.with_libcall_handler(&|libcall: LibCall, args: SmallVec<[DataValue; 1]>| {
use LibCall::*;
Ok(smallvec![match (libcall, &args[..]) {
(CeilF32, [DataValue::F32(a)]) => DataValue::F32(a.ceil()),
(CeilF64, [DataValue::F64(a)]) => DataValue::F64(a.ceil()),
(FloorF32, [DataValue::F32(a)]) => DataValue::F32(a.floor()),
(FloorF64, [DataValue::F64(a)]) => DataValue::F64(a.floor()),
(TruncF32, [DataValue::F32(a)]) => DataValue::F32(a.trunc()),
(TruncF64, [DataValue::F64(a)]) => DataValue::F64(a.trunc()),
_ => unreachable!(),
}])
});
Copy link
Contributor

Choose a reason for hiding this comment

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

What do you think of defining this function in function_generator.rs next to the array of allowed libcalls?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The only reason I'm hesitant to do this is that fuzzgen is supposed to be executor agnostic (i.e. icache needs none of this), so it feels kinda weird to have a interpreter specific function there.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, that makes sense. But this is weird for the same reason that the function references are: only outer fuzz target knows which functions and which libcalls are okay to call. So I think the set of allowed libcalls (and functions) should be provided by the fuzz target. But I also don't think that needs to block merging this PR, it's just something I think we should revisit soon.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So I think the set of allowed libcalls (and functions) should be provided by the fuzz target.

I like that!

But I also don't think that needs to block merging this PR, it's just something I think we should revisit soon.

👍

cranelift/interpreter/src/interpreter.rs Outdated Show resolved Hide resolved
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cranelift:module cranelift Issues related to the Cranelift code generator fuzzing Issues related to our fuzzing infrastructure
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants