-
Notifications
You must be signed in to change notification settings - Fork 98
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
Support GOT.func imports in mo-ld #1811
Conversation
This PR does not affect the produced WebAssembly code. |
@nomeata does the test input and outputs make sense to you? It'd be good if we had an example that updates value of the symbol |
Thinking more about it, maybe it’s not so much about mutability, but simply the fact that in C all pointers (even function pointers) need to be pointers into memory (so that you can do arithmetic, comparisons etc.), and maybe that’s the reason for the GOP indirection. |
I'm not sure. Looking at C11 spec, it doesn't seem to mention arithmetic on function pointers. It just says function pointers may be converted to different function types and back. Doing anything else with a function pointer seems to be illegal, though the compilers currently seem to allow basically everything. I can do |
I figured this out: https://groups.google.com/g/llvm-dev/c/yjGdJadhO9g/m/K-TXukQ6AwAJ I'll write a more detailed response on Monday but the link explains why we need the "GOT.func" import and how it's used. |
Did some more investigation on my, copying it here (just for my own reference maybe): function pointers on the stack are just
when compiled to a dynamic library with
produces
and there is a |
This is not correct. A function pointer in C is something like:
Here the value of symbol If you declare something like:
This is one level of indirection that you introduce, i.e. it's a pointer to a function pointer. That's why you see a I did some reading and experimenting with GOT.mem and GOT.func imports. Here's some notes and how I think we should implement GOT.mem and GOT.func imports:
|
Sounds good! |
c03e1c3
to
5d33d81
Compare
src/linking/linkModule.ml
Outdated
table (elem section) we add it to the table, and then replace the import | ||
with | ||
|
||
(global (;N;) i32 (i32.const M'_i)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if this needs to be a mutable global.
OT1H, the global was mutable before, and maybe some code actually mutates them?
OTOH, that would be quite odd, probably not intended, and maybe good to produce invalid wasm modules in that case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think these globals don't need to be mutable. It was mutable before because LLVM generates mutable globals for GOT.func imports, but maybe that's just laziness. I don't think address of a function can change in C.
8899df1
to
67ef95c
Compare
Here's a summary of this and why this has been tricky to implement correctly. We have imports
and in the same module, the functions and exports:
We need to add functions For that we need to create a map The tricky bit is to update global indices (keys) and function indices (values) in that map as we update the RTS module. I think I mostly figured this out, but it took a while. I'll hopefully finish this by the end of tomorrow. |
I can now build & run an example! |
faa58ff
to
93daf7c
Compare
I confirmed that with this patch I can use some of the Rust core functions in #1750 that I couldn't before. |
93daf7c
to
97cf076
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good job, almost there. I think we can actually simplify this:
- allocate table space based on
old_elem_size
of the first module - always create table entries for these fucntion.
This way things don’t break once tables become mutable, and the linker code might actually be smaller and simpler.
let global_idx = | ||
if is_global_import import.it.idesc.it then | ||
Int32.add global_idx (Int32.of_int 1) | ||
else | ||
global_idx | ||
in | ||
( global_idx, imports ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let global_idx = | |
if is_global_import import.it.idesc.it then | |
Int32.add global_idx (Int32.of_int 1) | |
else | |
global_idx | |
in | |
( global_idx, imports ) | |
if is_global_import import.it.idesc.it | |
then (Int32.add global_idx (Int32.of_int 1), imports) | |
else (global_idx, imports) |
seems simpler, at the expense of symmetry with the previous. Up to you.
de83479
to
6885dd8
Compare
(global (;1;) i32 (i32.const 2)) | ||
(global (;2;) i32 (i32.const 65536)) | ||
(start $link_start) | ||
(elem (;0;) (i32.const 1) func $f0 $f1)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Offset is 1
here because the first module (fun-ptr.wat
above) has a table with size 1. I think this could be 0
because the table in the first module is imported; it doesn't define any elems.
6885dd8
to
2c01e75
Compare
I think I addressed all comments and fixed the issues. We currently create one
Table alignment and table size are read from the dynlink section (see "tablesize" and "tablealignment"). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! A few nits only. Excellent note. (We will need it!)
Thanks for doing this, it opens doors.
2c01e75
to
20dc756
Compare
Fixes #1810
See comments for how this works.
Other changes:
The test 'closures' is updated to generate more than one table element in the
Wasm module. Not necessary to test this feature, but it helps to have more
than fun elements when working on element sections in the linker.
Make rule to build C files in linker tests updated:
(fails with "compile with -fPIC" errors even though the flag is already
passed).