2017-02-22 09:23:18 +08:00
|
|
|
//===- lib/MC/WasmObjectWriter.cpp - Wasm File Writer ---------------------===//
|
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2017-02-22 09:23:18 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file implements Wasm object file writer information.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "llvm/ADT/STLExtras.h"
|
|
|
|
#include "llvm/ADT/SmallPtrSet.h"
|
2017-06-07 11:48:56 +08:00
|
|
|
#include "llvm/BinaryFormat/Wasm.h"
|
2020-09-29 04:06:34 +08:00
|
|
|
#include "llvm/BinaryFormat/WasmTraits.h"
|
2018-04-30 22:59:11 +08:00
|
|
|
#include "llvm/Config/llvm-config.h"
|
2017-02-22 09:23:18 +08:00
|
|
|
#include "llvm/MC/MCAsmBackend.h"
|
|
|
|
#include "llvm/MC/MCAsmLayout.h"
|
|
|
|
#include "llvm/MC/MCAssembler.h"
|
|
|
|
#include "llvm/MC/MCContext.h"
|
|
|
|
#include "llvm/MC/MCExpr.h"
|
|
|
|
#include "llvm/MC/MCFixupKindInfo.h"
|
|
|
|
#include "llvm/MC/MCObjectWriter.h"
|
|
|
|
#include "llvm/MC/MCSectionWasm.h"
|
|
|
|
#include "llvm/MC/MCSymbolWasm.h"
|
|
|
|
#include "llvm/MC/MCValue.h"
|
|
|
|
#include "llvm/MC/MCWasmObjectWriter.h"
|
2017-02-25 07:18:00 +08:00
|
|
|
#include "llvm/Support/Casting.h"
|
2017-02-22 09:23:18 +08:00
|
|
|
#include "llvm/Support/Debug.h"
|
2020-04-17 02:31:45 +08:00
|
|
|
#include "llvm/Support/EndianStream.h"
|
2017-02-22 09:23:18 +08:00
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
2017-02-25 07:18:00 +08:00
|
|
|
#include "llvm/Support/LEB128.h"
|
2017-02-22 09:23:18 +08:00
|
|
|
#include "llvm/Support/StringSaver.h"
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
|
2017-07-07 10:01:29 +08:00
|
|
|
#define DEBUG_TYPE "mc"
|
2017-02-22 09:23:18 +08:00
|
|
|
|
|
|
|
namespace {
|
2017-06-03 10:01:24 +08:00
|
|
|
|
2020-11-26 00:31:05 +08:00
|
|
|
// When we create the indirect function table we start at 1, so that there is
|
|
|
|
// and empty slot at 0 and therefore calling a null function pointer will trap.
|
[WebAssembly] clang-tidy (NFC)
Summary:
This patch fixes clang-tidy warnings on wasm-only files.
The list of checks used is:
`-*,clang-diagnostic-*,llvm-*,misc-*,-misc-unused-parameters,readability-identifier-naming,modernize-*`
(LLVM's default .clang-tidy list is the same except it does not have
`modernize-*`. But I've seen in multiple CLs in LLVM the modernize style
was recommended and code was fixed based on the style, so I added it as
well.)
The common fixes are:
- Variable names start with an uppercase letter
- Function names start with a lowercase letter
- Use `auto` when you use casts so the type is evident
- Use inline initialization for class member variables
- Use `= default` for empty constructors / destructors
- Use `using` in place of `typedef`
Reviewers: sbc100, tlively, aardappel
Subscribers: dschuff, sunfish, jgravelle-google, yurydelendik, kripken, MatzeB, mgorny, rupprecht, llvm-commits
Differential Revision: https://reviews.llvm.org/D57500
llvm-svn: 353075
2019-02-05 03:13:39 +08:00
|
|
|
static const uint32_t InitialTableOffset = 1;
|
2018-01-20 02:57:01 +08:00
|
|
|
|
2017-02-25 07:18:00 +08:00
|
|
|
// For patching purposes, we need to remember where each section starts, both
|
|
|
|
// for patching up the section size field, and for patching up references to
|
|
|
|
// locations within the section.
|
|
|
|
struct SectionBookkeeping {
|
|
|
|
// Where the size of the section is written.
|
|
|
|
uint64_t SizeOffset;
|
2018-04-27 03:27:28 +08:00
|
|
|
// Where the section header ends (without custom section name).
|
|
|
|
uint64_t PayloadOffset;
|
|
|
|
// Where the contents of the section starts.
|
2017-02-25 07:18:00 +08:00
|
|
|
uint64_t ContentsOffset;
|
2018-04-25 02:11:36 +08:00
|
|
|
uint32_t Index;
|
2017-02-25 07:18:00 +08:00
|
|
|
};
|
|
|
|
|
2017-09-15 07:07:53 +08:00
|
|
|
// A wasm data segment. A wasm binary contains only a single data section
|
|
|
|
// but that can contain many segments, each with their own virtual location
|
|
|
|
// in memory. Each MCSection data created by llvm is modeled as its own
|
|
|
|
// wasm data segment.
|
|
|
|
struct WasmDataSegment {
|
|
|
|
MCSectionWasm *Section;
|
2017-09-21 03:03:35 +08:00
|
|
|
StringRef Name;
|
2019-02-20 06:56:19 +08:00
|
|
|
uint32_t InitFlags;
|
2020-06-30 08:53:09 +08:00
|
|
|
uint64_t Offset;
|
2017-09-30 00:50:08 +08:00
|
|
|
uint32_t Alignment;
|
2019-02-20 06:56:19 +08:00
|
|
|
uint32_t LinkerFlags;
|
2017-09-15 07:07:53 +08:00
|
|
|
SmallVector<char, 4> Data;
|
|
|
|
};
|
|
|
|
|
2017-06-03 10:01:24 +08:00
|
|
|
// A wasm function to be written into the function section.
|
|
|
|
struct WasmFunction {
|
2018-11-14 10:46:21 +08:00
|
|
|
uint32_t SigIndex;
|
2017-06-03 10:01:24 +08:00
|
|
|
const MCSymbolWasm *Sym;
|
|
|
|
};
|
|
|
|
|
|
|
|
// A wasm global to be written into the global section.
|
|
|
|
struct WasmGlobal {
|
2018-02-01 03:50:14 +08:00
|
|
|
wasm::WasmGlobalType Type;
|
2017-06-03 10:01:24 +08:00
|
|
|
uint64_t InitialValue;
|
|
|
|
};
|
|
|
|
|
2018-01-10 07:43:14 +08:00
|
|
|
// Information about a single item which is part of a COMDAT. For each data
|
|
|
|
// segment or function which is in the COMDAT, there is a corresponding
|
|
|
|
// WasmComdatEntry.
|
|
|
|
struct WasmComdatEntry {
|
|
|
|
unsigned Kind;
|
|
|
|
uint32_t Index;
|
|
|
|
};
|
|
|
|
|
2017-06-07 00:38:59 +08:00
|
|
|
// Information about a single relocation.
|
|
|
|
struct WasmRelocationEntry {
|
2018-09-05 09:27:38 +08:00
|
|
|
uint64_t Offset; // Where is the relocation.
|
|
|
|
const MCSymbolWasm *Symbol; // The symbol to relocate with.
|
|
|
|
int64_t Addend; // A value to add to the symbol.
|
|
|
|
unsigned Type; // The type of the relocation.
|
|
|
|
const MCSectionWasm *FixupSection; // The section the relocation is targeting.
|
2017-06-07 00:38:59 +08:00
|
|
|
|
|
|
|
WasmRelocationEntry(uint64_t Offset, const MCSymbolWasm *Symbol,
|
|
|
|
int64_t Addend, unsigned Type,
|
2017-06-22 07:46:41 +08:00
|
|
|
const MCSectionWasm *FixupSection)
|
2017-06-07 00:38:59 +08:00
|
|
|
: Offset(Offset), Symbol(Symbol), Addend(Addend), Type(Type),
|
|
|
|
FixupSection(FixupSection) {}
|
|
|
|
|
2019-06-26 08:52:42 +08:00
|
|
|
bool hasAddend() const { return wasm::relocTypeHasAddend(Type); }
|
2017-06-07 03:15:05 +08:00
|
|
|
|
2017-06-07 00:38:59 +08:00
|
|
|
void print(raw_ostream &Out) const {
|
2018-09-05 09:27:38 +08:00
|
|
|
Out << wasm::relocTypetoString(Type) << " Off=" << Offset
|
|
|
|
<< ", Sym=" << *Symbol << ", Addend=" << Addend
|
2020-04-16 06:49:05 +08:00
|
|
|
<< ", FixupSection=" << FixupSection->getName();
|
2017-06-07 00:38:59 +08:00
|
|
|
}
|
2017-06-20 12:04:59 +08:00
|
|
|
|
2017-10-15 22:32:27 +08:00
|
|
|
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
|
2017-06-20 12:04:59 +08:00
|
|
|
LLVM_DUMP_METHOD void dump() const { print(dbgs()); }
|
|
|
|
#endif
|
2017-06-07 00:38:59 +08:00
|
|
|
};
|
|
|
|
|
[WebAssembly] clang-tidy (NFC)
Summary:
This patch fixes clang-tidy warnings on wasm-only files.
The list of checks used is:
`-*,clang-diagnostic-*,llvm-*,misc-*,-misc-unused-parameters,readability-identifier-naming,modernize-*`
(LLVM's default .clang-tidy list is the same except it does not have
`modernize-*`. But I've seen in multiple CLs in LLVM the modernize style
was recommended and code was fixed based on the style, so I added it as
well.)
The common fixes are:
- Variable names start with an uppercase letter
- Function names start with a lowercase letter
- Use `auto` when you use casts so the type is evident
- Use inline initialization for class member variables
- Use `= default` for empty constructors / destructors
- Use `using` in place of `typedef`
Reviewers: sbc100, tlively, aardappel
Subscribers: dschuff, sunfish, jgravelle-google, yurydelendik, kripken, MatzeB, mgorny, rupprecht, llvm-commits
Differential Revision: https://reviews.llvm.org/D57500
llvm-svn: 353075
2019-02-05 03:13:39 +08:00
|
|
|
static const uint32_t InvalidIndex = -1;
|
2018-05-08 08:08:21 +08:00
|
|
|
|
2018-04-06 01:01:39 +08:00
|
|
|
struct WasmCustomSection {
|
2018-04-27 03:27:28 +08:00
|
|
|
|
2018-04-06 01:01:39 +08:00
|
|
|
StringRef Name;
|
2018-04-27 03:27:28 +08:00
|
|
|
MCSectionWasm *Section;
|
|
|
|
|
|
|
|
uint32_t OutputContentsOffset;
|
|
|
|
uint32_t OutputIndex;
|
2018-04-06 01:01:39 +08:00
|
|
|
|
2018-04-27 03:27:28 +08:00
|
|
|
WasmCustomSection(StringRef Name, MCSectionWasm *Section)
|
|
|
|
: Name(Name), Section(Section), OutputContentsOffset(0),
|
[WebAssembly] clang-tidy (NFC)
Summary:
This patch fixes clang-tidy warnings on wasm-only files.
The list of checks used is:
`-*,clang-diagnostic-*,llvm-*,misc-*,-misc-unused-parameters,readability-identifier-naming,modernize-*`
(LLVM's default .clang-tidy list is the same except it does not have
`modernize-*`. But I've seen in multiple CLs in LLVM the modernize style
was recommended and code was fixed based on the style, so I added it as
well.)
The common fixes are:
- Variable names start with an uppercase letter
- Function names start with a lowercase letter
- Use `auto` when you use casts so the type is evident
- Use inline initialization for class member variables
- Use `= default` for empty constructors / destructors
- Use `using` in place of `typedef`
Reviewers: sbc100, tlively, aardappel
Subscribers: dschuff, sunfish, jgravelle-google, yurydelendik, kripken, MatzeB, mgorny, rupprecht, llvm-commits
Differential Revision: https://reviews.llvm.org/D57500
llvm-svn: 353075
2019-02-05 03:13:39 +08:00
|
|
|
OutputIndex(InvalidIndex) {}
|
2018-04-06 01:01:39 +08:00
|
|
|
};
|
|
|
|
|
2017-06-20 13:05:10 +08:00
|
|
|
#if !defined(NDEBUG)
|
2017-06-20 12:47:58 +08:00
|
|
|
raw_ostream &operator<<(raw_ostream &OS, const WasmRelocationEntry &Rel) {
|
2017-06-20 12:04:59 +08:00
|
|
|
Rel.print(OS);
|
|
|
|
return OS;
|
|
|
|
}
|
2017-06-20 13:05:10 +08:00
|
|
|
#endif
|
2017-06-20 12:04:59 +08:00
|
|
|
|
2019-01-31 06:47:35 +08:00
|
|
|
// Write X as an (unsigned) LEB value at offset Offset in Stream, padded
|
|
|
|
// to allow patching.
|
2020-06-06 00:03:12 +08:00
|
|
|
template <int W>
|
|
|
|
void writePatchableLEB(raw_pwrite_stream &Stream, uint64_t X, uint64_t Offset) {
|
|
|
|
uint8_t Buffer[W];
|
|
|
|
unsigned SizeLen = encodeULEB128(X, Buffer, W);
|
|
|
|
assert(SizeLen == W);
|
2019-01-31 06:47:35 +08:00
|
|
|
Stream.pwrite((char *)Buffer, SizeLen, Offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Write X as an signed LEB value at offset Offset in Stream, padded
|
|
|
|
// to allow patching.
|
2020-06-06 00:03:12 +08:00
|
|
|
template <int W>
|
|
|
|
void writePatchableSLEB(raw_pwrite_stream &Stream, int64_t X, uint64_t Offset) {
|
|
|
|
uint8_t Buffer[W];
|
|
|
|
unsigned SizeLen = encodeSLEB128(X, Buffer, W);
|
|
|
|
assert(SizeLen == W);
|
2019-01-31 06:47:35 +08:00
|
|
|
Stream.pwrite((char *)Buffer, SizeLen, Offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Write X as a plain integer value at offset Offset in Stream.
|
2020-04-30 04:26:27 +08:00
|
|
|
static void patchI32(raw_pwrite_stream &Stream, uint32_t X, uint64_t Offset) {
|
2019-01-31 06:47:35 +08:00
|
|
|
uint8_t Buffer[4];
|
|
|
|
support::endian::write32le(Buffer, X);
|
|
|
|
Stream.pwrite((char *)Buffer, sizeof(Buffer), Offset);
|
|
|
|
}
|
|
|
|
|
2020-06-06 00:03:12 +08:00
|
|
|
static void patchI64(raw_pwrite_stream &Stream, uint64_t X, uint64_t Offset) {
|
|
|
|
uint8_t Buffer[8];
|
|
|
|
support::endian::write64le(Buffer, X);
|
|
|
|
Stream.pwrite((char *)Buffer, sizeof(Buffer), Offset);
|
|
|
|
}
|
|
|
|
|
2020-08-08 12:23:11 +08:00
|
|
|
bool isDwoSection(const MCSection &Sec) {
|
|
|
|
return Sec.getName().endswith(".dwo");
|
|
|
|
}
|
|
|
|
|
2017-02-22 09:23:18 +08:00
|
|
|
class WasmObjectWriter : public MCObjectWriter {
|
2020-08-08 12:23:11 +08:00
|
|
|
support::endian::Writer *W;
|
2018-05-22 02:17:42 +08:00
|
|
|
|
2017-02-22 09:23:18 +08:00
|
|
|
/// The target specific Wasm writer instance.
|
|
|
|
std::unique_ptr<MCWasmObjectTargetWriter> TargetObjectWriter;
|
|
|
|
|
2017-02-25 07:18:00 +08:00
|
|
|
// Relocations for fixing up references in the code section.
|
|
|
|
std::vector<WasmRelocationEntry> CodeRelocations;
|
|
|
|
// Relocations for fixing up references in the data section.
|
|
|
|
std::vector<WasmRelocationEntry> DataRelocations;
|
|
|
|
|
|
|
|
// Index values to use for fixing up call_indirect type indices.
|
2017-06-07 03:15:05 +08:00
|
|
|
// Maps function symbols to the index of the type of the function
|
|
|
|
DenseMap<const MCSymbolWasm *, uint32_t> TypeIndices;
|
2017-06-13 07:52:44 +08:00
|
|
|
// Maps function symbols to the table element index space. Used
|
|
|
|
// for TABLE_INDEX relocation types (i.e. address taken functions).
|
2018-02-01 03:28:47 +08:00
|
|
|
DenseMap<const MCSymbolWasm *, uint32_t> TableIndices;
|
2020-10-13 22:13:10 +08:00
|
|
|
// Maps function/global/table symbols to the
|
|
|
|
// function/global/table/event/section index space.
|
2018-02-23 13:08:34 +08:00
|
|
|
DenseMap<const MCSymbolWasm *, uint32_t> WasmIndices;
|
2019-03-27 03:46:15 +08:00
|
|
|
DenseMap<const MCSymbolWasm *, uint32_t> GOTIndices;
|
2018-02-23 13:08:34 +08:00
|
|
|
// Maps data symbols to the Wasm segment and offset/size with the segment.
|
|
|
|
DenseMap<const MCSymbolWasm *, wasm::WasmDataReference> DataLocations;
|
2018-04-27 03:27:28 +08:00
|
|
|
|
|
|
|
// Stores output data (index, relocations, content offset) for custom
|
|
|
|
// section.
|
|
|
|
std::vector<WasmCustomSection> CustomSections;
|
2019-01-17 10:29:55 +08:00
|
|
|
std::unique_ptr<WasmCustomSection> ProducersSection;
|
[WebAssembly] Target features section
Summary:
Implements a new target features section in assembly and object files
that records what features are used, required, and disallowed in
WebAssembly objects. The linker uses this information to ensure that
all objects participating in a link are feature-compatible and records
the set of used features in the output binary for use by optimizers
and other tools later in the toolchain.
The "atomics" feature is always required or disallowed to prevent
linking code with stripped atomics into multithreaded binaries. Other
features are marked used if they are enabled globally or on any
function in a module.
Future CLs will add linker flags for ignoring feature compatibility
checks and for specifying the set of allowed features, implement using
the presence of the "atomics" feature to control the type of memory
and segments in the linked binary, and add front-end flags for
relaxing the linkage policy for atomics.
Reviewers: aheejin, sbc100, dschuff
Subscribers: jgravelle-google, hiraditya, sunfish, mgrang, jfb, jdoerfert, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D59173
llvm-svn: 356610
2019-03-21 04:26:45 +08:00
|
|
|
std::unique_ptr<WasmCustomSection> TargetFeaturesSection;
|
2018-04-27 03:27:28 +08:00
|
|
|
// Relocations for fixing up references in the custom sections.
|
|
|
|
DenseMap<const MCSectionWasm *, std::vector<WasmRelocationEntry>>
|
|
|
|
CustomSectionsRelocations;
|
2017-06-07 03:15:05 +08:00
|
|
|
|
2018-05-18 01:15:15 +08:00
|
|
|
// Map from section to defining function symbol.
|
2018-05-17 04:09:05 +08:00
|
|
|
DenseMap<const MCSection *, const MCSymbol *> SectionFunctions;
|
|
|
|
|
2020-09-28 10:04:54 +08:00
|
|
|
DenseMap<wasm::WasmSignature, uint32_t> SignatureIndices;
|
|
|
|
SmallVector<wasm::WasmSignature, 4> Signatures;
|
2018-02-23 13:08:34 +08:00
|
|
|
SmallVector<WasmDataSegment, 4> DataSegments;
|
2018-01-18 03:28:43 +08:00
|
|
|
unsigned NumFunctionImports = 0;
|
2017-09-15 07:07:53 +08:00
|
|
|
unsigned NumGlobalImports = 0;
|
2020-11-26 00:31:05 +08:00
|
|
|
unsigned NumTableImports = 0;
|
2018-11-14 10:46:21 +08:00
|
|
|
unsigned NumEventImports = 0;
|
2018-04-25 04:30:56 +08:00
|
|
|
uint32_t SectionCount = 0;
|
2017-02-25 07:18:00 +08:00
|
|
|
|
2020-08-08 12:23:11 +08:00
|
|
|
enum class DwoMode {
|
|
|
|
AllSections,
|
|
|
|
NonDwoOnly,
|
|
|
|
DwoOnly,
|
|
|
|
};
|
|
|
|
bool IsSplitDwarf = false;
|
|
|
|
raw_pwrite_stream *OS = nullptr;
|
|
|
|
raw_pwrite_stream *DwoOS = nullptr;
|
|
|
|
|
|
|
|
// TargetObjectWriter wranppers.
|
2017-02-22 09:23:18 +08:00
|
|
|
bool is64Bit() const { return TargetObjectWriter->is64Bit(); }
|
2019-08-30 06:40:00 +08:00
|
|
|
bool isEmscripten() const { return TargetObjectWriter->isEmscripten(); }
|
2017-02-22 09:23:18 +08:00
|
|
|
|
2018-04-24 03:16:19 +08:00
|
|
|
void startSection(SectionBookkeeping &Section, unsigned SectionId);
|
|
|
|
void startCustomSection(SectionBookkeeping &Section, StringRef Name);
|
2017-02-25 07:18:00 +08:00
|
|
|
void endSection(SectionBookkeeping &Section);
|
|
|
|
|
2017-02-22 09:23:18 +08:00
|
|
|
public:
|
2017-10-10 09:15:10 +08:00
|
|
|
WasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW,
|
2020-08-08 12:23:11 +08:00
|
|
|
raw_pwrite_stream &OS_)
|
|
|
|
: TargetObjectWriter(std::move(MOTW)), OS(&OS_) {}
|
|
|
|
|
|
|
|
WasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW,
|
|
|
|
raw_pwrite_stream &OS_, raw_pwrite_stream &DwoOS_)
|
|
|
|
: TargetObjectWriter(std::move(MOTW)), IsSplitDwarf(true), OS(&OS_),
|
|
|
|
DwoOS(&DwoOS_) {}
|
2017-02-22 09:23:18 +08:00
|
|
|
|
2018-01-16 01:06:23 +08:00
|
|
|
private:
|
2017-06-07 03:15:05 +08:00
|
|
|
void reset() override {
|
|
|
|
CodeRelocations.clear();
|
|
|
|
DataRelocations.clear();
|
|
|
|
TypeIndices.clear();
|
2018-02-23 13:08:34 +08:00
|
|
|
WasmIndices.clear();
|
2019-03-27 03:46:15 +08:00
|
|
|
GOTIndices.clear();
|
2018-02-01 03:28:47 +08:00
|
|
|
TableIndices.clear();
|
2018-02-23 13:08:34 +08:00
|
|
|
DataLocations.clear();
|
2019-01-17 10:29:55 +08:00
|
|
|
CustomSections.clear();
|
|
|
|
ProducersSection.reset();
|
[WebAssembly] Target features section
Summary:
Implements a new target features section in assembly and object files
that records what features are used, required, and disallowed in
WebAssembly objects. The linker uses this information to ensure that
all objects participating in a link are feature-compatible and records
the set of used features in the output binary for use by optimizers
and other tools later in the toolchain.
The "atomics" feature is always required or disallowed to prevent
linking code with stripped atomics into multithreaded binaries. Other
features are marked used if they are enabled globally or on any
function in a module.
Future CLs will add linker flags for ignoring feature compatibility
checks and for specifying the set of allowed features, implement using
the presence of the "atomics" feature to control the type of memory
and segments in the linked binary, and add front-end flags for
relaxing the linkage policy for atomics.
Reviewers: aheejin, sbc100, dschuff
Subscribers: jgravelle-google, hiraditya, sunfish, mgrang, jfb, jdoerfert, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D59173
llvm-svn: 356610
2019-03-21 04:26:45 +08:00
|
|
|
TargetFeaturesSection.reset();
|
2018-04-27 03:27:28 +08:00
|
|
|
CustomSectionsRelocations.clear();
|
2018-11-14 10:46:21 +08:00
|
|
|
SignatureIndices.clear();
|
|
|
|
Signatures.clear();
|
2018-02-23 13:08:34 +08:00
|
|
|
DataSegments.clear();
|
2018-05-17 04:09:05 +08:00
|
|
|
SectionFunctions.clear();
|
2018-01-18 03:28:43 +08:00
|
|
|
NumFunctionImports = 0;
|
2017-09-15 07:07:53 +08:00
|
|
|
NumGlobalImports = 0;
|
2020-11-26 00:31:05 +08:00
|
|
|
NumTableImports = 0;
|
2018-05-30 10:57:20 +08:00
|
|
|
MCObjectWriter::reset();
|
2017-06-07 03:15:05 +08:00
|
|
|
}
|
|
|
|
|
2017-02-22 09:23:18 +08:00
|
|
|
void writeHeader(const MCAssembler &Asm);
|
|
|
|
|
|
|
|
void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
|
|
|
|
const MCFragment *Fragment, const MCFixup &Fixup,
|
2017-07-12 07:56:10 +08:00
|
|
|
MCValue Target, uint64_t &FixedValue) override;
|
2017-02-22 09:23:18 +08:00
|
|
|
|
|
|
|
void executePostLayoutBinding(MCAssembler &Asm,
|
|
|
|
const MCAsmLayout &Layout) override;
|
2020-08-08 12:23:11 +08:00
|
|
|
void prepareImports(SmallVectorImpl<wasm::WasmImport> &Imports,
|
|
|
|
MCAssembler &Asm, const MCAsmLayout &Layout);
|
2018-05-22 02:23:50 +08:00
|
|
|
uint64_t writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
|
2017-06-03 10:01:24 +08:00
|
|
|
|
2020-08-08 12:23:11 +08:00
|
|
|
uint64_t writeOneObject(MCAssembler &Asm, const MCAsmLayout &Layout,
|
|
|
|
DwoMode Mode);
|
|
|
|
|
2017-06-20 12:04:59 +08:00
|
|
|
void writeString(const StringRef Str) {
|
2020-08-08 12:23:11 +08:00
|
|
|
encodeULEB128(Str.size(), W->OS);
|
|
|
|
W->OS << Str;
|
2017-06-20 12:04:59 +08:00
|
|
|
}
|
|
|
|
|
2020-04-30 04:26:27 +08:00
|
|
|
void writeI32(int32_t val) {
|
|
|
|
char Buffer[4];
|
|
|
|
support::endian::write32le(Buffer, val);
|
2020-08-08 12:23:11 +08:00
|
|
|
W->OS.write(Buffer, sizeof(Buffer));
|
2020-04-30 04:26:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void writeI64(int64_t val) {
|
|
|
|
char Buffer[8];
|
|
|
|
support::endian::write64le(Buffer, val);
|
2020-08-08 12:23:11 +08:00
|
|
|
W->OS.write(Buffer, sizeof(Buffer));
|
2020-04-30 04:26:27 +08:00
|
|
|
}
|
|
|
|
|
2020-08-08 12:23:11 +08:00
|
|
|
void writeValueType(wasm::ValType Ty) { W->OS << static_cast<char>(Ty); }
|
2017-06-03 10:01:24 +08:00
|
|
|
|
2020-09-28 10:04:54 +08:00
|
|
|
void writeTypeSection(ArrayRef<wasm::WasmSignature> Signatures);
|
2020-06-30 08:53:09 +08:00
|
|
|
void writeImportSection(ArrayRef<wasm::WasmImport> Imports, uint64_t DataSize,
|
2017-12-12 07:03:38 +08:00
|
|
|
uint32_t NumElements);
|
2017-09-16 03:50:44 +08:00
|
|
|
void writeFunctionSection(ArrayRef<WasmFunction> Functions);
|
2018-02-13 06:41:29 +08:00
|
|
|
void writeExportSection(ArrayRef<wasm::WasmExport> Exports);
|
2021-03-04 17:30:00 +08:00
|
|
|
void writeElemSection(const MCSymbolWasm *IndirectFunctionTable,
|
|
|
|
ArrayRef<uint32_t> TableElems);
|
2019-04-13 06:27:48 +08:00
|
|
|
void writeDataCountSection();
|
2020-06-24 05:59:18 +08:00
|
|
|
uint32_t writeCodeSection(const MCAssembler &Asm, const MCAsmLayout &Layout,
|
|
|
|
ArrayRef<WasmFunction> Functions);
|
|
|
|
uint32_t writeDataSection(const MCAsmLayout &Layout);
|
2018-11-14 10:46:21 +08:00
|
|
|
void writeEventSection(ArrayRef<wasm::WasmEventType> Events);
|
2020-04-30 04:26:27 +08:00
|
|
|
void writeGlobalSection(ArrayRef<wasm::WasmGlobal> Globals);
|
2020-10-13 22:13:10 +08:00
|
|
|
void writeTableSection(ArrayRef<wasm::WasmTable> Tables);
|
2018-04-25 02:11:36 +08:00
|
|
|
void writeRelocSection(uint32_t SectionIndex, StringRef Name,
|
2018-09-05 09:27:38 +08:00
|
|
|
std::vector<WasmRelocationEntry> &Relocations);
|
2017-09-21 05:17:04 +08:00
|
|
|
void writeLinkingMetaDataSection(
|
2018-02-28 07:57:37 +08:00
|
|
|
ArrayRef<wasm::WasmSymbolInfo> SymbolInfos,
|
2018-01-10 07:43:14 +08:00
|
|
|
ArrayRef<std::pair<uint16_t, uint32_t>> InitFuncs,
|
2018-02-23 13:08:34 +08:00
|
|
|
const std::map<StringRef, std::vector<WasmComdatEntry>> &Comdats);
|
2019-01-17 10:29:55 +08:00
|
|
|
void writeCustomSection(WasmCustomSection &CustomSection,
|
|
|
|
const MCAssembler &Asm, const MCAsmLayout &Layout);
|
2018-04-27 03:27:28 +08:00
|
|
|
void writeCustomRelocSections();
|
2017-06-07 03:15:05 +08:00
|
|
|
|
2020-04-30 06:38:11 +08:00
|
|
|
uint64_t getProvisionalValue(const WasmRelocationEntry &RelEntry,
|
|
|
|
const MCAsmLayout &Layout);
|
2017-06-07 03:15:05 +08:00
|
|
|
void applyRelocations(ArrayRef<WasmRelocationEntry> Relocations,
|
2020-04-30 06:38:11 +08:00
|
|
|
uint64_t ContentsOffset, const MCAsmLayout &Layout);
|
2017-06-07 03:15:05 +08:00
|
|
|
|
|
|
|
uint32_t getRelocationIndexValue(const WasmRelocationEntry &RelEntry);
|
2018-04-25 02:11:36 +08:00
|
|
|
uint32_t getFunctionType(const MCSymbolWasm &Symbol);
|
2018-11-14 10:46:21 +08:00
|
|
|
uint32_t getEventType(const MCSymbolWasm &Symbol);
|
2018-11-20 08:38:10 +08:00
|
|
|
void registerFunctionType(const MCSymbolWasm &Symbol);
|
|
|
|
void registerEventType(const MCSymbolWasm &Symbol);
|
2017-02-22 09:23:18 +08:00
|
|
|
};
|
2017-06-03 10:01:24 +08:00
|
|
|
|
2017-02-22 09:23:18 +08:00
|
|
|
} // end anonymous namespace
|
|
|
|
|
2017-02-25 07:18:00 +08:00
|
|
|
// Write out a section header and a patchable section size field.
|
|
|
|
void WasmObjectWriter::startSection(SectionBookkeeping &Section,
|
2018-04-24 03:16:19 +08:00
|
|
|
unsigned SectionId) {
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "startSection " << SectionId << "\n");
|
2020-08-08 12:23:11 +08:00
|
|
|
W->OS << char(SectionId);
|
2017-02-25 07:18:00 +08:00
|
|
|
|
2020-08-08 12:23:11 +08:00
|
|
|
Section.SizeOffset = W->OS.tell();
|
2017-02-25 07:18:00 +08:00
|
|
|
|
|
|
|
// The section size. We don't know the size yet, so reserve enough space
|
|
|
|
// for any 32-bit value; we'll patch it later.
|
2020-08-08 12:23:11 +08:00
|
|
|
encodeULEB128(0, W->OS, 5);
|
2017-02-25 07:18:00 +08:00
|
|
|
|
|
|
|
// The position where the section starts, for measuring its size.
|
2020-08-08 12:23:11 +08:00
|
|
|
Section.ContentsOffset = W->OS.tell();
|
|
|
|
Section.PayloadOffset = W->OS.tell();
|
2018-04-25 02:11:36 +08:00
|
|
|
Section.Index = SectionCount++;
|
2018-04-24 03:16:19 +08:00
|
|
|
}
|
2017-02-25 07:18:00 +08:00
|
|
|
|
2018-04-24 03:16:19 +08:00
|
|
|
void WasmObjectWriter::startCustomSection(SectionBookkeeping &Section,
|
|
|
|
StringRef Name) {
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "startCustomSection " << Name << "\n");
|
2018-04-24 03:16:19 +08:00
|
|
|
startSection(Section, wasm::WASM_SEC_CUSTOM);
|
2018-04-27 03:27:28 +08:00
|
|
|
|
|
|
|
// The position where the section header ends, for measuring its size.
|
2020-08-08 12:23:11 +08:00
|
|
|
Section.PayloadOffset = W->OS.tell();
|
2018-04-27 03:27:28 +08:00
|
|
|
|
2017-02-25 07:18:00 +08:00
|
|
|
// Custom sections in wasm also have a string identifier.
|
2018-04-24 03:16:19 +08:00
|
|
|
writeString(Name);
|
2018-04-27 03:27:28 +08:00
|
|
|
|
|
|
|
// The position where the custom section starts.
|
2020-08-08 12:23:11 +08:00
|
|
|
Section.ContentsOffset = W->OS.tell();
|
2017-02-25 07:18:00 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Now that the section is complete and we know how big it is, patch up the
|
|
|
|
// section size field at the start of the section.
|
|
|
|
void WasmObjectWriter::endSection(SectionBookkeeping &Section) {
|
2020-08-08 12:23:11 +08:00
|
|
|
uint64_t Size = W->OS.tell();
|
2019-02-01 06:38:22 +08:00
|
|
|
// /dev/null doesn't support seek/tell and can report offset of 0.
|
|
|
|
// Simply skip this patching in that case.
|
|
|
|
if (!Size)
|
|
|
|
return;
|
|
|
|
|
|
|
|
Size -= Section.PayloadOffset;
|
2017-02-25 07:18:00 +08:00
|
|
|
if (uint32_t(Size) != Size)
|
|
|
|
report_fatal_error("section size does not fit in a uint32_t");
|
|
|
|
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "endSection size=" << Size << "\n");
|
2017-02-25 07:18:00 +08:00
|
|
|
|
|
|
|
// Write the final section size to the payload_len field, which follows
|
|
|
|
// the section id byte.
|
2020-08-08 12:23:11 +08:00
|
|
|
writePatchableLEB<5>(static_cast<raw_pwrite_stream &>(W->OS), Size,
|
2020-06-06 00:03:12 +08:00
|
|
|
Section.SizeOffset);
|
2017-02-25 07:18:00 +08:00
|
|
|
}
|
|
|
|
|
2017-02-22 09:23:18 +08:00
|
|
|
// Emit the Wasm header.
|
|
|
|
void WasmObjectWriter::writeHeader(const MCAssembler &Asm) {
|
2020-08-08 12:23:11 +08:00
|
|
|
W->OS.write(wasm::WasmMagic, sizeof(wasm::WasmMagic));
|
|
|
|
W->write<uint32_t>(wasm::WasmVersion);
|
2017-02-22 09:23:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void WasmObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
|
|
|
|
const MCAsmLayout &Layout) {
|
2021-02-12 18:22:13 +08:00
|
|
|
// Some compilation units require the indirect function table to be present
|
|
|
|
// but don't explicitly reference it. This is the case for call_indirect
|
|
|
|
// without the reference-types feature, and also function bitcasts in all
|
|
|
|
// cases. In those cases the __indirect_function_table has the
|
|
|
|
// WASM_SYMBOL_NO_STRIP attribute. Here we make sure this symbol makes it to
|
|
|
|
// the assembler, if needed.
|
|
|
|
if (auto *Sym = Asm.getContext().lookupSymbol("__indirect_function_table")) {
|
|
|
|
const auto *WasmSym = static_cast<const MCSymbolWasm *>(Sym);
|
|
|
|
if (WasmSym->isNoStrip())
|
|
|
|
Asm.registerSymbol(*Sym);
|
|
|
|
}
|
2021-01-20 06:29:05 +08:00
|
|
|
|
2018-05-17 04:09:05 +08:00
|
|
|
// Build a map of sections to the function that defines them, for use
|
|
|
|
// in recordRelocation.
|
|
|
|
for (const MCSymbol &S : Asm.symbols()) {
|
|
|
|
const auto &WS = static_cast<const MCSymbolWasm &>(S);
|
|
|
|
if (WS.isDefined() && WS.isFunction() && !WS.isVariable()) {
|
|
|
|
const auto &Sec = static_cast<const MCSectionWasm &>(S.getSection());
|
|
|
|
auto Pair = SectionFunctions.insert(std::make_pair(&Sec, &S));
|
|
|
|
if (!Pair.second)
|
|
|
|
report_fatal_error("section already has a defining function: " +
|
2020-04-16 06:49:05 +08:00
|
|
|
Sec.getName());
|
2018-05-17 04:09:05 +08:00
|
|
|
}
|
|
|
|
}
|
2017-02-22 09:23:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void WasmObjectWriter::recordRelocation(MCAssembler &Asm,
|
|
|
|
const MCAsmLayout &Layout,
|
|
|
|
const MCFragment *Fragment,
|
|
|
|
const MCFixup &Fixup, MCValue Target,
|
2017-07-12 07:56:10 +08:00
|
|
|
uint64_t &FixedValue) {
|
2019-08-20 08:33:50 +08:00
|
|
|
// The WebAssembly backend should never generate FKF_IsPCRel fixups
|
2019-08-20 10:02:57 +08:00
|
|
|
assert(!(Asm.getBackend().getFixupKindInfo(Fixup.getKind()).Flags &
|
2019-08-20 08:33:50 +08:00
|
|
|
MCFixupKindInfo::FKF_IsPCRel));
|
|
|
|
|
2017-06-22 07:46:41 +08:00
|
|
|
const auto &FixupSection = cast<MCSectionWasm>(*Fragment->getParent());
|
2017-02-25 07:18:00 +08:00
|
|
|
uint64_t C = Target.getConstant();
|
|
|
|
uint64_t FixupOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
|
|
|
|
MCContext &Ctx = Asm.getContext();
|
|
|
|
|
|
|
|
if (const MCSymbolRefExpr *RefB = Target.getSymB()) {
|
2019-08-20 08:33:50 +08:00
|
|
|
// To get here the A - B expression must have failed evaluateAsRelocatable.
|
|
|
|
// This means either A or B must be undefined and in WebAssembly we can't
|
|
|
|
// support either of those cases.
|
2017-02-25 07:18:00 +08:00
|
|
|
const auto &SymB = cast<MCSymbolWasm>(RefB->getSymbol());
|
2019-08-20 08:33:50 +08:00
|
|
|
Ctx.reportError(
|
|
|
|
Fixup.getLoc(),
|
|
|
|
Twine("symbol '") + SymB.getName() +
|
|
|
|
"': unsupported subtraction expression used in relocation.");
|
|
|
|
return;
|
2017-02-25 07:18:00 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// We either rejected the fixup or folded B into C at this point.
|
|
|
|
const MCSymbolRefExpr *RefA = Target.getSymA();
|
2019-08-20 08:33:50 +08:00
|
|
|
const auto *SymA = cast<MCSymbolWasm>(&RefA->getSymbol());
|
2017-02-25 07:18:00 +08:00
|
|
|
|
2020-03-31 08:37:01 +08:00
|
|
|
// The .init_array isn't translated as data, so don't do relocations in it.
|
2020-04-16 06:49:05 +08:00
|
|
|
if (FixupSection.getName().startswith(".init_array")) {
|
2020-03-31 08:37:01 +08:00
|
|
|
SymA->setUsedInInitArray();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-08-20 08:33:50 +08:00
|
|
|
if (SymA->isVariable()) {
|
2017-02-25 07:18:00 +08:00
|
|
|
const MCExpr *Expr = SymA->getVariableValue();
|
2020-04-30 06:38:11 +08:00
|
|
|
if (const auto *Inner = dyn_cast<MCSymbolRefExpr>(Expr))
|
|
|
|
if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF)
|
|
|
|
llvm_unreachable("weakref used in reloc not yet implemented");
|
2017-02-25 07:18:00 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Put any constant offset in an addend. Offsets can be negative, and
|
|
|
|
// LLVM expects wrapping, in contrast to wasm's immediates which can't
|
|
|
|
// be negative and don't wrap.
|
|
|
|
FixedValue = 0;
|
|
|
|
|
2019-03-28 10:07:28 +08:00
|
|
|
unsigned Type = TargetObjectWriter->getRelocType(Target, Fixup);
|
2017-06-17 07:59:10 +08:00
|
|
|
|
2018-05-03 07:11:38 +08:00
|
|
|
// Absolute offset within a section or a function.
|
|
|
|
// Currently only supported for for metadata sections.
|
|
|
|
// See: test/MC/WebAssembly/blockaddress.ll
|
2019-02-05 01:28:46 +08:00
|
|
|
if (Type == wasm::R_WASM_FUNCTION_OFFSET_I32 ||
|
2020-11-13 07:05:05 +08:00
|
|
|
Type == wasm::R_WASM_FUNCTION_OFFSET_I64 ||
|
2019-02-05 01:28:46 +08:00
|
|
|
Type == wasm::R_WASM_SECTION_OFFSET_I32) {
|
2018-05-03 07:11:38 +08:00
|
|
|
if (!FixupSection.getKind().isMetadata())
|
|
|
|
report_fatal_error("relocations for function or section offsets are "
|
|
|
|
"only supported in metadata sections");
|
|
|
|
|
|
|
|
const MCSymbol *SectionSymbol = nullptr;
|
|
|
|
const MCSection &SecA = SymA->getSection();
|
2021-02-02 09:28:00 +08:00
|
|
|
if (SecA.getKind().isText()) {
|
|
|
|
auto SecSymIt = SectionFunctions.find(&SecA);
|
|
|
|
if (SecSymIt == SectionFunctions.end())
|
|
|
|
report_fatal_error("section doesn\'t have defining symbol");
|
|
|
|
SectionSymbol = SecSymIt->second;
|
|
|
|
} else {
|
2018-05-03 07:11:38 +08:00
|
|
|
SectionSymbol = SecA.getBeginSymbol();
|
2021-02-02 09:28:00 +08:00
|
|
|
}
|
2018-05-03 07:11:38 +08:00
|
|
|
if (!SectionSymbol)
|
|
|
|
report_fatal_error("section symbol is required for relocation");
|
|
|
|
|
|
|
|
C += Layout.getSymbolOffset(*SymA);
|
|
|
|
SymA = cast<MCSymbolWasm>(SectionSymbol);
|
|
|
|
}
|
|
|
|
|
2020-11-26 00:31:05 +08:00
|
|
|
if (Type == wasm::R_WASM_TABLE_INDEX_REL_SLEB ||
|
|
|
|
Type == wasm::R_WASM_TABLE_INDEX_SLEB ||
|
|
|
|
Type == wasm::R_WASM_TABLE_INDEX_SLEB64 ||
|
|
|
|
Type == wasm::R_WASM_TABLE_INDEX_I32 ||
|
|
|
|
Type == wasm::R_WASM_TABLE_INDEX_I64) {
|
|
|
|
// TABLE_INDEX relocs implicitly use the default indirect function table.
|
2021-02-12 18:22:13 +08:00
|
|
|
// We require the function table to have already been defined.
|
2020-11-26 00:31:05 +08:00
|
|
|
auto TableName = "__indirect_function_table";
|
|
|
|
MCSymbolWasm *Sym = cast_or_null<MCSymbolWasm>(Ctx.lookupSymbol(TableName));
|
2021-02-12 18:22:13 +08:00
|
|
|
if (!Sym || !Sym->isFunctionTable()) {
|
|
|
|
Ctx.reportError(
|
|
|
|
Fixup.getLoc(),
|
|
|
|
"symbol '__indirect_function_table' is not a function table");
|
2020-11-26 00:31:05 +08:00
|
|
|
} else {
|
2021-02-12 18:22:13 +08:00
|
|
|
// Ensure that __indirect_function_table reaches the output.
|
|
|
|
Sym->setNoStrip();
|
|
|
|
Asm.registerSymbol(*Sym);
|
2020-11-26 00:31:05 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-05 01:28:46 +08:00
|
|
|
// Relocation other than R_WASM_TYPE_INDEX_LEB are required to be
|
2018-05-03 07:11:38 +08:00
|
|
|
// against a named symbol.
|
2019-02-05 01:28:46 +08:00
|
|
|
if (Type != wasm::R_WASM_TYPE_INDEX_LEB) {
|
2018-05-03 07:11:38 +08:00
|
|
|
if (SymA->getName().empty())
|
|
|
|
report_fatal_error("relocations against un-named temporaries are not yet "
|
|
|
|
"supported by wasm");
|
|
|
|
|
|
|
|
SymA->setUsedInReloc();
|
|
|
|
}
|
2017-06-14 02:51:50 +08:00
|
|
|
|
2019-03-27 03:46:15 +08:00
|
|
|
if (RefA->getKind() == MCSymbolRefExpr::VK_GOT)
|
|
|
|
SymA->setUsedInGOT();
|
|
|
|
|
2017-02-25 07:18:00 +08:00
|
|
|
WasmRelocationEntry Rec(FixupOffset, SymA, C, Type, &FixupSection);
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "WasmReloc: " << Rec << "\n");
|
2017-02-25 07:18:00 +08:00
|
|
|
|
2018-04-27 03:27:28 +08:00
|
|
|
if (FixupSection.isWasmData()) {
|
2017-02-25 07:18:00 +08:00
|
|
|
DataRelocations.push_back(Rec);
|
2018-04-27 03:27:28 +08:00
|
|
|
} else if (FixupSection.getKind().isText()) {
|
2017-10-21 05:28:38 +08:00
|
|
|
CodeRelocations.push_back(Rec);
|
2018-04-27 03:27:28 +08:00
|
|
|
} else if (FixupSection.getKind().isMetadata()) {
|
|
|
|
CustomSectionsRelocations[&FixupSection].push_back(Rec);
|
|
|
|
} else {
|
2017-10-21 05:28:38 +08:00
|
|
|
llvm_unreachable("unexpected section type");
|
2018-04-27 03:27:28 +08:00
|
|
|
}
|
2017-02-25 07:18:00 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Compute a value to write into the code at the location covered
|
2018-01-23 09:23:17 +08:00
|
|
|
// by RelEntry. This value isn't used by the static linker; it just serves
|
|
|
|
// to make the object format more readable and more likely to be directly
|
|
|
|
// useable.
|
2020-06-06 00:03:12 +08:00
|
|
|
uint64_t
|
2020-04-30 06:38:11 +08:00
|
|
|
WasmObjectWriter::getProvisionalValue(const WasmRelocationEntry &RelEntry,
|
|
|
|
const MCAsmLayout &Layout) {
|
2020-03-20 10:53:51 +08:00
|
|
|
if ((RelEntry.Type == wasm::R_WASM_GLOBAL_INDEX_LEB ||
|
|
|
|
RelEntry.Type == wasm::R_WASM_GLOBAL_INDEX_I32) &&
|
|
|
|
!RelEntry.Symbol->isGlobal()) {
|
2019-03-27 03:46:15 +08:00
|
|
|
assert(GOTIndices.count(RelEntry.Symbol) > 0 && "symbol not found in GOT index space");
|
|
|
|
return GOTIndices[RelEntry.Symbol];
|
|
|
|
}
|
|
|
|
|
2018-01-23 09:23:17 +08:00
|
|
|
switch (RelEntry.Type) {
|
2019-04-05 01:43:50 +08:00
|
|
|
case wasm::R_WASM_TABLE_INDEX_REL_SLEB:
|
2019-02-05 01:28:46 +08:00
|
|
|
case wasm::R_WASM_TABLE_INDEX_SLEB:
|
2020-07-11 07:51:01 +08:00
|
|
|
case wasm::R_WASM_TABLE_INDEX_SLEB64:
|
|
|
|
case wasm::R_WASM_TABLE_INDEX_I32:
|
|
|
|
case wasm::R_WASM_TABLE_INDEX_I64: {
|
2018-02-01 03:28:47 +08:00
|
|
|
// Provisional value is table address of the resolved symbol itself
|
2020-04-30 06:38:11 +08:00
|
|
|
const MCSymbolWasm *Base =
|
|
|
|
cast<MCSymbolWasm>(Layout.getBaseSymbol(*RelEntry.Symbol));
|
|
|
|
assert(Base->isFunction());
|
2020-05-29 09:39:27 +08:00
|
|
|
if (RelEntry.Type == wasm::R_WASM_TABLE_INDEX_REL_SLEB)
|
2020-04-30 06:38:11 +08:00
|
|
|
return TableIndices[Base] - InitialTableOffset;
|
2020-05-29 09:39:27 +08:00
|
|
|
else
|
2020-04-30 06:38:11 +08:00
|
|
|
return TableIndices[Base];
|
2018-02-01 03:28:47 +08:00
|
|
|
}
|
2019-02-05 01:28:46 +08:00
|
|
|
case wasm::R_WASM_TYPE_INDEX_LEB:
|
2018-02-23 13:08:34 +08:00
|
|
|
// Provisional value is same as the index
|
2018-01-23 09:23:17 +08:00
|
|
|
return getRelocationIndexValue(RelEntry);
|
2019-02-05 01:28:46 +08:00
|
|
|
case wasm::R_WASM_FUNCTION_INDEX_LEB:
|
|
|
|
case wasm::R_WASM_GLOBAL_INDEX_LEB:
|
2020-03-20 10:53:51 +08:00
|
|
|
case wasm::R_WASM_GLOBAL_INDEX_I32:
|
2019-02-05 01:28:46 +08:00
|
|
|
case wasm::R_WASM_EVENT_INDEX_LEB:
|
2020-10-23 23:36:06 +08:00
|
|
|
case wasm::R_WASM_TABLE_NUMBER_LEB:
|
2018-11-14 10:46:21 +08:00
|
|
|
// Provisional value is function/global/event Wasm index
|
2019-03-27 03:46:15 +08:00
|
|
|
assert(WasmIndices.count(RelEntry.Symbol) > 0 && "symbol not found in wasm index space");
|
2018-02-23 13:08:34 +08:00
|
|
|
return WasmIndices[RelEntry.Symbol];
|
2019-02-05 01:28:46 +08:00
|
|
|
case wasm::R_WASM_FUNCTION_OFFSET_I32:
|
2020-11-13 07:05:05 +08:00
|
|
|
case wasm::R_WASM_FUNCTION_OFFSET_I64:
|
2019-02-05 01:28:46 +08:00
|
|
|
case wasm::R_WASM_SECTION_OFFSET_I32: {
|
2018-04-27 03:27:28 +08:00
|
|
|
const auto &Section =
|
|
|
|
static_cast<const MCSectionWasm &>(RelEntry.Symbol->getSection());
|
|
|
|
return Section.getSectionOffset() + RelEntry.Addend;
|
|
|
|
}
|
2019-02-05 01:28:46 +08:00
|
|
|
case wasm::R_WASM_MEMORY_ADDR_LEB:
|
2020-06-06 00:03:12 +08:00
|
|
|
case wasm::R_WASM_MEMORY_ADDR_LEB64:
|
|
|
|
case wasm::R_WASM_MEMORY_ADDR_SLEB:
|
|
|
|
case wasm::R_WASM_MEMORY_ADDR_SLEB64:
|
2019-04-05 01:43:50 +08:00
|
|
|
case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
|
2020-06-06 00:03:12 +08:00
|
|
|
case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:
|
|
|
|
case wasm::R_WASM_MEMORY_ADDR_I32:
|
2020-11-11 09:46:52 +08:00
|
|
|
case wasm::R_WASM_MEMORY_ADDR_I64:
|
|
|
|
case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB: {
|
2020-09-09 09:17:05 +08:00
|
|
|
// Provisional value is address of the global plus the offset
|
2018-01-23 09:23:17 +08:00
|
|
|
// For undefined symbols, use zero
|
2021-02-08 10:51:42 +08:00
|
|
|
if (!RelEntry.Symbol->isDefined())
|
2018-01-23 09:23:17 +08:00
|
|
|
return 0;
|
2021-02-08 10:51:42 +08:00
|
|
|
const wasm::WasmDataReference &SymRef = DataLocations[RelEntry.Symbol];
|
|
|
|
const WasmDataSegment &Segment = DataSegments[SymRef.Segment];
|
2018-01-23 09:23:17 +08:00
|
|
|
// Ignore overflow. LLVM allows address arithmetic to silently wrap.
|
2021-02-08 10:51:42 +08:00
|
|
|
return Segment.Offset + SymRef.Offset + RelEntry.Addend;
|
2018-01-23 09:23:17 +08:00
|
|
|
}
|
|
|
|
default:
|
|
|
|
llvm_unreachable("invalid relocation type");
|
|
|
|
}
|
2017-02-25 07:18:00 +08:00
|
|
|
}
|
|
|
|
|
2017-09-16 04:54:59 +08:00
|
|
|
static void addData(SmallVectorImpl<char> &DataBytes,
|
2017-09-30 00:50:08 +08:00
|
|
|
MCSectionWasm &DataSection) {
|
2020-04-16 06:49:05 +08:00
|
|
|
LLVM_DEBUG(errs() << "addData: " << DataSection.getName() << "\n");
|
2017-09-16 04:54:59 +08:00
|
|
|
|
2017-09-30 00:50:08 +08:00
|
|
|
DataBytes.resize(alignTo(DataBytes.size(), DataSection.getAlignment()));
|
|
|
|
|
2017-09-16 04:54:59 +08:00
|
|
|
for (const MCFragment &Frag : DataSection) {
|
|
|
|
if (Frag.hasInstructions())
|
|
|
|
report_fatal_error("only data supported in data sections");
|
|
|
|
|
|
|
|
if (auto *Align = dyn_cast<MCAlignFragment>(&Frag)) {
|
|
|
|
if (Align->getValueSize() != 1)
|
|
|
|
report_fatal_error("only byte values supported for alignment");
|
|
|
|
// If nops are requested, use zeros, as this is the data section.
|
|
|
|
uint8_t Value = Align->hasEmitNops() ? 0 : Align->getValue();
|
2018-09-05 09:27:38 +08:00
|
|
|
uint64_t Size =
|
|
|
|
std::min<uint64_t>(alignTo(DataBytes.size(), Align->getAlignment()),
|
|
|
|
DataBytes.size() + Align->getMaxBytesToEmit());
|
2017-09-16 04:54:59 +08:00
|
|
|
DataBytes.resize(Size, Value);
|
|
|
|
} else if (auto *Fill = dyn_cast<MCFillFragment>(&Frag)) {
|
2018-05-19 01:45:48 +08:00
|
|
|
int64_t NumValues;
|
|
|
|
if (!Fill->getNumValues().evaluateAsAbsolute(NumValues))
|
2018-01-10 06:48:37 +08:00
|
|
|
llvm_unreachable("The fill should be an assembler constant");
|
2018-05-19 01:45:48 +08:00
|
|
|
DataBytes.insert(DataBytes.end(), Fill->getValueSize() * NumValues,
|
|
|
|
Fill->getValue());
|
Reland "[WebAssembly] LSDA info generation"
Summary:
This adds support for LSDA (exception table) generation for wasm EH.
Wasm EH mostly follows the structure of Itanium-style exception tables,
with one exception: a call site table entry in wasm EH corresponds to
not a call site but a landing pad.
In wasm EH, the VM is responsible for stack unwinding. After an
exception occurs and the stack is unwound, the control flow is
transferred to wasm 'catch' instruction by the VM, after which the
personality function is called from the compiler-generated code. (Refer
to WasmEHPrepare pass for more information on this part.)
This patch:
- Changes wasm.landingpad.index intrinsic to take a token argument, to
make this 1:1 match with a catchpad instruction
- Stores landingpad index info and catch type info MachineFunction in
before instruction selection
- Lowers wasm.lsda intrinsic to an MCSymbol pointing to the start of an
exception table
- Adds WasmException class with overridden methods for table generation
- Adds support for LSDA section in Wasm object writer
Reviewers: dschuff, sbc100, rnk
Subscribers: mgorny, jgravelle-google, sunfish, llvm-commits
Differential Revision: https://reviews.llvm.org/D52748
llvm-svn: 345345
2018-10-26 07:55:10 +08:00
|
|
|
} else if (auto *LEB = dyn_cast<MCLEBFragment>(&Frag)) {
|
|
|
|
const SmallVectorImpl<char> &Contents = LEB->getContents();
|
2021-01-07 10:27:33 +08:00
|
|
|
llvm::append_range(DataBytes, Contents);
|
2017-09-16 04:54:59 +08:00
|
|
|
} else {
|
|
|
|
const auto &DataFrag = cast<MCDataFragment>(Frag);
|
|
|
|
const SmallVectorImpl<char> &Contents = DataFrag.getContents();
|
2021-01-07 10:27:33 +08:00
|
|
|
llvm::append_range(DataBytes, Contents);
|
2017-09-16 04:54:59 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "addData -> " << DataBytes.size() << "\n");
|
2017-09-16 04:54:59 +08:00
|
|
|
}
|
|
|
|
|
2018-01-23 09:23:17 +08:00
|
|
|
uint32_t
|
|
|
|
WasmObjectWriter::getRelocationIndexValue(const WasmRelocationEntry &RelEntry) {
|
2019-02-05 01:28:46 +08:00
|
|
|
if (RelEntry.Type == wasm::R_WASM_TYPE_INDEX_LEB) {
|
2017-06-20 12:04:59 +08:00
|
|
|
if (!TypeIndices.count(RelEntry.Symbol))
|
2017-07-07 10:01:29 +08:00
|
|
|
report_fatal_error("symbol not found in type index space: " +
|
2017-06-20 12:04:59 +08:00
|
|
|
RelEntry.Symbol->getName());
|
2017-06-07 03:15:05 +08:00
|
|
|
return TypeIndices[RelEntry.Symbol];
|
|
|
|
}
|
2018-01-23 09:23:17 +08:00
|
|
|
|
2018-05-08 08:08:21 +08:00
|
|
|
return RelEntry.Symbol->getIndex();
|
2017-06-07 03:15:05 +08:00
|
|
|
}
|
|
|
|
|
2017-02-25 07:18:00 +08:00
|
|
|
// Apply the portions of the relocation records that we can handle ourselves
|
|
|
|
// directly.
|
2017-06-07 03:15:05 +08:00
|
|
|
void WasmObjectWriter::applyRelocations(
|
2020-04-30 06:38:11 +08:00
|
|
|
ArrayRef<WasmRelocationEntry> Relocations, uint64_t ContentsOffset,
|
|
|
|
const MCAsmLayout &Layout) {
|
2020-08-08 12:23:11 +08:00
|
|
|
auto &Stream = static_cast<raw_pwrite_stream &>(W->OS);
|
2017-02-25 07:18:00 +08:00
|
|
|
for (const WasmRelocationEntry &RelEntry : Relocations) {
|
|
|
|
uint64_t Offset = ContentsOffset +
|
|
|
|
RelEntry.FixupSection->getSectionOffset() +
|
|
|
|
RelEntry.Offset;
|
|
|
|
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "applyRelocation: " << RelEntry << "\n");
|
2020-04-30 06:38:11 +08:00
|
|
|
auto Value = getProvisionalValue(RelEntry, Layout);
|
2018-01-23 09:23:17 +08:00
|
|
|
|
2017-06-07 03:15:05 +08:00
|
|
|
switch (RelEntry.Type) {
|
2019-02-05 01:28:46 +08:00
|
|
|
case wasm::R_WASM_FUNCTION_INDEX_LEB:
|
|
|
|
case wasm::R_WASM_TYPE_INDEX_LEB:
|
|
|
|
case wasm::R_WASM_GLOBAL_INDEX_LEB:
|
|
|
|
case wasm::R_WASM_MEMORY_ADDR_LEB:
|
|
|
|
case wasm::R_WASM_EVENT_INDEX_LEB:
|
2020-10-23 23:36:06 +08:00
|
|
|
case wasm::R_WASM_TABLE_NUMBER_LEB:
|
2020-06-06 00:03:12 +08:00
|
|
|
writePatchableLEB<5>(Stream, Value, Offset);
|
|
|
|
break;
|
|
|
|
case wasm::R_WASM_MEMORY_ADDR_LEB64:
|
|
|
|
writePatchableLEB<10>(Stream, Value, Offset);
|
2017-02-25 07:18:00 +08:00
|
|
|
break;
|
2019-02-05 01:28:46 +08:00
|
|
|
case wasm::R_WASM_TABLE_INDEX_I32:
|
|
|
|
case wasm::R_WASM_MEMORY_ADDR_I32:
|
|
|
|
case wasm::R_WASM_FUNCTION_OFFSET_I32:
|
|
|
|
case wasm::R_WASM_SECTION_OFFSET_I32:
|
2020-03-20 10:53:51 +08:00
|
|
|
case wasm::R_WASM_GLOBAL_INDEX_I32:
|
2020-04-30 04:26:27 +08:00
|
|
|
patchI32(Stream, Value, Offset);
|
2017-02-25 07:18:00 +08:00
|
|
|
break;
|
2020-07-11 07:51:01 +08:00
|
|
|
case wasm::R_WASM_TABLE_INDEX_I64:
|
2020-06-06 00:03:12 +08:00
|
|
|
case wasm::R_WASM_MEMORY_ADDR_I64:
|
2020-11-13 07:05:05 +08:00
|
|
|
case wasm::R_WASM_FUNCTION_OFFSET_I64:
|
2020-06-06 00:03:12 +08:00
|
|
|
patchI64(Stream, Value, Offset);
|
|
|
|
break;
|
2019-02-05 01:28:46 +08:00
|
|
|
case wasm::R_WASM_TABLE_INDEX_SLEB:
|
2019-04-05 01:43:50 +08:00
|
|
|
case wasm::R_WASM_TABLE_INDEX_REL_SLEB:
|
2019-02-05 01:28:46 +08:00
|
|
|
case wasm::R_WASM_MEMORY_ADDR_SLEB:
|
2019-04-05 01:43:50 +08:00
|
|
|
case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
|
2020-11-11 09:46:52 +08:00
|
|
|
case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB:
|
2020-06-06 00:03:12 +08:00
|
|
|
writePatchableSLEB<5>(Stream, Value, Offset);
|
|
|
|
break;
|
2020-07-11 07:51:01 +08:00
|
|
|
case wasm::R_WASM_TABLE_INDEX_SLEB64:
|
2020-06-06 00:03:12 +08:00
|
|
|
case wasm::R_WASM_MEMORY_ADDR_SLEB64:
|
|
|
|
case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:
|
|
|
|
writePatchableSLEB<10>(Stream, Value, Offset);
|
2018-01-23 09:23:17 +08:00
|
|
|
break;
|
2017-02-25 07:18:00 +08:00
|
|
|
default:
|
2017-06-17 07:59:10 +08:00
|
|
|
llvm_unreachable("invalid relocation type");
|
2017-02-25 07:18:00 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-28 10:04:54 +08:00
|
|
|
void WasmObjectWriter::writeTypeSection(
|
|
|
|
ArrayRef<wasm::WasmSignature> Signatures) {
|
2018-11-14 10:46:21 +08:00
|
|
|
if (Signatures.empty())
|
2017-06-03 10:01:24 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
SectionBookkeeping Section;
|
|
|
|
startSection(Section, wasm::WASM_SEC_TYPE);
|
|
|
|
|
2020-08-08 12:23:11 +08:00
|
|
|
encodeULEB128(Signatures.size(), W->OS);
|
2017-06-03 10:01:24 +08:00
|
|
|
|
2020-09-28 10:04:54 +08:00
|
|
|
for (const wasm::WasmSignature &Sig : Signatures) {
|
2020-08-08 12:23:11 +08:00
|
|
|
W->OS << char(wasm::WASM_TYPE_FUNC);
|
|
|
|
encodeULEB128(Sig.Params.size(), W->OS);
|
2018-11-14 10:46:21 +08:00
|
|
|
for (wasm::ValType Ty : Sig.Params)
|
2017-06-03 10:01:24 +08:00
|
|
|
writeValueType(Ty);
|
2020-08-08 12:23:11 +08:00
|
|
|
encodeULEB128(Sig.Returns.size(), W->OS);
|
2018-11-14 10:46:21 +08:00
|
|
|
for (wasm::ValType Ty : Sig.Returns)
|
2017-06-03 10:01:24 +08:00
|
|
|
writeValueType(Ty);
|
|
|
|
}
|
|
|
|
|
|
|
|
endSection(Section);
|
|
|
|
}
|
|
|
|
|
2018-02-13 06:41:29 +08:00
|
|
|
void WasmObjectWriter::writeImportSection(ArrayRef<wasm::WasmImport> Imports,
|
2020-06-30 08:53:09 +08:00
|
|
|
uint64_t DataSize,
|
2017-12-12 07:03:38 +08:00
|
|
|
uint32_t NumElements) {
|
2017-06-03 10:01:24 +08:00
|
|
|
if (Imports.empty())
|
|
|
|
return;
|
|
|
|
|
2020-06-30 08:53:09 +08:00
|
|
|
uint64_t NumPages = (DataSize + wasm::WasmPageSize - 1) / wasm::WasmPageSize;
|
2017-12-12 07:03:38 +08:00
|
|
|
|
2017-06-03 10:01:24 +08:00
|
|
|
SectionBookkeeping Section;
|
|
|
|
startSection(Section, wasm::WASM_SEC_IMPORT);
|
|
|
|
|
2020-08-08 12:23:11 +08:00
|
|
|
encodeULEB128(Imports.size(), W->OS);
|
2018-02-13 06:41:29 +08:00
|
|
|
for (const wasm::WasmImport &Import : Imports) {
|
|
|
|
writeString(Import.Module);
|
|
|
|
writeString(Import.Field);
|
2020-08-08 12:23:11 +08:00
|
|
|
W->OS << char(Import.Kind);
|
2017-06-03 10:01:24 +08:00
|
|
|
|
|
|
|
switch (Import.Kind) {
|
|
|
|
case wasm::WASM_EXTERNAL_FUNCTION:
|
2020-08-08 12:23:11 +08:00
|
|
|
encodeULEB128(Import.SigIndex, W->OS);
|
2017-06-03 10:01:24 +08:00
|
|
|
break;
|
|
|
|
case wasm::WASM_EXTERNAL_GLOBAL:
|
2020-08-08 12:23:11 +08:00
|
|
|
W->OS << char(Import.Global.Type);
|
|
|
|
W->OS << char(Import.Global.Mutable ? 1 : 0);
|
2017-06-03 10:01:24 +08:00
|
|
|
break;
|
2017-12-12 07:03:38 +08:00
|
|
|
case wasm::WASM_EXTERNAL_MEMORY:
|
2020-08-08 12:23:11 +08:00
|
|
|
encodeULEB128(Import.Memory.Flags, W->OS);
|
|
|
|
encodeULEB128(NumPages, W->OS); // initial
|
2017-12-12 07:03:38 +08:00
|
|
|
break;
|
|
|
|
case wasm::WASM_EXTERNAL_TABLE:
|
2020-08-08 12:23:11 +08:00
|
|
|
W->OS << char(Import.Table.ElemType);
|
|
|
|
encodeULEB128(0, W->OS); // flags
|
|
|
|
encodeULEB128(NumElements, W->OS); // initial
|
2017-12-12 07:03:38 +08:00
|
|
|
break;
|
2018-11-14 10:46:21 +08:00
|
|
|
case wasm::WASM_EXTERNAL_EVENT:
|
2020-08-08 12:23:11 +08:00
|
|
|
encodeULEB128(Import.Event.Attribute, W->OS);
|
|
|
|
encodeULEB128(Import.Event.SigIndex, W->OS);
|
2018-11-14 10:46:21 +08:00
|
|
|
break;
|
2017-06-03 10:01:24 +08:00
|
|
|
default:
|
|
|
|
llvm_unreachable("unsupported import kind");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
endSection(Section);
|
|
|
|
}
|
|
|
|
|
2017-09-16 03:50:44 +08:00
|
|
|
void WasmObjectWriter::writeFunctionSection(ArrayRef<WasmFunction> Functions) {
|
2017-06-03 10:01:24 +08:00
|
|
|
if (Functions.empty())
|
|
|
|
return;
|
|
|
|
|
|
|
|
SectionBookkeeping Section;
|
|
|
|
startSection(Section, wasm::WASM_SEC_FUNCTION);
|
|
|
|
|
2020-08-08 12:23:11 +08:00
|
|
|
encodeULEB128(Functions.size(), W->OS);
|
2017-06-03 10:01:24 +08:00
|
|
|
for (const WasmFunction &Func : Functions)
|
2020-08-08 12:23:11 +08:00
|
|
|
encodeULEB128(Func.SigIndex, W->OS);
|
2017-06-03 10:01:24 +08:00
|
|
|
|
|
|
|
endSection(Section);
|
|
|
|
}
|
|
|
|
|
2018-11-14 10:46:21 +08:00
|
|
|
void WasmObjectWriter::writeEventSection(ArrayRef<wasm::WasmEventType> Events) {
|
|
|
|
if (Events.empty())
|
|
|
|
return;
|
|
|
|
|
|
|
|
SectionBookkeeping Section;
|
|
|
|
startSection(Section, wasm::WASM_SEC_EVENT);
|
|
|
|
|
2020-08-08 12:23:11 +08:00
|
|
|
encodeULEB128(Events.size(), W->OS);
|
2018-11-14 10:46:21 +08:00
|
|
|
for (const wasm::WasmEventType &Event : Events) {
|
2020-08-08 12:23:11 +08:00
|
|
|
encodeULEB128(Event.Attribute, W->OS);
|
|
|
|
encodeULEB128(Event.SigIndex, W->OS);
|
2018-11-14 10:46:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
endSection(Section);
|
|
|
|
}
|
|
|
|
|
2020-04-30 04:26:27 +08:00
|
|
|
void WasmObjectWriter::writeGlobalSection(ArrayRef<wasm::WasmGlobal> Globals) {
|
|
|
|
if (Globals.empty())
|
|
|
|
return;
|
|
|
|
|
|
|
|
SectionBookkeeping Section;
|
|
|
|
startSection(Section, wasm::WASM_SEC_GLOBAL);
|
|
|
|
|
2020-08-08 12:23:11 +08:00
|
|
|
encodeULEB128(Globals.size(), W->OS);
|
2020-04-30 04:26:27 +08:00
|
|
|
for (const wasm::WasmGlobal &Global : Globals) {
|
2020-08-08 12:23:11 +08:00
|
|
|
encodeULEB128(Global.Type.Type, W->OS);
|
|
|
|
W->OS << char(Global.Type.Mutable);
|
|
|
|
W->OS << char(Global.InitExpr.Opcode);
|
2020-04-30 04:26:27 +08:00
|
|
|
switch (Global.Type.Type) {
|
|
|
|
case wasm::WASM_TYPE_I32:
|
2020-08-08 12:23:11 +08:00
|
|
|
encodeSLEB128(0, W->OS);
|
2020-04-30 04:26:27 +08:00
|
|
|
break;
|
|
|
|
case wasm::WASM_TYPE_I64:
|
2020-08-08 12:23:11 +08:00
|
|
|
encodeSLEB128(0, W->OS);
|
2020-04-30 04:26:27 +08:00
|
|
|
break;
|
|
|
|
case wasm::WASM_TYPE_F32:
|
|
|
|
writeI32(0);
|
|
|
|
break;
|
|
|
|
case wasm::WASM_TYPE_F64:
|
|
|
|
writeI64(0);
|
|
|
|
break;
|
2020-06-17 06:41:20 +08:00
|
|
|
case wasm::WASM_TYPE_EXTERNREF:
|
|
|
|
writeValueType(wasm::ValType::EXTERNREF);
|
|
|
|
break;
|
2020-04-30 04:26:27 +08:00
|
|
|
default:
|
|
|
|
llvm_unreachable("unexpected type");
|
|
|
|
}
|
2020-08-08 12:23:11 +08:00
|
|
|
W->OS << char(wasm::WASM_OPCODE_END);
|
2020-04-30 04:26:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
endSection(Section);
|
|
|
|
}
|
|
|
|
|
2020-10-13 22:13:10 +08:00
|
|
|
void WasmObjectWriter::writeTableSection(ArrayRef<wasm::WasmTable> Tables) {
|
|
|
|
if (Tables.empty())
|
|
|
|
return;
|
|
|
|
|
|
|
|
SectionBookkeeping Section;
|
|
|
|
startSection(Section, wasm::WASM_SEC_TABLE);
|
|
|
|
|
|
|
|
encodeULEB128(Tables.size(), W->OS);
|
|
|
|
for (const wasm::WasmTable &Table : Tables) {
|
2020-11-25 23:54:31 +08:00
|
|
|
encodeULEB128(Table.Type.ElemType, W->OS);
|
|
|
|
encodeULEB128(Table.Type.Limits.Flags, W->OS);
|
|
|
|
encodeULEB128(Table.Type.Limits.Initial, W->OS);
|
|
|
|
if (Table.Type.Limits.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
|
|
|
|
encodeULEB128(Table.Type.Limits.Maximum, W->OS);
|
2020-10-13 22:13:10 +08:00
|
|
|
}
|
|
|
|
endSection(Section);
|
|
|
|
}
|
|
|
|
|
2018-02-13 06:41:29 +08:00
|
|
|
void WasmObjectWriter::writeExportSection(ArrayRef<wasm::WasmExport> Exports) {
|
2017-06-03 10:01:24 +08:00
|
|
|
if (Exports.empty())
|
|
|
|
return;
|
|
|
|
|
|
|
|
SectionBookkeeping Section;
|
|
|
|
startSection(Section, wasm::WASM_SEC_EXPORT);
|
|
|
|
|
2020-08-08 12:23:11 +08:00
|
|
|
encodeULEB128(Exports.size(), W->OS);
|
2018-02-13 06:41:29 +08:00
|
|
|
for (const wasm::WasmExport &Export : Exports) {
|
|
|
|
writeString(Export.Name);
|
2020-08-08 12:23:11 +08:00
|
|
|
W->OS << char(Export.Kind);
|
|
|
|
encodeULEB128(Export.Index, W->OS);
|
2017-06-03 10:01:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
endSection(Section);
|
|
|
|
}
|
|
|
|
|
2021-03-04 17:30:00 +08:00
|
|
|
void WasmObjectWriter::writeElemSection(
|
|
|
|
const MCSymbolWasm *IndirectFunctionTable, ArrayRef<uint32_t> TableElems) {
|
2017-06-03 10:01:24 +08:00
|
|
|
if (TableElems.empty())
|
|
|
|
return;
|
|
|
|
|
2021-03-04 17:30:00 +08:00
|
|
|
assert(IndirectFunctionTable);
|
|
|
|
|
2017-06-03 10:01:24 +08:00
|
|
|
SectionBookkeeping Section;
|
|
|
|
startSection(Section, wasm::WASM_SEC_ELEM);
|
|
|
|
|
2020-08-08 12:23:11 +08:00
|
|
|
encodeULEB128(1, W->OS); // number of "segments"
|
2021-03-04 17:30:00 +08:00
|
|
|
|
|
|
|
assert(WasmIndices.count(IndirectFunctionTable));
|
|
|
|
uint32_t TableNumber = WasmIndices.find(IndirectFunctionTable)->second;
|
|
|
|
uint32_t Flags = 0;
|
|
|
|
if (TableNumber)
|
|
|
|
Flags |= wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER;
|
|
|
|
encodeULEB128(Flags, W->OS);
|
|
|
|
if (Flags & wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER)
|
|
|
|
encodeULEB128(TableNumber, W->OS); // the table number
|
2017-06-03 10:01:24 +08:00
|
|
|
|
|
|
|
// init expr for starting offset
|
2020-08-08 12:23:11 +08:00
|
|
|
W->OS << char(wasm::WASM_OPCODE_I32_CONST);
|
|
|
|
encodeSLEB128(InitialTableOffset, W->OS);
|
|
|
|
W->OS << char(wasm::WASM_OPCODE_END);
|
2017-06-03 10:01:24 +08:00
|
|
|
|
2021-03-04 17:30:00 +08:00
|
|
|
if (Flags & wasm::WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND) {
|
|
|
|
// We only write active function table initializers, for which the elem kind
|
|
|
|
// is specified to be written as 0x00 and interpreted to mean "funcref".
|
|
|
|
const uint8_t ElemKind = 0;
|
|
|
|
W->OS << ElemKind;
|
|
|
|
}
|
|
|
|
|
2020-08-08 12:23:11 +08:00
|
|
|
encodeULEB128(TableElems.size(), W->OS);
|
2017-06-03 10:01:24 +08:00
|
|
|
for (uint32_t Elem : TableElems)
|
2020-08-08 12:23:11 +08:00
|
|
|
encodeULEB128(Elem, W->OS);
|
2017-06-03 10:01:24 +08:00
|
|
|
|
|
|
|
endSection(Section);
|
|
|
|
}
|
|
|
|
|
2019-04-13 06:27:48 +08:00
|
|
|
void WasmObjectWriter::writeDataCountSection() {
|
|
|
|
if (DataSegments.empty())
|
|
|
|
return;
|
|
|
|
|
|
|
|
SectionBookkeeping Section;
|
|
|
|
startSection(Section, wasm::WASM_SEC_DATACOUNT);
|
2020-08-08 12:23:11 +08:00
|
|
|
encodeULEB128(DataSegments.size(), W->OS);
|
2019-04-13 06:27:48 +08:00
|
|
|
endSection(Section);
|
|
|
|
}
|
|
|
|
|
2020-06-24 05:59:18 +08:00
|
|
|
uint32_t WasmObjectWriter::writeCodeSection(const MCAssembler &Asm,
|
|
|
|
const MCAsmLayout &Layout,
|
|
|
|
ArrayRef<WasmFunction> Functions) {
|
2017-06-03 10:01:24 +08:00
|
|
|
if (Functions.empty())
|
2020-06-24 05:59:18 +08:00
|
|
|
return 0;
|
2017-06-03 10:01:24 +08:00
|
|
|
|
|
|
|
SectionBookkeeping Section;
|
|
|
|
startSection(Section, wasm::WASM_SEC_CODE);
|
|
|
|
|
2020-08-08 12:23:11 +08:00
|
|
|
encodeULEB128(Functions.size(), W->OS);
|
2017-06-03 10:01:24 +08:00
|
|
|
|
|
|
|
for (const WasmFunction &Func : Functions) {
|
2017-06-22 07:46:41 +08:00
|
|
|
auto &FuncSection = static_cast<MCSectionWasm &>(Func.Sym->getSection());
|
2017-06-03 10:01:24 +08:00
|
|
|
|
|
|
|
int64_t Size = 0;
|
|
|
|
if (!Func.Sym->getSize()->evaluateAsAbsolute(Size, Layout))
|
|
|
|
report_fatal_error(".size expression must be evaluatable");
|
|
|
|
|
2020-08-08 12:23:11 +08:00
|
|
|
encodeULEB128(Size, W->OS);
|
|
|
|
FuncSection.setSectionOffset(W->OS.tell() - Section.ContentsOffset);
|
|
|
|
Asm.writeSectionData(W->OS, &FuncSection, Layout);
|
2017-06-03 10:01:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Apply fixups.
|
2020-04-30 06:38:11 +08:00
|
|
|
applyRelocations(CodeRelocations, Section.ContentsOffset, Layout);
|
2017-06-03 10:01:24 +08:00
|
|
|
|
|
|
|
endSection(Section);
|
2020-06-24 05:59:18 +08:00
|
|
|
return Section.Index;
|
2017-06-03 10:01:24 +08:00
|
|
|
}
|
|
|
|
|
2020-06-24 05:59:18 +08:00
|
|
|
uint32_t WasmObjectWriter::writeDataSection(const MCAsmLayout &Layout) {
|
2018-02-23 13:08:34 +08:00
|
|
|
if (DataSegments.empty())
|
2020-06-24 05:59:18 +08:00
|
|
|
return 0;
|
2017-06-03 10:01:24 +08:00
|
|
|
|
|
|
|
SectionBookkeeping Section;
|
|
|
|
startSection(Section, wasm::WASM_SEC_DATA);
|
|
|
|
|
2020-08-08 12:23:11 +08:00
|
|
|
encodeULEB128(DataSegments.size(), W->OS); // count
|
2017-09-15 07:07:53 +08:00
|
|
|
|
2018-02-23 13:08:34 +08:00
|
|
|
for (const WasmDataSegment &Segment : DataSegments) {
|
2020-08-08 12:23:11 +08:00
|
|
|
encodeULEB128(Segment.InitFlags, W->OS); // flags
|
2020-11-30 21:55:29 +08:00
|
|
|
if (Segment.InitFlags & wasm::WASM_DATA_SEGMENT_HAS_MEMINDEX)
|
2020-08-08 12:23:11 +08:00
|
|
|
encodeULEB128(0, W->OS); // memory index
|
2020-11-30 21:55:29 +08:00
|
|
|
if ((Segment.InitFlags & wasm::WASM_DATA_SEGMENT_IS_PASSIVE) == 0) {
|
2021-01-29 08:38:24 +08:00
|
|
|
W->OS << char(is64Bit() ? wasm::WASM_OPCODE_I64_CONST
|
|
|
|
: wasm::WASM_OPCODE_I32_CONST);
|
2020-08-08 12:23:11 +08:00
|
|
|
encodeSLEB128(Segment.Offset, W->OS); // offset
|
|
|
|
W->OS << char(wasm::WASM_OPCODE_END);
|
2019-02-20 06:56:19 +08:00
|
|
|
}
|
2020-08-08 12:23:11 +08:00
|
|
|
encodeULEB128(Segment.Data.size(), W->OS); // size
|
|
|
|
Segment.Section->setSectionOffset(W->OS.tell() - Section.ContentsOffset);
|
|
|
|
W->OS << Segment.Data; // data
|
2017-09-15 07:07:53 +08:00
|
|
|
}
|
2017-06-03 10:01:24 +08:00
|
|
|
|
|
|
|
// Apply fixups.
|
2020-04-30 06:38:11 +08:00
|
|
|
applyRelocations(DataRelocations, Section.ContentsOffset, Layout);
|
2017-06-03 10:01:24 +08:00
|
|
|
|
|
|
|
endSection(Section);
|
2020-06-24 05:59:18 +08:00
|
|
|
return Section.Index;
|
2017-06-03 10:01:24 +08:00
|
|
|
}
|
|
|
|
|
2018-04-25 02:11:36 +08:00
|
|
|
void WasmObjectWriter::writeRelocSection(
|
|
|
|
uint32_t SectionIndex, StringRef Name,
|
2018-09-05 09:27:38 +08:00
|
|
|
std::vector<WasmRelocationEntry> &Relocs) {
|
2017-06-03 10:01:24 +08:00
|
|
|
// See: https://github.com/WebAssembly/tool-conventions/blob/master/Linking.md
|
|
|
|
// for descriptions of the reloc sections.
|
|
|
|
|
2018-08-23 01:27:31 +08:00
|
|
|
if (Relocs.empty())
|
2017-06-03 10:01:24 +08:00
|
|
|
return;
|
|
|
|
|
2018-08-23 01:27:31 +08:00
|
|
|
// First, ensure the relocations are sorted in offset order. In general they
|
|
|
|
// should already be sorted since `recordRelocation` is called in offset
|
|
|
|
// order, but for the code section we combine many MC sections into single
|
|
|
|
// wasm section, and this order is determined by the order of Asm.Symbols()
|
|
|
|
// not the sections order.
|
2019-04-23 22:51:27 +08:00
|
|
|
llvm::stable_sort(
|
|
|
|
Relocs, [](const WasmRelocationEntry &A, const WasmRelocationEntry &B) {
|
2018-08-23 01:27:31 +08:00
|
|
|
return (A.Offset + A.FixupSection->getSectionOffset()) <
|
|
|
|
(B.Offset + B.FixupSection->getSectionOffset());
|
|
|
|
});
|
|
|
|
|
2017-06-03 10:01:24 +08:00
|
|
|
SectionBookkeeping Section;
|
2018-04-25 02:11:36 +08:00
|
|
|
startCustomSection(Section, std::string("reloc.") + Name.str());
|
2017-06-03 10:01:24 +08:00
|
|
|
|
2020-08-08 12:23:11 +08:00
|
|
|
encodeULEB128(SectionIndex, W->OS);
|
|
|
|
encodeULEB128(Relocs.size(), W->OS);
|
2018-09-05 09:27:38 +08:00
|
|
|
for (const WasmRelocationEntry &RelEntry : Relocs) {
|
|
|
|
uint64_t Offset =
|
|
|
|
RelEntry.Offset + RelEntry.FixupSection->getSectionOffset();
|
2018-04-25 02:11:36 +08:00
|
|
|
uint32_t Index = getRelocationIndexValue(RelEntry);
|
2017-06-03 10:01:24 +08:00
|
|
|
|
2020-08-08 12:23:11 +08:00
|
|
|
W->OS << char(RelEntry.Type);
|
|
|
|
encodeULEB128(Offset, W->OS);
|
|
|
|
encodeULEB128(Index, W->OS);
|
2018-04-25 02:11:36 +08:00
|
|
|
if (RelEntry.hasAddend())
|
2020-08-08 12:23:11 +08:00
|
|
|
encodeSLEB128(RelEntry.Addend, W->OS);
|
2018-04-25 02:11:36 +08:00
|
|
|
}
|
2017-06-03 10:01:24 +08:00
|
|
|
|
|
|
|
endSection(Section);
|
|
|
|
}
|
|
|
|
|
2018-04-27 03:27:28 +08:00
|
|
|
void WasmObjectWriter::writeCustomRelocSections() {
|
|
|
|
for (const auto &Sec : CustomSections) {
|
|
|
|
auto &Relocations = CustomSectionsRelocations[Sec.Section];
|
|
|
|
writeRelocSection(Sec.OutputIndex, Sec.Name, Relocations);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-03 10:01:24 +08:00
|
|
|
void WasmObjectWriter::writeLinkingMetaDataSection(
|
2018-02-28 07:57:37 +08:00
|
|
|
ArrayRef<wasm::WasmSymbolInfo> SymbolInfos,
|
2018-01-10 07:43:14 +08:00
|
|
|
ArrayRef<std::pair<uint16_t, uint32_t>> InitFuncs,
|
2018-02-23 13:08:34 +08:00
|
|
|
const std::map<StringRef, std::vector<WasmComdatEntry>> &Comdats) {
|
2017-06-03 10:01:24 +08:00
|
|
|
SectionBookkeeping Section;
|
2018-04-24 03:16:19 +08:00
|
|
|
startCustomSection(Section, "linking");
|
2020-08-08 12:23:11 +08:00
|
|
|
encodeULEB128(wasm::WasmMetadataVersion, W->OS);
|
2017-06-03 10:01:24 +08:00
|
|
|
|
2018-04-27 02:15:32 +08:00
|
|
|
SectionBookkeeping SubSection;
|
2018-02-23 13:08:34 +08:00
|
|
|
if (SymbolInfos.size() != 0) {
|
|
|
|
startSection(SubSection, wasm::WASM_SYMBOL_TABLE);
|
2020-08-08 12:23:11 +08:00
|
|
|
encodeULEB128(SymbolInfos.size(), W->OS);
|
2018-02-23 13:08:34 +08:00
|
|
|
for (const wasm::WasmSymbolInfo &Sym : SymbolInfos) {
|
2020-08-08 12:23:11 +08:00
|
|
|
encodeULEB128(Sym.Kind, W->OS);
|
|
|
|
encodeULEB128(Sym.Flags, W->OS);
|
2018-02-23 13:08:34 +08:00
|
|
|
switch (Sym.Kind) {
|
|
|
|
case wasm::WASM_SYMBOL_TYPE_FUNCTION:
|
|
|
|
case wasm::WASM_SYMBOL_TYPE_GLOBAL:
|
2018-11-14 10:46:21 +08:00
|
|
|
case wasm::WASM_SYMBOL_TYPE_EVENT:
|
2020-10-13 22:13:10 +08:00
|
|
|
case wasm::WASM_SYMBOL_TYPE_TABLE:
|
2020-08-08 12:23:11 +08:00
|
|
|
encodeULEB128(Sym.ElementIndex, W->OS);
|
2019-02-08 06:03:32 +08:00
|
|
|
if ((Sym.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0 ||
|
|
|
|
(Sym.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
|
2018-02-23 13:08:34 +08:00
|
|
|
writeString(Sym.Name);
|
|
|
|
break;
|
|
|
|
case wasm::WASM_SYMBOL_TYPE_DATA:
|
|
|
|
writeString(Sym.Name);
|
|
|
|
if ((Sym.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0) {
|
2020-08-08 12:23:11 +08:00
|
|
|
encodeULEB128(Sym.DataRef.Segment, W->OS);
|
|
|
|
encodeULEB128(Sym.DataRef.Offset, W->OS);
|
|
|
|
encodeULEB128(Sym.DataRef.Size, W->OS);
|
2018-02-23 13:08:34 +08:00
|
|
|
}
|
|
|
|
break;
|
2018-04-27 03:27:28 +08:00
|
|
|
case wasm::WASM_SYMBOL_TYPE_SECTION: {
|
|
|
|
const uint32_t SectionIndex =
|
|
|
|
CustomSections[Sym.ElementIndex].OutputIndex;
|
2020-08-08 12:23:11 +08:00
|
|
|
encodeULEB128(SectionIndex, W->OS);
|
2018-04-27 03:27:28 +08:00
|
|
|
break;
|
|
|
|
}
|
2018-02-23 13:08:34 +08:00
|
|
|
default:
|
|
|
|
llvm_unreachable("unexpected kind");
|
|
|
|
}
|
2017-06-20 12:04:59 +08:00
|
|
|
}
|
|
|
|
endSection(SubSection);
|
|
|
|
}
|
2017-06-03 10:01:24 +08:00
|
|
|
|
2018-02-23 13:08:34 +08:00
|
|
|
if (DataSegments.size()) {
|
2017-09-30 00:50:08 +08:00
|
|
|
startSection(SubSection, wasm::WASM_SEGMENT_INFO);
|
2020-08-08 12:23:11 +08:00
|
|
|
encodeULEB128(DataSegments.size(), W->OS);
|
2018-02-23 13:08:34 +08:00
|
|
|
for (const WasmDataSegment &Segment : DataSegments) {
|
2017-09-21 03:03:35 +08:00
|
|
|
writeString(Segment.Name);
|
2020-08-08 12:23:11 +08:00
|
|
|
encodeULEB128(Segment.Alignment, W->OS);
|
|
|
|
encodeULEB128(Segment.LinkerFlags, W->OS);
|
2017-09-30 00:50:08 +08:00
|
|
|
}
|
2017-09-21 03:03:35 +08:00
|
|
|
endSection(SubSection);
|
|
|
|
}
|
|
|
|
|
2017-12-15 08:17:10 +08:00
|
|
|
if (!InitFuncs.empty()) {
|
|
|
|
startSection(SubSection, wasm::WASM_INIT_FUNCS);
|
2020-08-08 12:23:11 +08:00
|
|
|
encodeULEB128(InitFuncs.size(), W->OS);
|
2017-12-15 08:17:10 +08:00
|
|
|
for (auto &StartFunc : InitFuncs) {
|
2020-08-08 12:23:11 +08:00
|
|
|
encodeULEB128(StartFunc.first, W->OS); // priority
|
|
|
|
encodeULEB128(StartFunc.second, W->OS); // function index
|
2017-12-15 08:17:10 +08:00
|
|
|
}
|
|
|
|
endSection(SubSection);
|
|
|
|
}
|
|
|
|
|
2018-01-10 07:43:14 +08:00
|
|
|
if (Comdats.size()) {
|
|
|
|
startSection(SubSection, wasm::WASM_COMDAT_INFO);
|
2020-08-08 12:23:11 +08:00
|
|
|
encodeULEB128(Comdats.size(), W->OS);
|
2018-01-10 07:43:14 +08:00
|
|
|
for (const auto &C : Comdats) {
|
|
|
|
writeString(C.first);
|
2020-08-08 12:23:11 +08:00
|
|
|
encodeULEB128(0, W->OS); // flags for future use
|
|
|
|
encodeULEB128(C.second.size(), W->OS);
|
2018-01-10 07:43:14 +08:00
|
|
|
for (const WasmComdatEntry &Entry : C.second) {
|
2020-08-08 12:23:11 +08:00
|
|
|
encodeULEB128(Entry.Kind, W->OS);
|
|
|
|
encodeULEB128(Entry.Index, W->OS);
|
2018-01-10 07:43:14 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
endSection(SubSection);
|
|
|
|
}
|
|
|
|
|
2017-06-03 10:01:24 +08:00
|
|
|
endSection(Section);
|
|
|
|
}
|
|
|
|
|
2019-01-17 10:29:55 +08:00
|
|
|
void WasmObjectWriter::writeCustomSection(WasmCustomSection &CustomSection,
|
|
|
|
const MCAssembler &Asm,
|
|
|
|
const MCAsmLayout &Layout) {
|
|
|
|
SectionBookkeeping Section;
|
|
|
|
auto *Sec = CustomSection.Section;
|
|
|
|
startCustomSection(Section, CustomSection.Name);
|
2018-04-27 03:27:28 +08:00
|
|
|
|
2020-08-08 12:23:11 +08:00
|
|
|
Sec->setSectionOffset(W->OS.tell() - Section.ContentsOffset);
|
|
|
|
Asm.writeSectionData(W->OS, Sec, Layout);
|
2018-04-27 03:27:28 +08:00
|
|
|
|
2019-01-17 10:29:55 +08:00
|
|
|
CustomSection.OutputContentsOffset = Section.ContentsOffset;
|
|
|
|
CustomSection.OutputIndex = Section.Index;
|
2018-04-27 03:27:28 +08:00
|
|
|
|
2019-01-17 10:29:55 +08:00
|
|
|
endSection(Section);
|
2018-04-27 03:27:28 +08:00
|
|
|
|
2019-01-17 10:29:55 +08:00
|
|
|
// Apply fixups.
|
|
|
|
auto &Relocations = CustomSectionsRelocations[CustomSection.Section];
|
2020-04-30 06:38:11 +08:00
|
|
|
applyRelocations(Relocations, CustomSection.OutputContentsOffset, Layout);
|
2018-04-27 03:27:28 +08:00
|
|
|
}
|
|
|
|
|
2018-09-05 09:27:38 +08:00
|
|
|
uint32_t WasmObjectWriter::getFunctionType(const MCSymbolWasm &Symbol) {
|
2017-07-07 10:01:29 +08:00
|
|
|
assert(Symbol.isFunction());
|
|
|
|
assert(TypeIndices.count(&Symbol));
|
|
|
|
return TypeIndices[&Symbol];
|
|
|
|
}
|
|
|
|
|
2018-11-14 10:46:21 +08:00
|
|
|
uint32_t WasmObjectWriter::getEventType(const MCSymbolWasm &Symbol) {
|
|
|
|
assert(Symbol.isEvent());
|
|
|
|
assert(TypeIndices.count(&Symbol));
|
|
|
|
return TypeIndices[&Symbol];
|
|
|
|
}
|
|
|
|
|
2018-11-20 08:38:10 +08:00
|
|
|
void WasmObjectWriter::registerFunctionType(const MCSymbolWasm &Symbol) {
|
2017-07-07 10:01:29 +08:00
|
|
|
assert(Symbol.isFunction());
|
|
|
|
|
2020-09-28 10:04:54 +08:00
|
|
|
wasm::WasmSignature S;
|
2020-04-30 06:38:11 +08:00
|
|
|
|
|
|
|
if (auto *Sig = Symbol.getSignature()) {
|
2018-11-14 10:46:21 +08:00
|
|
|
S.Returns = Sig->Returns;
|
|
|
|
S.Params = Sig->Params;
|
2018-10-04 06:22:48 +08:00
|
|
|
}
|
2017-07-07 10:01:29 +08:00
|
|
|
|
2018-11-14 10:46:21 +08:00
|
|
|
auto Pair = SignatureIndices.insert(std::make_pair(S, Signatures.size()));
|
2017-07-07 10:01:29 +08:00
|
|
|
if (Pair.second)
|
2018-11-14 10:46:21 +08:00
|
|
|
Signatures.push_back(S);
|
2017-07-07 10:01:29 +08:00
|
|
|
TypeIndices[&Symbol] = Pair.first->second;
|
|
|
|
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "registerFunctionType: " << Symbol
|
|
|
|
<< " new:" << Pair.second << "\n");
|
|
|
|
LLVM_DEBUG(dbgs() << " -> type index: " << Pair.first->second << "\n");
|
2017-07-07 10:01:29 +08:00
|
|
|
}
|
|
|
|
|
2018-11-20 08:38:10 +08:00
|
|
|
void WasmObjectWriter::registerEventType(const MCSymbolWasm &Symbol) {
|
2018-11-14 10:46:21 +08:00
|
|
|
assert(Symbol.isEvent());
|
|
|
|
|
|
|
|
// TODO Currently we don't generate imported exceptions, but if we do, we
|
|
|
|
// should have a way of infering types of imported exceptions.
|
2020-09-28 10:04:54 +08:00
|
|
|
wasm::WasmSignature S;
|
2018-11-14 10:46:21 +08:00
|
|
|
if (auto *Sig = Symbol.getSignature()) {
|
|
|
|
S.Returns = Sig->Returns;
|
|
|
|
S.Params = Sig->Params;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto Pair = SignatureIndices.insert(std::make_pair(S, Signatures.size()));
|
|
|
|
if (Pair.second)
|
|
|
|
Signatures.push_back(S);
|
|
|
|
TypeIndices[&Symbol] = Pair.first->second;
|
|
|
|
|
|
|
|
LLVM_DEBUG(dbgs() << "registerEventType: " << Symbol << " new:" << Pair.second
|
|
|
|
<< "\n");
|
|
|
|
LLVM_DEBUG(dbgs() << " -> type index: " << Pair.first->second << "\n");
|
|
|
|
}
|
|
|
|
|
2018-05-03 07:11:38 +08:00
|
|
|
static bool isInSymtab(const MCSymbolWasm &Sym) {
|
2020-03-31 08:37:01 +08:00
|
|
|
if (Sym.isUsedInReloc() || Sym.isUsedInInitArray())
|
2018-05-03 07:11:38 +08:00
|
|
|
return true;
|
|
|
|
|
|
|
|
if (Sym.isComdat() && !Sym.isDefined())
|
|
|
|
return false;
|
|
|
|
|
2020-03-31 08:37:01 +08:00
|
|
|
if (Sym.isTemporary())
|
2018-05-03 07:11:38 +08:00
|
|
|
return false;
|
|
|
|
|
|
|
|
if (Sym.isSection())
|
|
|
|
return false;
|
|
|
|
|
2021-02-12 18:22:13 +08:00
|
|
|
if (Sym.omitFromLinkingSection())
|
|
|
|
return false;
|
|
|
|
|
2018-05-03 07:11:38 +08:00
|
|
|
return true;
|
|
|
|
}
|
2020-12-22 02:24:32 +08:00
|
|
|
|
2020-08-08 12:23:11 +08:00
|
|
|
void WasmObjectWriter::prepareImports(
|
|
|
|
SmallVectorImpl<wasm::WasmImport> &Imports, MCAssembler &Asm,
|
|
|
|
const MCAsmLayout &Layout) {
|
2017-12-12 07:03:38 +08:00
|
|
|
// For now, always emit the memory import, since loads and stores are not
|
|
|
|
// valid without it. In the future, we could perhaps be more clever and omit
|
|
|
|
// it if there are no loads or stores.
|
2018-02-13 06:41:29 +08:00
|
|
|
wasm::WasmImport MemImport;
|
2019-02-22 01:05:19 +08:00
|
|
|
MemImport.Module = "env";
|
|
|
|
MemImport.Field = "__linear_memory";
|
2017-12-12 07:03:38 +08:00
|
|
|
MemImport.Kind = wasm::WASM_EXTERNAL_MEMORY;
|
2020-07-08 08:47:43 +08:00
|
|
|
MemImport.Memory.Flags = is64Bit() ? wasm::WASM_LIMITS_FLAG_IS_64
|
|
|
|
: wasm::WASM_LIMITS_FLAG_NONE;
|
2017-12-12 07:03:38 +08:00
|
|
|
Imports.push_back(MemImport);
|
|
|
|
|
2018-11-14 10:46:21 +08:00
|
|
|
// Populate SignatureIndices, and Imports and WasmIndices for undefined
|
2018-03-01 01:19:48 +08:00
|
|
|
// symbols. This must be done before populating WasmIndices for defined
|
|
|
|
// symbols.
|
2017-12-06 02:29:48 +08:00
|
|
|
for (const MCSymbol &S : Asm.symbols()) {
|
|
|
|
const auto &WS = static_cast<const MCSymbolWasm &>(S);
|
|
|
|
|
|
|
|
// Register types for all functions, including those with private linkage
|
2018-01-18 03:28:43 +08:00
|
|
|
// (because wasm always needs a type signature).
|
2020-04-30 06:38:11 +08:00
|
|
|
if (WS.isFunction()) {
|
2020-09-09 09:17:05 +08:00
|
|
|
const auto *BS = Layout.getBaseSymbol(S);
|
|
|
|
if (!BS)
|
|
|
|
report_fatal_error(Twine(S.getName()) +
|
|
|
|
": absolute addressing not supported!");
|
|
|
|
registerFunctionType(*cast<MCSymbolWasm>(BS));
|
2020-04-30 06:38:11 +08:00
|
|
|
}
|
2017-12-06 02:29:48 +08:00
|
|
|
|
2018-11-14 10:46:21 +08:00
|
|
|
if (WS.isEvent())
|
|
|
|
registerEventType(WS);
|
|
|
|
|
2017-12-06 02:29:48 +08:00
|
|
|
if (WS.isTemporary())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// If the symbol is not defined in this translation unit, import it.
|
2018-02-23 13:08:34 +08:00
|
|
|
if (!WS.isDefined() && !WS.isComdat()) {
|
2017-12-06 02:29:48 +08:00
|
|
|
if (WS.isFunction()) {
|
2018-02-23 13:08:34 +08:00
|
|
|
wasm::WasmImport Import;
|
2019-02-02 06:27:34 +08:00
|
|
|
Import.Module = WS.getImportModule();
|
|
|
|
Import.Field = WS.getImportName();
|
2017-12-06 02:29:48 +08:00
|
|
|
Import.Kind = wasm::WASM_EXTERNAL_FUNCTION;
|
2018-02-13 06:41:29 +08:00
|
|
|
Import.SigIndex = getFunctionType(WS);
|
2018-02-23 13:08:34 +08:00
|
|
|
Imports.push_back(Import);
|
2019-03-27 03:46:15 +08:00
|
|
|
assert(WasmIndices.count(&WS) == 0);
|
2018-02-23 13:08:34 +08:00
|
|
|
WasmIndices[&WS] = NumFunctionImports++;
|
|
|
|
} else if (WS.isGlobal()) {
|
2018-03-10 00:30:44 +08:00
|
|
|
if (WS.isWeak())
|
|
|
|
report_fatal_error("undefined global symbol cannot be weak");
|
|
|
|
|
2018-02-23 13:08:34 +08:00
|
|
|
wasm::WasmImport Import;
|
2019-02-02 06:27:34 +08:00
|
|
|
Import.Field = WS.getImportName();
|
2017-12-06 02:29:48 +08:00
|
|
|
Import.Kind = wasm::WASM_EXTERNAL_GLOBAL;
|
2019-03-27 03:46:15 +08:00
|
|
|
Import.Module = WS.getImportModule();
|
2018-02-23 13:08:34 +08:00
|
|
|
Import.Global = WS.getGlobalType();
|
|
|
|
Imports.push_back(Import);
|
2019-03-27 03:46:15 +08:00
|
|
|
assert(WasmIndices.count(&WS) == 0);
|
2018-02-23 13:08:34 +08:00
|
|
|
WasmIndices[&WS] = NumGlobalImports++;
|
2018-11-14 10:46:21 +08:00
|
|
|
} else if (WS.isEvent()) {
|
|
|
|
if (WS.isWeak())
|
|
|
|
report_fatal_error("undefined event symbol cannot be weak");
|
|
|
|
|
|
|
|
wasm::WasmImport Import;
|
2019-02-02 06:27:34 +08:00
|
|
|
Import.Module = WS.getImportModule();
|
|
|
|
Import.Field = WS.getImportName();
|
2018-11-14 10:46:21 +08:00
|
|
|
Import.Kind = wasm::WASM_EXTERNAL_EVENT;
|
|
|
|
Import.Event.Attribute = wasm::WASM_EVENT_ATTRIBUTE_EXCEPTION;
|
|
|
|
Import.Event.SigIndex = getEventType(WS);
|
|
|
|
Imports.push_back(Import);
|
2019-03-27 03:46:15 +08:00
|
|
|
assert(WasmIndices.count(&WS) == 0);
|
2018-11-14 10:46:21 +08:00
|
|
|
WasmIndices[&WS] = NumEventImports++;
|
2020-11-26 00:31:05 +08:00
|
|
|
} else if (WS.isTable()) {
|
|
|
|
if (WS.isWeak())
|
|
|
|
report_fatal_error("undefined table symbol cannot be weak");
|
|
|
|
|
|
|
|
wasm::WasmImport Import;
|
|
|
|
Import.Module = WS.getImportModule();
|
|
|
|
Import.Field = WS.getImportName();
|
|
|
|
Import.Kind = wasm::WASM_EXTERNAL_TABLE;
|
|
|
|
wasm::ValType ElemType = WS.getTableType();
|
|
|
|
Import.Table.ElemType = uint8_t(ElemType);
|
|
|
|
// FIXME: Extend table type to include limits? For now we don't specify
|
|
|
|
// a min or max which does not place any restrictions on the size of the
|
|
|
|
// imported table.
|
|
|
|
Import.Table.Limits = {wasm::WASM_LIMITS_FLAG_NONE, 0, 0};
|
|
|
|
Imports.push_back(Import);
|
|
|
|
assert(WasmIndices.count(&WS) == 0);
|
|
|
|
WasmIndices[&WS] = NumTableImports++;
|
2017-12-06 02:29:48 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-27 03:46:15 +08:00
|
|
|
// Add imports for GOT globals
|
|
|
|
for (const MCSymbol &S : Asm.symbols()) {
|
|
|
|
const auto &WS = static_cast<const MCSymbolWasm &>(S);
|
|
|
|
if (WS.isUsedInGOT()) {
|
|
|
|
wasm::WasmImport Import;
|
|
|
|
if (WS.isFunction())
|
|
|
|
Import.Module = "GOT.func";
|
|
|
|
else
|
|
|
|
Import.Module = "GOT.mem";
|
|
|
|
Import.Field = WS.getName();
|
|
|
|
Import.Kind = wasm::WASM_EXTERNAL_GLOBAL;
|
|
|
|
Import.Global = {wasm::WASM_TYPE_I32, true};
|
|
|
|
Imports.push_back(Import);
|
|
|
|
assert(GOTIndices.count(&WS) == 0);
|
|
|
|
GOTIndices[&WS] = NumGlobalImports++;
|
|
|
|
}
|
|
|
|
}
|
2020-08-08 12:23:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
|
|
|
|
const MCAsmLayout &Layout) {
|
|
|
|
support::endian::Writer MainWriter(*OS, support::little);
|
|
|
|
W = &MainWriter;
|
|
|
|
if (IsSplitDwarf) {
|
|
|
|
uint64_t TotalSize = writeOneObject(Asm, Layout, DwoMode::NonDwoOnly);
|
|
|
|
assert(DwoOS);
|
|
|
|
support::endian::Writer DwoWriter(*DwoOS, support::little);
|
|
|
|
W = &DwoWriter;
|
|
|
|
return TotalSize + writeOneObject(Asm, Layout, DwoMode::DwoOnly);
|
|
|
|
} else {
|
|
|
|
return writeOneObject(Asm, Layout, DwoMode::AllSections);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm,
|
|
|
|
const MCAsmLayout &Layout,
|
|
|
|
DwoMode Mode) {
|
|
|
|
uint64_t StartOffset = W->OS.tell();
|
|
|
|
SectionCount = 0;
|
|
|
|
CustomSections.clear();
|
2019-03-27 03:46:15 +08:00
|
|
|
|
2020-08-08 12:23:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "WasmObjectWriter::writeObject\n");
|
|
|
|
|
|
|
|
// Collect information from the available symbols.
|
|
|
|
SmallVector<WasmFunction, 4> Functions;
|
|
|
|
SmallVector<uint32_t, 4> TableElems;
|
|
|
|
SmallVector<wasm::WasmImport, 4> Imports;
|
|
|
|
SmallVector<wasm::WasmExport, 4> Exports;
|
|
|
|
SmallVector<wasm::WasmEventType, 1> Events;
|
|
|
|
SmallVector<wasm::WasmGlobal, 1> Globals;
|
2020-10-13 22:13:10 +08:00
|
|
|
SmallVector<wasm::WasmTable, 1> Tables;
|
2020-08-08 12:23:11 +08:00
|
|
|
SmallVector<wasm::WasmSymbolInfo, 4> SymbolInfos;
|
|
|
|
SmallVector<std::pair<uint16_t, uint32_t>, 2> InitFuncs;
|
|
|
|
std::map<StringRef, std::vector<WasmComdatEntry>> Comdats;
|
|
|
|
uint64_t DataSize = 0;
|
|
|
|
if (Mode != DwoMode::DwoOnly) {
|
|
|
|
prepareImports(Imports, Asm, Layout);
|
|
|
|
}
|
2020-12-22 02:24:32 +08:00
|
|
|
|
2018-05-03 07:11:38 +08:00
|
|
|
// Populate DataSegments and CustomSections, which must be done before
|
|
|
|
// populating DataLocations.
|
2017-09-16 04:54:59 +08:00
|
|
|
for (MCSection &Sec : Asm) {
|
|
|
|
auto &Section = static_cast<MCSectionWasm &>(Sec);
|
2020-04-16 06:49:05 +08:00
|
|
|
StringRef SectionName = Section.getName();
|
2017-09-16 04:54:59 +08:00
|
|
|
|
2020-08-08 12:23:11 +08:00
|
|
|
if (Mode == DwoMode::NonDwoOnly && isDwoSection(Sec))
|
|
|
|
continue;
|
|
|
|
if (Mode == DwoMode::DwoOnly && !isDwoSection(Sec))
|
|
|
|
continue;
|
|
|
|
|
2020-12-11 08:40:08 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Processing Section " << SectionName << " group "
|
|
|
|
<< Section.getGroup() << "\n";);
|
|
|
|
|
2017-12-15 08:17:10 +08:00
|
|
|
// .init_array sections are handled specially elsewhere.
|
2018-05-03 07:11:38 +08:00
|
|
|
if (SectionName.startswith(".init_array"))
|
2017-12-15 08:17:10 +08:00
|
|
|
continue;
|
|
|
|
|
2018-05-03 07:11:38 +08:00
|
|
|
// Code is handled separately
|
|
|
|
if (Section.getKind().isText())
|
2018-04-27 03:27:28 +08:00
|
|
|
continue;
|
|
|
|
|
2018-05-03 07:11:38 +08:00
|
|
|
if (Section.isWasmData()) {
|
|
|
|
uint32_t SegmentIndex = DataSegments.size();
|
|
|
|
DataSize = alignTo(DataSize, Section.getAlignment());
|
|
|
|
DataSegments.emplace_back();
|
|
|
|
WasmDataSegment &Segment = DataSegments.back();
|
|
|
|
Segment.Name = SectionName;
|
2020-11-30 21:55:29 +08:00
|
|
|
Segment.InitFlags = Section.getPassive()
|
|
|
|
? (uint32_t)wasm::WASM_DATA_SEGMENT_IS_PASSIVE
|
|
|
|
: 0;
|
2018-05-03 07:11:38 +08:00
|
|
|
Segment.Offset = DataSize;
|
|
|
|
Segment.Section = &Section;
|
|
|
|
addData(Segment.Data, Section);
|
2019-01-16 09:34:48 +08:00
|
|
|
Segment.Alignment = Log2_32(Section.getAlignment());
|
2019-02-20 06:56:19 +08:00
|
|
|
Segment.LinkerFlags = 0;
|
2018-05-03 07:11:38 +08:00
|
|
|
DataSize += Segment.Data.size();
|
|
|
|
Section.setSegmentIndex(SegmentIndex);
|
|
|
|
|
|
|
|
if (const MCSymbolWasm *C = Section.getGroup()) {
|
|
|
|
Comdats[C->getName()].emplace_back(
|
|
|
|
WasmComdatEntry{wasm::WASM_COMDAT_DATA, SegmentIndex});
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Create custom sections
|
|
|
|
assert(Sec.getKind().isMetadata());
|
2018-04-27 03:27:28 +08:00
|
|
|
|
2018-05-03 07:11:38 +08:00
|
|
|
StringRef Name = SectionName;
|
2018-04-27 03:27:28 +08:00
|
|
|
|
2018-05-03 07:11:38 +08:00
|
|
|
// For user-defined custom sections, strip the prefix
|
|
|
|
if (Name.startswith(".custom_section."))
|
|
|
|
Name = Name.substr(strlen(".custom_section."));
|
|
|
|
|
2018-09-05 09:27:38 +08:00
|
|
|
MCSymbol *Begin = Sec.getBeginSymbol();
|
2018-05-08 03:40:50 +08:00
|
|
|
if (Begin) {
|
2020-12-22 02:24:32 +08:00
|
|
|
assert(WasmIndices.count(cast<MCSymbolWasm>(Begin)) == 0);
|
2018-05-03 07:11:38 +08:00
|
|
|
WasmIndices[cast<MCSymbolWasm>(Begin)] = CustomSections.size();
|
2018-05-08 03:40:50 +08:00
|
|
|
}
|
2019-01-17 10:29:55 +08:00
|
|
|
|
[WebAssembly] Target features section
Summary:
Implements a new target features section in assembly and object files
that records what features are used, required, and disallowed in
WebAssembly objects. The linker uses this information to ensure that
all objects participating in a link are feature-compatible and records
the set of used features in the output binary for use by optimizers
and other tools later in the toolchain.
The "atomics" feature is always required or disallowed to prevent
linking code with stripped atomics into multithreaded binaries. Other
features are marked used if they are enabled globally or on any
function in a module.
Future CLs will add linker flags for ignoring feature compatibility
checks and for specifying the set of allowed features, implement using
the presence of the "atomics" feature to control the type of memory
and segments in the linked binary, and add front-end flags for
relaxing the linkage policy for atomics.
Reviewers: aheejin, sbc100, dschuff
Subscribers: jgravelle-google, hiraditya, sunfish, mgrang, jfb, jdoerfert, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D59173
llvm-svn: 356610
2019-03-21 04:26:45 +08:00
|
|
|
// Separate out the producers and target features sections
|
2019-01-17 10:29:55 +08:00
|
|
|
if (Name == "producers") {
|
2019-08-15 23:54:37 +08:00
|
|
|
ProducersSection = std::make_unique<WasmCustomSection>(Name, &Section);
|
2019-01-17 10:29:55 +08:00
|
|
|
continue;
|
|
|
|
}
|
[WebAssembly] Target features section
Summary:
Implements a new target features section in assembly and object files
that records what features are used, required, and disallowed in
WebAssembly objects. The linker uses this information to ensure that
all objects participating in a link are feature-compatible and records
the set of used features in the output binary for use by optimizers
and other tools later in the toolchain.
The "atomics" feature is always required or disallowed to prevent
linking code with stripped atomics into multithreaded binaries. Other
features are marked used if they are enabled globally or on any
function in a module.
Future CLs will add linker flags for ignoring feature compatibility
checks and for specifying the set of allowed features, implement using
the presence of the "atomics" feature to control the type of memory
and segments in the linked binary, and add front-end flags for
relaxing the linkage policy for atomics.
Reviewers: aheejin, sbc100, dschuff
Subscribers: jgravelle-google, hiraditya, sunfish, mgrang, jfb, jdoerfert, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D59173
llvm-svn: 356610
2019-03-21 04:26:45 +08:00
|
|
|
if (Name == "target_features") {
|
|
|
|
TargetFeaturesSection =
|
2019-08-15 23:54:37 +08:00
|
|
|
std::make_unique<WasmCustomSection>(Name, &Section);
|
[WebAssembly] Target features section
Summary:
Implements a new target features section in assembly and object files
that records what features are used, required, and disallowed in
WebAssembly objects. The linker uses this information to ensure that
all objects participating in a link are feature-compatible and records
the set of used features in the output binary for use by optimizers
and other tools later in the toolchain.
The "atomics" feature is always required or disallowed to prevent
linking code with stripped atomics into multithreaded binaries. Other
features are marked used if they are enabled globally or on any
function in a module.
Future CLs will add linker flags for ignoring feature compatibility
checks and for specifying the set of allowed features, implement using
the presence of the "atomics" feature to control the type of memory
and segments in the linked binary, and add front-end flags for
relaxing the linkage policy for atomics.
Reviewers: aheejin, sbc100, dschuff
Subscribers: jgravelle-google, hiraditya, sunfish, mgrang, jfb, jdoerfert, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D59173
llvm-svn: 356610
2019-03-21 04:26:45 +08:00
|
|
|
continue;
|
|
|
|
}
|
2019-01-17 10:29:55 +08:00
|
|
|
|
2020-12-05 05:45:42 +08:00
|
|
|
// Custom sections can also belong to COMDAT groups. In this case the
|
|
|
|
// decriptor's "index" field is the section index (in the final object
|
|
|
|
// file), but that is not known until after layout, so it must be fixed up
|
|
|
|
// later
|
|
|
|
if (const MCSymbolWasm *C = Section.getGroup()) {
|
|
|
|
Comdats[C->getName()].emplace_back(
|
|
|
|
WasmComdatEntry{wasm::WASM_COMDAT_SECTION,
|
|
|
|
static_cast<uint32_t>(CustomSections.size())});
|
|
|
|
}
|
|
|
|
|
2018-05-03 07:11:38 +08:00
|
|
|
CustomSections.emplace_back(Name, &Section);
|
|
|
|
}
|
2018-04-27 03:27:28 +08:00
|
|
|
}
|
|
|
|
|
2020-12-22 02:24:32 +08:00
|
|
|
if (Mode != DwoMode::DwoOnly) {
|
|
|
|
// Populate WasmIndices and DataLocations for defined symbols.
|
|
|
|
for (const MCSymbol &S : Asm.symbols()) {
|
|
|
|
// Ignore unnamed temporary symbols, which aren't ever exported, imported,
|
|
|
|
// or used in relocations.
|
|
|
|
if (S.isTemporary() && S.getName().empty())
|
|
|
|
continue;
|
2017-06-20 12:04:59 +08:00
|
|
|
|
2020-12-22 02:24:32 +08:00
|
|
|
const auto &WS = static_cast<const MCSymbolWasm &>(S);
|
2021-02-02 09:28:00 +08:00
|
|
|
LLVM_DEBUG(dbgs()
|
|
|
|
<< "MCSymbol: "
|
|
|
|
<< toString(WS.getType().getValueOr(wasm::WASM_SYMBOL_TYPE_DATA))
|
|
|
|
<< " '" << S << "'"
|
2020-12-22 02:24:32 +08:00
|
|
|
<< " isDefined=" << S.isDefined() << " isExternal="
|
|
|
|
<< S.isExternal() << " isTemporary=" << S.isTemporary()
|
|
|
|
<< " isWeak=" << WS.isWeak() << " isHidden=" << WS.isHidden()
|
|
|
|
<< " isVariable=" << WS.isVariable() << "\n");
|
2017-06-20 12:04:59 +08:00
|
|
|
|
2020-12-22 02:24:32 +08:00
|
|
|
if (WS.isVariable())
|
|
|
|
continue;
|
|
|
|
if (WS.isComdat() && !WS.isDefined())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (WS.isFunction()) {
|
|
|
|
unsigned Index;
|
|
|
|
if (WS.isDefined()) {
|
|
|
|
if (WS.getOffset() != 0)
|
|
|
|
report_fatal_error(
|
|
|
|
"function sections must contain one function each");
|
|
|
|
|
|
|
|
if (WS.getSize() == nullptr)
|
|
|
|
report_fatal_error(
|
|
|
|
"function symbols must have a size set with .size");
|
|
|
|
|
|
|
|
// A definition. Write out the function body.
|
|
|
|
Index = NumFunctionImports + Functions.size();
|
|
|
|
WasmFunction Func;
|
|
|
|
Func.SigIndex = getFunctionType(WS);
|
|
|
|
Func.Sym = &WS;
|
|
|
|
assert(WasmIndices.count(&WS) == 0);
|
|
|
|
WasmIndices[&WS] = Index;
|
|
|
|
Functions.push_back(Func);
|
|
|
|
|
|
|
|
auto &Section = static_cast<MCSectionWasm &>(WS.getSection());
|
|
|
|
if (const MCSymbolWasm *C = Section.getGroup()) {
|
|
|
|
Comdats[C->getName()].emplace_back(
|
|
|
|
WasmComdatEntry{wasm::WASM_COMDAT_FUNCTION, Index});
|
|
|
|
}
|
|
|
|
|
|
|
|
if (WS.hasExportName()) {
|
|
|
|
wasm::WasmExport Export;
|
|
|
|
Export.Name = WS.getExportName();
|
|
|
|
Export.Kind = wasm::WASM_EXTERNAL_FUNCTION;
|
|
|
|
Export.Index = Index;
|
|
|
|
Exports.push_back(Export);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// An import; the index was assigned above.
|
|
|
|
Index = WasmIndices.find(&WS)->second;
|
2018-02-23 13:08:34 +08:00
|
|
|
}
|
2019-11-06 02:15:56 +08:00
|
|
|
|
2020-12-22 02:24:32 +08:00
|
|
|
LLVM_DEBUG(dbgs() << " -> function index: " << Index << "\n");
|
|
|
|
|
|
|
|
} else if (WS.isData()) {
|
|
|
|
if (!isInSymtab(WS))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!WS.isDefined()) {
|
|
|
|
LLVM_DEBUG(dbgs() << " -> segment index: -1"
|
|
|
|
<< "\n");
|
|
|
|
continue;
|
2019-11-06 02:15:56 +08:00
|
|
|
}
|
2017-02-25 07:18:00 +08:00
|
|
|
|
2020-12-22 02:24:32 +08:00
|
|
|
if (!WS.getSize())
|
|
|
|
report_fatal_error("data symbols must have a size set with .size: " +
|
|
|
|
WS.getName());
|
2018-11-14 10:46:21 +08:00
|
|
|
|
2020-12-22 02:24:32 +08:00
|
|
|
int64_t Size = 0;
|
|
|
|
if (!WS.getSize()->evaluateAsAbsolute(Size, Layout))
|
|
|
|
report_fatal_error(".size expression must be evaluatable");
|
2017-02-25 07:18:00 +08:00
|
|
|
|
2020-12-22 02:24:32 +08:00
|
|
|
auto &DataSection = static_cast<MCSectionWasm &>(WS.getSection());
|
|
|
|
if (!DataSection.isWasmData())
|
|
|
|
report_fatal_error("data symbols must live in a data section: " +
|
|
|
|
WS.getName());
|
2017-05-26 05:08:07 +08:00
|
|
|
|
2020-12-22 02:24:32 +08:00
|
|
|
// For each data symbol, export it in the symtab as a reference to the
|
|
|
|
// corresponding Wasm data segment.
|
|
|
|
wasm::WasmDataReference Ref = wasm::WasmDataReference{
|
|
|
|
DataSection.getSegmentIndex(), Layout.getSymbolOffset(WS),
|
|
|
|
static_cast<uint64_t>(Size)};
|
|
|
|
assert(DataLocations.count(&WS) == 0);
|
|
|
|
DataLocations[&WS] = Ref;
|
|
|
|
LLVM_DEBUG(dbgs() << " -> segment index: " << Ref.Segment << "\n");
|
|
|
|
|
|
|
|
} else if (WS.isGlobal()) {
|
|
|
|
// A "true" Wasm global (currently just __stack_pointer)
|
|
|
|
if (WS.isDefined()) {
|
|
|
|
wasm::WasmGlobal Global;
|
|
|
|
Global.Type = WS.getGlobalType();
|
|
|
|
Global.Index = NumGlobalImports + Globals.size();
|
|
|
|
switch (Global.Type.Type) {
|
|
|
|
case wasm::WASM_TYPE_I32:
|
|
|
|
Global.InitExpr.Opcode = wasm::WASM_OPCODE_I32_CONST;
|
|
|
|
break;
|
|
|
|
case wasm::WASM_TYPE_I64:
|
|
|
|
Global.InitExpr.Opcode = wasm::WASM_OPCODE_I64_CONST;
|
|
|
|
break;
|
|
|
|
case wasm::WASM_TYPE_F32:
|
|
|
|
Global.InitExpr.Opcode = wasm::WASM_OPCODE_F32_CONST;
|
|
|
|
break;
|
|
|
|
case wasm::WASM_TYPE_F64:
|
|
|
|
Global.InitExpr.Opcode = wasm::WASM_OPCODE_F64_CONST;
|
|
|
|
break;
|
|
|
|
case wasm::WASM_TYPE_EXTERNREF:
|
|
|
|
Global.InitExpr.Opcode = wasm::WASM_OPCODE_REF_NULL;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
llvm_unreachable("unexpected type");
|
|
|
|
}
|
|
|
|
assert(WasmIndices.count(&WS) == 0);
|
|
|
|
WasmIndices[&WS] = Global.Index;
|
|
|
|
Globals.push_back(Global);
|
|
|
|
} else {
|
|
|
|
// An import; the index was assigned above
|
|
|
|
LLVM_DEBUG(dbgs() << " -> global index: "
|
|
|
|
<< WasmIndices.find(&WS)->second << "\n");
|
2020-04-30 04:26:27 +08:00
|
|
|
}
|
2020-12-22 02:24:32 +08:00
|
|
|
} else if (WS.isTable()) {
|
|
|
|
if (WS.isDefined()) {
|
|
|
|
wasm::WasmTable Table;
|
|
|
|
Table.Index = NumTableImports + Tables.size();
|
|
|
|
Table.Type.ElemType = static_cast<uint8_t>(WS.getTableType());
|
|
|
|
// FIXME: Work on custom limits is ongoing
|
|
|
|
Table.Type.Limits = {wasm::WASM_LIMITS_FLAG_NONE, 0, 0};
|
|
|
|
assert(WasmIndices.count(&WS) == 0);
|
|
|
|
WasmIndices[&WS] = Table.Index;
|
|
|
|
Tables.push_back(Table);
|
|
|
|
}
|
|
|
|
LLVM_DEBUG(dbgs() << " -> table index: "
|
2020-04-30 04:26:27 +08:00
|
|
|
<< WasmIndices.find(&WS)->second << "\n");
|
2020-12-22 02:24:32 +08:00
|
|
|
} else if (WS.isEvent()) {
|
|
|
|
// C++ exception symbol (__cpp_exception)
|
|
|
|
unsigned Index;
|
|
|
|
if (WS.isDefined()) {
|
|
|
|
Index = NumEventImports + Events.size();
|
|
|
|
wasm::WasmEventType Event;
|
|
|
|
Event.SigIndex = getEventType(WS);
|
|
|
|
Event.Attribute = wasm::WASM_EVENT_ATTRIBUTE_EXCEPTION;
|
|
|
|
assert(WasmIndices.count(&WS) == 0);
|
|
|
|
WasmIndices[&WS] = Index;
|
|
|
|
Events.push_back(Event);
|
|
|
|
} else {
|
|
|
|
// An import; the index was assigned above.
|
|
|
|
assert(WasmIndices.count(&WS) > 0);
|
|
|
|
}
|
|
|
|
LLVM_DEBUG(dbgs() << " -> event index: "
|
|
|
|
<< WasmIndices.find(&WS)->second << "\n");
|
|
|
|
|
2018-11-14 10:46:21 +08:00
|
|
|
} else {
|
2020-12-22 02:24:32 +08:00
|
|
|
assert(WS.isSection());
|
2018-11-14 10:46:21 +08:00
|
|
|
}
|
2017-02-25 07:18:00 +08:00
|
|
|
}
|
|
|
|
|
2020-12-22 02:24:32 +08:00
|
|
|
// Populate WasmIndices and DataLocations for aliased symbols. We need to
|
|
|
|
// process these in a separate pass because we need to have processed the
|
|
|
|
// target of the alias before the alias itself and the symbols are not
|
|
|
|
// necessarily ordered in this way.
|
|
|
|
for (const MCSymbol &S : Asm.symbols()) {
|
|
|
|
if (!S.isVariable())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
assert(S.isDefined());
|
2017-09-21 05:17:04 +08:00
|
|
|
|
2020-12-22 02:24:32 +08:00
|
|
|
const auto *BS = Layout.getBaseSymbol(S);
|
|
|
|
if (!BS)
|
|
|
|
report_fatal_error(Twine(S.getName()) +
|
|
|
|
": absolute addressing not supported!");
|
|
|
|
const MCSymbolWasm *Base = cast<MCSymbolWasm>(BS);
|
2017-06-20 12:04:59 +08:00
|
|
|
|
2020-12-22 02:24:32 +08:00
|
|
|
// Find the target symbol of this weak alias and export that index
|
|
|
|
const auto &WS = static_cast<const MCSymbolWasm &>(S);
|
|
|
|
LLVM_DEBUG(dbgs() << WS.getName() << ": weak alias of '" << *Base
|
|
|
|
<< "'\n");
|
2020-04-30 06:38:11 +08:00
|
|
|
|
2020-12-22 02:24:32 +08:00
|
|
|
if (Base->isFunction()) {
|
|
|
|
assert(WasmIndices.count(Base) > 0);
|
|
|
|
uint32_t WasmIndex = WasmIndices.find(Base)->second;
|
|
|
|
assert(WasmIndices.count(&WS) == 0);
|
|
|
|
WasmIndices[&WS] = WasmIndex;
|
|
|
|
LLVM_DEBUG(dbgs() << " -> index:" << WasmIndex << "\n");
|
|
|
|
} else if (Base->isData()) {
|
|
|
|
auto &DataSection = static_cast<MCSectionWasm &>(WS.getSection());
|
|
|
|
uint64_t Offset = Layout.getSymbolOffset(S);
|
|
|
|
int64_t Size = 0;
|
|
|
|
// For data symbol alias we use the size of the base symbol as the
|
|
|
|
// size of the alias. When an offset from the base is involved this
|
|
|
|
// can result in a offset + size goes past the end of the data section
|
|
|
|
// which out object format doesn't support. So we must clamp it.
|
|
|
|
if (!Base->getSize()->evaluateAsAbsolute(Size, Layout))
|
|
|
|
report_fatal_error(".size expression must be evaluatable");
|
|
|
|
const WasmDataSegment &Segment =
|
|
|
|
DataSegments[DataSection.getSegmentIndex()];
|
|
|
|
Size =
|
|
|
|
std::min(static_cast<uint64_t>(Size), Segment.Data.size() - Offset);
|
|
|
|
wasm::WasmDataReference Ref = wasm::WasmDataReference{
|
|
|
|
DataSection.getSegmentIndex(),
|
|
|
|
static_cast<uint32_t>(Layout.getSymbolOffset(S)),
|
|
|
|
static_cast<uint32_t>(Size)};
|
|
|
|
DataLocations[&WS] = Ref;
|
|
|
|
LLVM_DEBUG(dbgs() << " -> index:" << Ref.Segment << "\n");
|
|
|
|
} else {
|
|
|
|
report_fatal_error("don't yet support global/event aliases");
|
|
|
|
}
|
2018-02-23 13:08:34 +08:00
|
|
|
}
|
2018-03-01 01:19:48 +08:00
|
|
|
}
|
2018-02-23 13:08:34 +08:00
|
|
|
|
2018-03-01 01:19:48 +08:00
|
|
|
// Finally, populate the symbol table itself, in its "natural" order.
|
|
|
|
for (const MCSymbol &S : Asm.symbols()) {
|
|
|
|
const auto &WS = static_cast<const MCSymbolWasm &>(S);
|
2018-05-08 08:08:21 +08:00
|
|
|
if (!isInSymtab(WS)) {
|
[WebAssembly] clang-tidy (NFC)
Summary:
This patch fixes clang-tidy warnings on wasm-only files.
The list of checks used is:
`-*,clang-diagnostic-*,llvm-*,misc-*,-misc-unused-parameters,readability-identifier-naming,modernize-*`
(LLVM's default .clang-tidy list is the same except it does not have
`modernize-*`. But I've seen in multiple CLs in LLVM the modernize style
was recommended and code was fixed based on the style, so I added it as
well.)
The common fixes are:
- Variable names start with an uppercase letter
- Function names start with a lowercase letter
- Use `auto` when you use casts so the type is evident
- Use inline initialization for class member variables
- Use `= default` for empty constructors / destructors
- Use `using` in place of `typedef`
Reviewers: sbc100, tlively, aardappel
Subscribers: dschuff, sunfish, jgravelle-google, yurydelendik, kripken, MatzeB, mgorny, rupprecht, llvm-commits
Differential Revision: https://reviews.llvm.org/D57500
llvm-svn: 353075
2019-02-05 03:13:39 +08:00
|
|
|
WS.setIndex(InvalidIndex);
|
2018-03-01 01:19:48 +08:00
|
|
|
continue;
|
2018-05-08 08:08:21 +08:00
|
|
|
}
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "adding to symtab: " << WS << "\n");
|
2018-03-01 01:19:48 +08:00
|
|
|
|
|
|
|
uint32_t Flags = 0;
|
|
|
|
if (WS.isWeak())
|
|
|
|
Flags |= wasm::WASM_SYMBOL_BINDING_WEAK;
|
|
|
|
if (WS.isHidden())
|
|
|
|
Flags |= wasm::WASM_SYMBOL_VISIBILITY_HIDDEN;
|
|
|
|
if (!WS.isExternal() && WS.isDefined())
|
|
|
|
Flags |= wasm::WASM_SYMBOL_BINDING_LOCAL;
|
|
|
|
if (WS.isUndefined())
|
|
|
|
Flags |= wasm::WASM_SYMBOL_UNDEFINED;
|
2019-08-30 06:40:00 +08:00
|
|
|
if (WS.isNoStrip()) {
|
|
|
|
Flags |= wasm::WASM_SYMBOL_NO_STRIP;
|
|
|
|
if (isEmscripten()) {
|
|
|
|
Flags |= wasm::WASM_SYMBOL_EXPORTED;
|
|
|
|
}
|
|
|
|
}
|
2019-12-02 02:49:03 +08:00
|
|
|
if (WS.hasImportName())
|
2019-02-08 06:03:32 +08:00
|
|
|
Flags |= wasm::WASM_SYMBOL_EXPLICIT_NAME;
|
2019-11-06 02:15:56 +08:00
|
|
|
if (WS.hasExportName())
|
|
|
|
Flags |= wasm::WASM_SYMBOL_EXPORTED;
|
2018-03-01 01:19:48 +08:00
|
|
|
|
|
|
|
wasm::WasmSymbolInfo Info;
|
|
|
|
Info.Name = WS.getName();
|
2021-02-02 09:28:00 +08:00
|
|
|
Info.Kind = WS.getType().getValueOr(wasm::WASM_SYMBOL_TYPE_DATA);
|
2018-03-01 01:19:48 +08:00
|
|
|
Info.Flags = Flags;
|
2018-05-03 07:11:38 +08:00
|
|
|
if (!WS.isData()) {
|
|
|
|
assert(WasmIndices.count(&WS) > 0);
|
2018-03-01 01:19:48 +08:00
|
|
|
Info.ElementIndex = WasmIndices.find(&WS)->second;
|
2018-05-03 07:11:38 +08:00
|
|
|
} else if (WS.isDefined()) {
|
|
|
|
assert(DataLocations.count(&WS) > 0);
|
2018-03-01 01:19:48 +08:00
|
|
|
Info.DataRef = DataLocations.find(&WS)->second;
|
2018-05-03 07:11:38 +08:00
|
|
|
}
|
2018-05-08 08:08:21 +08:00
|
|
|
WS.setIndex(SymbolInfos.size());
|
2018-03-01 01:19:48 +08:00
|
|
|
SymbolInfos.emplace_back(Info);
|
2017-06-20 12:04:59 +08:00
|
|
|
}
|
|
|
|
|
2017-12-23 04:31:39 +08:00
|
|
|
{
|
|
|
|
auto HandleReloc = [&](const WasmRelocationEntry &Rel) {
|
2018-02-01 03:28:47 +08:00
|
|
|
// Functions referenced by a relocation need to put in the table. This is
|
|
|
|
// purely to make the object file's provisional values readable, and is
|
|
|
|
// ignored by the linker, which re-calculates the relocations itself.
|
2019-02-05 01:28:46 +08:00
|
|
|
if (Rel.Type != wasm::R_WASM_TABLE_INDEX_I32 &&
|
2020-07-11 07:51:01 +08:00
|
|
|
Rel.Type != wasm::R_WASM_TABLE_INDEX_I64 &&
|
2020-05-29 09:39:27 +08:00
|
|
|
Rel.Type != wasm::R_WASM_TABLE_INDEX_SLEB &&
|
2020-07-11 07:51:01 +08:00
|
|
|
Rel.Type != wasm::R_WASM_TABLE_INDEX_SLEB64 &&
|
2020-05-29 09:39:27 +08:00
|
|
|
Rel.Type != wasm::R_WASM_TABLE_INDEX_REL_SLEB)
|
2018-02-01 03:28:47 +08:00
|
|
|
return;
|
|
|
|
assert(Rel.Symbol->isFunction());
|
2020-04-30 06:38:11 +08:00
|
|
|
const MCSymbolWasm *Base =
|
|
|
|
cast<MCSymbolWasm>(Layout.getBaseSymbol(*Rel.Symbol));
|
|
|
|
uint32_t FunctionIndex = WasmIndices.find(Base)->second;
|
[WebAssembly] clang-tidy (NFC)
Summary:
This patch fixes clang-tidy warnings on wasm-only files.
The list of checks used is:
`-*,clang-diagnostic-*,llvm-*,misc-*,-misc-unused-parameters,readability-identifier-naming,modernize-*`
(LLVM's default .clang-tidy list is the same except it does not have
`modernize-*`. But I've seen in multiple CLs in LLVM the modernize style
was recommended and code was fixed based on the style, so I added it as
well.)
The common fixes are:
- Variable names start with an uppercase letter
- Function names start with a lowercase letter
- Use `auto` when you use casts so the type is evident
- Use inline initialization for class member variables
- Use `= default` for empty constructors / destructors
- Use `using` in place of `typedef`
Reviewers: sbc100, tlively, aardappel
Subscribers: dschuff, sunfish, jgravelle-google, yurydelendik, kripken, MatzeB, mgorny, rupprecht, llvm-commits
Differential Revision: https://reviews.llvm.org/D57500
llvm-svn: 353075
2019-02-05 03:13:39 +08:00
|
|
|
uint32_t TableIndex = TableElems.size() + InitialTableOffset;
|
2020-04-30 06:38:11 +08:00
|
|
|
if (TableIndices.try_emplace(Base, TableIndex).second) {
|
|
|
|
LLVM_DEBUG(dbgs() << " -> adding " << Base->getName()
|
2018-05-14 20:53:11 +08:00
|
|
|
<< " to table: " << TableIndex << "\n");
|
2018-02-23 13:08:34 +08:00
|
|
|
TableElems.push_back(FunctionIndex);
|
2020-04-30 06:38:11 +08:00
|
|
|
registerFunctionType(*Base);
|
2017-12-23 04:31:39 +08:00
|
|
|
}
|
|
|
|
};
|
2017-03-31 07:58:19 +08:00
|
|
|
|
2017-12-23 04:31:39 +08:00
|
|
|
for (const WasmRelocationEntry &RelEntry : CodeRelocations)
|
|
|
|
HandleReloc(RelEntry);
|
|
|
|
for (const WasmRelocationEntry &RelEntry : DataRelocations)
|
|
|
|
HandleReloc(RelEntry);
|
2017-02-25 07:18:00 +08:00
|
|
|
}
|
|
|
|
|
2017-12-15 08:17:10 +08:00
|
|
|
// Translate .init_array section contents into start functions.
|
|
|
|
for (const MCSection &S : Asm) {
|
|
|
|
const auto &WS = static_cast<const MCSectionWasm &>(S);
|
2020-04-16 06:49:05 +08:00
|
|
|
if (WS.getName().startswith(".fini_array"))
|
2017-12-15 08:17:10 +08:00
|
|
|
report_fatal_error(".fini_array sections are unsupported");
|
2020-04-16 06:49:05 +08:00
|
|
|
if (!WS.getName().startswith(".init_array"))
|
2017-12-15 08:17:10 +08:00
|
|
|
continue;
|
|
|
|
if (WS.getFragmentList().empty())
|
|
|
|
continue;
|
2018-05-11 01:38:35 +08:00
|
|
|
|
|
|
|
// init_array is expected to contain a single non-empty data fragment
|
|
|
|
if (WS.getFragmentList().size() != 3)
|
2017-12-15 08:17:10 +08:00
|
|
|
report_fatal_error("only one .init_array section fragment supported");
|
2018-05-11 01:38:35 +08:00
|
|
|
|
|
|
|
auto IT = WS.begin();
|
|
|
|
const MCFragment &EmptyFrag = *IT;
|
|
|
|
if (EmptyFrag.getKind() != MCFragment::FT_Data)
|
|
|
|
report_fatal_error(".init_array section should be aligned");
|
|
|
|
|
|
|
|
IT = std::next(IT);
|
|
|
|
const MCFragment &AlignFrag = *IT;
|
2017-12-15 08:17:10 +08:00
|
|
|
if (AlignFrag.getKind() != MCFragment::FT_Align)
|
|
|
|
report_fatal_error(".init_array section should be aligned");
|
|
|
|
if (cast<MCAlignFragment>(AlignFrag).getAlignment() != (is64Bit() ? 8 : 4))
|
|
|
|
report_fatal_error(".init_array section should be aligned for pointers");
|
2018-05-11 01:38:35 +08:00
|
|
|
|
|
|
|
const MCFragment &Frag = *std::next(IT);
|
2017-12-15 08:17:10 +08:00
|
|
|
if (Frag.hasInstructions() || Frag.getKind() != MCFragment::FT_Data)
|
|
|
|
report_fatal_error("only data supported in .init_array section");
|
2018-05-11 01:38:35 +08:00
|
|
|
|
2017-12-15 08:17:10 +08:00
|
|
|
uint16_t Priority = UINT16_MAX;
|
2018-05-03 07:11:38 +08:00
|
|
|
unsigned PrefixLength = strlen(".init_array");
|
2020-04-16 06:49:05 +08:00
|
|
|
if (WS.getName().size() > PrefixLength) {
|
|
|
|
if (WS.getName()[PrefixLength] != '.')
|
2018-09-05 09:27:38 +08:00
|
|
|
report_fatal_error(
|
|
|
|
".init_array section priority should start with '.'");
|
2020-04-16 06:49:05 +08:00
|
|
|
if (WS.getName().substr(PrefixLength + 1).getAsInteger(10, Priority))
|
2017-12-15 08:17:10 +08:00
|
|
|
report_fatal_error("invalid .init_array section priority");
|
|
|
|
}
|
|
|
|
const auto &DataFrag = cast<MCDataFragment>(Frag);
|
|
|
|
const SmallVectorImpl<char> &Contents = DataFrag.getContents();
|
2018-09-05 09:27:38 +08:00
|
|
|
for (const uint8_t *
|
[WebAssembly] clang-tidy (NFC)
Summary:
This patch fixes clang-tidy warnings on wasm-only files.
The list of checks used is:
`-*,clang-diagnostic-*,llvm-*,misc-*,-misc-unused-parameters,readability-identifier-naming,modernize-*`
(LLVM's default .clang-tidy list is the same except it does not have
`modernize-*`. But I've seen in multiple CLs in LLVM the modernize style
was recommended and code was fixed based on the style, so I added it as
well.)
The common fixes are:
- Variable names start with an uppercase letter
- Function names start with a lowercase letter
- Use `auto` when you use casts so the type is evident
- Use inline initialization for class member variables
- Use `= default` for empty constructors / destructors
- Use `using` in place of `typedef`
Reviewers: sbc100, tlively, aardappel
Subscribers: dschuff, sunfish, jgravelle-google, yurydelendik, kripken, MatzeB, mgorny, rupprecht, llvm-commits
Differential Revision: https://reviews.llvm.org/D57500
llvm-svn: 353075
2019-02-05 03:13:39 +08:00
|
|
|
P = (const uint8_t *)Contents.data(),
|
|
|
|
*End = (const uint8_t *)Contents.data() + Contents.size();
|
|
|
|
P != End; ++P) {
|
|
|
|
if (*P != 0)
|
2017-12-15 08:17:10 +08:00
|
|
|
report_fatal_error("non-symbolic data in .init_array section");
|
|
|
|
}
|
|
|
|
for (const MCFixup &Fixup : DataFrag.getFixups()) {
|
2018-09-05 09:27:38 +08:00
|
|
|
assert(Fixup.getKind() ==
|
|
|
|
MCFixup::getKindForSize(is64Bit() ? 8 : 4, false));
|
2017-12-15 08:17:10 +08:00
|
|
|
const MCExpr *Expr = Fixup.getValue();
|
2019-02-23 06:29:34 +08:00
|
|
|
auto *SymRef = dyn_cast<MCSymbolRefExpr>(Expr);
|
|
|
|
if (!SymRef)
|
2017-12-15 08:17:10 +08:00
|
|
|
report_fatal_error("fixups in .init_array should be symbol references");
|
2019-02-23 06:29:34 +08:00
|
|
|
const auto &TargetSym = cast<const MCSymbolWasm>(SymRef->getSymbol());
|
|
|
|
if (TargetSym.getIndex() == InvalidIndex)
|
2020-03-31 08:37:01 +08:00
|
|
|
report_fatal_error("symbols in .init_array should exist in symtab");
|
2019-02-23 06:29:34 +08:00
|
|
|
if (!TargetSym.isFunction())
|
|
|
|
report_fatal_error("symbols in .init_array should be for functions");
|
2018-05-08 08:08:21 +08:00
|
|
|
InitFuncs.push_back(
|
2019-02-23 06:29:34 +08:00
|
|
|
std::make_pair(Priority, TargetSym.getIndex()));
|
2017-12-15 08:17:10 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-22 09:23:18 +08:00
|
|
|
// Write out the Wasm header.
|
|
|
|
writeHeader(Asm);
|
|
|
|
|
2020-08-08 12:23:11 +08:00
|
|
|
uint32_t CodeSectionIndex, DataSectionIndex;
|
|
|
|
if (Mode != DwoMode::DwoOnly) {
|
|
|
|
writeTypeSection(Signatures);
|
|
|
|
writeImportSection(Imports, DataSize, TableElems.size());
|
|
|
|
writeFunctionSection(Functions);
|
2020-11-30 23:16:33 +08:00
|
|
|
writeTableSection(Tables);
|
2020-08-08 12:23:11 +08:00
|
|
|
// Skip the "memory" section; we import the memory instead.
|
|
|
|
writeEventSection(Events);
|
|
|
|
writeGlobalSection(Globals);
|
|
|
|
writeExportSection(Exports);
|
2021-03-04 17:30:00 +08:00
|
|
|
const MCSymbol *IndirectFunctionTable =
|
|
|
|
Asm.getContext().lookupSymbol("__indirect_function_table");
|
|
|
|
writeElemSection(cast_or_null<const MCSymbolWasm>(IndirectFunctionTable),
|
|
|
|
TableElems);
|
2020-08-08 12:23:11 +08:00
|
|
|
writeDataCountSection();
|
|
|
|
|
|
|
|
CodeSectionIndex = writeCodeSection(Asm, Layout, Functions);
|
|
|
|
DataSectionIndex = writeDataSection(Layout);
|
|
|
|
}
|
|
|
|
|
2020-12-05 05:45:42 +08:00
|
|
|
// The Sections in the COMDAT list have placeholder indices (their index among
|
|
|
|
// custom sections, rather than among all sections). Fix them up here.
|
|
|
|
for (auto &Group : Comdats) {
|
|
|
|
for (auto &Entry : Group.second) {
|
|
|
|
if (Entry.Kind == wasm::WASM_COMDAT_SECTION) {
|
|
|
|
Entry.Index += SectionCount;
|
|
|
|
}
|
|
|
|
}
|
2020-08-08 12:23:11 +08:00
|
|
|
}
|
2020-12-05 05:45:42 +08:00
|
|
|
for (auto &CustomSection : CustomSections)
|
|
|
|
writeCustomSection(CustomSection, Asm, Layout);
|
2020-08-08 12:23:11 +08:00
|
|
|
|
|
|
|
if (Mode != DwoMode::DwoOnly) {
|
|
|
|
writeLinkingMetaDataSection(SymbolInfos, InitFuncs, Comdats);
|
|
|
|
|
|
|
|
writeRelocSection(CodeSectionIndex, "CODE", CodeRelocations);
|
|
|
|
writeRelocSection(DataSectionIndex, "DATA", DataRelocations);
|
|
|
|
}
|
2018-04-27 03:27:28 +08:00
|
|
|
writeCustomRelocSections();
|
2019-01-17 10:29:55 +08:00
|
|
|
if (ProducersSection)
|
|
|
|
writeCustomSection(*ProducersSection, Asm, Layout);
|
[WebAssembly] Target features section
Summary:
Implements a new target features section in assembly and object files
that records what features are used, required, and disallowed in
WebAssembly objects. The linker uses this information to ensure that
all objects participating in a link are feature-compatible and records
the set of used features in the output binary for use by optimizers
and other tools later in the toolchain.
The "atomics" feature is always required or disallowed to prevent
linking code with stripped atomics into multithreaded binaries. Other
features are marked used if they are enabled globally or on any
function in a module.
Future CLs will add linker flags for ignoring feature compatibility
checks and for specifying the set of allowed features, implement using
the presence of the "atomics" feature to control the type of memory
and segments in the linked binary, and add front-end flags for
relaxing the linkage policy for atomics.
Reviewers: aheejin, sbc100, dschuff
Subscribers: jgravelle-google, hiraditya, sunfish, mgrang, jfb, jdoerfert, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D59173
llvm-svn: 356610
2019-03-21 04:26:45 +08:00
|
|
|
if (TargetFeaturesSection)
|
|
|
|
writeCustomSection(*TargetFeaturesSection, Asm, Layout);
|
2017-03-31 07:58:19 +08:00
|
|
|
|
2017-02-25 07:18:00 +08:00
|
|
|
// TODO: Translate the .comment section to the output.
|
2020-08-08 12:23:11 +08:00
|
|
|
return W->OS.tell() - StartOffset;
|
2017-02-22 09:23:18 +08:00
|
|
|
}
|
|
|
|
|
2017-10-11 00:28:07 +08:00
|
|
|
std::unique_ptr<MCObjectWriter>
|
2017-10-10 09:15:10 +08:00
|
|
|
llvm::createWasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW,
|
|
|
|
raw_pwrite_stream &OS) {
|
2019-08-15 23:54:37 +08:00
|
|
|
return std::make_unique<WasmObjectWriter>(std::move(MOTW), OS);
|
2017-02-22 09:23:18 +08:00
|
|
|
}
|
2020-08-08 12:23:11 +08:00
|
|
|
|
|
|
|
std::unique_ptr<MCObjectWriter>
|
|
|
|
llvm::createWasmDwoObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW,
|
|
|
|
raw_pwrite_stream &OS,
|
|
|
|
raw_pwrite_stream &DwoOS) {
|
|
|
|
return std::make_unique<WasmObjectWriter>(std::move(MOTW), OS, DwoOS);
|
|
|
|
}
|