Stream: git-cranelift

Topic: cranelift / Issue #1404 add cranelift-module interface fo...


view this post on Zulip GitHub (Feb 24 2020 at 18:14):

froydnj opened Issue #1404:

Feature

lucetc needs some way of accessing the trap sites for every function it compiles:

https://github.com/bytecodealliance/lucet/blob/23305e5d8e08bed442c244d282b1a0389ed3d822/lucetc/src/output.rs#L69-L89

In the above snippet, the trap site access happens after Module::finish has been called, so we're working with faerie interfaces.

We are trying to port lucetc to use object instead of faerie underneath, mostly so lucetc can start generating PE/COFF objects with ease. It would reduce risk somewhat to be able to use cranelift-module as a high-level interface, swap between cranelift-object and cranelift-faerie with as few lines of code as possible, and deal with object and faerie themselves as little as possible (probably just to write out the .o file). Therefore, it would be convenient if this information about traps associated with each function were accessible through cranelift-module interfaces, rather than through lower-level interfaces.

Benefit

Trap information would be more easily accessible prior to module finalization. Though I don't know of anybody else who needs this kind of information about besides lucetc at this point.

Implementation

This is the tricky bit, because the three in-tree implementations differ substantially in their approach to trap collection:

I don't think there is a single method that all three interfaces could easily implement to iterate over (string-name, &Vec<TrapSite>) pairs. To implement such an interface, cranelift-object would need to have a way to map from FuncId to string-name, and that's awkward to do, given that object itself doesn't deal with symbol names as strings, but as Vec<u8>.

The alternative, iterating over (FuncId, &Vec<TrapSite>) pairs, would require some kind of modification to cranelift-faerie. We could change cranelift-faerie to map from string-name to FuncId: cranelift-faerie could grow a separate table for storing that mapping, but cranelift-module is already storing that mapping, and requiring cranelift-faerie to store it seems like wasted effort. Alternatively, the way cranelift-faerie stores its traps could be modified to look more like cranelift-object.

But then maybe the right thing to do is just moving trap collection into cranelift-module itself? Module::new would then grow a flag for indicating whether trap collection should be done. Module itself would probably contain a FuncId to Vec<TrapSite> mapping similar to cranelift-object, and then Backend::define_function would receive Option<&mut Vec<TrapSite>> for potentially accumulating traps.

Since cranelift-simplejit doesn't collect traps, it doesn't matter too much what interface gets decided on.

I think I prefer moving trap collection into cranelift-module itself, but modifying cranelift-faerie to make it more like cranelift-object and the implementing some sort of common iterator interface works, too.

Alternatives

The alternative is to keep the status quo, and lucetc would need to write two sets of code for defining certain pieces of information: one that defines those pieces with faerie and another that defines them with object.

view this post on Zulip GitHub (Feb 25 2020 at 00:28):

philipc commented on Issue #1404:

To implement such an interface, cranelift-object would need to have a way to map from FuncId to string-name

cranelift-module already has a map from FuncId to ModuleFunction which includes a name and is accessible via the ModuleNamespace that is commonly passed to backend methods.

Another alternative is to return the traps when defining functions, instead of storing them in the backend. So lucetc will need to build its trap tables as it goes, instead of doing it all at then end. I haven't looked deeply to see how nicely this would work out, but it seems that each function trap table gets its own independent symbol so I think it could be okay.

view this post on Zulip GitHub (Feb 25 2020 at 01:36):

pchickey commented on Issue #1404:

Returning the traps when defining functions seems like a good way to divide the responsibilities into cranelift-module and lucet. That would mean changing the codegen model of cranelift-module to do it at definition, rather than at finalize, but I don't think that is necessarily a bad thing.

view this post on Zulip GitHub (Feb 25 2020 at 01:36):

pchickey edited a comment on Issue #1404:

Returning the traps when defining functions seems like a good way to divide the responsibilities into cranelift-module and lucet. That would mean changing cranelift-module to perform codegen at definition time, rather than at finalize, but I don't think that is necessarily a bad thing.

view this post on Zulip GitHub (Feb 25 2020 at 19:43):

froydnj commented on Issue #1404:

That would mean changing cranelift-module to perform codegen at definition time, rather than at finalize, but I don't think that is necessarily a bad thing.

Doesn't cranelift-module already do this? cranelift-object's define_function says:

https://github.com/bytecodealliance/cranelift/blob/ea922e17f9c5febffe8f43019bc8697cf4656f04/cranelift-object/src/backend.rs#L177-L211

and cranelift-faerie/cranelift-simplejit do very similar things. I guess they don't have to, but the documentation on cranelift-module::define_function says "Define a function, producing the function body from the given Context."

view this post on Zulip GitHub (Feb 26 2020 at 16:13):

pchickey commented on Issue #1404:

Sorry, bad memory on my part, cranelift-module does do it that way, the system in lucet that preceeded it waited until the end.

view this post on Zulip GitHub (Feb 28 2020 at 23:28):

alexcrichton transferred Issue #1404:

Feature

lucetc needs some way of accessing the trap sites for every function it compiles:

https://github.com/bytecodealliance/lucet/blob/23305e5d8e08bed442c244d282b1a0389ed3d822/lucetc/src/output.rs#L69-L89

In the above snippet, the trap site access happens after Module::finish has been called, so we're working with faerie interfaces.

We are trying to port lucetc to use object instead of faerie underneath, mostly so lucetc can start generating PE/COFF objects with ease. It would reduce risk somewhat to be able to use cranelift-module as a high-level interface, swap between cranelift-object and cranelift-faerie with as few lines of code as possible, and deal with object and faerie themselves as little as possible (probably just to write out the .o file). Therefore, it would be convenient if this information about traps associated with each function were accessible through cranelift-module interfaces, rather than through lower-level interfaces.

Benefit

Trap information would be more easily accessible prior to module finalization. Though I don't know of anybody else who needs this kind of information about besides lucetc at this point.

Implementation

This is the tricky bit, because the three in-tree implementations differ substantially in their approach to trap collection:

I don't think there is a single method that all three interfaces could easily implement to iterate over (string-name, &Vec<TrapSite>) pairs. To implement such an interface, cranelift-object would need to have a way to map from FuncId to string-name, and that's awkward to do, given that object itself doesn't deal with symbol names as strings, but as Vec<u8>.

The alternative, iterating over (FuncId, &Vec<TrapSite>) pairs, would require some kind of modification to cranelift-faerie. We could change cranelift-faerie to map from string-name to FuncId: cranelift-faerie could grow a separate table for storing that mapping, but cranelift-module is already storing that mapping, and requiring cranelift-faerie to store it seems like wasted effort. Alternatively, the way cranelift-faerie stores its traps could be modified to look more like cranelift-object.

But then maybe the right thing to do is just moving trap collection into cranelift-module itself? Module::new would then grow a flag for indicating whether trap collection should be done. Module itself would probably contain a FuncId to Vec<TrapSite> mapping similar to cranelift-object, and then Backend::define_function would receive Option<&mut Vec<TrapSite>> for potentially accumulating traps.

Since cranelift-simplejit doesn't collect traps, it doesn't matter too much what interface gets decided on.

I think I prefer moving trap collection into cranelift-module itself, but modifying cranelift-faerie to make it more like cranelift-object and the implementing some sort of common iterator interface works, too.

Alternatives

The alternative is to keep the status quo, and lucetc would need to write two sets of code for defining certain pieces of information: one that defines those pieces with faerie and another that defines them with object.


Last updated: Dec 23 2024 at 13:07 UTC