mirror of
https://github.com/RPCSX/llvm.git
synced 2025-01-31 09:22:31 +00:00
[WebAssembly] Add skeleton MC support for the Wasm container format
This just adds the basic skeleton for supporting a new object file format. All of the actual encoding will be implemented in followup patches. Differential Revision: https://reviews.llvm.org/D26722 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@295803 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
9a736108d4
commit
d660a5d68c
@ -171,6 +171,28 @@ public:
|
||||
const GlobalValue *GV) const override;
|
||||
};
|
||||
|
||||
class TargetLoweringObjectFileWasm : public TargetLoweringObjectFile {
|
||||
public:
|
||||
TargetLoweringObjectFileWasm() {}
|
||||
|
||||
~TargetLoweringObjectFileWasm() override {}
|
||||
|
||||
MCSection *getExplicitSectionGlobal(const GlobalObject *GO, SectionKind Kind,
|
||||
const TargetMachine &TM) const override;
|
||||
|
||||
MCSection *SelectSectionForGlobal(const GlobalObject *GO, SectionKind Kind,
|
||||
const TargetMachine &TM) const override;
|
||||
|
||||
bool shouldPutJumpTableInFunctionSection(bool UsesLabelDifference,
|
||||
const Function &F) const override;
|
||||
|
||||
void InitializeWasm();
|
||||
|
||||
const MCExpr *lowerRelativeReference(const GlobalValue *LHS,
|
||||
const GlobalValue *RHS,
|
||||
const TargetMachine &TM) const override;
|
||||
};
|
||||
|
||||
void emitLinkerFlagsForGlobalCOFF(raw_ostream &OS, const GlobalValue *GV,
|
||||
const Triple &TT, Mangler &Mangler);
|
||||
|
||||
|
24
include/llvm/MC/MCAsmInfoWasm.h
Normal file
24
include/llvm/MC/MCAsmInfoWasm.h
Normal file
@ -0,0 +1,24 @@
|
||||
//===-- llvm/MC/MCAsmInfoWasm.h - Wasm Asm info -----------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_MC_MCASMINFOWASM_H
|
||||
#define LLVM_MC_MCASMINFOWASM_H
|
||||
|
||||
#include "llvm/MC/MCAsmInfo.h"
|
||||
|
||||
namespace llvm {
|
||||
class MCAsmInfoWasm : public MCAsmInfo {
|
||||
virtual void anchor();
|
||||
|
||||
protected:
|
||||
MCAsmInfoWasm();
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -45,8 +45,10 @@ namespace llvm {
|
||||
class MCSectionCOFF;
|
||||
class MCSectionELF;
|
||||
class MCSectionMachO;
|
||||
class MCSectionWasm;
|
||||
class MCSymbol;
|
||||
class MCSymbolELF;
|
||||
class MCSymbolWasm;
|
||||
class SMLoc;
|
||||
|
||||
/// Context object for machine code objects. This class owns all of the
|
||||
@ -83,6 +85,7 @@ namespace llvm {
|
||||
SpecificBumpPtrAllocator<MCSectionCOFF> COFFAllocator;
|
||||
SpecificBumpPtrAllocator<MCSectionELF> ELFAllocator;
|
||||
SpecificBumpPtrAllocator<MCSectionMachO> MachOAllocator;
|
||||
SpecificBumpPtrAllocator<MCSectionWasm> WasmAllocator;
|
||||
|
||||
/// Bindings of names to symbols.
|
||||
SymbolTable Symbols;
|
||||
@ -216,10 +219,28 @@ namespace llvm {
|
||||
}
|
||||
};
|
||||
|
||||
struct WasmSectionKey {
|
||||
std::string SectionName;
|
||||
StringRef GroupName;
|
||||
unsigned UniqueID;
|
||||
WasmSectionKey(StringRef SectionName, StringRef GroupName,
|
||||
unsigned UniqueID)
|
||||
: SectionName(SectionName), GroupName(GroupName), UniqueID(UniqueID) {
|
||||
}
|
||||
bool operator<(const WasmSectionKey &Other) const {
|
||||
if (SectionName != Other.SectionName)
|
||||
return SectionName < Other.SectionName;
|
||||
if (GroupName != Other.GroupName)
|
||||
return GroupName < Other.GroupName;
|
||||
return UniqueID < Other.UniqueID;
|
||||
}
|
||||
};
|
||||
|
||||
StringMap<MCSectionMachO *> MachOUniquingMap;
|
||||
std::map<ELFSectionKey, MCSectionELF *> ELFUniquingMap;
|
||||
std::map<COFFSectionKey, MCSectionCOFF *> COFFUniquingMap;
|
||||
StringMap<bool> ELFRelSecNames;
|
||||
std::map<WasmSectionKey, MCSectionWasm *> WasmUniquingMap;
|
||||
StringMap<bool> RelSecNames;
|
||||
|
||||
SpecificBumpPtrAllocator<MCSubtargetInfo> MCSubtargetAllocator;
|
||||
|
||||
@ -416,6 +437,54 @@ namespace llvm {
|
||||
getAssociativeCOFFSection(MCSectionCOFF *Sec, const MCSymbol *KeySym,
|
||||
unsigned UniqueID = GenericSectionID);
|
||||
|
||||
MCSectionWasm *getWasmSection(const Twine &Section, unsigned Type,
|
||||
unsigned Flags) {
|
||||
return getWasmSection(Section, Type, Flags, nullptr);
|
||||
}
|
||||
|
||||
MCSectionWasm *getWasmSection(const Twine &Section, unsigned Type,
|
||||
unsigned Flags, const char *BeginSymName) {
|
||||
return getWasmSection(Section, Type, Flags, "", BeginSymName);
|
||||
}
|
||||
|
||||
MCSectionWasm *getWasmSection(const Twine &Section, unsigned Type,
|
||||
unsigned Flags, const Twine &Group) {
|
||||
return getWasmSection(Section, Type, Flags, Group, nullptr);
|
||||
}
|
||||
|
||||
MCSectionWasm *getWasmSection(const Twine &Section, unsigned Type,
|
||||
unsigned Flags, const Twine &Group,
|
||||
const char *BeginSymName) {
|
||||
return getWasmSection(Section, Type, Flags, Group, ~0, BeginSymName);
|
||||
}
|
||||
|
||||
MCSectionWasm *getWasmSection(const Twine &Section, unsigned Type,
|
||||
unsigned Flags, const Twine &Group,
|
||||
unsigned UniqueID) {
|
||||
return getWasmSection(Section, Type, Flags, Group, UniqueID, nullptr);
|
||||
}
|
||||
|
||||
MCSectionWasm *getWasmSection(const Twine &Section, unsigned Type,
|
||||
unsigned Flags, const Twine &Group,
|
||||
unsigned UniqueID, const char *BeginSymName);
|
||||
|
||||
MCSectionWasm *getWasmSection(const Twine &Section, unsigned Type,
|
||||
unsigned Flags, const MCSymbolWasm *Group,
|
||||
unsigned UniqueID, const char *BeginSymName);
|
||||
|
||||
/// Get a section with the provided group identifier. This section is
|
||||
/// named by concatenating \p Prefix with '.' then \p Suffix. The \p Type
|
||||
/// describes the type of the section and \p Flags are used to further
|
||||
/// configure this named section.
|
||||
MCSectionWasm *getWasmNamedSection(const Twine &Prefix, const Twine &Suffix,
|
||||
unsigned Type, unsigned Flags);
|
||||
|
||||
MCSectionWasm *createWasmRelSection(const Twine &Name, unsigned Type,
|
||||
unsigned Flags,
|
||||
const MCSymbolWasm *Group);
|
||||
|
||||
void renameWasmSection(MCSectionWasm *Section, StringRef Name);
|
||||
|
||||
// Create and save a copy of STI and return a reference to the copy.
|
||||
MCSubtargetInfo &getSubtargetCopy(const MCSubtargetInfo &STI);
|
||||
|
||||
|
@ -129,7 +129,7 @@ protected:
|
||||
/// it'll go here.
|
||||
MCSection *TLSExtraDataSection;
|
||||
|
||||
/// Section directive for Thread Local data. ELF, MachO and COFF.
|
||||
/// Section directive for Thread Local data. ELF, MachO, COFF, and Wasm.
|
||||
MCSection *TLSDataSection; // Defaults to ".tdata".
|
||||
|
||||
/// Section directive for Thread Local uninitialized data.
|
||||
@ -338,7 +338,7 @@ public:
|
||||
return EHFrameSection;
|
||||
}
|
||||
|
||||
enum Environment { IsMachO, IsELF, IsCOFF };
|
||||
enum Environment { IsMachO, IsELF, IsCOFF, IsWasm };
|
||||
Environment getObjectFileType() const { return Env; }
|
||||
|
||||
bool isPositionIndependent() const { return PositionIndependent; }
|
||||
@ -353,6 +353,7 @@ private:
|
||||
void initMachOMCObjectFileInfo(const Triple &T);
|
||||
void initELFMCObjectFileInfo(const Triple &T);
|
||||
void initCOFFMCObjectFileInfo(const Triple &T);
|
||||
void initWasmMCObjectFileInfo(const Triple &T);
|
||||
|
||||
public:
|
||||
const Triple &getTargetTriple() const { return TT; }
|
||||
|
@ -38,7 +38,7 @@ template <> struct ilist_alloc_traits<MCFragment> {
|
||||
/// current translation unit. The MCContext class uniques and creates these.
|
||||
class MCSection {
|
||||
public:
|
||||
enum SectionVariant { SV_COFF = 0, SV_ELF, SV_MachO };
|
||||
enum SectionVariant { SV_COFF = 0, SV_ELF, SV_MachO, SV_Wasm };
|
||||
|
||||
/// \brief Express the state of bundle locked groups while emitting code.
|
||||
enum BundleLockStateType {
|
||||
|
80
include/llvm/MC/MCSectionWasm.h
Normal file
80
include/llvm/MC/MCSectionWasm.h
Normal file
@ -0,0 +1,80 @@
|
||||
//===- MCSectionWasm.h - Wasm Machine Code Sections -------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file declares the MCSectionWasm class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_MC_MCSECTIONWASM_H
|
||||
#define LLVM_MC_MCSECTIONWASM_H
|
||||
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/MC/MCSection.h"
|
||||
#include "llvm/MC/MCSymbolWasm.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class MCSymbol;
|
||||
|
||||
/// This represents a section on wasm.
|
||||
class MCSectionWasm final : public MCSection {
|
||||
/// This is the name of the section. The referenced memory is owned by
|
||||
/// TargetLoweringObjectFileWasm's WasmUniqueMap.
|
||||
StringRef SectionName;
|
||||
|
||||
/// This is the sh_type field of a section, drawn from the enums below.
|
||||
unsigned Type;
|
||||
|
||||
/// This is the sh_flags field of a section, drawn from the enums below.
|
||||
unsigned Flags;
|
||||
|
||||
unsigned UniqueID;
|
||||
|
||||
const MCSymbolWasm *Group;
|
||||
|
||||
private:
|
||||
friend class MCContext;
|
||||
MCSectionWasm(StringRef Section, unsigned type, unsigned flags, SectionKind K,
|
||||
const MCSymbolWasm *group, unsigned UniqueID, MCSymbol *Begin)
|
||||
: MCSection(SV_Wasm, K, Begin), SectionName(Section), Type(type),
|
||||
Flags(flags), UniqueID(UniqueID), Group(group) {
|
||||
}
|
||||
|
||||
void setSectionName(StringRef Name) { SectionName = Name; }
|
||||
|
||||
public:
|
||||
~MCSectionWasm();
|
||||
|
||||
/// Decides whether a '.section' directive should be printed before the
|
||||
/// section name
|
||||
bool ShouldOmitSectionDirective(StringRef Name, const MCAsmInfo &MAI) const;
|
||||
|
||||
StringRef getSectionName() const { return SectionName; }
|
||||
unsigned getType() const { return Type; }
|
||||
unsigned getFlags() const { return Flags; }
|
||||
void setFlags(unsigned F) { Flags = F; }
|
||||
const MCSymbolWasm *getGroup() const { return Group; }
|
||||
|
||||
void PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
|
||||
raw_ostream &OS,
|
||||
const MCExpr *Subsection) const override;
|
||||
bool UseCodeAlign() const override;
|
||||
bool isVirtualSection() const override;
|
||||
|
||||
bool isUnique() const { return UniqueID != ~0U; }
|
||||
unsigned getUniqueID() const { return UniqueID; }
|
||||
|
||||
static bool classof(const MCSection *S) { return S->getVariant() == SV_Wasm; }
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
@ -44,6 +44,7 @@ class MCInstPrinter;
|
||||
class MCSection;
|
||||
class MCStreamer;
|
||||
class MCSymbolRefExpr;
|
||||
class MCSymbolWasm;
|
||||
class MCSubtargetInfo;
|
||||
class raw_ostream;
|
||||
class Twine;
|
||||
|
@ -48,6 +48,7 @@ protected:
|
||||
SymbolKindCOFF,
|
||||
SymbolKindELF,
|
||||
SymbolKindMachO,
|
||||
SymbolKindWasm,
|
||||
};
|
||||
|
||||
/// A symbol can contain an Offset, or Value, or be Common, but never more
|
||||
@ -100,7 +101,7 @@ protected:
|
||||
|
||||
/// LLVM RTTI discriminator. This is actually a SymbolKind enumerator, but is
|
||||
/// unsigned to avoid sign extension and achieve better bitpacking with MSVC.
|
||||
unsigned Kind : 2;
|
||||
unsigned Kind : 3;
|
||||
|
||||
/// True if we have created a relocation that uses this symbol.
|
||||
mutable unsigned IsUsedInReloc : 1;
|
||||
@ -284,6 +285,8 @@ public:
|
||||
|
||||
bool isMachO() const { return Kind == SymbolKindMachO; }
|
||||
|
||||
bool isWasm() const { return Kind == SymbolKindWasm; }
|
||||
|
||||
/// @}
|
||||
/// \name Variable Symbols
|
||||
/// @{
|
||||
|
24
include/llvm/MC/MCSymbolWasm.h
Normal file
24
include/llvm/MC/MCSymbolWasm.h
Normal file
@ -0,0 +1,24 @@
|
||||
//===- MCSymbolWasm.h - ----------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#ifndef LLVM_MC_MCSYMBOLWASM_H
|
||||
#define LLVM_MC_MCSYMBOLWASM_H
|
||||
|
||||
#include "llvm/MC/MCSymbol.h"
|
||||
|
||||
namespace llvm {
|
||||
class MCSymbolWasm : public MCSymbol {
|
||||
public:
|
||||
MCSymbolWasm(const StringMapEntry<bool> *Name, bool isTemporary)
|
||||
: MCSymbol(SymbolKindWasm, Name, isTemporary) {}
|
||||
|
||||
static bool classof(const MCSymbol *S) { return S->isWasm(); }
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
78
include/llvm/MC/MCWasmObjectWriter.h
Normal file
78
include/llvm/MC/MCWasmObjectWriter.h
Normal file
@ -0,0 +1,78 @@
|
||||
//===-- llvm/MC/MCWasmObjectWriter.h - Wasm Object Writer -------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_MC_MCWASMOBJECTWRITER_H
|
||||
#define LLVM_MC_MCWASMOBJECTWRITER_H
|
||||
|
||||
#include "llvm/ADT/Triple.h"
|
||||
#include "llvm/MC/MCValue.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
class MCAssembler;
|
||||
class MCContext;
|
||||
class MCFixup;
|
||||
class MCFragment;
|
||||
class MCObjectWriter;
|
||||
class MCSymbol;
|
||||
class MCSymbolWasm;
|
||||
class MCValue;
|
||||
class raw_pwrite_stream;
|
||||
|
||||
struct WasmRelocationEntry {
|
||||
uint64_t Offset; // Where is the relocation.
|
||||
const MCSymbolWasm *Symbol; // The symbol to relocate with.
|
||||
unsigned Type; // The type of the relocation.
|
||||
|
||||
WasmRelocationEntry(uint64_t Offset, const MCSymbolWasm *Symbol,
|
||||
unsigned Type)
|
||||
: Offset(Offset), Symbol(Symbol), Type(Type) {}
|
||||
|
||||
void print(raw_ostream &Out) const {
|
||||
Out << "Off=" << Offset << ", Sym=" << Symbol << ", Type=" << Type;
|
||||
}
|
||||
void dump() const { print(errs()); }
|
||||
};
|
||||
|
||||
class MCWasmObjectTargetWriter {
|
||||
const unsigned Is64Bit : 1;
|
||||
|
||||
protected:
|
||||
explicit MCWasmObjectTargetWriter(bool Is64Bit_);
|
||||
|
||||
public:
|
||||
virtual ~MCWasmObjectTargetWriter() {}
|
||||
|
||||
virtual unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
|
||||
const MCFixup &Fixup, bool IsPCRel) const = 0;
|
||||
|
||||
virtual bool needsRelocateWithSymbol(const MCSymbol &Sym,
|
||||
unsigned Type) const;
|
||||
|
||||
virtual void sortRelocs(const MCAssembler &Asm,
|
||||
std::vector<WasmRelocationEntry> &Relocs);
|
||||
|
||||
/// \name Accessors
|
||||
/// @{
|
||||
bool is64Bit() const { return Is64Bit; }
|
||||
/// @}
|
||||
};
|
||||
|
||||
/// \brief Construct a new Wasm writer instance.
|
||||
///
|
||||
/// \param MOTW - The target specific Wasm writer subclass.
|
||||
/// \param OS - The stream to write to.
|
||||
/// \returns The constructed object writer.
|
||||
MCObjectWriter *createWasmObjectWriter(MCWasmObjectTargetWriter *MOTW,
|
||||
raw_pwrite_stream &OS);
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
87
include/llvm/MC/MCWasmStreamer.h
Normal file
87
include/llvm/MC/MCWasmStreamer.h
Normal file
@ -0,0 +1,87 @@
|
||||
//===- MCWasmStreamer.h - MCStreamer Wasm Object File Interface -*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_MC_MCWASMSTREAMER_H
|
||||
#define LLVM_MC_MCWASMSTREAMER_H
|
||||
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/MC/MCDirectives.h"
|
||||
#include "llvm/MC/MCObjectStreamer.h"
|
||||
#include "llvm/MC/SectionKind.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
|
||||
namespace llvm {
|
||||
class MCAsmBackend;
|
||||
class MCAssembler;
|
||||
class MCCodeEmitter;
|
||||
class MCExpr;
|
||||
class MCInst;
|
||||
class raw_ostream;
|
||||
|
||||
class MCWasmStreamer : public MCObjectStreamer {
|
||||
public:
|
||||
MCWasmStreamer(MCContext &Context, MCAsmBackend &TAB, raw_pwrite_stream &OS,
|
||||
MCCodeEmitter *Emitter)
|
||||
: MCObjectStreamer(Context, TAB, OS, Emitter), SeenIdent(false) {}
|
||||
|
||||
~MCWasmStreamer() override;
|
||||
|
||||
/// state management
|
||||
void reset() override {
|
||||
SeenIdent = false;
|
||||
MCObjectStreamer::reset();
|
||||
}
|
||||
|
||||
/// \name MCStreamer Interface
|
||||
/// @{
|
||||
|
||||
void ChangeSection(MCSection *Section, const MCExpr *Subsection) override;
|
||||
void EmitAssemblerFlag(MCAssemblerFlag Flag) override;
|
||||
void EmitThumbFunc(MCSymbol *Func) override;
|
||||
void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) override;
|
||||
bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override;
|
||||
void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override;
|
||||
void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
|
||||
unsigned ByteAlignment) override;
|
||||
void BeginCOFFSymbolDef(const MCSymbol *Symbol) override;
|
||||
void EmitCOFFSymbolStorageClass(int StorageClass) override;
|
||||
void EmitCOFFSymbolType(int Type) override;
|
||||
void EndCOFFSymbolDef() override;
|
||||
|
||||
void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
|
||||
unsigned ByteAlignment) override;
|
||||
|
||||
void EmitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,
|
||||
uint64_t Size = 0, unsigned ByteAlignment = 0) override;
|
||||
void EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size,
|
||||
unsigned ByteAlignment = 0) override;
|
||||
void EmitValueImpl(const MCExpr *Value, unsigned Size,
|
||||
SMLoc Loc = SMLoc()) override;
|
||||
|
||||
void EmitFileDirective(StringRef Filename) override;
|
||||
|
||||
void EmitIdent(StringRef IdentString) override;
|
||||
|
||||
void EmitValueToAlignment(unsigned, int64_t, unsigned, unsigned) override;
|
||||
|
||||
void FinishImpl() override;
|
||||
|
||||
private:
|
||||
void EmitInstToFragment(const MCInst &Inst, const MCSubtargetInfo &) override;
|
||||
void EmitInstToData(const MCInst &Inst, const MCSubtargetInfo &) override;
|
||||
|
||||
/// \brief Merge the content of the fragment \p EF into the fragment \p DF.
|
||||
void mergeFragment(MCDataFragment *, MCDataFragment *);
|
||||
|
||||
bool SeenIdent;
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
@ -68,6 +68,9 @@ MCStreamer *createMachOStreamer(MCContext &Ctx, MCAsmBackend &TAB,
|
||||
raw_pwrite_stream &OS, MCCodeEmitter *CE,
|
||||
bool RelaxAll, bool DWARFMustBeAtTheEnd,
|
||||
bool LabelSections = false);
|
||||
MCStreamer *createWasmStreamer(MCContext &Ctx, MCAsmBackend &TAB,
|
||||
raw_pwrite_stream &OS, MCCodeEmitter *CE,
|
||||
bool RelaxAll);
|
||||
|
||||
MCRelocationInfo *createMCRelocationInfo(const Triple &TT, MCContext &Ctx);
|
||||
|
||||
@ -143,6 +146,11 @@ public:
|
||||
MCCodeEmitter *Emitter,
|
||||
bool RelaxAll,
|
||||
bool IncrementalLinkerCompatible);
|
||||
typedef MCStreamer *(*WasmStreamerCtorTy)(const Triple &T, MCContext &Ctx,
|
||||
MCAsmBackend &TAB,
|
||||
raw_pwrite_stream &OS,
|
||||
MCCodeEmitter *Emitter,
|
||||
bool RelaxAll);
|
||||
typedef MCTargetStreamer *(*NullTargetStreamerCtorTy)(MCStreamer &S);
|
||||
typedef MCTargetStreamer *(*AsmTargetStreamerCtorTy)(
|
||||
MCStreamer &S, formatted_raw_ostream &OS, MCInstPrinter *InstPrint,
|
||||
@ -227,6 +235,7 @@ private:
|
||||
COFFStreamerCtorTy COFFStreamerCtorFn;
|
||||
MachOStreamerCtorTy MachOStreamerCtorFn;
|
||||
ELFStreamerCtorTy ELFStreamerCtorFn;
|
||||
WasmStreamerCtorTy WasmStreamerCtorFn;
|
||||
|
||||
/// Construction function for this target's null TargetStreamer, if
|
||||
/// registered (default = nullptr).
|
||||
@ -251,7 +260,8 @@ private:
|
||||
public:
|
||||
Target()
|
||||
: COFFStreamerCtorFn(nullptr), MachOStreamerCtorFn(nullptr),
|
||||
ELFStreamerCtorFn(nullptr), NullTargetStreamerCtorFn(nullptr),
|
||||
ELFStreamerCtorFn(nullptr), WasmStreamerCtorFn(nullptr),
|
||||
NullTargetStreamerCtorFn(nullptr),
|
||||
AsmTargetStreamerCtorFn(nullptr), ObjectTargetStreamerCtorFn(nullptr),
|
||||
MCRelocationInfoCtorFn(nullptr), MCSymbolizerCtorFn(nullptr) {}
|
||||
|
||||
@ -461,6 +471,12 @@ public:
|
||||
else
|
||||
S = createELFStreamer(Ctx, TAB, OS, Emitter, RelaxAll);
|
||||
break;
|
||||
case Triple::Wasm:
|
||||
if (WasmStreamerCtorFn)
|
||||
S = WasmStreamerCtorFn(T, Ctx, TAB, OS, Emitter, RelaxAll);
|
||||
else
|
||||
S = createWasmStreamer(Ctx, TAB, OS, Emitter, RelaxAll);
|
||||
break;
|
||||
}
|
||||
if (ObjectTargetStreamerCtorFn)
|
||||
ObjectTargetStreamerCtorFn(*S, STI);
|
||||
@ -800,6 +816,10 @@ struct TargetRegistry {
|
||||
T.ELFStreamerCtorFn = Fn;
|
||||
}
|
||||
|
||||
static void RegisterWasmStreamer(Target &T, Target::WasmStreamerCtorTy Fn) {
|
||||
T.WasmStreamerCtorFn = Fn;
|
||||
}
|
||||
|
||||
static void RegisterNullTargetStreamer(Target &T,
|
||||
Target::NullTargetStreamerCtorTy Fn) {
|
||||
T.NullTargetStreamerCtorFn = Fn;
|
||||
|
@ -30,8 +30,10 @@
|
||||
#include "llvm/MC/MCSectionCOFF.h"
|
||||
#include "llvm/MC/MCSectionELF.h"
|
||||
#include "llvm/MC/MCSectionMachO.h"
|
||||
#include "llvm/MC/MCSectionWasm.h"
|
||||
#include "llvm/MC/MCStreamer.h"
|
||||
#include "llvm/MC/MCSymbolELF.h"
|
||||
#include "llvm/MC/MCSymbolWasm.h"
|
||||
#include "llvm/MC/MCValue.h"
|
||||
#include "llvm/ProfileData/InstrProf.h"
|
||||
#include "llvm/Support/COFF.h"
|
||||
@ -1155,3 +1157,53 @@ void TargetLoweringObjectFileCOFF::emitLinkerFlagsForGlobal(
|
||||
raw_ostream &OS, const GlobalValue *GV) const {
|
||||
emitLinkerFlagsForGlobalCOFF(OS, GV, getTargetTriple(), getMangler());
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Wasm
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
MCSection *TargetLoweringObjectFileWasm::getExplicitSectionGlobal(
|
||||
const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
|
||||
llvm_unreachable("getExplicitSectionGlobal not yet implemented");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MCSection *TargetLoweringObjectFileWasm::SelectSectionForGlobal(
|
||||
const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
|
||||
if (Kind.isText())
|
||||
return TextSection;
|
||||
assert(!Kind.isMetadata() && "metadata sections not yet implemented");
|
||||
return DataSection;
|
||||
}
|
||||
|
||||
bool TargetLoweringObjectFileWasm::shouldPutJumpTableInFunctionSection(
|
||||
bool UsesLabelDifference, const Function &F) const {
|
||||
// We can always create relative relocations, so use another section
|
||||
// that can be marked non-executable.
|
||||
return false;
|
||||
}
|
||||
|
||||
const MCExpr *TargetLoweringObjectFileWasm::lowerRelativeReference(
|
||||
const GlobalValue *LHS, const GlobalValue *RHS,
|
||||
const TargetMachine &TM) const {
|
||||
// We may only use a PLT-relative relocation to refer to unnamed_addr
|
||||
// functions.
|
||||
if (!LHS->hasGlobalUnnamedAddr() || !LHS->getValueType()->isFunctionTy())
|
||||
return nullptr;
|
||||
|
||||
// Basic sanity checks.
|
||||
if (LHS->getType()->getPointerAddressSpace() != 0 ||
|
||||
RHS->getType()->getPointerAddressSpace() != 0 || LHS->isThreadLocal() ||
|
||||
RHS->isThreadLocal())
|
||||
return nullptr;
|
||||
|
||||
return MCBinaryExpr::createSub(
|
||||
MCSymbolRefExpr::create(TM.getSymbol(LHS), MCSymbolRefExpr::VK_None,
|
||||
getContext()),
|
||||
MCSymbolRefExpr::create(TM.getSymbol(RHS), getContext()), getContext());
|
||||
}
|
||||
|
||||
void
|
||||
TargetLoweringObjectFileWasm::InitializeWasm() {
|
||||
// TODO: Initialize StaticCtorSection and StaticDtorSection.
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ add_llvm_library(LLVMMC
|
||||
MCAsmInfoCOFF.cpp
|
||||
MCAsmInfoDarwin.cpp
|
||||
MCAsmInfoELF.cpp
|
||||
MCAsmInfoWasm.cpp
|
||||
MCAsmStreamer.cpp
|
||||
MCAssembler.cpp
|
||||
MCCodeEmitter.cpp
|
||||
@ -34,17 +35,21 @@ add_llvm_library(LLVMMC
|
||||
MCSectionCOFF.cpp
|
||||
MCSectionELF.cpp
|
||||
MCSectionMachO.cpp
|
||||
MCSectionWasm.cpp
|
||||
MCStreamer.cpp
|
||||
MCSubtargetInfo.cpp
|
||||
MCSymbol.cpp
|
||||
MCSymbolELF.cpp
|
||||
MCTargetOptions.cpp
|
||||
MCValue.cpp
|
||||
MCWasmObjectTargetWriter.cpp
|
||||
MCWasmStreamer.cpp
|
||||
MCWin64EH.cpp
|
||||
MCWinEH.cpp
|
||||
MachObjectWriter.cpp
|
||||
StringTableBuilder.cpp
|
||||
SubtargetFeature.cpp
|
||||
WasmObjectWriter.cpp
|
||||
WinCOFFObjectWriter.cpp
|
||||
WinCOFFStreamer.cpp
|
||||
|
||||
|
27
lib/MC/MCAsmInfoWasm.cpp
Normal file
27
lib/MC/MCAsmInfoWasm.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
//===-- MCAsmInfoWasm.cpp - Wasm asm properties -----------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines target asm properties related what form asm statements
|
||||
// should take in general on Wasm-based targets
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/MC/MCAsmInfoWasm.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
#include "llvm/MC/MCSectionWasm.h"
|
||||
using namespace llvm;
|
||||
|
||||
void MCAsmInfoWasm::anchor() { }
|
||||
|
||||
MCAsmInfoWasm::MCAsmInfoWasm() {
|
||||
HasIdentDirective = true;
|
||||
WeakRefDirective = "\t.weak\t";
|
||||
PrivateGlobalPrefix = ".L";
|
||||
PrivateLabelPrefix = ".L";
|
||||
}
|
@ -23,11 +23,13 @@
|
||||
#include "llvm/MC/MCSectionCOFF.h"
|
||||
#include "llvm/MC/MCSectionELF.h"
|
||||
#include "llvm/MC/MCSectionMachO.h"
|
||||
#include "llvm/MC/MCSectionWasm.h"
|
||||
#include "llvm/MC/MCStreamer.h"
|
||||
#include "llvm/MC/MCSymbol.h"
|
||||
#include "llvm/MC/MCSymbolCOFF.h"
|
||||
#include "llvm/MC/MCSymbolELF.h"
|
||||
#include "llvm/MC/MCSymbolMachO.h"
|
||||
#include "llvm/MC/MCSymbolWasm.h"
|
||||
#include "llvm/MC/SectionKind.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/COFF.h"
|
||||
@ -154,6 +156,8 @@ MCSymbol *MCContext::createSymbolImpl(const StringMapEntry<bool> *Name,
|
||||
return new (Name, *this) MCSymbolELF(Name, IsTemporary);
|
||||
case MCObjectFileInfo::IsMachO:
|
||||
return new (Name, *this) MCSymbolMachO(Name, IsTemporary);
|
||||
case MCObjectFileInfo::IsWasm:
|
||||
return new (Name, *this) MCSymbolWasm(Name, IsTemporary);
|
||||
}
|
||||
}
|
||||
return new (Name, *this) MCSymbol(MCSymbol::SymbolKindUnset, Name,
|
||||
@ -345,7 +349,7 @@ MCSectionELF *MCContext::createELFRelSection(const Twine &Name, unsigned Type,
|
||||
StringMap<bool>::iterator I;
|
||||
bool Inserted;
|
||||
std::tie(I, Inserted) =
|
||||
ELFRelSecNames.insert(std::make_pair(Name.str(), true));
|
||||
RelSecNames.insert(std::make_pair(Name.str(), true));
|
||||
|
||||
return createELFSectionImpl(I->getKey(), Type, Flags,
|
||||
SectionKind::getReadOnly(), EntrySize, Group,
|
||||
@ -477,6 +481,80 @@ MCSectionCOFF *MCContext::getAssociativeCOFFSection(MCSectionCOFF *Sec,
|
||||
"", 0, UniqueID);
|
||||
}
|
||||
|
||||
void MCContext::renameWasmSection(MCSectionWasm *Section, StringRef Name) {
|
||||
StringRef GroupName;
|
||||
assert(!Section->getGroup() && "not yet implemented");
|
||||
|
||||
unsigned UniqueID = Section->getUniqueID();
|
||||
WasmUniquingMap.erase(
|
||||
WasmSectionKey{Section->getSectionName(), GroupName, UniqueID});
|
||||
auto I = WasmUniquingMap.insert(std::make_pair(
|
||||
WasmSectionKey{Name, GroupName, UniqueID},
|
||||
Section))
|
||||
.first;
|
||||
StringRef CachedName = I->first.SectionName;
|
||||
const_cast<MCSectionWasm *>(Section)->setSectionName(CachedName);
|
||||
}
|
||||
|
||||
MCSectionWasm *MCContext::createWasmRelSection(const Twine &Name, unsigned Type,
|
||||
unsigned Flags,
|
||||
const MCSymbolWasm *Group) {
|
||||
StringMap<bool>::iterator I;
|
||||
bool Inserted;
|
||||
std::tie(I, Inserted) =
|
||||
RelSecNames.insert(std::make_pair(Name.str(), true));
|
||||
|
||||
return new (WasmAllocator.Allocate())
|
||||
MCSectionWasm(I->getKey(), Type, Flags, SectionKind::getReadOnly(),
|
||||
Group, ~0, nullptr);
|
||||
}
|
||||
|
||||
MCSectionWasm *MCContext::getWasmNamedSection(const Twine &Prefix,
|
||||
const Twine &Suffix, unsigned Type,
|
||||
unsigned Flags) {
|
||||
return getWasmSection(Prefix + "." + Suffix, Type, Flags, Suffix);
|
||||
}
|
||||
|
||||
MCSectionWasm *MCContext::getWasmSection(const Twine &Section, unsigned Type,
|
||||
unsigned Flags,
|
||||
const Twine &Group, unsigned UniqueID,
|
||||
const char *BeginSymName) {
|
||||
MCSymbolWasm *GroupSym = nullptr;
|
||||
if (!Group.isTriviallyEmpty() && !Group.str().empty())
|
||||
GroupSym = cast<MCSymbolWasm>(getOrCreateSymbol(Group));
|
||||
|
||||
return getWasmSection(Section, Type, Flags, GroupSym, UniqueID, BeginSymName);
|
||||
}
|
||||
|
||||
MCSectionWasm *MCContext::getWasmSection(const Twine &Section, unsigned Type,
|
||||
unsigned Flags,
|
||||
const MCSymbolWasm *GroupSym,
|
||||
unsigned UniqueID,
|
||||
const char *BeginSymName) {
|
||||
StringRef Group = "";
|
||||
if (GroupSym)
|
||||
Group = GroupSym->getName();
|
||||
// Do the lookup, if we have a hit, return it.
|
||||
auto IterBool = WasmUniquingMap.insert(
|
||||
std::make_pair(WasmSectionKey{Section.str(), Group, UniqueID}, nullptr));
|
||||
auto &Entry = *IterBool.first;
|
||||
if (!IterBool.second)
|
||||
return Entry.second;
|
||||
|
||||
StringRef CachedName = Entry.first.SectionName;
|
||||
|
||||
SectionKind Kind = SectionKind::getText();
|
||||
|
||||
MCSymbol *Begin = nullptr;
|
||||
if (BeginSymName)
|
||||
Begin = createTempSymbol(BeginSymName, false);
|
||||
|
||||
MCSectionWasm *Result = new (WasmAllocator.Allocate())
|
||||
MCSectionWasm(CachedName, Type, Flags, Kind, GroupSym, UniqueID, Begin);
|
||||
Entry.second = Result;
|
||||
return Result;
|
||||
}
|
||||
|
||||
MCSubtargetInfo &MCContext::getSubtargetCopy(const MCSubtargetInfo &STI) {
|
||||
return *new (MCSubtargetAllocator.Allocate()) MCSubtargetInfo(STI);
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "llvm/MC/MCSectionCOFF.h"
|
||||
#include "llvm/MC/MCSectionELF.h"
|
||||
#include "llvm/MC/MCSectionMachO.h"
|
||||
#include "llvm/MC/MCSectionWasm.h"
|
||||
#include "llvm/Support/COFF.h"
|
||||
#include "llvm/Support/ELF.h"
|
||||
|
||||
@ -798,6 +799,30 @@ void MCObjectFileInfo::initCOFFMCObjectFileInfo(const Triple &T) {
|
||||
SectionKind::getReadOnly());
|
||||
}
|
||||
|
||||
void MCObjectFileInfo::initWasmMCObjectFileInfo(const Triple &T) {
|
||||
// TODO: Set the section types and flags.
|
||||
TextSection = Ctx->getWasmSection("", 0, 0);
|
||||
DataSection = Ctx->getWasmSection("", 0, 0);
|
||||
|
||||
// TODO: Set the section types and flags.
|
||||
DwarfLineSection = Ctx->getWasmSection(".debug_line", 0, 0);
|
||||
DwarfStrSection = Ctx->getWasmSection(".debug_str", 0, 0);
|
||||
DwarfLocSection = Ctx->getWasmSection(".debug_loc", 0, 0);
|
||||
DwarfAbbrevSection = Ctx->getWasmSection(".debug_abbrev", 0, 0, "section_abbrev");
|
||||
DwarfARangesSection = Ctx->getWasmSection(".debug_aranges", 0, 0);
|
||||
DwarfRangesSection = Ctx->getWasmSection(".debug_ranges", 0, 0, "debug_range");
|
||||
DwarfMacinfoSection = Ctx->getWasmSection(".debug_macinfo", 0, 0, "debug_macinfo");
|
||||
DwarfAddrSection = Ctx->getWasmSection(".debug_addr", 0, 0);
|
||||
DwarfCUIndexSection = Ctx->getWasmSection(".debug_cu_index", 0, 0);
|
||||
DwarfTUIndexSection = Ctx->getWasmSection(".debug_tu_index", 0, 0);
|
||||
DwarfInfoSection = Ctx->getWasmSection(".debug_info", 0, 0, "section_info");
|
||||
DwarfFrameSection = Ctx->getWasmSection(".debug_frame", 0, 0);
|
||||
DwarfPubNamesSection = Ctx->getWasmSection(".debug_pubnames", 0, 0);
|
||||
DwarfPubTypesSection = Ctx->getWasmSection(".debug_pubtypes", 0, 0);
|
||||
|
||||
// TODO: Define more sections.
|
||||
}
|
||||
|
||||
void MCObjectFileInfo::InitMCObjectFileInfo(const Triple &TheTriple, bool PIC,
|
||||
CodeModel::Model cm,
|
||||
MCContext &ctx) {
|
||||
@ -843,7 +868,8 @@ void MCObjectFileInfo::InitMCObjectFileInfo(const Triple &TheTriple, bool PIC,
|
||||
initELFMCObjectFileInfo(TT);
|
||||
break;
|
||||
case Triple::Wasm:
|
||||
report_fatal_error("Cannot initialize MC for wasm object file format yet.");
|
||||
Env = IsWasm;
|
||||
initWasmMCObjectFileInfo(TT);
|
||||
break;
|
||||
case Triple::UnknownObjectFormat:
|
||||
report_fatal_error("Cannot initialize MC for unknown object file format.");
|
||||
|
@ -596,6 +596,9 @@ AsmParser::AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
|
||||
case MCObjectFileInfo::IsELF:
|
||||
PlatformParser.reset(createELFAsmParser());
|
||||
break;
|
||||
case MCObjectFileInfo::IsWasm:
|
||||
llvm_unreachable("Wasm parsing not supported yet");
|
||||
break;
|
||||
}
|
||||
|
||||
PlatformParser->Initialize(*this);
|
||||
|
97
lib/MC/MCSectionWasm.cpp
Normal file
97
lib/MC/MCSectionWasm.cpp
Normal file
@ -0,0 +1,97 @@
|
||||
//===- lib/MC/MCSectionWasm.cpp - Wasm Code Section Representation --------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/MC/MCSectionWasm.h"
|
||||
#include "llvm/MC/MCAsmInfo.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
#include "llvm/MC/MCSymbol.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
MCSectionWasm::~MCSectionWasm() {} // anchor.
|
||||
|
||||
// Decides whether a '.section' directive
|
||||
// should be printed before the section name.
|
||||
bool MCSectionWasm::ShouldOmitSectionDirective(StringRef Name,
|
||||
const MCAsmInfo &MAI) const {
|
||||
return MAI.shouldOmitSectionDirective(Name);
|
||||
}
|
||||
|
||||
static void printName(raw_ostream &OS, StringRef Name) {
|
||||
if (Name.find_first_not_of("0123456789_."
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ") == Name.npos) {
|
||||
OS << Name;
|
||||
return;
|
||||
}
|
||||
OS << '"';
|
||||
for (const char *B = Name.begin(), *E = Name.end(); B < E; ++B) {
|
||||
if (*B == '"') // Unquoted "
|
||||
OS << "\\\"";
|
||||
else if (*B != '\\') // Neither " or backslash
|
||||
OS << *B;
|
||||
else if (B + 1 == E) // Trailing backslash
|
||||
OS << "\\\\";
|
||||
else {
|
||||
OS << B[0] << B[1]; // Quoted character
|
||||
++B;
|
||||
}
|
||||
}
|
||||
OS << '"';
|
||||
}
|
||||
|
||||
void MCSectionWasm::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
|
||||
raw_ostream &OS,
|
||||
const MCExpr *Subsection) const {
|
||||
|
||||
if (ShouldOmitSectionDirective(SectionName, MAI)) {
|
||||
OS << '\t' << getSectionName();
|
||||
if (Subsection) {
|
||||
OS << '\t';
|
||||
Subsection->print(OS, &MAI);
|
||||
}
|
||||
OS << '\n';
|
||||
return;
|
||||
}
|
||||
|
||||
OS << "\t.section\t";
|
||||
printName(OS, getSectionName());
|
||||
OS << ",\"";
|
||||
|
||||
// TODO: Print section flags.
|
||||
|
||||
OS << '"';
|
||||
|
||||
OS << ',';
|
||||
|
||||
// If comment string is '@', e.g. as on ARM - use '%' instead
|
||||
if (MAI.getCommentString()[0] == '@')
|
||||
OS << '%';
|
||||
else
|
||||
OS << '@';
|
||||
|
||||
// TODO: Print section type.
|
||||
|
||||
if (isUnique())
|
||||
OS << ",unique," << UniqueID;
|
||||
|
||||
OS << '\n';
|
||||
|
||||
if (Subsection) {
|
||||
OS << "\t.subsection\t";
|
||||
Subsection->print(OS, &MAI);
|
||||
OS << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
bool MCSectionWasm::UseCodeAlign() const { return false; }
|
||||
|
||||
bool MCSectionWasm::isVirtualSection() const { return false; }
|
27
lib/MC/MCWasmObjectTargetWriter.cpp
Normal file
27
lib/MC/MCWasmObjectTargetWriter.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
//===-- MCWasmObjectTargetWriter.cpp - Wasm Target Writer Subclass --------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
#include "llvm/MC/MCValue.h"
|
||||
#include "llvm/MC/MCWasmObjectWriter.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
MCWasmObjectTargetWriter::MCWasmObjectTargetWriter(bool Is64Bit_)
|
||||
: Is64Bit(Is64Bit_) {}
|
||||
|
||||
bool MCWasmObjectTargetWriter::needsRelocateWithSymbol(const MCSymbol &Sym,
|
||||
unsigned Type) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
void MCWasmObjectTargetWriter::sortRelocs(
|
||||
const MCAssembler &Asm, std::vector<WasmRelocationEntry> &Relocs) {
|
||||
}
|
203
lib/MC/MCWasmStreamer.cpp
Normal file
203
lib/MC/MCWasmStreamer.cpp
Normal file
@ -0,0 +1,203 @@
|
||||
//===- lib/MC/MCWasmStreamer.cpp - Wasm Object Output ---------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file assembles .s files and emits Wasm .o object files.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/MC/MCWasmStreamer.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/MC/MCAsmBackend.h"
|
||||
#include "llvm/MC/MCAsmInfo.h"
|
||||
#include "llvm/MC/MCAsmLayout.h"
|
||||
#include "llvm/MC/MCAssembler.h"
|
||||
#include "llvm/MC/MCCodeEmitter.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
#include "llvm/MC/MCInst.h"
|
||||
#include "llvm/MC/MCObjectFileInfo.h"
|
||||
#include "llvm/MC/MCObjectStreamer.h"
|
||||
#include "llvm/MC/MCObjectWriter.h"
|
||||
#include "llvm/MC/MCSection.h"
|
||||
#include "llvm/MC/MCSectionWasm.h"
|
||||
#include "llvm/MC/MCSymbol.h"
|
||||
#include "llvm/MC/MCSymbolWasm.h"
|
||||
#include "llvm/MC/MCValue.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/TargetRegistry.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
MCWasmStreamer::~MCWasmStreamer() {}
|
||||
|
||||
void MCWasmStreamer::mergeFragment(MCDataFragment *DF, MCDataFragment *EF) {
|
||||
flushPendingLabels(DF, DF->getContents().size());
|
||||
|
||||
for (unsigned i = 0, e = EF->getFixups().size(); i != e; ++i) {
|
||||
EF->getFixups()[i].setOffset(EF->getFixups()[i].getOffset() +
|
||||
DF->getContents().size());
|
||||
DF->getFixups().push_back(EF->getFixups()[i]);
|
||||
}
|
||||
DF->setHasInstructions(true);
|
||||
DF->getContents().append(EF->getContents().begin(), EF->getContents().end());
|
||||
}
|
||||
|
||||
void MCWasmStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
|
||||
// Let the target do whatever target specific stuff it needs to do.
|
||||
getAssembler().getBackend().handleAssemblerFlag(Flag);
|
||||
|
||||
// Do any generic stuff we need to do.
|
||||
llvm_unreachable("invalid assembler flag!");
|
||||
}
|
||||
|
||||
void MCWasmStreamer::ChangeSection(MCSection *Section,
|
||||
const MCExpr *Subsection) {
|
||||
MCAssembler &Asm = getAssembler();
|
||||
auto *SectionWasm = static_cast<const MCSectionWasm *>(Section);
|
||||
const MCSymbol *Grp = SectionWasm->getGroup();
|
||||
if (Grp)
|
||||
Asm.registerSymbol(*Grp);
|
||||
|
||||
this->MCObjectStreamer::ChangeSection(Section, Subsection);
|
||||
}
|
||||
|
||||
void MCWasmStreamer::EmitWeakReference(MCSymbol *Alias,
|
||||
const MCSymbol *Symbol) {
|
||||
getAssembler().registerSymbol(*Symbol);
|
||||
const MCExpr *Value = MCSymbolRefExpr::create(
|
||||
Symbol, MCSymbolRefExpr::VK_WEAKREF, getContext());
|
||||
Alias->setVariableValue(Value);
|
||||
}
|
||||
|
||||
bool MCWasmStreamer::EmitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) {
|
||||
assert(Attribute != MCSA_IndirectSymbol && "indirect symbols not supported");
|
||||
|
||||
auto *Symbol = cast<MCSymbolWasm>(S);
|
||||
|
||||
// Adding a symbol attribute always introduces the symbol, note that an
|
||||
// important side effect of calling registerSymbol here is to register
|
||||
// the symbol with the assembler.
|
||||
getAssembler().registerSymbol(*Symbol);
|
||||
|
||||
// TODO: Set the symbol binding, type, etc.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MCWasmStreamer::EmitCommonSymbol(MCSymbol *S, uint64_t Size,
|
||||
unsigned ByteAlignment) {
|
||||
llvm_unreachable("Common symbols are not yet implemented for Wasm");
|
||||
}
|
||||
|
||||
void MCWasmStreamer::EmitLocalCommonSymbol(MCSymbol *S, uint64_t Size,
|
||||
unsigned ByteAlignment) {
|
||||
llvm_unreachable("Local common symbols are not yet implemented for Wasm");
|
||||
}
|
||||
|
||||
void MCWasmStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size,
|
||||
SMLoc Loc) {
|
||||
MCObjectStreamer::EmitValueImpl(Value, Size, Loc);
|
||||
}
|
||||
|
||||
void MCWasmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value,
|
||||
unsigned ValueSize,
|
||||
unsigned MaxBytesToEmit) {
|
||||
MCObjectStreamer::EmitValueToAlignment(ByteAlignment, Value, ValueSize,
|
||||
MaxBytesToEmit);
|
||||
}
|
||||
|
||||
// Add a symbol for the file name of this module. They start after the
|
||||
// null symbol and don't count as normal symbol, i.e. a non-STT_FILE symbol
|
||||
// with the same name may appear.
|
||||
void MCWasmStreamer::EmitFileDirective(StringRef Filename) {
|
||||
getAssembler().addFileName(Filename);
|
||||
}
|
||||
|
||||
void MCWasmStreamer::EmitIdent(StringRef IdentString) {
|
||||
llvm_unreachable("Ident sections not yet implemented for wasm");
|
||||
}
|
||||
|
||||
void MCWasmStreamer::EmitInstToFragment(const MCInst &Inst,
|
||||
const MCSubtargetInfo &STI) {
|
||||
this->MCObjectStreamer::EmitInstToFragment(Inst, STI);
|
||||
}
|
||||
|
||||
void MCWasmStreamer::EmitInstToData(const MCInst &Inst,
|
||||
const MCSubtargetInfo &STI) {
|
||||
MCAssembler &Assembler = getAssembler();
|
||||
SmallVector<MCFixup, 4> Fixups;
|
||||
SmallString<256> Code;
|
||||
raw_svector_ostream VecOS(Code);
|
||||
Assembler.getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI);
|
||||
|
||||
// Append the encoded instruction to the current data fragment (or create a
|
||||
// new such fragment if the current fragment is not a data fragment).
|
||||
MCDataFragment *DF = getOrCreateDataFragment();
|
||||
|
||||
// Add the fixups and data.
|
||||
for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
|
||||
Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size());
|
||||
DF->getFixups().push_back(Fixups[i]);
|
||||
}
|
||||
DF->setHasInstructions(true);
|
||||
DF->getContents().append(Code.begin(), Code.end());
|
||||
}
|
||||
|
||||
void MCWasmStreamer::FinishImpl() {
|
||||
EmitFrames(nullptr);
|
||||
|
||||
this->MCObjectStreamer::FinishImpl();
|
||||
}
|
||||
|
||||
MCStreamer *llvm::createWasmStreamer(MCContext &Context, MCAsmBackend &MAB,
|
||||
raw_pwrite_stream &OS, MCCodeEmitter *CE,
|
||||
bool RelaxAll) {
|
||||
MCWasmStreamer *S = new MCWasmStreamer(Context, MAB, OS, CE);
|
||||
if (RelaxAll)
|
||||
S->getAssembler().setRelaxAll(true);
|
||||
return S;
|
||||
}
|
||||
|
||||
void MCWasmStreamer::EmitThumbFunc(MCSymbol *Func) {
|
||||
llvm_unreachable("Generic Wasm doesn't support this directive");
|
||||
}
|
||||
|
||||
void MCWasmStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
|
||||
llvm_unreachable("Wasm doesn't support this directive");
|
||||
}
|
||||
|
||||
void MCWasmStreamer::BeginCOFFSymbolDef(const MCSymbol *Symbol) {
|
||||
llvm_unreachable("Wasm doesn't support this directive");
|
||||
}
|
||||
|
||||
void MCWasmStreamer::EmitCOFFSymbolStorageClass(int StorageClass) {
|
||||
llvm_unreachable("Wasm doesn't support this directive");
|
||||
}
|
||||
|
||||
void MCWasmStreamer::EmitCOFFSymbolType(int Type) {
|
||||
llvm_unreachable("Wasm doesn't support this directive");
|
||||
}
|
||||
|
||||
void MCWasmStreamer::EndCOFFSymbolDef() {
|
||||
llvm_unreachable("Wasm doesn't support this directive");
|
||||
}
|
||||
|
||||
void MCWasmStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol,
|
||||
uint64_t Size, unsigned ByteAlignment) {
|
||||
llvm_unreachable("Wasm doesn't support this directive");
|
||||
}
|
||||
|
||||
void MCWasmStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
|
||||
uint64_t Size, unsigned ByteAlignment) {
|
||||
llvm_unreachable("Wasm doesn't support this directive");
|
||||
}
|
119
lib/MC/WasmObjectWriter.cpp
Normal file
119
lib/MC/WasmObjectWriter.cpp
Normal file
@ -0,0 +1,119 @@
|
||||
//===- lib/MC/WasmObjectWriter.cpp - Wasm File Writer ---------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements Wasm object file writer information.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/MC/MCAsmBackend.h"
|
||||
#include "llvm/MC/MCAsmInfo.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/MCObjectFileInfo.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"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/StringSaver.h"
|
||||
#include <vector>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
#undef DEBUG_TYPE
|
||||
#define DEBUG_TYPE "reloc-info"
|
||||
|
||||
namespace {
|
||||
typedef DenseMap<const MCSectionWasm *, uint32_t> SectionIndexMapTy;
|
||||
|
||||
class WasmObjectWriter : public MCObjectWriter {
|
||||
/// Helper struct for containing some precomputed information on symbols.
|
||||
struct WasmSymbolData {
|
||||
const MCSymbolWasm *Symbol;
|
||||
StringRef Name;
|
||||
|
||||
// Support lexicographic sorting.
|
||||
bool operator<(const WasmSymbolData &RHS) const { return Name < RHS.Name; }
|
||||
};
|
||||
|
||||
/// The target specific Wasm writer instance.
|
||||
std::unique_ptr<MCWasmObjectTargetWriter> TargetObjectWriter;
|
||||
|
||||
// TargetObjectWriter wrappers.
|
||||
bool is64Bit() const { return TargetObjectWriter->is64Bit(); }
|
||||
unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
|
||||
const MCFixup &Fixup, bool IsPCRel) const {
|
||||
return TargetObjectWriter->getRelocType(Ctx, Target, Fixup, IsPCRel);
|
||||
}
|
||||
|
||||
public:
|
||||
WasmObjectWriter(MCWasmObjectTargetWriter *MOTW, raw_pwrite_stream &OS)
|
||||
: MCObjectWriter(OS, /*IsLittleEndian=*/true), TargetObjectWriter(MOTW) {}
|
||||
|
||||
void reset() override {
|
||||
MCObjectWriter::reset();
|
||||
}
|
||||
|
||||
~WasmObjectWriter() override;
|
||||
|
||||
void writeHeader(const MCAssembler &Asm);
|
||||
|
||||
void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
|
||||
const MCFragment *Fragment, const MCFixup &Fixup,
|
||||
MCValue Target, bool &IsPCRel,
|
||||
uint64_t &FixedValue) override;
|
||||
|
||||
void executePostLayoutBinding(MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout) override;
|
||||
|
||||
void writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
WasmObjectWriter::~WasmObjectWriter() {}
|
||||
|
||||
// Emit the Wasm header.
|
||||
void WasmObjectWriter::writeHeader(const MCAssembler &Asm) {
|
||||
// TODO: write the magic cookie and the version.
|
||||
}
|
||||
|
||||
void WasmObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout) {
|
||||
}
|
||||
|
||||
void WasmObjectWriter::recordRelocation(MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout,
|
||||
const MCFragment *Fragment,
|
||||
const MCFixup &Fixup, MCValue Target,
|
||||
bool &IsPCRel, uint64_t &FixedValue) {
|
||||
// TODO: Implement
|
||||
}
|
||||
|
||||
void WasmObjectWriter::writeObject(MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout) {
|
||||
// Write out the Wasm header.
|
||||
writeHeader(Asm);
|
||||
|
||||
// TODO: Write the contents.
|
||||
}
|
||||
|
||||
MCObjectWriter *llvm::createWasmObjectWriter(MCWasmObjectTargetWriter *MOTW,
|
||||
raw_pwrite_stream &OS) {
|
||||
return new WasmObjectWriter(MOTW, OS);
|
||||
}
|
@ -5484,7 +5484,8 @@ bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
|
||||
enum {
|
||||
COFF = (1 << MCObjectFileInfo::IsCOFF),
|
||||
ELF = (1 << MCObjectFileInfo::IsELF),
|
||||
MACHO = (1 << MCObjectFileInfo::IsMachO)
|
||||
MACHO = (1 << MCObjectFileInfo::IsMachO),
|
||||
WASM = (1 << MCObjectFileInfo::IsWasm),
|
||||
};
|
||||
static const struct PrefixEntry {
|
||||
const char *Spelling;
|
||||
@ -5518,6 +5519,9 @@ bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
|
||||
case MCObjectFileInfo::IsCOFF:
|
||||
CurrentFormat = COFF;
|
||||
break;
|
||||
case MCObjectFileInfo::IsWasm:
|
||||
CurrentFormat = WASM;
|
||||
break;
|
||||
}
|
||||
|
||||
if (~Prefix->SupportedFormats & CurrentFormat) {
|
||||
|
@ -5,4 +5,5 @@ add_llvm_library(LLVMWebAssemblyDesc
|
||||
WebAssemblyMCCodeEmitter.cpp
|
||||
WebAssemblyMCTargetDesc.cpp
|
||||
WebAssemblyTargetStreamer.cpp
|
||||
WebAssemblyWasmObjectWriter.cpp
|
||||
)
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "llvm/MC/MCAssembler.h"
|
||||
#include "llvm/MC/MCDirectives.h"
|
||||
#include "llvm/MC/MCELFObjectWriter.h"
|
||||
#include "llvm/MC/MCWasmObjectWriter.h"
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
#include "llvm/MC/MCFixupKindInfo.h"
|
||||
#include "llvm/MC/MCObjectWriter.h"
|
||||
@ -27,6 +28,40 @@
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
class WebAssemblyAsmBackendELF final : public MCAsmBackend {
|
||||
bool Is64Bit;
|
||||
|
||||
public:
|
||||
explicit WebAssemblyAsmBackendELF(bool Is64Bit)
|
||||
: MCAsmBackend(), Is64Bit(Is64Bit) {}
|
||||
~WebAssemblyAsmBackendELF() override {}
|
||||
|
||||
void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize,
|
||||
uint64_t Value, bool IsPCRel) const override;
|
||||
|
||||
MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override;
|
||||
|
||||
// No instruction requires relaxation
|
||||
bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
|
||||
const MCRelaxableFragment *DF,
|
||||
const MCAsmLayout &Layout) const override {
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned getNumFixupKinds() const override {
|
||||
// We currently just use the generic fixups in MCFixup.h and don't have any
|
||||
// target-specific fixups.
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool mayNeedRelaxation(const MCInst &Inst) const override { return false; }
|
||||
|
||||
void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
|
||||
MCInst &Res) const override {}
|
||||
|
||||
bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override;
|
||||
};
|
||||
|
||||
class WebAssemblyAsmBackend final : public MCAsmBackend {
|
||||
bool Is64Bit;
|
||||
|
||||
@ -61,6 +96,41 @@ public:
|
||||
bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override;
|
||||
};
|
||||
|
||||
bool WebAssemblyAsmBackendELF::writeNopData(uint64_t Count,
|
||||
MCObjectWriter *OW) const {
|
||||
for (uint64_t i = 0; i < Count; ++i)
|
||||
OW->write8(WebAssembly::Nop);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void WebAssemblyAsmBackendELF::applyFixup(const MCFixup &Fixup, char *Data,
|
||||
unsigned DataSize, uint64_t Value,
|
||||
bool IsPCRel) const {
|
||||
const MCFixupKindInfo &Info = getFixupKindInfo(Fixup.getKind());
|
||||
assert(Info.Flags == 0 && "WebAssembly does not use MCFixupKindInfo flags");
|
||||
|
||||
unsigned NumBytes = alignTo(Info.TargetSize, 8) / 8;
|
||||
if (Value == 0)
|
||||
return; // Doesn't change encoding.
|
||||
|
||||
// Shift the value into position.
|
||||
Value <<= Info.TargetOffset;
|
||||
|
||||
unsigned Offset = Fixup.getOffset();
|
||||
assert(Offset + NumBytes <= DataSize && "Invalid fixup offset!");
|
||||
|
||||
// For each byte of the fragment that the fixup touches, mask in the
|
||||
// bits from the fixup value.
|
||||
for (unsigned i = 0; i != NumBytes; ++i)
|
||||
Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff);
|
||||
}
|
||||
|
||||
MCObjectWriter *
|
||||
WebAssemblyAsmBackendELF::createObjectWriter(raw_pwrite_stream &OS) const {
|
||||
return createWebAssemblyELFObjectWriter(OS, Is64Bit, 0);
|
||||
}
|
||||
|
||||
bool WebAssemblyAsmBackend::writeNopData(uint64_t Count,
|
||||
MCObjectWriter *OW) const {
|
||||
if (Count == 0)
|
||||
@ -78,7 +148,7 @@ void WebAssemblyAsmBackend::applyFixup(const MCFixup &Fixup, char *Data,
|
||||
const MCFixupKindInfo &Info = getFixupKindInfo(Fixup.getKind());
|
||||
assert(Info.Flags == 0 && "WebAssembly does not use MCFixupKindInfo flags");
|
||||
|
||||
unsigned NumBytes = (Info.TargetSize + 7) / 8;
|
||||
unsigned NumBytes = alignTo(Info.TargetSize, 8) / 8;
|
||||
if (Value == 0)
|
||||
return; // Doesn't change encoding.
|
||||
|
||||
@ -96,10 +166,12 @@ void WebAssemblyAsmBackend::applyFixup(const MCFixup &Fixup, char *Data,
|
||||
|
||||
MCObjectWriter *
|
||||
WebAssemblyAsmBackend::createObjectWriter(raw_pwrite_stream &OS) const {
|
||||
return createWebAssemblyELFObjectWriter(OS, Is64Bit, 0);
|
||||
return createWebAssemblyWasmObjectWriter(OS, Is64Bit);
|
||||
}
|
||||
} // end anonymous namespace
|
||||
|
||||
MCAsmBackend *llvm::createWebAssemblyAsmBackend(const Triple &TT) {
|
||||
if (TT.isOSBinFormatELF())
|
||||
return new WebAssemblyAsmBackendELF(TT.isArch64Bit());
|
||||
return new WebAssemblyAsmBackend(TT.isArch64Bit());
|
||||
}
|
||||
|
@ -19,9 +19,9 @@ using namespace llvm;
|
||||
|
||||
#define DEBUG_TYPE "wasm-mc-asm-info"
|
||||
|
||||
WebAssemblyMCAsmInfo::~WebAssemblyMCAsmInfo() {}
|
||||
WebAssemblyMCAsmInfoELF::~WebAssemblyMCAsmInfoELF() {}
|
||||
|
||||
WebAssemblyMCAsmInfo::WebAssemblyMCAsmInfo(const Triple &T) {
|
||||
WebAssemblyMCAsmInfoELF::WebAssemblyMCAsmInfoELF(const Triple &T) {
|
||||
PointerSize = CalleeSaveStackSlotSize = T.isArch64Bit() ? 8 : 4;
|
||||
|
||||
// TODO: What should MaxInstLength be?
|
||||
@ -51,3 +51,33 @@ WebAssemblyMCAsmInfo::WebAssemblyMCAsmInfo(const Triple &T) {
|
||||
// WebAssembly's stack is never executable.
|
||||
UsesNonexecutableStackSection = false;
|
||||
}
|
||||
|
||||
WebAssemblyMCAsmInfo::~WebAssemblyMCAsmInfo() {}
|
||||
|
||||
WebAssemblyMCAsmInfo::WebAssemblyMCAsmInfo(const Triple &T) {
|
||||
PointerSize = CalleeSaveStackSlotSize = T.isArch64Bit() ? 8 : 4;
|
||||
|
||||
// TODO: What should MaxInstLength be?
|
||||
|
||||
UseDataRegionDirectives = true;
|
||||
|
||||
// Use .skip instead of .zero because .zero is confusing when used with two
|
||||
// arguments (it doesn't actually zero things out).
|
||||
ZeroDirective = "\t.skip\t";
|
||||
|
||||
Data8bitsDirective = "\t.int8\t";
|
||||
Data16bitsDirective = "\t.int16\t";
|
||||
Data32bitsDirective = "\t.int32\t";
|
||||
Data64bitsDirective = "\t.int64\t";
|
||||
|
||||
AlignmentIsInBytes = false;
|
||||
COMMDirectiveAlignmentIsInBytes = false;
|
||||
LCOMMDirectiveAlignmentType = LCOMM::Log2Alignment;
|
||||
|
||||
SupportsDebugInformation = true;
|
||||
|
||||
// For now, WebAssembly does not support exceptions.
|
||||
ExceptionsType = ExceptionHandling::None;
|
||||
|
||||
// TODO: UseIntegratedAssembler?
|
||||
}
|
||||
|
@ -16,12 +16,19 @@
|
||||
#define LLVM_LIB_TARGET_WEBASSEMBLY_MCTARGETDESC_WEBASSEMBLYMCASMINFO_H
|
||||
|
||||
#include "llvm/MC/MCAsmInfoELF.h"
|
||||
#include "llvm/MC/MCAsmInfoWasm.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class Triple;
|
||||
|
||||
class WebAssemblyMCAsmInfo final : public MCAsmInfoELF {
|
||||
class WebAssemblyMCAsmInfoELF final : public MCAsmInfoELF {
|
||||
public:
|
||||
explicit WebAssemblyMCAsmInfoELF(const Triple &T);
|
||||
~WebAssemblyMCAsmInfoELF() override;
|
||||
};
|
||||
|
||||
class WebAssemblyMCAsmInfo final : public MCAsmInfoWasm {
|
||||
public:
|
||||
explicit WebAssemblyMCAsmInfo(const Triple &T);
|
||||
~WebAssemblyMCAsmInfo() override;
|
||||
|
@ -36,6 +36,8 @@ using namespace llvm;
|
||||
|
||||
static MCAsmInfo *createMCAsmInfo(const MCRegisterInfo & /*MRI*/,
|
||||
const Triple &TT) {
|
||||
if (TT.isOSBinFormatELF())
|
||||
return new WebAssemblyMCAsmInfoELF(TT);
|
||||
return new WebAssemblyMCAsmInfo(TT);
|
||||
}
|
||||
|
||||
@ -88,8 +90,12 @@ static MCSubtargetInfo *createMCSubtargetInfo(const Triple &TT, StringRef CPU,
|
||||
}
|
||||
|
||||
static MCTargetStreamer *
|
||||
createObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo & /*STI*/) {
|
||||
return new WebAssemblyTargetELFStreamer(S);
|
||||
createObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) {
|
||||
const Triple &TT = STI.getTargetTriple();
|
||||
if (TT.isOSBinFormatELF())
|
||||
return new WebAssemblyTargetELFStreamer(S);
|
||||
|
||||
return new WebAssemblyTargetWasmStreamer(S);
|
||||
}
|
||||
|
||||
static MCTargetStreamer *createAsmTargetStreamer(MCStreamer &S,
|
||||
|
@ -42,6 +42,9 @@ MCAsmBackend *createWebAssemblyAsmBackend(const Triple &TT);
|
||||
MCObjectWriter *createWebAssemblyELFObjectWriter(raw_pwrite_stream &OS,
|
||||
bool Is64Bit, uint8_t OSABI);
|
||||
|
||||
MCObjectWriter *createWebAssemblyWasmObjectWriter(raw_pwrite_stream &OS,
|
||||
bool Is64Bit);
|
||||
|
||||
namespace WebAssembly {
|
||||
enum OperandType {
|
||||
/// Basic block label in a branch construct.
|
||||
|
@ -18,9 +18,10 @@
|
||||
#include "WebAssemblyMCTargetDesc.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
#include "llvm/MC/MCSectionELF.h"
|
||||
#include "llvm/MC/MCSectionWasm.h"
|
||||
#include "llvm/MC/MCSubtargetInfo.h"
|
||||
#include "llvm/MC/MCSymbolELF.h"
|
||||
#include "llvm/Support/ELF.h"
|
||||
#include "llvm/MC/MCSymbolWasm.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/FormattedStream.h"
|
||||
using namespace llvm;
|
||||
@ -35,6 +36,9 @@ WebAssemblyTargetAsmStreamer::WebAssemblyTargetAsmStreamer(
|
||||
WebAssemblyTargetELFStreamer::WebAssemblyTargetELFStreamer(MCStreamer &S)
|
||||
: WebAssemblyTargetStreamer(S) {}
|
||||
|
||||
WebAssemblyTargetWasmStreamer::WebAssemblyTargetWasmStreamer(MCStreamer &S)
|
||||
: WebAssemblyTargetStreamer(S) {}
|
||||
|
||||
static void PrintTypes(formatted_raw_ostream &OS, ArrayRef<MVT> Types) {
|
||||
bool First = true;
|
||||
for (MVT Type : Types) {
|
||||
@ -117,4 +121,35 @@ void WebAssemblyTargetELFStreamer::emitIndirectFunctionType(
|
||||
}
|
||||
|
||||
void WebAssemblyTargetELFStreamer::emitGlobalImport(StringRef name) {
|
||||
}
|
||||
}
|
||||
|
||||
void WebAssemblyTargetWasmStreamer::emitParam(ArrayRef<MVT> Types) {
|
||||
// Nothing to emit; params are declared as part of the function signature.
|
||||
}
|
||||
|
||||
void WebAssemblyTargetWasmStreamer::emitResult(ArrayRef<MVT> Types) {
|
||||
// Nothing to emit; results are declared as part of the function signature.
|
||||
}
|
||||
|
||||
void WebAssemblyTargetWasmStreamer::emitLocal(ArrayRef<MVT> Types) {
|
||||
Streamer.EmitULEB128IntValue(Types.size());
|
||||
for (MVT Type : Types)
|
||||
Streamer.EmitIntValue(int64_t(WebAssembly::toValType(Type)), 1);
|
||||
}
|
||||
|
||||
void WebAssemblyTargetWasmStreamer::emitEndFunc() {
|
||||
Streamer.EmitIntValue(WebAssembly::End, 1);
|
||||
}
|
||||
|
||||
void WebAssemblyTargetWasmStreamer::emitIndIdx(const MCExpr *Value) {
|
||||
llvm_unreachable(".indidx encoding not yet implemented");
|
||||
}
|
||||
|
||||
void WebAssemblyTargetWasmStreamer::emitIndirectFunctionType(
|
||||
StringRef name, SmallVectorImpl<MVT> &Params, SmallVectorImpl<MVT> &Results) {
|
||||
// Nothing to emit here. TODO: Re-design how linking works and re-evaluate
|
||||
// whether it's necessary for .o files to declare indirect function types.
|
||||
}
|
||||
|
||||
void WebAssemblyTargetWasmStreamer::emitGlobalImport(StringRef name) {
|
||||
}
|
||||
|
@ -22,6 +22,7 @@
|
||||
namespace llvm {
|
||||
|
||||
class MCELFStreamer;
|
||||
class MCWasmStreamer;
|
||||
|
||||
/// WebAssembly-specific streamer interface, to implement support
|
||||
/// WebAssembly-specific assembly directives.
|
||||
@ -83,6 +84,22 @@ public:
|
||||
void emitGlobalImport(StringRef name) override;
|
||||
};
|
||||
|
||||
/// This part is for Wasm object output
|
||||
class WebAssemblyTargetWasmStreamer final : public WebAssemblyTargetStreamer {
|
||||
public:
|
||||
explicit WebAssemblyTargetWasmStreamer(MCStreamer &S);
|
||||
|
||||
void emitParam(ArrayRef<MVT> Types) override;
|
||||
void emitResult(ArrayRef<MVT> Types) override;
|
||||
void emitLocal(ArrayRef<MVT> Types) override;
|
||||
void emitEndFunc() override;
|
||||
void emitIndirectFunctionType(StringRef name,
|
||||
SmallVectorImpl<MVT> &Params,
|
||||
SmallVectorImpl<MVT> &Results) override;
|
||||
void emitIndIdx(const MCExpr *Value) override;
|
||||
void emitGlobalImport(StringRef name) override;
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
|
@ -0,0 +1,48 @@
|
||||
//===-- WebAssemblyWasmObjectWriter.cpp - WebAssembly Wasm Writer ---------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
/// \brief This file handles Wasm-specific object emission, converting LLVM's
|
||||
/// internal fixups into the appropriate relocations.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
|
||||
#include "llvm/MC/MCFixup.h"
|
||||
#include "llvm/MC/MCWasmObjectWriter.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
class WebAssemblyWasmObjectWriter final : public MCWasmObjectTargetWriter {
|
||||
public:
|
||||
explicit WebAssemblyWasmObjectWriter(bool Is64Bit);
|
||||
|
||||
private:
|
||||
unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
|
||||
const MCFixup &Fixup, bool IsPCRel) const override;
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
WebAssemblyWasmObjectWriter::WebAssemblyWasmObjectWriter(bool Is64Bit)
|
||||
: MCWasmObjectTargetWriter(Is64Bit) {}
|
||||
|
||||
unsigned WebAssemblyWasmObjectWriter::getRelocType(MCContext &Ctx,
|
||||
const MCValue &Target,
|
||||
const MCFixup &Fixup,
|
||||
bool IsPCRel) const {
|
||||
llvm_unreachable("Relocations not yet implemented");
|
||||
return 0;
|
||||
}
|
||||
|
||||
MCObjectWriter *llvm::createWebAssemblyWasmObjectWriter(raw_pwrite_stream &OS,
|
||||
bool Is64Bit) {
|
||||
MCWasmObjectTargetWriter *MOTW = new WebAssemblyWasmObjectWriter(Is64Bit);
|
||||
return createWasmObjectWriter(MOTW, OS);
|
||||
}
|
@ -74,7 +74,11 @@ WebAssemblyTargetMachine::WebAssemblyTargetMachine(
|
||||
: "e-m:e-p:32:32-i64:64-n32:64-S128",
|
||||
TT, CPU, FS, Options, getEffectiveRelocModel(RM),
|
||||
CM, OL),
|
||||
TLOF(make_unique<WebAssemblyTargetObjectFile>()) {
|
||||
TLOF(TT.isOSBinFormatELF() ?
|
||||
static_cast<TargetLoweringObjectFile*>(
|
||||
new WebAssemblyTargetObjectFileELF()) :
|
||||
static_cast<TargetLoweringObjectFile*>(
|
||||
new WebAssemblyTargetObjectFile())) {
|
||||
// WebAssembly type-checks instructions, but a noreturn function with a return
|
||||
// type that doesn't match the context will cause a check failure. So we lower
|
||||
// LLVM 'unreachable' to ISD::TRAP and then lower that to WebAssembly's
|
||||
|
@ -17,8 +17,14 @@
|
||||
#include "WebAssemblyTargetMachine.h"
|
||||
using namespace llvm;
|
||||
|
||||
void WebAssemblyTargetObjectFile::Initialize(MCContext &Ctx,
|
||||
const TargetMachine &TM) {
|
||||
void WebAssemblyTargetObjectFileELF::Initialize(MCContext &Ctx,
|
||||
const TargetMachine &TM) {
|
||||
TargetLoweringObjectFileELF::Initialize(Ctx, TM);
|
||||
InitializeELF(TM.Options.UseInitArray);
|
||||
}
|
||||
|
||||
void WebAssemblyTargetObjectFile::Initialize(MCContext &Ctx,
|
||||
const TargetMachine &TM) {
|
||||
TargetLoweringObjectFileWasm::Initialize(Ctx, TM);
|
||||
InitializeWasm();
|
||||
}
|
||||
|
@ -20,7 +20,13 @@
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class WebAssemblyTargetObjectFile final : public TargetLoweringObjectFileELF {
|
||||
class WebAssemblyTargetObjectFileELF final
|
||||
: public TargetLoweringObjectFileELF {
|
||||
public:
|
||||
void Initialize(MCContext &Ctx, const TargetMachine &TM) override;
|
||||
};
|
||||
|
||||
class WebAssemblyTargetObjectFile final : public TargetLoweringObjectFileWasm {
|
||||
public:
|
||||
void Initialize(MCContext &Ctx, const TargetMachine &TM) override;
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user