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

New codegen backend: Start emitting code. #971

Merged
merged 1 commit into from
Feb 21, 2024
Merged

Conversation

vext01
Copy link
Contributor

@vext01 vext01 commented Feb 9, 2024

This makes a start at emitting X86_64 code from the JIT IR.

Obviously this is non-functional at this point (it's currently not even called from the JIT pipeline), but should serve as something we can iterate upon and at least unit test in isolation.

Many things missing:

  • Trace input handling.
  • Correct allocation sizes.
  • Stackmaps
  • Debugger support.
  • Loads more testing.
  • Cross-arch testing support.

This PR is already large, so I've held off doing those for now.

Raising as a draft, as I think this could perhaps use some more tests.


#[test]
fn simple_codegen() {
let mut aot_mod = aot_ir::Module::default();
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@ltratt @ptersilie take a look at this test. Here we have to build an AOT module so that the JIT module can refer to parts of it. It's a bit awkward.

We could make the JIT module independent of the AOT module at the cost of copying. Is it worth the performance hit for testing?

Copy link
Contributor

Choose a reason for hiding this comment

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

Is it worth the performance hit for testing?

If it's the difference between "testing is intolerable" and "testing is tolerable" then I think "yes".

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@ptersilie what do you think?

Copy link
Contributor

Choose a reason for hiding this comment

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

I dunno. I seems a bit backwards to me to affect your performance for the sake of making testing easier. But if it makes us test less because it's such a hassle then that's also bad. Maybe we could have a general AOT module that we then use for all the tests. Or we make a helper that makes it easier to construct the AOT module. Maybe some syntax where you make a trace and it then generates the corresponding AOT module automatically.

I dunno, since @ltratt was so adamant we never ever copy from the AOT if we can help it, I think he will have to make that decision.

Copy link
Contributor

Choose a reason for hiding this comment

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

I didn't think about the impact of testing. Given the choice between "make testing plausible" and "squeeze every last drop of performance" I would go for "make testing plausible".

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 that's a no on generating the AOT/JIT module automatically from some description for testing?

It sounds like it could be fiddly to be honest.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think he means that in order to not copy the same type multiple types you need to know if you've already copied it and then return the copy instead.

One could do that, or just use a local hashmap instead. Either way, it's not a big deal IMHO.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We could use a hashmap, yes, but I thought you wouldn't like it. If that's OK then it simplifies some other paces where that idiom is in use too (separate PR).

Copy link
Contributor

Choose a reason for hiding this comment

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

The other possibility is to have two modes: a testing mode where we copy everything; and a non-testing mode where we reference things. Ultimately "make it testable" is our goal. We won't get everything right, but if that's our goal, at least we'll know what to prioritise.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

OK, so I think we should roll will "make it testable". I've made a note for two future PRs based on this discussion. Thanks.


#[test]
fn simple_codegen() {
let mut aot_mod = aot_ir::Module::default();
Copy link
Contributor

Choose a reason for hiding this comment

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

Is it worth the performance hit for testing?

If it's the difference between "testing is intolerable" and "testing is tolerable" then I think "yes".

@ltratt
Copy link
Contributor

ltratt commented Feb 9, 2024

This is a decent start! My main suggestion (other than the testing aspect) is that the PR currently uses impl extension in a way that's not very idiomatic and also very constraining. I think we probably want something like:

struct MachineIndependentStuff { ... }

impl MachineIndependentStuff { ... }

trait MachineDependent {
  fn emit_blah(...)
}

and then x86 impls that trait. This is a very rough sketch, though, obviously!

@vext01
Copy link
Contributor Author

vext01 commented Feb 12, 2024

I agree with your concerns about a statically compiled-in backend. I don't like it because it means we can only test one codegen backend on any given arch, when in reality we can test a lot of it, just not execution of another arch.

If it's OK with you, I think that should be another unit of work.

@ltratt
Copy link
Contributor

ltratt commented Feb 12, 2024

I agree with your concerns about a statically compiled-in backend. I don't like it because it means we can only test one codegen backend on any given arch, when in reality we can test a lot of it, just not execution of another arch.

I really think we need to improve this in this PR.

@vext01
Copy link
Contributor Author

vext01 commented Feb 13, 2024

Note: I've note modularised any of the stuff that might be common between different codegen backends, e.g. the abstract stack and allocation bits. Thinking of kicking that down the line until the time comes for another backend.

@ltratt
Copy link
Contributor

ltratt commented Feb 13, 2024

Thinking of kicking that down the line until the time comes for another backend.

I suggest that when it's easy to do so we should break things out: and it will often be as easy to break it out as not. But it doesn't have to be a big concern.

@vext01
Copy link
Contributor Author

vext01 commented Feb 13, 2024

I suggest that when it's easy to do so we should break things out

It's easy soonish. We won't know if I got it right until we have another backend of course.

@ltratt
Copy link
Contributor

ltratt commented Feb 13, 2024

It's easy soonish. We won't know if I got it right until we have another backend of course.

What I meant is: as we add new functionality, let's break it out. We of course won't get it 100% right, but inlining everything (especially when breaking it out is equally easy) is definitely 100% wrong :)

@vext01
Copy link
Contributor Author

vext01 commented Feb 13, 2024

What I meant is: as we add new functionality, let's break it out

So that means break it out right now in this PR. I'll start on that after lunch.

@vext01
Copy link
Contributor Author

vext01 commented Feb 19, 2024

Those last 3 commits do the "splitting out" and kill some unnecessary x86 guards.

If this looks good I can squash and sync the branch.

@vext01 vext01 marked this pull request as ready for review February 20, 2024 09:24
/// generation. The abstract stack pointer is zero-based, so the stack pointer value also serves as
/// the size of the stack.
///
/// The implementation is platform agnostic: as the stack gets bigger, the stack pointer grows
Copy link
Contributor

Choose a reason for hiding this comment

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

s/the stack pointer/abstract stack pointer/

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 6527226

@vext01
Copy link
Contributor Author

vext01 commented Feb 21, 2024

OK to squash?

@ltratt
Copy link
Contributor

ltratt commented Feb 21, 2024

Please squash.

@vext01
Copy link
Contributor Author

vext01 commented Feb 21, 2024

splat.

@ltratt ltratt added this pull request to the merge queue Feb 21, 2024
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Feb 21, 2024
@vext01
Copy link
Contributor Author

vext01 commented Feb 21, 2024

I need to update my local Rust :)

@vext01
Copy link
Contributor Author

vext01 commented Feb 21, 2024

Fixed. OK to squash?

@ltratt
Copy link
Contributor

ltratt commented Feb 21, 2024

Please squash.

@vext01
Copy link
Contributor Author

vext01 commented Feb 21, 2024

splat.

@ltratt ltratt added this pull request to the merge queue Feb 21, 2024
github-merge-queue bot pushed a commit that referenced this pull request Feb 21, 2024
New codegen backend: Start emitting code.
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Feb 21, 2024
@vext01
Copy link
Contributor Author

vext01 commented Feb 21, 2024

This failure is leaks being detected by address sanitiser. I guess I have to audit the changes for potential leaks.

@@ -92,6 +99,18 @@ macro_rules! index_16bit {
self.0.into()
}
}

// impl From<usize> for $struct {
Copy link
Contributor

Choose a reason for hiding this comment

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

Left over comments?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ug, yes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 3eb9bac

@vext01
Copy link
Contributor Author

vext01 commented Feb 21, 2024

As per offline discussion, disable asan for now. See #981

@vext01
Copy link
Contributor Author

vext01 commented Feb 21, 2024

OK to squash?

@ltratt
Copy link
Contributor

ltratt commented Feb 21, 2024

Please squash.

This makes a start at emitting X86_64 code from the JIT IR.

Obviously this is non-functional at this point (it's currently not even
called from the JIT pipeline), but should serve as something we can
iterate upon and at least unit test in isolation.

Many things missing:
 - Trace input handling.
 - Correct allocation sizes.
 - Stackmaps
 - Debugger support.
 - Loads more testing.

Note we disable asan for now:
ykjit#981
@vext01
Copy link
Contributor Author

vext01 commented Feb 21, 2024

splat.

@ltratt ltratt added this pull request to the merge queue Feb 21, 2024
Merged via the queue into ykjit:master with commit 7c6b99e Feb 21, 2024
2 checks passed
@vext01 vext01 deleted the gen-code branch February 21, 2024 13:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants