Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

wasm-ld: Implement function pointer alignment #105532

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

Open
wants to merge 9 commits into
base: main
Choose a base branch
Loading
from

Conversation

ethanaobrien
Copy link

WIP implementation of function pointer alignment. Currently all values are statically declared.

padding: Waits x values before beginning the first function pointer. This can be useful for users needing to align on even numbers, or on odd numbers. This should possibly be equal to tableBase by default?
alignment: Inserts x-1 nullptr values into the function table.

Previous discussion: emscripten-core/emscripten#22369

@ethanaobrien ethanaobrien marked this pull request as draft August 21, 2024 14:07
Copy link

Thank you for submitting a Pull Request (PR) to the LLVM Project!

This PR will be automatically labeled and the relevant teams will be notified.

If you wish to, you can add reviewers by using the "Reviewers" section on this page.

If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using @ followed by their GitHub username.

If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers.

If you have further questions, they may be answered by the LLVM GitHub User Guide.

You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums.

@llvmbot
Copy link
Member

llvmbot commented Aug 21, 2024

@llvm/pr-subscribers-lld

@llvm/pr-subscribers-lld-wasm

Author: Ethan O'Brien (ethanaobrien)

Changes

WIP implementation of function pointer alignment. Currently all values are statically declared.

padding: Waits x values before beginning the first function pointer. This can be useful for users needing to align on even numbers, or on odd numbers. This should possibly be equal to tableBase by default?
alignment: Inserts x-1 nullptr values into the function table.

Previous discussion: emscripten-core/emscripten#22369


Full diff: https://github.com/llvm/llvm-project/pull/105532.diff

1 Files Affected:

  • (modified) lld/wasm/SyntheticSections.cpp (+22)
diff --git a/lld/wasm/SyntheticSections.cpp b/lld/wasm/SyntheticSections.cpp
index f02f55519a2512..13333a67378681 100644
--- a/lld/wasm/SyntheticSections.cpp
+++ b/lld/wasm/SyntheticSections.cpp
@@ -563,8 +563,24 @@ void ElemSection::addEntry(FunctionSymbol *sym) {
   // They only exist so that the calls to missing functions can validate.
   if (sym->hasTableIndex() || sym->isStub)
     return;
+
+  uint32_t padding = 0;
+  uint64_t alignment = 1;
+
+  if (indirectFunctions.size() == 0 && padding > 0) {
+    for (uint32_t i=0; i<padding; i++) {
+      indirectFunctions.push_back(nullptr);
+    }
+  }
+
   sym->setTableIndex(config->tableBase + indirectFunctions.size());
   indirectFunctions.emplace_back(sym);
+
+  if (alignment > 1) {
+    for (uint32_t i=0; i<alignment-1; i++) {
+      indirectFunctions.push_back(nullptr);
+    }
+  }
 }
 
 void ElemSection::writeBody() {
@@ -602,6 +618,12 @@ void ElemSection::writeBody() {
   writeUleb128(os, indirectFunctions.size(), "elem count");
   uint32_t tableIndex = config->tableBase;
   for (const FunctionSymbol *sym : indirectFunctions) {
+    if (sym == nullptr) {
+      (void) tableIndex;
+      writeUleb128(os, 0, "function index");
+      ++tableIndex;
+      continue;
+    }
     assert(sym->getTableIndex() == tableIndex);
     (void) tableIndex;
     writeUleb128(os, sym->getFunctionIndex(), "function index");

@ethanaobrien
Copy link
Author

@sbc100 Could I get some help cleaning this PR up and adding CLI arguments to influence these variables? I've tried a few times the last few months but don't seem to be familiar enough with the codebase to know how.

@sbc100
Copy link
Collaborator

sbc100 commented Dec 30, 2024

@sbc100 Could I get some help cleaning this PR up and adding CLI arguments to influence these variables? I've tried a few times the last few months but don't seem to be familiar enough with the codebase to know how.

To add new command line flags you would edit lld/wasm/Options.td to add your new flags and then lld/wasm/Config.h to add a place to store then update readConfigs in lld/wasm/Driver.cpp

@ethanaobrien
Copy link
Author

Thanks! Before I do this, do you have opinions on what the flags should be?

From what I've been able to tell, to mimic how align-functions works on other targets, we would need to set padding to a static value of 1, and set alignment to the argument, though should the flag be align-functions? Should both padding and alignment be configurable?

@sbc100
Copy link
Collaborator

sbc100 commented Dec 30, 2024

Since we are implementing this as a linker flag and not a compiler flag I don't think there any need to mimik the existing compiler flags. I think simply --function-alignment=X is fine, or maybe even --function-pointer-alignment=X (since this only effects function pointer and not functions.

I don't think need a separate padding flag since we already have --table-base.

@ethanaobrien ethanaobrien changed the title [WIP] wasm-ld: Implement function pointer alignment wasm-ld: Implement function pointer alignment Dec 30, 2024
@ethanaobrien ethanaobrien marked this pull request as ready for review December 30, 2024 18:35
@ethanaobrien
Copy link
Author

Thanks! This has been added, and is now ready for review.

Should this option also be added as an emscripten option? It seems it already was once upon a time. https://github.com/emscripten-core/emscripten/blob/b94d6e6ced33576a1ad96c7f6e701788c6f49211/src/settings.js#L2209C5-L2209C31

@BinBashBanana
Copy link

Merge this! :D

@ethanaobrien
Copy link
Author

Hey @sbc100 is there any info on getting this reviewed? Thanks

@BinBashBanana
Copy link

bump

lld/wasm/SyntheticSections.cpp Outdated Show resolved Hide resolved
lld/wasm/SyntheticSections.cpp Show resolved Hide resolved
@sbc100
Copy link
Collaborator

sbc100 commented Jan 22, 2025

Sorry I had some comments that were "Pending" since for a long time.

Copy link

⚠️ C/C++ code formatter, clang-format found issues in your code. ⚠️

You can test this locally with the following command:
git-clang-format --diff 9a95c097d0466c594f40a4ba9ced8a155574fdff 50aa21781adc97bad015d1fab5ad3415dfefcd58 --extensions cpp,h -- lld/wasm/Config.h lld/wasm/Driver.cpp lld/wasm/SyntheticSections.cpp
View the diff from clang-format here.
diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp
index d8fd2b7820..4a0e923868 100644
--- a/lld/wasm/Driver.cpp
+++ b/lld/wasm/Driver.cpp
@@ -636,7 +636,8 @@ static void readConfigs(opt::InputArgList &args) {
   LLVM_DEBUG(errorHandler().verbose = true);
 
   ctx.arg.tableBase = args::getInteger(args, OPT_table_base, 0);
-  ctx.arg.functionPointerAlignment = args::getInteger(args, OPT_function_pointer_alignment, 0);
+  ctx.arg.functionPointerAlignment =
+      args::getInteger(args, OPT_function_pointer_alignment, 0);
   ctx.arg.globalBase = args::getInteger(args, OPT_global_base, 0);
   ctx.arg.initialHeap = args::getInteger(args, OPT_initial_heap, 0);
   ctx.arg.initialMemory = args::getInteger(args, OPT_initial_memory, 0);
diff --git a/lld/wasm/SyntheticSections.cpp b/lld/wasm/SyntheticSections.cpp
index 3fcef7cb3d..5ce0c5cbb4 100644
--- a/lld/wasm/SyntheticSections.cpp
+++ b/lld/wasm/SyntheticSections.cpp
@@ -570,7 +570,7 @@ void ElemSection::addEntry(FunctionSymbol *sym) {
   indirectFunctions.emplace_back(sym);
 
   if (ctx.arg.functionPointerAlignment > 1) {
-    for (uint32_t i=0; i<ctx.arg.functionPointerAlignment-1; i++) {
+    for (uint32_t i = 0; i < ctx.arg.functionPointerAlignment - 1; i++) {
       indirectFunctions.push_back(nullptr);
     }
   }
@@ -611,7 +611,7 @@ void ElemSection::writeBody() {
   uint32_t tableIndex = ctx.arg.tableBase;
   for (const FunctionSymbol *sym : indirectFunctions) {
     if (sym == nullptr) {
-      (void) tableIndex;
+      (void)tableIndex;
       writeUleb128(os, 0, "function index");
       ++tableIndex;
       continue;

@ethanaobrien
Copy link
Author

All good @sbc100, I've also had that happen a few times too many 😄. This PR should be good to go now, with requested changes

@ethanaobrien ethanaobrien requested a review from sbc100 January 23, 2025 17:44
@ethanaobrien
Copy link
Author

Hey @sbc100, is there anything this is waiting on?

Copy link
Collaborator

@sbc100 sbc100 left a comment

Choose a reason for hiding this comment

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

Sorry for the delay. I think we still need a test for this new option. lgtm once we have a test.

@ethanaobrien
Copy link
Author

May be a silly question - could you link where the emscripten tests are (so I can have something to base it off of and know where to put it). I'm unfamiliar with how this repo is organized

@sbc100
Copy link
Collaborator

sbc100 commented Feb 28, 2025

The wasm-ld tests live in lld/test/wasm. You can run them using llvm-lit. e.g. path/to/bin/llvm-lit lld/test/wasm/mytest.s (you can add -v and/or -a to get more info about what the test is doing.

@ethanaobrien
Copy link
Author

Hey @sbc100! Sorry for the delay, I finally got the time to figure out how to write a test. I've added tests for default, an alignmnet of 2, and an alignment of 3

@ethanaobrien
Copy link
Author

Er-wait, I'm now getting the null function or function signature mismatch when building with the first function at a different start index. This needs to be changed elsewhere too?
{670CD65F-ABB9-4F8A-BA46-CF0BFF94ADCD}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants
Morty Proxy This is a proxified and sanitized view of the page, visit original site.