[clang] [lld] [llvm] [LLVM][WebAssembly] Implement branch hinting proposal (PR #146230)

Lukas Döllerer via cfe-commits cfe-commits at lists.llvm.org
Thu Aug 14 01:58:15 PDT 2025


================
@@ -440,6 +452,42 @@ void WebAssemblyAsmPrinter::emitEndOfAsmFile(Module &M) {
   EmitProducerInfo(M);
   EmitTargetFeatures(M);
   EmitFunctionAttributes(M);
+
+  // Subtarget may be null if no functions have been defined in file
+  if (Subtarget && Subtarget->hasBranchHinting())
+    emitBranchHintSection();
+}
+
+void WebAssemblyAsmPrinter::emitBranchHintSection() const {
+  MCSectionWasm *BranchHintsSection = OutContext.getWasmSection(
+      ".custom_section.metadata.code.branch_hint", SectionKind::getMetadata());
+  const uint32_t NumFunctionHints =
+      std::count_if(BranchHints.begin(), BranchHints.end(),
+                    [](const auto &BHR) { return !BHR.Hints.empty(); });
+  if (NumFunctionHints == 0)
+    return;
+  OutStreamer->pushSection();
+  OutStreamer->switchSection(BranchHintsSection);
+  OutStreamer->emitULEB128IntValue(NumFunctionHints);
+  for (const auto &BHR : BranchHints) {
+    if (BHR.Hints.empty())
+      continue;
+    // emit relocatable function index for the function symbol
+    OutStreamer->emitULEB128Value(MCSymbolRefExpr::create(
+        BHR.FuncSym, WebAssembly::S_FUNCINDEX, OutContext));
+    // emit the number of hints for this function (is constant -> does not need
+    // handling by target streamer for reloc)
+    OutStreamer->emitULEB128IntValue(BHR.Hints.size());
+    for (const auto &[instrSym, hint] : BHR.Hints) {
+      assert(hint == 0 || hint == 1);
+      // offset from function start
+      OutStreamer->emitULEB128Value(MCSymbolRefExpr::create(
+          instrSym, WebAssembly::S_DEBUG_REF, OutContext));
----------------
Lukasdoe wrote:

The debugref was only introduced to cleanly identify `MCSymbolRefExpr`s that can / must be relaxed in `WebAssemblyAsmBackend::relaxLEB128` because they don't need relocations.

I'm not too familiar with the mechanism behind dwarf debug entries, however it looks like wasm largely uses the normal llvm debug info mechanism which generates the appropriate fixups for the symbol references.

The required relaxation, however, is leb128 fragment specific, since non-absolute leb128 fragments (like our symbol references) can't be emitted without relaxation.

I'm open for naming suggestions though, if the name itself is a problem :)

https://github.com/llvm/llvm-project/pull/146230


More information about the cfe-commits mailing list