Skip to content

Commit

Permalink
[WebAssembly] Add support for local symbol bindings
Browse files Browse the repository at this point in the history
Differential Revision: https://reviews.llvm.org/D38096

llvm-svn: 313817
  • Loading branch information
sbc100 committed Sep 20, 2017
1 parent 1e72f65 commit 31a2c80
Show file tree
Hide file tree
Showing 9 changed files with 81 additions and 38 deletions.
6 changes: 5 additions & 1 deletion llvm/include/llvm/BinaryFormat/Wasm.h
Expand Up @@ -188,8 +188,12 @@ enum : unsigned {
WASM_SEGMENT_NAMES = 0x5,
};

const unsigned WASM_SYMBOL_BINDING_MASK = 0x3;

enum : unsigned {
WASM_SYMBOL_FLAG_WEAK = 0x1,
WASM_SYMBOL_BINDING_GLOBAL = 0x0,
WASM_SYMBOL_BINDING_WEAK = 0x1,
WASM_SYMBOL_BINDING_LOCAL = 0x2,
};

#define WASM_RELOC(name, value) name = value,
Expand Down
15 changes: 14 additions & 1 deletion llvm/include/llvm/Object/Wasm.h
Expand Up @@ -56,7 +56,19 @@ class WasmSymbol {
uint32_t ElementIndex;

bool isWeak() const {
return Flags & wasm::WASM_SYMBOL_FLAG_WEAK;
return getBinding() == wasm::WASM_SYMBOL_BINDING_WEAK;
}

bool isGlobal() const {
return getBinding() == wasm::WASM_SYMBOL_BINDING_GLOBAL;
}

bool isLocal() const {
return getBinding() == wasm::WASM_SYMBOL_BINDING_LOCAL;
}

unsigned getBinding() const {
return Flags & wasm::WASM_SYMBOL_BINDING_MASK;
}

void print(raw_ostream &Out) const {
Expand Down Expand Up @@ -132,6 +144,7 @@ class WasmObjectFile : public ObjectFile {
Expected<StringRef> getSymbolName(DataRefImpl Symb) const override;

Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override;
uint64_t getWasmSymbolValue(const WasmSymbol& Sym) const;
uint64_t getSymbolValueImpl(DataRefImpl Symb) const override;
uint32_t getSymbolAlignment(DataRefImpl Symb) const override;
uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override;
Expand Down
37 changes: 22 additions & 15 deletions llvm/lib/MC/WasmObjectWriter.cpp
Expand Up @@ -280,11 +280,11 @@ class WasmObjectWriter : public MCObjectWriter {
uint32_t NumFuncImports);
void writeCodeRelocSection();
void writeDataRelocSection();
void writeLinkingMetaDataSection(ArrayRef<WasmDataSegment> Segments,
uint32_t DataSize, uint32_t DataAlignment,
ArrayRef<StringRef> WeakSymbols,
bool HasStackPointer,
uint32_t StackPointerGlobal);
void writeLinkingMetaDataSection(
ArrayRef<WasmDataSegment> Segments, uint32_t DataSize,
uint32_t DataAlignment,
SmallVector<std::pair<StringRef, uint32_t>, 4> SymbolFlags,
bool HasStackPointer, uint32_t StackPointerGlobal);

uint32_t getProvisionalValue(const WasmRelocationEntry &RelEntry);
void applyRelocations(ArrayRef<WasmRelocationEntry> Relocations,
Expand Down Expand Up @@ -914,7 +914,8 @@ void WasmObjectWriter::writeDataRelocSection() {

void WasmObjectWriter::writeLinkingMetaDataSection(
ArrayRef<WasmDataSegment> Segments, uint32_t DataSize,
uint32_t DataAlignment, ArrayRef<StringRef> WeakSymbols,
uint32_t DataAlignment,
SmallVector<std::pair<StringRef, uint32_t>, 4> SymbolFlags,
bool HasStackPointer, uint32_t StackPointerGlobal) {
SectionBookkeeping Section;
startSection(Section, wasm::WASM_SEC_CUSTOM, "linking");
Expand All @@ -926,12 +927,12 @@ void WasmObjectWriter::writeLinkingMetaDataSection(
endSection(SubSection);
}

if (WeakSymbols.size() != 0) {
if (SymbolFlags.size() != 0) {
startSection(SubSection, wasm::WASM_SYMBOL_INFO);
encodeULEB128(WeakSymbols.size(), getStream());
for (const StringRef Export: WeakSymbols) {
writeString(Export);
encodeULEB128(wasm::WASM_SYMBOL_FLAG_WEAK, getStream());
encodeULEB128(SymbolFlags.size(), getStream());
for (auto Pair: SymbolFlags) {
writeString(Pair.first);
encodeULEB128(Pair.second, getStream());
}
endSection(SubSection);
}
Expand Down Expand Up @@ -993,7 +994,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
SmallVector<uint32_t, 4> TableElems;
SmallVector<WasmImport, 4> Imports;
SmallVector<WasmExport, 4> Exports;
SmallVector<StringRef, 4> WeakSymbols;
SmallVector<std::pair<StringRef, uint32_t>, 4> SymbolFlags;
SmallPtrSet<const MCSymbolWasm *, 4> IsAddressTaken;
unsigned NumFuncImports = 0;
SmallVector<WasmDataSegment, 4> DataSegments;
Expand Down Expand Up @@ -1164,7 +1165,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
<< " isVariable=" << WS.isVariable() << "\n");

if (WS.isWeak())
WeakSymbols.push_back(WS.getName());
SymbolFlags.emplace_back(WS.getName(), wasm::WASM_SYMBOL_BINDING_WEAK);

if (WS.isVariable())
continue;
Expand Down Expand Up @@ -1235,7 +1236,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
}

// If the symbol is visible outside this translation unit, export it.
if ((WS.isExternal() && WS.isDefined(/*SetUsed=*/false))) {
if (WS.isDefined(/*SetUsed=*/false)) {
WasmExport Export;
Export.FieldName = WS.getName();
Export.Index = Index;
Expand All @@ -1245,6 +1246,8 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
Export.Kind = wasm::WASM_EXTERNAL_GLOBAL;
DEBUG(dbgs() << " -> export " << Exports.size() << "\n");
Exports.push_back(Export);
if (!WS.isExternal())
SymbolFlags.emplace_back(WS.getName(), wasm::WASM_SYMBOL_BINDING_LOCAL);
}
}

Expand All @@ -1254,6 +1257,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
for (const MCSymbol &S : Asm.symbols()) {
if (!S.isVariable())
continue;

assert(S.isDefined(/*SetUsed=*/false));

// Find the target symbol of this weak alias and export that index
Expand All @@ -1273,6 +1277,9 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
Export.Kind = wasm::WASM_EXTERNAL_GLOBAL;
DEBUG(dbgs() << " -> export " << Exports.size() << "\n");
Exports.push_back(Export);

if (!WS.isExternal())
SymbolFlags.emplace_back(WS.getName(), wasm::WASM_SYMBOL_BINDING_LOCAL);
}

// Add types for indirect function calls.
Expand Down Expand Up @@ -1301,7 +1308,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
writeCodeRelocSection();
writeDataRelocSection();
writeLinkingMetaDataSection(DataSegments, DataSize, DataAlignment,
WeakSymbols, HasStackPointer, StackPointerGlobal);
SymbolFlags, HasStackPointer, StackPointerGlobal);

// TODO: Translate the .comment section to the output.
// TODO: Translate debug sections to the output.
Expand Down
14 changes: 9 additions & 5 deletions llvm/lib/Object/WasmObjectFile.cpp
Expand Up @@ -767,15 +767,17 @@ uint32_t WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const {
const WasmSymbol &Sym = getWasmSymbol(Symb);

DEBUG(dbgs() << "getSymbolFlags: ptr=" << &Sym << " " << Sym << "\n");
if (Sym.Flags & wasm::WASM_SYMBOL_FLAG_WEAK)
if (Sym.isWeak())
Result |= SymbolRef::SF_Weak;
else if (Sym.isGlobal())
Result |= SymbolRef::SF_Global;

switch (Sym.Type) {
case WasmSymbol::SymbolType::FUNCTION_IMPORT:
Result |= SymbolRef::SF_Undefined | SymbolRef::SF_Executable;
break;
case WasmSymbol::SymbolType::FUNCTION_EXPORT:
Result |= SymbolRef::SF_Global | SymbolRef::SF_Executable;
Result |= SymbolRef::SF_Executable;
break;
case WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME:
Result |= SymbolRef::SF_Executable;
Expand All @@ -785,7 +787,6 @@ uint32_t WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const {
Result |= SymbolRef::SF_Undefined;
break;
case WasmSymbol::SymbolType::GLOBAL_EXPORT:
Result |= SymbolRef::SF_Global;
break;
}

Expand Down Expand Up @@ -820,8 +821,7 @@ Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const {
return getSymbolValue(Symb);
}

uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
const WasmSymbol& Sym = getWasmSymbol(Symb);
uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol& Sym) const {
switch (Sym.Type) {
case WasmSymbol::SymbolType::FUNCTION_IMPORT:
case WasmSymbol::SymbolType::GLOBAL_IMPORT:
Expand All @@ -842,6 +842,10 @@ uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
llvm_unreachable("invalid symbol type");
}

uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
return getWasmSymbolValue(getWasmSymbol(Symb));
}

uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb) const {
llvm_unreachable("not yet implemented");
return 0;
Expand Down
17 changes: 14 additions & 3 deletions llvm/test/MC/WebAssembly/unnamed-data.ll
Expand Up @@ -26,11 +26,17 @@
; CHECK-NEXT: Value: 16
; CHECK-NEXT: - Type: I32
; CHECK-NEXT: Mutable: false
; CHECK-NEXT: InitExpr:
; CHECK-NEXT: InitExpr:
; CHECK-NEXT: Opcode: I32_CONST
; CHECK-NEXT: Value: 24
; CHECK-NEXT: - Type: EXPORT
; CHECK-NEXT: Exports:
; CHECK-NEXT: Exports:
; CHECK-NEXT: - Name: .L.str1
; CHECK-NEXT: Kind: GLOBAL
; CHECK-NEXT: Index: 0
; CHECK-NEXT: - Name: .L.str2
; CHECK-NEXT: Kind: GLOBAL
; CHECK-NEXT: Index: 1
; CHECK-NEXT: - Name: a
; CHECK-NEXT: Kind: GLOBAL
; CHECK-NEXT: Index: 2
Expand Down Expand Up @@ -74,6 +80,11 @@
; CHECK-NEXT: Name: linking
; CHECK-NEXT: DataSize: 28
; CHECK-NEXT: DataAlignment: 8
; CHECK-NEXT: SymbolInfo:
; CHECK-NEXT: - Name: .L.str1
; CHECK-NEXT: Flags: 2
; CHECK-NEXT: - Name: .L.str2
; CHECK-NEXT: Flags: 2
; CHECK-NEXT: SegmentNames:
; CHECK-NEXT: - Index: 0
; CHECK-NEXT: Name: .rodata..L.str1
Expand All @@ -83,4 +94,4 @@
; CHECK-NEXT: Name: .data.a
; CHECK-NEXT: - Index: 3
; CHECK-NEXT: Name: .data.b
; CHECK-NEXT: ...
; CHECK_NEXT: ...
8 changes: 8 additions & 0 deletions llvm/test/tools/llvm-nm/wasm/local-symbols.ll
@@ -0,0 +1,8 @@
; RUN: llc -filetype=obj -mtriple=wasm32-unknown-unknown-wasm -o %t.o %s
; RUN: llvm-nm %t.o | FileCheck %s

@foo = internal global i32 1, align 4
@bar = global i32 1, align 4

; CHECK: 00000004 D bar
; CHECK: 00000000 d foo
10 changes: 5 additions & 5 deletions llvm/test/tools/llvm-objdump/WebAssembly/symbol-table.test
@@ -1,11 +1,11 @@
RUN: llvm-objdump -t %p/../Inputs/trivial.obj.wasm | FileCheck %s

CHECK: SYMBOL TABLE:
CHECK-NEXT: 00000000 l F name puts
CHECK-NEXT: 00000001 l F name SomeOtherFunction
CHECK-NEXT: 00000002 l F name main
CHECK-NEXT: 00000000 l F IMPORT puts
CHECK-NEXT: 00000000 l F IMPORT SomeOtherFunction
CHECK-NEXT: 00000000 g F name puts
CHECK-NEXT: 00000001 g F name SomeOtherFunction
CHECK-NEXT: 00000002 g F name main
CHECK-NEXT: 00000000 g F IMPORT puts
CHECK-NEXT: 00000000 g F IMPORT SomeOtherFunction
CHECK-NEXT: 00000002 g F EXPORT main
CHECK-NEXT: 00000010 g EXPORT var

1 change: 1 addition & 0 deletions llvm/tools/llvm-cfi-verify/CMakeLists.txt
Expand Up @@ -5,6 +5,7 @@ set(LLVM_LINK_COMPONENTS
AllTargetsDisassemblers
AllTargetsInfos
MC
Object
MCParser
Object
Support
Expand Down
11 changes: 3 additions & 8 deletions llvm/tools/obj2yaml/wasm2yaml.cpp
Expand Up @@ -54,16 +54,11 @@ std::unique_ptr<WasmYAML::CustomSection> WasmDumper::dumpCustomSection(const Was
if (WasmSec.Name == "name") {
std::unique_ptr<WasmYAML::NameSection> NameSec = make_unique<WasmYAML::NameSection>();
for (const object::SymbolRef& Sym: Obj.symbols()) {
uint32_t Flags = Sym.getFlags();
// Skip over symbols that come from imports or exports
if (Flags &
(object::SymbolRef::SF_Global | object::SymbolRef::SF_Undefined))
continue;
Expected<StringRef> NameOrError = Sym.getName();
if (!NameOrError)
const object::WasmSymbol Symbol = Obj.getWasmSymbol(Sym);
if (Symbol.Type != object::WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME)
continue;
WasmYAML::NameEntry NameEntry;
NameEntry.Name = *NameOrError;
NameEntry.Name = Symbol.Name;
NameEntry.Index = Sym.getValue();
NameSec->FunctionNames.push_back(NameEntry);
}
Expand Down

0 comments on commit 31a2c80

Please sign in to comment.