Skip to content

[WebAssembly] Allocate MCSymbolWasm data on MCContext #85866

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

Merged
merged 1 commit into from
Apr 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions llvm/include/llvm/MC/MCContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/MD5.h"
#include "llvm/Support/StringSaver.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
Expand Down Expand Up @@ -70,6 +71,10 @@ class SMLoc;
class SourceMgr;
enum class EmitDwarfUnwindType;

namespace wasm {
struct WasmSignature;
}

/// Context object for machine code objects. This class owns all of the
/// sections that it creates.
///
Expand Down Expand Up @@ -139,6 +144,8 @@ class MCContext {
SpecificBumpPtrAllocator<MCSectionXCOFF> XCOFFAllocator;
SpecificBumpPtrAllocator<MCInst> MCInstAllocator;

SpecificBumpPtrAllocator<wasm::WasmSignature> WasmSignatureAllocator;

/// Bindings of names to symbols.
SymbolTable Symbols;

Expand Down Expand Up @@ -538,6 +545,10 @@ class MCContext {
/// inline assembly.
void registerInlineAsmLabel(MCSymbol *Sym);

/// Allocates and returns a new `WasmSignature` instance (with empty parameter
/// and return type lists).
wasm::WasmSignature *createWasmSignature();

/// @}

/// \name Section Management
Expand Down Expand Up @@ -850,6 +861,12 @@ class MCContext {

void deallocate(void *Ptr) {}

/// Allocates a copy of the given string on the allocator managed by this
/// context and returns the result.
StringRef allocateString(StringRef s) {
return StringSaver(Allocator).save(s);
}

bool hadError() { return HadError; }
void diagnose(const SMDiagnostic &SMD);
void reportError(SMLoc L, const Twine &Msg);
Expand Down
5 changes: 5 additions & 0 deletions llvm/lib/MC/MCContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ void MCContext::reset() {
XCOFFAllocator.DestroyAll();
MCInstAllocator.DestroyAll();
SPIRVAllocator.DestroyAll();
WasmSignatureAllocator.DestroyAll();

MCSubtargetAllocator.DestroyAll();
InlineAsmUsedLabelNames.clear();
Expand Down Expand Up @@ -375,6 +376,10 @@ void MCContext::registerInlineAsmLabel(MCSymbol *Sym) {
InlineAsmUsedLabelNames[Sym->getName()] = Sym;
}

wasm::WasmSignature *MCContext::createWasmSignature() {
return new (WasmSignatureAllocator.Allocate()) wasm::WasmSignature;
}

MCSymbolXCOFF *
MCContext::createXCOFFSymbolImpl(const StringMapEntry<bool> *Name,
bool IsTemporary) {
Expand Down
45 changes: 14 additions & 31 deletions llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,10 +196,6 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
MCAsmParser &Parser;
MCAsmLexer &Lexer;

// Much like WebAssemblyAsmPrinter in the backend, we have to own these.
std::vector<std::unique_ptr<wasm::WasmSignature>> Signatures;
std::vector<std::unique_ptr<std::string>> Names;

// Order of labels, directives and instructions in a .s file have no
// syntactical enforcement. This class is a callback from the actual parser,
// and yet we have to be feeding data to the streamer in a very particular
Expand Down Expand Up @@ -287,16 +283,6 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
return Parser.Error(Loc.isValid() ? Loc : Lexer.getTok().getLoc(), Msg);
}

void addSignature(std::unique_ptr<wasm::WasmSignature> &&Sig) {
Signatures.push_back(std::move(Sig));
}

StringRef storeName(StringRef Name) {
std::unique_ptr<std::string> N = std::make_unique<std::string>(Name);
Names.push_back(std::move(N));
return *Names.back();
}

std::pair<StringRef, StringRef> nestingString(NestingType NT) {
switch (NT) {
case Function:
Expand Down Expand Up @@ -640,21 +626,20 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
// represent as a signature, such that we can re-build this signature,
// attach it to an anonymous symbol, which is what WasmObjectWriter
// expects to be able to recreate the actual unique-ified type indices.
auto &Ctx = getContext();
auto Loc = Parser.getTok();
auto Signature = std::make_unique<wasm::WasmSignature>();
if (parseSignature(Signature.get()))
auto Signature = Ctx.createWasmSignature();
if (parseSignature(Signature))
return true;
// Got signature as block type, don't need more
TC.setLastSig(*Signature.get());
TC.setLastSig(*Signature);
if (ExpectBlockType)
NestingStack.back().Sig = *Signature.get();
NestingStack.back().Sig = *Signature;
ExpectBlockType = false;
auto &Ctx = getContext();
// The "true" here will cause this to be a nameless symbol.
MCSymbol *Sym = Ctx.createTempSymbol("typeindex", true);
auto *WasmSym = cast<MCSymbolWasm>(Sym);
WasmSym->setSignature(Signature.get());
addSignature(std::move(Signature));
WasmSym->setSignature(Signature);
WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
const MCExpr *Expr = MCSymbolRefExpr::create(
WasmSym, MCSymbolRefExpr::VK_WASM_TYPEINDEX, Ctx);
Expand Down Expand Up @@ -887,12 +872,11 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
CurrentState = FunctionStart;
LastFunctionLabel = WasmSym;
}
auto Signature = std::make_unique<wasm::WasmSignature>();
if (parseSignature(Signature.get()))
auto Signature = Ctx.createWasmSignature();
if (parseSignature(Signature))
return ParseStatus::Failure;
TC.funcDecl(*Signature);
WasmSym->setSignature(Signature.get());
addSignature(std::move(Signature));
WasmSym->setSignature(Signature);
WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
TOut.emitFunctionType(WasmSym);
// TODO: backend also calls TOut.emitIndIdx, but that is not implemented.
Expand All @@ -909,7 +893,7 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
if (ExportName.empty())
return ParseStatus::Failure;
auto WasmSym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(SymName));
WasmSym->setExportName(storeName(ExportName));
WasmSym->setExportName(Ctx.allocateString(ExportName));
TOut.emitExportName(WasmSym, ExportName);
return expect(AsmToken::EndOfStatement, "EOL");
}
Expand All @@ -924,7 +908,7 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
if (ImportModule.empty())
return ParseStatus::Failure;
auto WasmSym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(SymName));
WasmSym->setImportModule(storeName(ImportModule));
WasmSym->setImportModule(Ctx.allocateString(ImportModule));
TOut.emitImportModule(WasmSym, ImportModule);
return expect(AsmToken::EndOfStatement, "EOL");
}
Expand All @@ -939,7 +923,7 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
if (ImportName.empty())
return ParseStatus::Failure;
auto WasmSym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(SymName));
WasmSym->setImportName(storeName(ImportName));
WasmSym->setImportName(Ctx.allocateString(ImportName));
TOut.emitImportName(WasmSym, ImportName);
return expect(AsmToken::EndOfStatement, "EOL");
}
Expand All @@ -949,11 +933,10 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
if (SymName.empty())
return ParseStatus::Failure;
auto WasmSym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(SymName));
auto Signature = std::make_unique<wasm::WasmSignature>();
auto Signature = Ctx.createWasmSignature();
if (parseRegTypeList(Signature->Params))
return ParseStatus::Failure;
WasmSym->setSignature(Signature.get());
addSignature(std::move(Signature));
WasmSym->setSignature(Signature);
WasmSym->setType(wasm::WASM_SYMBOL_TYPE_TAG);
TOut.emitTagType(WasmSym);
// TODO: backend also calls TOut.emitIndIdx, but that is not implemented.
Expand Down
29 changes: 12 additions & 17 deletions llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -266,10 +266,10 @@ MCSymbol *WebAssemblyAsmPrinter::getOrCreateWasmSymbol(StringRef Name) {
WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
WebAssembly::getLibcallSignature(Subtarget, Name, Returns, Params);
}
auto Signature = std::make_unique<wasm::WasmSignature>(std::move(Returns),
std::move(Params));
WasmSym->setSignature(Signature.get());
addSignature(std::move(Signature));
auto Signature = OutContext.createWasmSignature();
Signature->Returns = std::move(Returns);
Signature->Params = std::move(Params);
WasmSym->setSignature(Signature);

return WasmSym;
}
Expand Down Expand Up @@ -338,11 +338,11 @@ void WebAssemblyAsmPrinter::emitDecls(const Module &M) {
// and thus also contain a signature, but we need to get the signature
// anyway here in case it is an invoke that has not yet been created. We
// will discard it later if it turns out not to be necessary.
auto Signature = signatureFromMVTs(Results, Params);
auto Signature = signatureFromMVTs(OutContext, Results, Params);
bool InvokeDetected = false;
auto *Sym = getMCSymbolForFunction(
&F, WebAssembly::WasmEnableEmEH || WebAssembly::WasmEnableEmSjLj,
Signature.get(), InvokeDetected);
Signature, InvokeDetected);

// Multiple functions can be mapped to the same invoke symbol. For
// example, two IR functions '__invoke_void_i8*' and '__invoke_void_i32'
Expand All @@ -353,19 +353,15 @@ void WebAssemblyAsmPrinter::emitDecls(const Module &M) {

Sym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
if (!Sym->getSignature()) {
Sym->setSignature(Signature.get());
addSignature(std::move(Signature));
} else {
// This symbol has already been created and had a signature. Discard it.
Signature.reset();
Sym->setSignature(Signature);
}

getTargetStreamer()->emitFunctionType(Sym);

if (F.hasFnAttribute("wasm-import-module")) {
StringRef Name =
F.getFnAttribute("wasm-import-module").getValueAsString();
Sym->setImportModule(storeName(Name));
Sym->setImportModule(OutContext.allocateString(Name));
getTargetStreamer()->emitImportModule(Sym, Name);
}
if (F.hasFnAttribute("wasm-import-name")) {
Expand All @@ -375,14 +371,14 @@ void WebAssemblyAsmPrinter::emitDecls(const Module &M) {
InvokeDetected
? Sym->getName()
: F.getFnAttribute("wasm-import-name").getValueAsString();
Sym->setImportName(storeName(Name));
Sym->setImportName(OutContext.allocateString(Name));
getTargetStreamer()->emitImportName(Sym, Name);
}

if (F.hasFnAttribute("wasm-export-name")) {
auto *Sym = cast<MCSymbolWasm>(getSymbol(&F));
StringRef Name = F.getFnAttribute("wasm-export-name").getValueAsString();
Sym->setExportName(storeName(Name));
Sym->setExportName(OutContext.allocateString(Name));
getTargetStreamer()->emitExportName(Sym, Name);
}
}
Expand Down Expand Up @@ -618,10 +614,9 @@ void WebAssemblyAsmPrinter::emitFunctionBodyStart() {
SmallVector<MVT, 4> ParamVTs;
computeSignatureVTs(F.getFunctionType(), &F, F, TM, ParamVTs, ResultVTs);

auto Signature = signatureFromMVTs(ResultVTs, ParamVTs);
auto Signature = signatureFromMVTs(OutContext, ResultVTs, ParamVTs);
auto *WasmSym = cast<MCSymbolWasm>(CurrentFnSym);
WasmSym->setSignature(Signature.get());
addSignature(std::move(Signature));
WasmSym->setSignature(Signature);
WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);

getTargetStreamer()->emitFunctionType(WasmSym);
Expand Down
12 changes: 0 additions & 12 deletions llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,8 @@ class LLVM_LIBRARY_VISIBILITY WebAssemblyAsmPrinter final : public AsmPrinter {
const WebAssemblySubtarget *Subtarget;
const MachineRegisterInfo *MRI;
WebAssemblyFunctionInfo *MFI;
// TODO: Do the uniquing of Signatures here instead of ObjectFileWriter?
std::vector<std::unique_ptr<wasm::WasmSignature>> Signatures;
std::vector<std::unique_ptr<std::string>> Names;
bool signaturesEmitted = false;

StringRef storeName(StringRef Name) {
std::unique_ptr<std::string> N = std::make_unique<std::string>(Name);
Names.push_back(std::move(N));
return *Names.back();
}

public:
explicit WebAssemblyAsmPrinter(TargetMachine &TM,
std::unique_ptr<MCStreamer> Streamer)
Expand All @@ -44,9 +35,6 @@ class LLVM_LIBRARY_VISIBILITY WebAssemblyAsmPrinter final : public AsmPrinter {
}

const WebAssemblySubtarget &getSubtarget() const { return *Subtarget; }
void addSignature(std::unique_ptr<wasm::WasmSignature> &&Sig) {
Signatures.push_back(std::move(Sig));
}

//===------------------------------------------------------------------===//
// MachineFunctionPass Implementation.
Expand Down
15 changes: 7 additions & 8 deletions llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,14 +73,13 @@ WebAssemblyMCInstLower::GetGlobalAddressSymbol(const MachineOperand &MO) const {
SmallVector<MVT, 4> ParamMVTs;
const auto *const F = dyn_cast<Function>(Global);
computeSignatureVTs(FuncTy, F, CurrentFunc, TM, ParamMVTs, ResultMVTs);
auto Signature = signatureFromMVTs(ResultMVTs, ParamMVTs);
auto Signature = signatureFromMVTs(Ctx, ResultMVTs, ParamMVTs);

bool InvokeDetected = false;
auto *WasmSym = Printer.getMCSymbolForFunction(
F, WebAssembly::WasmEnableEmEH || WebAssembly::WasmEnableEmSjLj,
Signature.get(), InvokeDetected);
WasmSym->setSignature(Signature.get());
Printer.addSignature(std::move(Signature));
Signature, InvokeDetected);
WasmSym->setSignature(Signature);
WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
return WasmSym;
}
Expand Down Expand Up @@ -142,12 +141,12 @@ MCOperand WebAssemblyMCInstLower::lowerSymbolOperand(const MachineOperand &MO,
MCOperand WebAssemblyMCInstLower::lowerTypeIndexOperand(
SmallVectorImpl<wasm::ValType> &&Returns,
SmallVectorImpl<wasm::ValType> &&Params) const {
auto Signature = std::make_unique<wasm::WasmSignature>(std::move(Returns),
std::move(Params));
auto Signature = Ctx.createWasmSignature();
Signature->Returns = std::move(Returns);
Signature->Params = std::move(Params);
MCSymbol *Sym = Printer.createTempSymbol("typeindex");
auto *WasmSym = cast<MCSymbolWasm>(Sym);
WasmSym->setSignature(Signature.get());
Printer.addSignature(std::move(Signature));
WasmSym->setSignature(Signature);
WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
const MCExpr *Expr =
MCSymbolRefExpr::create(WasmSym, MCSymbolRefExpr::VK_WASM_TYPEINDEX, Ctx);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,10 @@ void llvm::valTypesFromMVTs(ArrayRef<MVT> In,
Out.push_back(WebAssembly::toValType(Ty));
}

std::unique_ptr<wasm::WasmSignature>
llvm::signatureFromMVTs(const SmallVectorImpl<MVT> &Results,
wasm::WasmSignature *
llvm::signatureFromMVTs(MCContext &Ctx, const SmallVectorImpl<MVT> &Results,
const SmallVectorImpl<MVT> &Params) {
auto Sig = std::make_unique<wasm::WasmSignature>();
auto Sig = Ctx.createWasmSignature();
valTypesFromMVTs(Results, Sig->Returns);
valTypesFromMVTs(Params, Sig->Params);
return Sig;
Expand Down
6 changes: 3 additions & 3 deletions llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,9 +171,9 @@ void computeSignatureVTs(const FunctionType *Ty, const Function *TargetFunc,

void valTypesFromMVTs(ArrayRef<MVT> In, SmallVectorImpl<wasm::ValType> &Out);

std::unique_ptr<wasm::WasmSignature>
signatureFromMVTs(const SmallVectorImpl<MVT> &Results,
const SmallVectorImpl<MVT> &Params);
wasm::WasmSignature *signatureFromMVTs(MCContext &Ctx,
const SmallVectorImpl<MVT> &Results,
const SmallVectorImpl<MVT> &Params);

namespace yaml {

Expand Down
25 changes: 25 additions & 0 deletions llvm/test/MC/WebAssembly/module-asm.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
; Ensure that symbols from module ASM are properly exported.
;
; Regression test for https://github.com/llvm/llvm-project/issues/85578.

; RUN: llc -mtriple=wasm32-unknown-unknown -filetype=obj %s -o - | obj2yaml | FileCheck %s

module asm "test_func:"
module asm " .globl test_func"
module asm " .functype test_func (i32) -> (i32)"
module asm " .export_name test_func, test_export"
module asm " end_function"

; CHECK: - Type: TYPE
; CHECK-NEXT: Signatures:
; CHECK-NEXT: - Index: 0
; CHECK-NEXT: ParamTypes:
; CHECK-NEXT: - I32
; CHECK-NEXT: ReturnTypes:
; CHECK-NEXT: - I32

; CHECK: - Type: EXPORT
; CHECK-NEXT: Exports:
; CHECK-NEXT: - Name: test_export
; CHECK-NEXT: Kind: FUNCTION
; CHECK-NEXT: Index: 0