Index: include/llvm/CodeGen/TargetLoweringObjectFileImpl.h =================================================================== --- include/llvm/CodeGen/TargetLoweringObjectFileImpl.h +++ include/llvm/CodeGen/TargetLoweringObjectFileImpl.h @@ -171,6 +171,28 @@ 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; +}; + } // end namespace llvm #endif Index: include/llvm/MC/MCAsmInfoWasm.h =================================================================== --- include/llvm/MC/MCAsmInfoWasm.h +++ include/llvm/MC/MCAsmInfoWasm.h @@ -1,4 +1,4 @@ -//===-- llvm/MC/MCAsmInfoELF.h - ELF Asm info -------------------*- C++ -*-===// +//===-- llvm/MC/MCAsmInfoWasm.h - Wasm Asm info -------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,22 +7,17 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_MC_MCASMINFOELF_H -#define LLVM_MC_MCASMINFOELF_H +#ifndef LLVM_MC_MCASMINFOWASM_H +#define LLVM_MC_MCASMINFOWASM_H #include "llvm/MC/MCAsmInfo.h" namespace llvm { -class MCAsmInfoELF : public MCAsmInfo { +class MCAsmInfoWasm : public MCAsmInfo { virtual void anchor(); - MCSection *getNonexecutableStackSection(MCContext &Ctx) const final; protected: - /// Targets which have non-executable stacks by default can set this to false - /// to disable the special section which requests a non-executable stack. - bool UsesNonexecutableStackSection; - - MCAsmInfoELF(); + MCAsmInfoWasm(); }; } Index: include/llvm/MC/MCContext.h =================================================================== --- include/llvm/MC/MCContext.h +++ include/llvm/MC/MCContext.h @@ -32,6 +32,7 @@ class MCSection; class MCSymbol; class MCSymbolELF; + class MCSymbolWasm; class MCLabel; struct MCDwarfFile; class MCDwarfLoc; @@ -42,6 +43,7 @@ class MCSectionMachO; class MCSectionELF; class MCSectionCOFF; + class MCSectionWasm; class CodeViewContext; /// Context object for machine code objects. This class owns all of the @@ -78,13 +80,14 @@ SpecificBumpPtrAllocator COFFAllocator; SpecificBumpPtrAllocator ELFAllocator; SpecificBumpPtrAllocator MachOAllocator; + SpecificBumpPtrAllocator WasmAllocator; /// Bindings of names to symbols. SymbolTable Symbols; /// ELF sections can have a corresponding symbol. This maps one to the /// other. - DenseMap SectionSymbols; + DenseMap SectionSymbols; /// A mapping from a local label number and an instance count to a symbol. /// For example, in the assembly @@ -211,10 +214,28 @@ } }; + 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 MachOUniquingMap; std::map ELFUniquingMap; std::map COFFUniquingMap; - StringMap ELFRelSecNames; + std::map WasmUniquingMap; + StringMap RelSecNames; SpecificBumpPtrAllocator MCSubtargetAllocator; @@ -288,6 +309,7 @@ MCSymbol *getOrCreateSymbol(const Twine &Name); MCSymbolELF *getOrCreateSectionSymbol(const MCSectionELF &Section); + MCSymbolWasm *getOrCreateSectionSymbol(const MCSectionWasm &Section); /// Gets a symbol that will be defined to the final stack offset of a local /// variable after codegen. @@ -412,6 +434,56 @@ 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, + const MCSectionWasm *Associated); + + /// 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, + const MCSectionWasm *Associated); + + 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); Index: include/llvm/MC/MCELFStreamer.h =================================================================== --- include/llvm/MC/MCELFStreamer.h +++ include/llvm/MC/MCELFStreamer.h @@ -57,7 +57,7 @@ void EmitCOFFSymbolType(int Type) override; void EndCOFFSymbolDef() override; - void emitELFSize(MCSymbolELF *Symbol, const MCExpr *Value) override; + void emitELFSize(MCSymbol *Symbol, const MCExpr *Value) override; void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) override; Index: include/llvm/MC/MCObjectFileInfo.h =================================================================== --- include/llvm/MC/MCObjectFileInfo.h +++ include/llvm/MC/MCObjectFileInfo.h @@ -129,7 +129,7 @@ /// 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 @@ 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 @@ 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; } Index: include/llvm/MC/MCSection.h =================================================================== --- include/llvm/MC/MCSection.h +++ include/llvm/MC/MCSection.h @@ -39,7 +39,7 @@ /// 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 { Index: include/llvm/MC/MCSectionWasm.h =================================================================== --- include/llvm/MC/MCSectionWasm.h +++ include/llvm/MC/MCSectionWasm.h @@ -1,4 +1,4 @@ -//===- MCSectionELF.h - ELF Machine Code Sections ---------------*- C++ -*-===// +//===- MCSectionWasm.h - Wasm Machine Code Sections -------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,18 +7,17 @@ // //===----------------------------------------------------------------------===// // -// This file declares the MCSectionELF class. +// This file declares the MCSectionWasm class. // //===----------------------------------------------------------------------===// -#ifndef LLVM_MC_MCSECTIONELF_H -#define LLVM_MC_MCSECTIONELF_H +#ifndef LLVM_MC_MCSECTIONWASM_H +#define LLVM_MC_MCSECTIONWASM_H #include "llvm/ADT/Twine.h" #include "llvm/MC/MCSection.h" -#include "llvm/MC/MCSymbolELF.h" +#include "llvm/MC/MCSymbolWasm.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/ELF.h" #include "llvm/Support/raw_ostream.h" namespace llvm { @@ -27,9 +26,9 @@ /// This represents a section on linux, lots of unix variants and some bare /// metal systems. -class MCSectionELF final : public MCSection { +class MCSectionWasm final : public MCSection { /// This is the name of the section. The referenced memory is owned by - /// TargetLoweringObjectFileELF's ELFUniqueMap. + /// TargetLoweringObjectFileWasm's WasmUniqueMap. StringRef SectionName; /// This is the sh_type field of a section, drawn from the enums below. @@ -40,32 +39,24 @@ unsigned UniqueID; - /// The size of each entry in this section. This size only makes sense for - /// sections that contain fixed-sized entries. If a section does not contain - /// fixed-sized entries 'EntrySize' will be 0. - unsigned EntrySize; - - const MCSymbolELF *Group; + const MCSymbolWasm *Group; /// Depending on the type of the section this is sh_link or sh_info. - const MCSectionELF *Associated; + const MCSectionWasm *Associated; private: friend class MCContext; - MCSectionELF(StringRef Section, unsigned type, unsigned flags, SectionKind K, - unsigned entrySize, const MCSymbolELF *group, unsigned UniqueID, - MCSymbol *Begin, const MCSectionELF *Associated) - : MCSection(SV_ELF, K, Begin), SectionName(Section), Type(type), - Flags(flags), UniqueID(UniqueID), EntrySize(entrySize), Group(group), - Associated(Associated) { - if (Group) - Group->setIsSignature(); + MCSectionWasm(StringRef Section, unsigned type, unsigned flags, SectionKind K, + const MCSymbolWasm *group, unsigned UniqueID, + MCSymbol *Begin, const MCSectionWasm *Associated) + : MCSection(SV_Wasm, K, Begin), SectionName(Section), Type(type), + Flags(flags), UniqueID(UniqueID), Group(group), Associated(Associated) { } void setSectionName(StringRef Name) { SectionName = Name; } public: - ~MCSectionELF(); + ~MCSectionWasm(); /// Decides whether a '.section' directive should be printed before the /// section name @@ -74,9 +65,8 @@ StringRef getSectionName() const { return SectionName; } unsigned getType() const { return Type; } unsigned getFlags() const { return Flags; } - unsigned getEntrySize() const { return EntrySize; } void setFlags(unsigned F) { Flags = F; } - const MCSymbolELF *getGroup() const { return Group; } + const MCSymbolWasm *getGroup() const { return Group; } void PrintSwitchToSection(const MCAsmInfo &MAI, raw_ostream &OS, const MCExpr *Subsection) const override; @@ -86,10 +76,10 @@ bool isUnique() const { return UniqueID != ~0U; } unsigned getUniqueID() const { return UniqueID; } - const MCSectionELF *getAssociatedSection() const { return Associated; } + const MCSectionWasm *getAssociatedSection() const { return Associated; } static bool classof(const MCSection *S) { - return S->getVariant() == SV_ELF; + return S->getVariant() == SV_Wasm; } }; Index: include/llvm/MC/MCStreamer.h =================================================================== --- include/llvm/MC/MCStreamer.h +++ include/llvm/MC/MCStreamer.h @@ -36,12 +36,15 @@ class MCStreamer; class MCSymbolELF; class MCSymbolRefExpr; +class MCSymbolWasm; class MCSubtargetInfo; class StringRef; class Twine; class raw_ostream; class formatted_raw_ostream; class AssemblerConstantPools; +class GlobalValue; +struct WasmSignature; typedef std::pair MCSectionSubPair; @@ -476,7 +479,14 @@ /// /// This corresponds to an assembler statement such as: /// .size symbol, expression - virtual void emitELFSize(MCSymbolELF *Symbol, const MCExpr *Value); + virtual void emitELFSize(MCSymbol *Symbol, const MCExpr *Value); + + /// \brief Emit a Wasm .signature directive. + /// + /// This corresponds to an assembler statement such as: + /// .signature symbol, signature + virtual void emitWasmSignature(MCSymbolWasm *Symbol, + const WasmSignature &Signature); /// \brief Emit a Linker Optimization Hint (LOH) directive. /// \param Args - Arguments of the LOH. Index: include/llvm/MC/MCSymbol.h =================================================================== --- include/llvm/MC/MCSymbol.h +++ include/llvm/MC/MCSymbol.h @@ -45,6 +45,7 @@ SymbolKindCOFF, SymbolKindELF, SymbolKindMachO, + SymbolKindWasm, }; /// A symbol can contain an Offset, or Value, or be Common, but never more @@ -97,7 +98,7 @@ /// 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; @@ -281,6 +282,8 @@ bool isMachO() const { return Kind == SymbolKindMachO; } + bool isWasm() const { return Kind == SymbolKindWasm; } + /// @} /// \name Variable Symbols /// @{ Index: include/llvm/MC/MCSymbolWasm.h =================================================================== --- include/llvm/MC/MCSymbolWasm.h +++ include/llvm/MC/MCSymbolWasm.h @@ -1,4 +1,4 @@ -//===- MCSymbolELF.h - -----------------------------------------*- C++ -*-===// +//===- MCSymbolWasm.h - ----------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -6,45 +6,18 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -#ifndef LLVM_MC_MCSYMBOLELF_H -#define LLVM_MC_MCSYMBOLELF_H +#ifndef LLVM_MC_MCSYMBOLWASM_H +#define LLVM_MC_MCSYMBOLWASM_H #include "llvm/MC/MCSymbol.h" namespace llvm { -class MCSymbolELF : public MCSymbol { - /// An expression describing how to calculate the size of a symbol. If a - /// symbol has no size this field will be NULL. - const MCExpr *SymbolSize = nullptr; - +class MCSymbolWasm : public MCSymbol { public: - MCSymbolELF(const StringMapEntry *Name, bool isTemporary) - : MCSymbol(SymbolKindELF, Name, isTemporary) {} - void setSize(const MCExpr *SS) { SymbolSize = SS; } - - const MCExpr *getSize() const { return SymbolSize; } - - void setVisibility(unsigned Visibility); - unsigned getVisibility() const; - - void setOther(unsigned Other); - unsigned getOther() const; - - void setType(unsigned Type) const; - unsigned getType() const; - - void setBinding(unsigned Binding) const; - unsigned getBinding() const; - - bool isBindingSet() const; - - void setIsWeakrefUsedInReloc() const; - bool isWeakrefUsedInReloc() const; - - void setIsSignature() const; - bool isSignature() const; + MCSymbolWasm(const StringMapEntry *Name, bool isTemporary) + : MCSymbol(SymbolKindWasm, Name, isTemporary) {} - static bool classof(const MCSymbol *S) { return S->isELF(); } + static bool classof(const MCSymbol *S) { return S->isWasm(); } private: void setIsBindingSet() const; Index: include/llvm/MC/MCWasmObjectWriter.h =================================================================== --- include/llvm/MC/MCWasmObjectWriter.h +++ include/llvm/MC/MCWasmObjectWriter.h @@ -1,4 +1,4 @@ -//===-- llvm/MC/MCELFObjectWriter.h - ELF Object Writer ---------*- C++ -*-===// +//===-- llvm/MC/MCWasmObjectWriter.h - Wasm Object Writer -------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,13 +7,12 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_MC_MCELFOBJECTWRITER_H -#define LLVM_MC_MCELFOBJECTWRITER_H +#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/ELF.h" #include "llvm/Support/raw_ostream.h" #include @@ -24,21 +23,21 @@ class MCFragment; class MCObjectWriter; class MCSymbol; -class MCSymbolELF; +class MCSymbolWasm; class MCValue; class raw_pwrite_stream; -struct ELFRelocationEntry { +struct WasmRelocationEntry { uint64_t Offset; // Where is the relocation. - const MCSymbolELF *Symbol; // The symbol to relocate with. + const MCSymbolWasm *Symbol; // The symbol to relocate with. unsigned Type; // The type of the relocation. uint64_t Addend; // The addend to use. - const MCSymbolELF *OriginalSymbol; // The original value of Symbol if we changed it. + const MCSymbolWasm *OriginalSymbol; // The original value of Symbol if we changed it. uint64_t OriginalAddend; // The original value of addend. - ELFRelocationEntry(uint64_t Offset, const MCSymbolELF *Symbol, unsigned Type, - uint64_t Addend, const MCSymbolELF *OriginalSymbol, - uint64_t OriginalAddend) + WasmRelocationEntry(uint64_t Offset, const MCSymbolWasm *Symbol, unsigned Type, + uint64_t Addend, const MCSymbolWasm *OriginalSymbol, + uint64_t OriginalAddend) : Offset(Offset), Symbol(Symbol), Type(Type), Addend(Addend), OriginalSymbol(OriginalSymbol), OriginalAddend(OriginalAddend) {} @@ -50,33 +49,15 @@ void dump() const { print(errs()); } }; -class MCELFObjectTargetWriter { - const uint8_t OSABI; - const uint16_t EMachine; - const unsigned HasRelocationAddend : 1; +class MCWasmObjectTargetWriter { const unsigned Is64Bit : 1; - const unsigned IsN64 : 1; protected: - MCELFObjectTargetWriter(bool Is64Bit_, uint8_t OSABI_, - uint16_t EMachine_, bool HasRelocationAddend, - bool IsN64=false); + explicit MCWasmObjectTargetWriter(bool Is64Bit_); public: - static uint8_t getOSABI(Triple::OSType OSType) { - switch (OSType) { - case Triple::CloudABI: - return ELF::ELFOSABI_CLOUDABI; - case Triple::PS4: - case Triple::FreeBSD: - return ELF::ELFOSABI_FREEBSD; - default: - return ELF::ELFOSABI_NONE; - } - } - - virtual ~MCELFObjectTargetWriter() {} + virtual ~MCWasmObjectTargetWriter() {} virtual unsigned getRelocType(MCContext &Ctx, const MCValue &Target, const MCFixup &Fixup, bool IsPCRel) const = 0; @@ -85,15 +66,11 @@ unsigned Type) const; virtual void sortRelocs(const MCAssembler &Asm, - std::vector &Relocs); + std::vector &Relocs); /// \name Accessors /// @{ - uint8_t getOSABI() const { return OSABI; } - uint16_t getEMachine() const { return EMachine; } - bool hasRelocationAddend() const { return HasRelocationAddend; } bool is64Bit() const { return Is64Bit; } - bool isN64() const { return IsN64; } /// @} // Instead of changing everyone's API we pack the N64 Type fields @@ -136,14 +113,13 @@ } }; -/// \brief Construct a new ELF writer instance. +/// \brief Construct a new Wasm writer instance. /// -/// \param MOTW - The target specific ELF writer subclass. +/// \param MOTW - The target specific Wasm writer subclass. /// \param OS - The stream to write to. /// \returns The constructed object writer. -MCObjectWriter *createELFObjectWriter(MCELFObjectTargetWriter *MOTW, - raw_pwrite_stream &OS, - bool IsLittleEndian); +MCObjectWriter *createWasmObjectWriter(MCWasmObjectTargetWriter *MOTW, + raw_pwrite_stream &OS); } // End llvm namespace #endif Index: include/llvm/MC/MCWasmStreamer.h =================================================================== --- include/llvm/MC/MCWasmStreamer.h +++ include/llvm/MC/MCWasmStreamer.h @@ -1,4 +1,4 @@ -//===- MCELFStreamer.h - MCStreamer ELF Object File Interface ---*- C++ -*-===// +//===- MCWasmStreamer.h - MCStreamer Wasm Object File Interface -*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_MC_MCELFSTREAMER_H -#define LLVM_MC_MCELFSTREAMER_H +#ifndef LLVM_MC_MCWASMSTREAMER_H +#define LLVM_MC_MCWASMSTREAMER_H #include "llvm/ADT/SmallPtrSet.h" #include "llvm/MC/MCDirectives.h" @@ -24,18 +24,17 @@ class MCInst; class raw_ostream; -class MCELFStreamer : public MCObjectStreamer { +class MCWasmStreamer : public MCObjectStreamer { public: - MCELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_pwrite_stream &OS, - MCCodeEmitter *Emitter) + MCWasmStreamer(MCContext &Context, MCAsmBackend &TAB, raw_pwrite_stream &OS, + MCCodeEmitter *Emitter) : MCObjectStreamer(Context, TAB, OS, Emitter), SeenIdent(false) {} - ~MCELFStreamer() override; + ~MCWasmStreamer() override; /// state management void reset() override { SeenIdent = false; - BundleGroups.clear(); MCObjectStreamer::reset(); } @@ -44,7 +43,6 @@ void InitSections(bool NoExecStack) override; void ChangeSection(MCSection *Section, const MCExpr *Subsection) override; - void EmitLabel(MCSymbol *Symbol) override; void EmitAssemblerFlag(MCAssemblerFlag Flag) override; void EmitThumbFunc(MCSymbol *Func) override; void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) override; @@ -57,8 +55,6 @@ void EmitCOFFSymbolType(int Type) override; void EndCOFFSymbolDef() override; - void emitELFSize(MCSymbolELF *Symbol, const MCExpr *Value) override; - void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) override; @@ -77,32 +73,16 @@ void FinishImpl() override; - void EmitBundleAlignMode(unsigned AlignPow2) override; - void EmitBundleLock(bool AlignToEnd) override; - void EmitBundleUnlock() override; - private: - bool isBundleLocked() const; void EmitInstToFragment(const MCInst &Inst, const MCSubtargetInfo &) override; void EmitInstToData(const MCInst &Inst, const MCSubtargetInfo &) override; - void fixSymbolsInTLSFixups(const MCExpr *expr); - /// \brief Merge the content of the fragment \p EF into the fragment \p DF. void mergeFragment(MCDataFragment *, MCDataFragment *); bool SeenIdent; - - /// BundleGroups - The stack of fragments holding the bundle-locked - /// instructions. - llvm::SmallVector BundleGroups; }; -MCELFStreamer *createARMELFStreamer(MCContext &Context, MCAsmBackend &TAB, - raw_pwrite_stream &OS, - MCCodeEmitter *Emitter, bool RelaxAll, - bool IsThumb); - } // end namespace llvm #endif Index: include/llvm/Support/TargetRegistry.h =================================================================== --- include/llvm/Support/TargetRegistry.h +++ include/llvm/Support/TargetRegistry.h @@ -68,6 +68,9 @@ 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 @@ 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 @@ COFFStreamerCtorTy COFFStreamerCtorFn; MachOStreamerCtorTy MachOStreamerCtorFn; ELFStreamerCtorTy ELFStreamerCtorFn; + WasmStreamerCtorTy WasmStreamerCtorFn; /// Construction function for this target's null TargetStreamer, if /// registered (default = nullptr). @@ -251,7 +260,8 @@ 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 @@ 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 @@ 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; Index: lib/CodeGen/AsmPrinter/AsmPrinter.cpp =================================================================== --- lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -526,7 +526,7 @@ if (MAI->hasDotTypeDotSizeDirective()) // .size foo, 42 - OutStreamer->emitELFSize(cast(EmittedInitSym), + OutStreamer->emitELFSize(EmittedInitSym, MCConstantExpr::create(Size, OutContext)); OutStreamer->AddBlankLine(); @@ -949,8 +949,7 @@ const MCExpr *SizeExp = MCBinaryExpr::createSub( MCSymbolRefExpr::create(CurrentFnEnd, OutContext), MCSymbolRefExpr::create(CurrentFnSymForSize, OutContext), OutContext); - if (auto Sym = dyn_cast(CurrentFnSym)) - OutStreamer->emitELFSize(Sym, SizeExp); + OutStreamer->emitELFSize(CurrentFnSym, SizeExp); } for (const HandlerInfo &HI : Handlers) { @@ -1090,7 +1089,7 @@ (!BaseObject || BaseObject->hasPrivateLinkage())) { const DataLayout &DL = M.getDataLayout(); uint64_t Size = DL.getTypeAllocSize(GA->getValueType()); - OutStreamer->emitELFSize(cast(Name), + OutStreamer->emitELFSize(Name, MCConstantExpr::create(Size, OutContext)); } } Index: lib/CodeGen/TargetLoweringObjectFileImpl.cpp =================================================================== --- lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -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" @@ -1147,3 +1149,55 @@ OS << ",data"; } } + +//===----------------------------------------------------------------------===// +// 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, getMangler()), + MCSymbolRefExpr::VK_None, + getContext()), + MCSymbolRefExpr::create(TM.getSymbol(RHS, getMangler()), getContext()), + getContext()); +} + +void +TargetLoweringObjectFileWasm::InitializeWasm() { + // TODO: Initialize StaticCtorSection and StaticDtorSection. +} Index: lib/MC/CMakeLists.txt =================================================================== --- lib/MC/CMakeLists.txt +++ lib/MC/CMakeLists.txt @@ -6,6 +6,7 @@ MCAsmInfoCOFF.cpp MCAsmInfoDarwin.cpp MCAsmInfoELF.cpp + MCAsmInfoWasm.cpp MCAsmStreamer.cpp MCAssembler.cpp MCCodeEmitter.cpp @@ -34,17 +35,21 @@ 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 Index: lib/MC/MCAsmInfoWasm.cpp =================================================================== --- lib/MC/MCAsmInfoWasm.cpp +++ lib/MC/MCAsmInfoWasm.cpp @@ -1,4 +1,4 @@ -//===-- MCAsmInfoELF.cpp - ELF asm properties -------------------*- C++ -*-===// +//===-- MCAsmInfoWasm.cpp - Wasm asm properties -----------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -8,28 +8,20 @@ //===----------------------------------------------------------------------===// // // This file defines target asm properties related what form asm statements -// should take in general on ELF-based targets +// should take in general on Wasm-based targets // //===----------------------------------------------------------------------===// -#include "llvm/MC/MCAsmInfoELF.h" +#include "llvm/MC/MCAsmInfoWasm.h" #include "llvm/MC/MCContext.h" -#include "llvm/MC/MCSectionELF.h" -#include "llvm/Support/ELF.h" +#include "llvm/MC/MCSectionWasm.h" using namespace llvm; -void MCAsmInfoELF::anchor() { } +void MCAsmInfoWasm::anchor() { } -MCSection *MCAsmInfoELF::getNonexecutableStackSection(MCContext &Ctx) const { - if (!UsesNonexecutableStackSection) - return nullptr; - return Ctx.getELFSection(".note.GNU-stack", ELF::SHT_PROGBITS, 0); -} - -MCAsmInfoELF::MCAsmInfoELF() { +MCAsmInfoWasm::MCAsmInfoWasm() { HasIdentDirective = true; WeakRefDirective = "\t.weak\t"; PrivateGlobalPrefix = ".L"; PrivateLabelPrefix = ".L"; - UsesNonexecutableStackSection = true; } Index: lib/MC/MCAsmStreamer.cpp =================================================================== --- lib/MC/MCAsmStreamer.cpp +++ lib/MC/MCAsmStreamer.cpp @@ -151,7 +151,7 @@ void EmitCOFFSafeSEH(MCSymbol const *Symbol) override; void EmitCOFFSectionIndex(MCSymbol const *Symbol) override; void EmitCOFFSecRel32(MCSymbol const *Symbol) override; - void emitELFSize(MCSymbolELF *Symbol, const MCExpr *Value) override; + void emitELFSize(MCSymbol *Symbol, const MCExpr *Value) override; void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) override; @@ -620,7 +620,7 @@ EmitEOL(); } -void MCAsmStreamer::emitELFSize(MCSymbolELF *Symbol, const MCExpr *Value) { +void MCAsmStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) { assert(MAI->hasDotTypeDotSizeDirective()); OS << "\t.size\t"; Symbol->print(OS, MAI); Index: lib/MC/MCContext.cpp =================================================================== --- lib/MC/MCContext.cpp +++ lib/MC/MCContext.cpp @@ -20,10 +20,12 @@ #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/MCSymbolCOFF.h" #include "llvm/MC/MCSymbolELF.h" #include "llvm/MC/MCSymbolMachO.h" +#include "llvm/MC/MCSymbolWasm.h" #include "llvm/Support/COFF.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ELF.h" @@ -125,15 +127,27 @@ } MCSymbolELF *MCContext::getOrCreateSectionSymbol(const MCSectionELF &Section) { - MCSymbolELF *&Sym = SectionSymbols[&Section]; + MCSymbol *&Sym = SectionSymbols[&Section]; if (Sym) - return Sym; + return cast(Sym); StringRef Name = Section.getSectionName(); auto NameIter = UsedNames.insert(std::make_pair(Name, false)).first; Sym = new (&*NameIter, *this) MCSymbolELF(&*NameIter, /*isTemporary*/ false); - return Sym; + return cast(Sym); +} + +MCSymbolWasm *MCContext::getOrCreateSectionSymbol(const MCSectionWasm &Section) { + MCSymbol *&Sym = SectionSymbols[&Section]; + if (Sym) + return cast(Sym); + + StringRef Name = Section.getSectionName(); + auto NameIter = UsedNames.insert(std::make_pair(Name, false)).first; + Sym = new (&*NameIter, *this) MCSymbolWasm(&*NameIter, /*isTemporary*/ false); + + return cast(Sym); } MCSymbol *MCContext::getOrCreateFrameAllocSymbol(StringRef FuncName, @@ -162,6 +176,8 @@ 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, @@ -316,7 +332,7 @@ StringMap::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 new (ELFAllocator.Allocate()) MCSectionELF(I->getKey(), Type, Flags, SectionKind::getReadOnly(), @@ -453,6 +469,84 @@ "", 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(Section)->setSectionName(CachedName); +} + +MCSectionWasm *MCContext::createWasmRelSection(const Twine &Name, unsigned Type, + unsigned Flags, + const MCSymbolWasm *Group, + const MCSectionWasm *Associated) { + StringMap::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, Associated); +} + +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(getOrCreateSymbol(Group)); + + return getWasmSection(Section, Type, Flags, GroupSym, UniqueID, BeginSymName, + nullptr); +} + +MCSectionWasm *MCContext::getWasmSection(const Twine &Section, unsigned Type, + unsigned Flags, + const MCSymbolWasm *GroupSym, + unsigned UniqueID, + const char *BeginSymName, + const MCSectionWasm *Associated) { + 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, Associated); + Entry.second = Result; + return Result; +} + MCSubtargetInfo &MCContext::getSubtargetCopy(const MCSubtargetInfo &STI) { return *new (MCSubtargetAllocator.Allocate()) MCSubtargetInfo(STI); } Index: lib/MC/MCELFStreamer.cpp =================================================================== --- lib/MC/MCELFStreamer.cpp +++ lib/MC/MCELFStreamer.cpp @@ -329,8 +329,8 @@ ->setSize(MCConstantExpr::create(Size, getContext())); } -void MCELFStreamer::emitELFSize(MCSymbolELF *Symbol, const MCExpr *Value) { - Symbol->setSize(Value); +void MCELFStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) { + cast(Symbol)->setSize(Value); } void MCELFStreamer::EmitLocalCommonSymbol(MCSymbol *S, uint64_t Size, Index: lib/MC/MCObjectFileInfo.cpp =================================================================== --- lib/MC/MCObjectFileInfo.cpp +++ lib/MC/MCObjectFileInfo.cpp @@ -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" using namespace llvm; @@ -799,6 +800,30 @@ 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,6 +868,10 @@ Env = IsELF; initELFMCObjectFileInfo(TT); break; + case Triple::Wasm: + Env = IsWasm; + initWasmMCObjectFileInfo(TT); + break; case Triple::UnknownObjectFormat: report_fatal_error("Cannot initialize MC for unknown object file format."); break; Index: lib/MC/MCSectionWasm.cpp =================================================================== --- lib/MC/MCSectionWasm.cpp +++ lib/MC/MCSectionWasm.cpp @@ -1,4 +1,4 @@ -//===- lib/MC/MCSectionELF.cpp - ELF Code Section Representation ----------===// +//===- lib/MC/MCSectionWasm.cpp - Wasm Code Section Representation --------===// // // The LLVM Compiler Infrastructure // @@ -7,26 +7,21 @@ // //===----------------------------------------------------------------------===// -#include "llvm/MC/MCSectionELF.h" +#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/ELF.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; -MCSectionELF::~MCSectionELF() {} // anchor. +MCSectionWasm::~MCSectionWasm() {} // anchor. // Decides whether a '.section' directive // should be printed before the section name. -bool MCSectionELF::ShouldOmitSectionDirective(StringRef Name, - const MCAsmInfo &MAI) const { - - if (isUnique()) - return false; - +bool MCSectionWasm::ShouldOmitSectionDirective(StringRef Name, + const MCAsmInfo &MAI) const { return MAI.shouldOmitSectionDirective(Name); } @@ -53,9 +48,9 @@ OS << '"'; } -void MCSectionELF::PrintSwitchToSection(const MCAsmInfo &MAI, - raw_ostream &OS, - const MCExpr *Subsection) const { +void MCSectionWasm::PrintSwitchToSection(const MCAsmInfo &MAI, + raw_ostream &OS, + const MCExpr *Subsection) const { if (ShouldOmitSectionDirective(SectionName, MAI)) { OS << '\t' << getSectionName(); @@ -69,47 +64,9 @@ OS << "\t.section\t"; printName(OS, getSectionName()); - - // Handle the weird solaris syntax if desired. - if (MAI.usesSunStyleELFSectionSwitchSyntax() && - !(Flags & ELF::SHF_MERGE)) { - if (Flags & ELF::SHF_ALLOC) - OS << ",#alloc"; - if (Flags & ELF::SHF_EXECINSTR) - OS << ",#execinstr"; - if (Flags & ELF::SHF_WRITE) - OS << ",#write"; - if (Flags & ELF::SHF_EXCLUDE) - OS << ",#exclude"; - if (Flags & ELF::SHF_TLS) - OS << ",#tls"; - OS << '\n'; - return; - } - OS << ",\""; - if (Flags & ELF::SHF_ALLOC) - OS << 'a'; - if (Flags & ELF::SHF_EXCLUDE) - OS << 'e'; - if (Flags & ELF::SHF_EXECINSTR) - OS << 'x'; - if (Flags & ELF::SHF_GROUP) - OS << 'G'; - if (Flags & ELF::SHF_WRITE) - OS << 'w'; - if (Flags & ELF::SHF_MERGE) - OS << 'M'; - if (Flags & ELF::SHF_STRINGS) - OS << 'S'; - if (Flags & ELF::SHF_TLS) - OS << 'T'; - - // If there are target-specific flags, print them. - if (Flags & ELF::XCORE_SHF_CP_SECTION) - OS << 'c'; - if (Flags & ELF::XCORE_SHF_DP_SECTION) - OS << 'd'; + + // TODO: Print section flags. OS << '"'; @@ -121,31 +78,7 @@ else OS << '@'; - if (Type == ELF::SHT_INIT_ARRAY) - OS << "init_array"; - else if (Type == ELF::SHT_FINI_ARRAY) - OS << "fini_array"; - else if (Type == ELF::SHT_PREINIT_ARRAY) - OS << "preinit_array"; - else if (Type == ELF::SHT_NOBITS) - OS << "nobits"; - else if (Type == ELF::SHT_NOTE) - OS << "note"; - else if (Type == ELF::SHT_PROGBITS) - OS << "progbits"; - else if (Type == ELF::SHT_X86_64_UNWIND) - OS << "unwind"; - - if (EntrySize) { - assert(Flags & ELF::SHF_MERGE); - OS << "," << EntrySize; - } - - if (Flags & ELF::SHF_GROUP) { - OS << ","; - printName(OS, Group->getName()); - OS << ",comdat"; - } + // TODO: Print section type. if (isUnique()) OS << ",unique," << UniqueID; @@ -159,10 +92,10 @@ } } -bool MCSectionELF::UseCodeAlign() const { - return getFlags() & ELF::SHF_EXECINSTR; +bool MCSectionWasm::UseCodeAlign() const { + return false; } -bool MCSectionELF::isVirtualSection() const { - return getType() == ELF::SHT_NOBITS; +bool MCSectionWasm::isVirtualSection() const { + return false; } Index: lib/MC/MCStreamer.cpp =================================================================== --- lib/MC/MCStreamer.cpp +++ lib/MC/MCStreamer.cpp @@ -805,7 +805,8 @@ void MCStreamer::EmitFileDirective(StringRef Filename) {} void MCStreamer::EmitCOFFSymbolStorageClass(int StorageClass) {} void MCStreamer::EmitCOFFSymbolType(int Type) {} -void MCStreamer::emitELFSize(MCSymbolELF *Symbol, const MCExpr *Value) {} +void MCStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {} +void MCStreamer::emitWasmSignature(MCSymbolWasm *Symbol, const WasmSignature &Signature) {} void MCStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) {} void MCStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, Index: lib/MC/MCWasmObjectTargetWriter.cpp =================================================================== --- lib/MC/MCWasmObjectTargetWriter.cpp +++ lib/MC/MCWasmObjectTargetWriter.cpp @@ -1,4 +1,4 @@ -//===-- MCELFObjectTargetWriter.cpp - ELF Target Writer Subclass ----------===// +//===-- MCWasmObjectTargetWriter.cpp - Wasm Target Writer Subclass ----------===// // // The LLVM Compiler Infrastructure // @@ -8,28 +8,22 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/STLExtras.h" -#include "llvm/MC/MCELFObjectWriter.h" +#include "llvm/MC/MCWasmObjectWriter.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCValue.h" using namespace llvm; -MCELFObjectTargetWriter::MCELFObjectTargetWriter(bool Is64Bit_, - uint8_t OSABI_, - uint16_t EMachine_, - bool HasRelocationAddend_, - bool IsN64_) - : OSABI(OSABI_), EMachine(EMachine_), - HasRelocationAddend(HasRelocationAddend_), Is64Bit(Is64Bit_), - IsN64(IsN64_){ +MCWasmObjectTargetWriter::MCWasmObjectTargetWriter(bool Is64Bit_) + : Is64Bit(Is64Bit_) { } -bool MCELFObjectTargetWriter::needsRelocateWithSymbol(const MCSymbol &Sym, - unsigned Type) const { +bool MCWasmObjectTargetWriter::needsRelocateWithSymbol(const MCSymbol &Sym, + unsigned Type) const { return false; } void -MCELFObjectTargetWriter::sortRelocs(const MCAssembler &Asm, - std::vector &Relocs) { +MCWasmObjectTargetWriter::sortRelocs(const MCAssembler &Asm, + std::vector &Relocs) { } Index: lib/MC/MCWasmStreamer.cpp =================================================================== --- lib/MC/MCWasmStreamer.cpp +++ lib/MC/MCWasmStreamer.cpp @@ -1,4 +1,4 @@ -//===- lib/MC/MCELFStreamer.cpp - ELF Object Output -----------------------===// +//===- lib/MC/MCWasmStreamer.cpp - Wasm Object Output ---------------------===// // // The LLVM Compiler Infrastructure // @@ -7,11 +7,11 @@ // //===----------------------------------------------------------------------===// // -// This file assembles .s files and emits ELF .o object files. +// This file assembles .s files and emits Wasm .o object files. // //===----------------------------------------------------------------------===// -#include "llvm/MC/MCELFStreamer.h" +#include "llvm/MC/MCWasmStreamer.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/MC/MCAsmBackend.h" @@ -26,55 +26,22 @@ #include "llvm/MC/MCObjectStreamer.h" #include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCSection.h" -#include "llvm/MC/MCSectionELF.h" -#include "llvm/MC/MCSymbolELF.h" +#include "llvm/MC/MCSectionWasm.h" +#include "llvm/MC/MCSymbolWasm.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCValue.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/ELF.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; -bool MCELFStreamer::isBundleLocked() const { - return getCurrentSectionOnly()->isBundleLocked(); +MCWasmStreamer::~MCWasmStreamer() { } -MCELFStreamer::~MCELFStreamer() { -} - -void MCELFStreamer::mergeFragment(MCDataFragment *DF, - MCDataFragment *EF) { - MCAssembler &Assembler = getAssembler(); - - if (Assembler.isBundlingEnabled() && Assembler.getRelaxAll()) { - uint64_t FSize = EF->getContents().size(); - - if (FSize > Assembler.getBundleAlignSize()) - report_fatal_error("Fragment can't be larger than a bundle size"); - - uint64_t RequiredBundlePadding = computeBundlePadding( - Assembler, EF, DF->getContents().size(), FSize); - - if (RequiredBundlePadding > UINT8_MAX) - report_fatal_error("Padding cannot exceed 255 bytes"); - - if (RequiredBundlePadding > 0) { - SmallString<256> Code; - raw_svector_ostream VecOS(Code); - MCObjectWriter *OW = Assembler.getBackend().createObjectWriter(VecOS); - - EF->setBundlePadding(static_cast(RequiredBundlePadding)); - - Assembler.writeFragmentPadding(*EF, FSize, OW); - delete OW; - - DF->getContents().append(Code.begin(), Code.end()); - } - } - +void MCWasmStreamer::mergeFragment(MCDataFragment *DF, + MCDataFragment *EF) { flushPendingLabels(DF, DF->getContents().size()); for (unsigned i = 0, e = EF->getFixups().size(); i != e; ++i) { @@ -86,28 +53,12 @@ DF->getContents().append(EF->getContents().begin(), EF->getContents().end()); } -void MCELFStreamer::InitSections(bool NoExecStack) { +void MCWasmStreamer::InitSections(bool /*NoExecStack*/) { MCContext &Ctx = getContext(); SwitchSection(Ctx.getObjectFileInfo()->getTextSection()); - EmitCodeAlignment(4); - - if (NoExecStack) - SwitchSection(Ctx.getAsmInfo()->getNonexecutableStackSection(Ctx)); } -void MCELFStreamer::EmitLabel(MCSymbol *S) { - auto *Symbol = cast(S); - assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); - - MCObjectStreamer::EmitLabel(Symbol); - - const MCSectionELF &Section = - static_cast(*getCurrentSectionOnly()); - if (Section.getFlags() & ELF::SHF_TLS) - Symbol->setType(ELF::STT_TLS); -} - -void MCELFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { +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. @@ -124,70 +75,34 @@ llvm_unreachable("invalid assembler flag!"); } -// If bundle alignment is used and there are any instructions in the section, it -// needs to be aligned to at least the bundle size. -static void setSectionAlignmentForBundling(const MCAssembler &Assembler, - MCSection *Section) { - if (Section && Assembler.isBundlingEnabled() && Section->hasInstructions() && - Section->getAlignment() < Assembler.getBundleAlignSize()) - Section->setAlignment(Assembler.getBundleAlignSize()); -} - -void MCELFStreamer::ChangeSection(MCSection *Section, - const MCExpr *Subsection) { - MCSection *CurSection = getCurrentSectionOnly(); - if (CurSection && isBundleLocked()) - report_fatal_error("Unterminated .bundle_lock when changing a section"); - +void MCWasmStreamer::ChangeSection(MCSection *Section, + const MCExpr *Subsection) { MCAssembler &Asm = getAssembler(); - // Ensure the previous section gets aligned if necessary. - setSectionAlignmentForBundling(Asm, CurSection); - auto *SectionELF = static_cast(Section); - const MCSymbol *Grp = SectionELF->getGroup(); + auto *SectionWasm = static_cast(Section); + const MCSymbol *Grp = SectionWasm->getGroup(); if (Grp) Asm.registerSymbol(*Grp); this->MCObjectStreamer::ChangeSection(Section, Subsection); MCContext &Ctx = getContext(); - auto *Begin = cast_or_null(Section->getBeginSymbol()); + auto *Begin = cast_or_null(Section->getBeginSymbol()); if (!Begin) { - Begin = Ctx.getOrCreateSectionSymbol(*SectionELF); + Begin = Ctx.getOrCreateSectionSymbol(*SectionWasm); Section->setBeginSymbol(Begin); } - if (Begin->isUndefined()) { + if (Begin->isUndefined()) Asm.registerSymbol(*Begin); - Begin->setType(ELF::STT_SECTION); - } } -void MCELFStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) { +void MCWasmStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) { getAssembler().registerSymbol(*Symbol); const MCExpr *Value = MCSymbolRefExpr::create( Symbol, MCSymbolRefExpr::VK_WEAKREF, getContext()); Alias->setVariableValue(Value); } -// When GNU as encounters more than one .type declaration for an object it seems -// to use a mechanism similar to the one below to decide which type is actually -// used in the object file. The greater of T1 and T2 is selected based on the -// following ordering: -// STT_NOTYPE < STT_OBJECT < STT_FUNC < STT_GNU_IFUNC < STT_TLS < anything else -// If neither T1 < T2 nor T2 < T1 according to this ordering, use T2 (the user -// provided type). -static unsigned CombineSymbolTypes(unsigned T1, unsigned T2) { - for (unsigned Type : {ELF::STT_NOTYPE, ELF::STT_OBJECT, ELF::STT_FUNC, - ELF::STT_GNU_IFUNC, ELF::STT_TLS}) { - if (T1 == Type) - return T2; - if (T2 == Type) - return T1; - } - - return T2; -} - -bool MCELFStreamer::EmitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) { - auto *Symbol = cast(S); +bool MCWasmStreamer::EmitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) { + auto *Symbol = cast(S); // Indirect symbols are handled differently, to match how 'as' handles // them. This makes writing matching .o files easier. if (Attribute == MCSA_IndirectSymbol) { @@ -205,158 +120,30 @@ // the symbol with the assembler. getAssembler().registerSymbol(*Symbol); - // The implementation of symbol attributes is designed to match 'as', but it - // leaves much to desired. It doesn't really make sense to arbitrarily add and - // remove flags, but 'as' allows this (in particular, see .desc). - // - // In the future it might be worth trying to make these operations more well - // defined. - switch (Attribute) { - case MCSA_LazyReference: - case MCSA_Reference: - case MCSA_SymbolResolver: - case MCSA_PrivateExtern: - case MCSA_WeakDefinition: - case MCSA_WeakDefAutoPrivate: - case MCSA_Invalid: - case MCSA_IndirectSymbol: - return false; - - case MCSA_NoDeadStrip: - // Ignore for now. - break; - - case MCSA_ELF_TypeGnuUniqueObject: - Symbol->setType(CombineSymbolTypes(Symbol->getType(), ELF::STT_OBJECT)); - Symbol->setBinding(ELF::STB_GNU_UNIQUE); - Symbol->setExternal(true); - break; - - case MCSA_Global: - Symbol->setBinding(ELF::STB_GLOBAL); - Symbol->setExternal(true); - break; - - case MCSA_WeakReference: - case MCSA_Weak: - Symbol->setBinding(ELF::STB_WEAK); - Symbol->setExternal(true); - break; - - case MCSA_Local: - Symbol->setBinding(ELF::STB_LOCAL); - Symbol->setExternal(false); - break; - - case MCSA_ELF_TypeFunction: - Symbol->setType(CombineSymbolTypes(Symbol->getType(), ELF::STT_FUNC)); - break; - - case MCSA_ELF_TypeIndFunction: - Symbol->setType(CombineSymbolTypes(Symbol->getType(), ELF::STT_GNU_IFUNC)); - break; - - case MCSA_ELF_TypeObject: - Symbol->setType(CombineSymbolTypes(Symbol->getType(), ELF::STT_OBJECT)); - break; - - case MCSA_ELF_TypeTLS: - Symbol->setType(CombineSymbolTypes(Symbol->getType(), ELF::STT_TLS)); - break; - - case MCSA_ELF_TypeCommon: - // TODO: Emit these as a common symbol. - Symbol->setType(CombineSymbolTypes(Symbol->getType(), ELF::STT_OBJECT)); - break; - - case MCSA_ELF_TypeNoType: - Symbol->setType(CombineSymbolTypes(Symbol->getType(), ELF::STT_NOTYPE)); - break; - - case MCSA_Protected: - Symbol->setVisibility(ELF::STV_PROTECTED); - break; - - case MCSA_Hidden: - Symbol->setVisibility(ELF::STV_HIDDEN); - break; - - case MCSA_Internal: - Symbol->setVisibility(ELF::STV_INTERNAL); - break; - - case MCSA_AltEntry: - llvm_unreachable("ELF doesn't support the .alt_entry attribute"); - } + // TODO: Set the symbol binding, type, etc. return true; } -void MCELFStreamer::EmitCommonSymbol(MCSymbol *S, uint64_t Size, - unsigned ByteAlignment) { - auto *Symbol = cast(S); - getAssembler().registerSymbol(*Symbol); - - if (!Symbol->isBindingSet()) { - Symbol->setBinding(ELF::STB_GLOBAL); - Symbol->setExternal(true); - } - - Symbol->setType(ELF::STT_OBJECT); - - if (Symbol->getBinding() == ELF::STB_LOCAL) { - MCSection &Section = *getAssembler().getContext().getELFSection( - ".bss", ELF::SHT_NOBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC); - MCSectionSubPair P = getCurrentSection(); - SwitchSection(&Section); - - EmitValueToAlignment(ByteAlignment, 0, 1, 0); - EmitLabel(Symbol); - EmitZeros(Size); - - // Update the maximum alignment of the section if necessary. - if (ByteAlignment > Section.getAlignment()) - Section.setAlignment(ByteAlignment); - - SwitchSection(P.first, P.second); - } else { - if(Symbol->declareCommon(Size, ByteAlignment)) - report_fatal_error("Symbol: " + Symbol->getName() + - " redeclared as different type"); - } - - cast(Symbol) - ->setSize(MCConstantExpr::create(Size, getContext())); +void MCWasmStreamer::EmitCommonSymbol(MCSymbol *S, uint64_t Size, + unsigned ByteAlignment) { + llvm_unreachable("Common symbols are not yet implemented for Wasm"); } -void MCELFStreamer::emitELFSize(MCSymbolELF *Symbol, const MCExpr *Value) { - Symbol->setSize(Value); +void MCWasmStreamer::EmitLocalCommonSymbol(MCSymbol *S, uint64_t Size, + unsigned ByteAlignment) { + llvm_unreachable("Local common symbols are not yet implemented for Wasm"); } -void MCELFStreamer::EmitLocalCommonSymbol(MCSymbol *S, uint64_t Size, - unsigned ByteAlignment) { - auto *Symbol = cast(S); - // FIXME: Should this be caught and done earlier? - getAssembler().registerSymbol(*Symbol); - Symbol->setBinding(ELF::STB_LOCAL); - Symbol->setExternal(false); - EmitCommonSymbol(Symbol, Size, ByteAlignment); -} - -void MCELFStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, - SMLoc Loc) { - if (isBundleLocked()) - report_fatal_error("Emitting values inside a locked bundle is forbidden"); - fixSymbolsInTLSFixups(Value); +void MCWasmStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, + SMLoc Loc) { MCObjectStreamer::EmitValueImpl(Value, Size, Loc); } -void MCELFStreamer::EmitValueToAlignment(unsigned ByteAlignment, - int64_t Value, - unsigned ValueSize, - unsigned MaxBytesToEmit) { - if (isBundleLocked()) - report_fatal_error("Emitting values inside a locked bundle is forbidden"); +void MCWasmStreamer::EmitValueToAlignment(unsigned ByteAlignment, + int64_t Value, + unsigned ValueSize, + unsigned MaxBytesToEmit) { MCObjectStreamer::EmitValueToAlignment(ByteAlignment, Value, ValueSize, MaxBytesToEmit); } @@ -364,180 +151,30 @@ // 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 MCELFStreamer::EmitFileDirective(StringRef Filename) { +void MCWasmStreamer::EmitFileDirective(StringRef Filename) { getAssembler().addFileName(Filename); } -void MCELFStreamer::EmitIdent(StringRef IdentString) { - MCSection *Comment = getAssembler().getContext().getELFSection( - ".comment", ELF::SHT_PROGBITS, ELF::SHF_MERGE | ELF::SHF_STRINGS, 1, ""); - PushSection(); - SwitchSection(Comment); - if (!SeenIdent) { - EmitIntValue(0, 1); - SeenIdent = true; - } - EmitBytes(IdentString); - EmitIntValue(0, 1); - PopSection(); -} - -void MCELFStreamer::fixSymbolsInTLSFixups(const MCExpr *expr) { - switch (expr->getKind()) { - case MCExpr::Target: - cast(expr)->fixELFSymbolsInTLSFixups(getAssembler()); - break; - case MCExpr::Constant: - break; - - case MCExpr::Binary: { - const MCBinaryExpr *be = cast(expr); - fixSymbolsInTLSFixups(be->getLHS()); - fixSymbolsInTLSFixups(be->getRHS()); - break; - } - - case MCExpr::SymbolRef: { - const MCSymbolRefExpr &symRef = *cast(expr); - switch (symRef.getKind()) { - default: - return; - case MCSymbolRefExpr::VK_GOTTPOFF: - case MCSymbolRefExpr::VK_INDNTPOFF: - case MCSymbolRefExpr::VK_NTPOFF: - case MCSymbolRefExpr::VK_GOTNTPOFF: - case MCSymbolRefExpr::VK_TLSGD: - case MCSymbolRefExpr::VK_TLSLD: - case MCSymbolRefExpr::VK_TLSLDM: - case MCSymbolRefExpr::VK_TPOFF: - case MCSymbolRefExpr::VK_TPREL: - case MCSymbolRefExpr::VK_DTPOFF: - case MCSymbolRefExpr::VK_DTPREL: - case MCSymbolRefExpr::VK_PPC_DTPMOD: - case MCSymbolRefExpr::VK_PPC_TPREL_LO: - case MCSymbolRefExpr::VK_PPC_TPREL_HI: - case MCSymbolRefExpr::VK_PPC_TPREL_HA: - case MCSymbolRefExpr::VK_PPC_TPREL_HIGHER: - case MCSymbolRefExpr::VK_PPC_TPREL_HIGHERA: - case MCSymbolRefExpr::VK_PPC_TPREL_HIGHEST: - case MCSymbolRefExpr::VK_PPC_TPREL_HIGHESTA: - case MCSymbolRefExpr::VK_PPC_DTPREL_LO: - case MCSymbolRefExpr::VK_PPC_DTPREL_HI: - case MCSymbolRefExpr::VK_PPC_DTPREL_HA: - case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHER: - case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHERA: - case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHEST: - case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHESTA: - case MCSymbolRefExpr::VK_PPC_GOT_TPREL: - case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO: - case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HI: - case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HA: - case MCSymbolRefExpr::VK_PPC_GOT_DTPREL: - case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO: - case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HI: - case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HA: - case MCSymbolRefExpr::VK_PPC_TLS: - case MCSymbolRefExpr::VK_PPC_GOT_TLSGD: - case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_LO: - case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HI: - case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HA: - case MCSymbolRefExpr::VK_PPC_TLSGD: - case MCSymbolRefExpr::VK_PPC_GOT_TLSLD: - case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO: - case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HI: - case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HA: - case MCSymbolRefExpr::VK_PPC_TLSLD: - break; - } - getAssembler().registerSymbol(symRef.getSymbol()); - cast(symRef.getSymbol()).setType(ELF::STT_TLS); - break; - } - - case MCExpr::Unary: - fixSymbolsInTLSFixups(cast(expr)->getSubExpr()); - break; - } +void MCWasmStreamer::EmitIdent(StringRef IdentString) { + llvm_unreachable("Ident sections not yet implemented for wasm"); } -void MCELFStreamer::EmitInstToFragment(const MCInst &Inst, - const MCSubtargetInfo &STI) { +void MCWasmStreamer::EmitInstToFragment(const MCInst &Inst, + const MCSubtargetInfo &STI) { this->MCObjectStreamer::EmitInstToFragment(Inst, STI); - MCRelaxableFragment &F = *cast(getCurrentFragment()); - - for (unsigned i = 0, e = F.getFixups().size(); i != e; ++i) - fixSymbolsInTLSFixups(F.getFixups()[i].getValue()); } -void MCELFStreamer::EmitInstToData(const MCInst &Inst, - const MCSubtargetInfo &STI) { +void MCWasmStreamer::EmitInstToData(const MCInst &Inst, + const MCSubtargetInfo &STI) { MCAssembler &Assembler = getAssembler(); SmallVector Fixups; SmallString<256> Code; raw_svector_ostream VecOS(Code); Assembler.getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI); - for (unsigned i = 0, e = Fixups.size(); i != e; ++i) - fixSymbolsInTLSFixups(Fixups[i].getValue()); - - // There are several possibilities here: - // - // If bundling is disabled, append the encoded instruction to the current data - // fragment (or create a new such fragment if the current fragment is not a - // data fragment). - // - // If bundling is enabled: - // - If we're not in a bundle-locked group, emit the instruction into a - // fragment of its own. If there are no fixups registered for the - // instruction, emit a MCCompactEncodedInstFragment. Otherwise, emit a - // MCDataFragment. - // - If we're in a bundle-locked group, append the instruction to the current - // data fragment because we want all the instructions in a group to get into - // the same fragment. Be careful not to do that for the first instruction in - // the group, though. - MCDataFragment *DF; - - if (Assembler.isBundlingEnabled()) { - MCSection &Sec = *getCurrentSectionOnly(); - if (Assembler.getRelaxAll() && isBundleLocked()) - // If the -mc-relax-all flag is used and we are bundle-locked, we re-use - // the current bundle group. - DF = BundleGroups.back(); - else if (Assembler.getRelaxAll() && !isBundleLocked()) - // When not in a bundle-locked group and the -mc-relax-all flag is used, - // we create a new temporary fragment which will be later merged into - // the current fragment. - DF = new MCDataFragment(); - else if (isBundleLocked() && !Sec.isBundleGroupBeforeFirstInst()) - // If we are bundle-locked, we re-use the current fragment. - // The bundle-locking directive ensures this is a new data fragment. - DF = cast(getCurrentFragment()); - else if (!isBundleLocked() && Fixups.size() == 0) { - // Optimize memory usage by emitting the instruction to a - // MCCompactEncodedInstFragment when not in a bundle-locked group and - // there are no fixups registered. - MCCompactEncodedInstFragment *CEIF = new MCCompactEncodedInstFragment(); - insert(CEIF); - CEIF->getContents().append(Code.begin(), Code.end()); - return; - } else { - DF = new MCDataFragment(); - insert(DF); - } - if (Sec.getBundleLockState() == MCSection::BundleLockedAlignToEnd) { - // If this fragment is for a group marked "align_to_end", set a flag - // in the fragment. This can happen after the fragment has already been - // created if there are nested bundle_align groups and an inner one - // is the one marked align_to_end. - DF->setAlignToBundleEnd(true); - } - - // We're now emitting an instruction in a bundle group, so this flag has - // to be turned off. - Sec.setBundleGroupBeforeFirstInst(false); - } else { - DF = getOrCreateDataFragment(); - } + // 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) { @@ -546,129 +183,53 @@ } DF->setHasInstructions(true); DF->getContents().append(Code.begin(), Code.end()); - - if (Assembler.isBundlingEnabled() && Assembler.getRelaxAll()) { - if (!isBundleLocked()) { - mergeFragment(getOrCreateDataFragment(), DF); - delete DF; - } - } } -void MCELFStreamer::EmitBundleAlignMode(unsigned AlignPow2) { - assert(AlignPow2 <= 30 && "Invalid bundle alignment"); - MCAssembler &Assembler = getAssembler(); - if (AlignPow2 > 0 && (Assembler.getBundleAlignSize() == 0 || - Assembler.getBundleAlignSize() == 1U << AlignPow2)) - Assembler.setBundleAlignSize(1U << AlignPow2); - else - report_fatal_error(".bundle_align_mode cannot be changed once set"); -} - -void MCELFStreamer::EmitBundleLock(bool AlignToEnd) { - MCSection &Sec = *getCurrentSectionOnly(); - - // Sanity checks - // - if (!getAssembler().isBundlingEnabled()) - report_fatal_error(".bundle_lock forbidden when bundling is disabled"); - - if (!isBundleLocked()) - Sec.setBundleGroupBeforeFirstInst(true); - - if (getAssembler().getRelaxAll() && !isBundleLocked()) { - // TODO: drop the lock state and set directly in the fragment - MCDataFragment *DF = new MCDataFragment(); - BundleGroups.push_back(DF); - } - - Sec.setBundleLockState(AlignToEnd ? MCSection::BundleLockedAlignToEnd - : MCSection::BundleLocked); -} - -void MCELFStreamer::EmitBundleUnlock() { - MCSection &Sec = *getCurrentSectionOnly(); - - // Sanity checks - if (!getAssembler().isBundlingEnabled()) - report_fatal_error(".bundle_unlock forbidden when bundling is disabled"); - else if (!isBundleLocked()) - report_fatal_error(".bundle_unlock without matching lock"); - else if (Sec.isBundleGroupBeforeFirstInst()) - report_fatal_error("Empty bundle-locked group is forbidden"); - - // When the -mc-relax-all flag is used, we emit instructions to fragments - // stored on a stack. When the bundle unlock is emitted, we pop a fragment - // from the stack a merge it to the one below. - if (getAssembler().getRelaxAll()) { - assert(!BundleGroups.empty() && "There are no bundle groups"); - MCDataFragment *DF = BundleGroups.back(); - - // FIXME: Use BundleGroups to track the lock state instead. - Sec.setBundleLockState(MCSection::NotBundleLocked); - - // FIXME: Use more separate fragments for nested groups. - if (!isBundleLocked()) { - mergeFragment(getOrCreateDataFragment(), DF); - BundleGroups.pop_back(); - delete DF; - } - - if (Sec.getBundleLockState() != MCSection::BundleLockedAlignToEnd) - getOrCreateDataFragment()->setAlignToBundleEnd(false); - } else - Sec.setBundleLockState(MCSection::NotBundleLocked); -} - -void MCELFStreamer::FinishImpl() { - // Ensure the last section gets aligned if necessary. - MCSection *CurSection = getCurrentSectionOnly(); - setSectionAlignmentForBundling(getAssembler(), CurSection); - +void MCWasmStreamer::FinishImpl() { EmitFrames(nullptr); this->MCObjectStreamer::FinishImpl(); } -MCStreamer *llvm::createELFStreamer(MCContext &Context, MCAsmBackend &MAB, - raw_pwrite_stream &OS, MCCodeEmitter *CE, - bool RelaxAll) { - MCELFStreamer *S = new MCELFStreamer(Context, MAB, OS, CE); +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 MCELFStreamer::EmitThumbFunc(MCSymbol *Func) { - llvm_unreachable("Generic ELF doesn't support this directive"); +void MCWasmStreamer::EmitThumbFunc(MCSymbol *Func) { + llvm_unreachable("Generic Wasm doesn't support this directive"); } -void MCELFStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { - llvm_unreachable("ELF doesn't support this directive"); +void MCWasmStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { + llvm_unreachable("Wasm doesn't support this directive"); } -void MCELFStreamer::BeginCOFFSymbolDef(const MCSymbol *Symbol) { - llvm_unreachable("ELF doesn't support this directive"); +void MCWasmStreamer::BeginCOFFSymbolDef(const MCSymbol *Symbol) { + llvm_unreachable("Wasm doesn't support this directive"); } -void MCELFStreamer::EmitCOFFSymbolStorageClass(int StorageClass) { - llvm_unreachable("ELF doesn't support this directive"); +void MCWasmStreamer::EmitCOFFSymbolStorageClass(int StorageClass) { + llvm_unreachable("Wasm doesn't support this directive"); } -void MCELFStreamer::EmitCOFFSymbolType(int Type) { - llvm_unreachable("ELF doesn't support this directive"); +void MCWasmStreamer::EmitCOFFSymbolType(int Type) { + llvm_unreachable("Wasm doesn't support this directive"); } -void MCELFStreamer::EndCOFFSymbolDef() { - llvm_unreachable("ELF doesn't support this directive"); +void MCWasmStreamer::EndCOFFSymbolDef() { + llvm_unreachable("Wasm doesn't support this directive"); } -void MCELFStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol, - uint64_t Size, unsigned ByteAlignment) { - llvm_unreachable("ELF 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 MCELFStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, - uint64_t Size, unsigned ByteAlignment) { - llvm_unreachable("ELF 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"); } Index: lib/MC/WasmObjectWriter.cpp =================================================================== --- lib/MC/WasmObjectWriter.cpp +++ lib/MC/WasmObjectWriter.cpp @@ -1,4 +1,4 @@ -//===- lib/MC/ELFObjectWriter.cpp - ELF File Writer -----------------------===// +//===- lib/MC/WasmObjectWriter.cpp - Wasm File Writer ---------------------===// // // The LLVM Compiler Infrastructure // @@ -7,11 +7,11 @@ // //===----------------------------------------------------------------------===// // -// This file implements ELF object file writer information. +// This file implements Wasm object file writer information. // //===----------------------------------------------------------------------===// -#include "llvm/MC/MCELFObjectWriter.h" +#include "llvm/MC/MCWasmObjectWriter.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" @@ -23,14 +23,12 @@ #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/MCSectionELF.h" -#include "llvm/MC/MCSymbolELF.h" +#include "llvm/MC/MCSectionWasm.h" +#include "llvm/MC/MCSymbolWasm.h" #include "llvm/MC/MCValue.h" -#include "llvm/MC/StringTableBuilder.h" -#include "llvm/Support/Compression.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/ELF.h" #include "llvm/Support/Endian.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/StringSaver.h" @@ -42,65 +40,24 @@ #define DEBUG_TYPE "reloc-info" namespace { -typedef DenseMap SectionIndexMapTy; - -class ELFObjectWriter; - -class SymbolTableWriter { - ELFObjectWriter &EWriter; - bool Is64Bit; - - // indexes we are going to write to .symtab_shndx. - std::vector ShndxIndexes; - - // The numbel of symbols written so far. - unsigned NumWritten; - - void createSymtabShndx(); - - template void write(T Value); - -public: - SymbolTableWriter(ELFObjectWriter &EWriter, bool Is64Bit); - - void writeSymbol(uint32_t name, uint8_t info, uint64_t value, uint64_t size, - uint8_t other, uint32_t shndx, bool Reserved); - - ArrayRef getShndxIndexes() const { return ShndxIndexes; } -}; - -class ELFObjectWriter : public MCObjectWriter { - static uint64_t SymbolValue(const MCSymbol &Sym, const MCAsmLayout &Layout); - static bool isInSymtab(const MCAsmLayout &Layout, const MCSymbolELF &Symbol, - bool Used, bool Renamed); +typedef DenseMap SectionIndexMapTy; +class WasmObjectWriter : public MCObjectWriter { /// Helper struct for containing some precomputed information on symbols. - struct ELFSymbolData { - const MCSymbolELF *Symbol; - uint32_t SectionIndex; + struct WasmSymbolData { + const MCSymbolWasm *Symbol; StringRef Name; // Support lexicographic sorting. - bool operator<(const ELFSymbolData &RHS) const { - unsigned LHSType = Symbol->getType(); - unsigned RHSType = RHS.Symbol->getType(); - if (LHSType == ELF::STT_SECTION && RHSType != ELF::STT_SECTION) - return false; - if (LHSType != ELF::STT_SECTION && RHSType == ELF::STT_SECTION) - return true; - if (LHSType == ELF::STT_SECTION && RHSType == ELF::STT_SECTION) - return SectionIndex < RHS.SectionIndex; + bool operator<(const WasmSymbolData &RHS) const { return Name < RHS.Name; } }; - /// The target specific ELF writer instance. - std::unique_ptr TargetObjectWriter; - - DenseMap Renames; + /// The target specific Wasm writer instance. + std::unique_ptr TargetObjectWriter; - llvm::DenseMap> - Relocations; + DenseMap Renames; /// @} /// @name Symbol Table Data @@ -108,268 +65,55 @@ BumpPtrAllocator Alloc; StringSaver VersionSymSaver{Alloc}; - StringTableBuilder StrTabBuilder{StringTableBuilder::ELF}; /// @} - // This holds the symbol table index of the last local symbol. - unsigned LastLocalSymbolIndex; - // This holds the .strtab section index. - unsigned StringTableIndex; - // This holds the .symtab section index. - unsigned SymbolTableIndex; - - // Sections in the order they are to be output in the section table. - std::vector SectionTable; - unsigned addToSectionTable(const MCSectionELF *Sec); - // TargetObjectWriter wrappers. bool is64Bit() const { return TargetObjectWriter->is64Bit(); } - bool hasRelocationAddend() const { - return TargetObjectWriter->hasRelocationAddend(); - } unsigned getRelocType(MCContext &Ctx, const MCValue &Target, const MCFixup &Fixup, bool IsPCRel) const { return TargetObjectWriter->getRelocType(Ctx, Target, Fixup, IsPCRel); } - void align(unsigned Alignment); - - bool maybeWriteCompression(uint64_t Size, - SmallVectorImpl &CompressedContents, - bool ZLibStyle, unsigned Alignment); - public: - ELFObjectWriter(MCELFObjectTargetWriter *MOTW, raw_pwrite_stream &OS, - bool IsLittleEndian) - : MCObjectWriter(OS, IsLittleEndian), TargetObjectWriter(MOTW) {} + WasmObjectWriter(MCWasmObjectTargetWriter *MOTW, raw_pwrite_stream &OS) + : MCObjectWriter(OS, /*IsLittleEndian=*/true), TargetObjectWriter(MOTW) {} void reset() override { Renames.clear(); - Relocations.clear(); - StrTabBuilder.clear(); - SectionTable.clear(); MCObjectWriter::reset(); } - ~ELFObjectWriter() override; - - void WriteWord(uint64_t W) { - if (is64Bit()) - write64(W); - else - write32(W); - } - - template void write(T Val) { - if (IsLittleEndian) - support::endian::Writer(getStream()).write(Val); - else - support::endian::Writer(getStream()).write(Val); - } + ~WasmObjectWriter() override; void writeHeader(const MCAssembler &Asm); - void writeSymbol(SymbolTableWriter &Writer, uint32_t StringIndex, - ELFSymbolData &MSD, const MCAsmLayout &Layout); - - // Start and end offset of each section - typedef std::map> - SectionOffsetsTy; - - bool shouldRelocateWithSymbol(const MCAssembler &Asm, - const MCSymbolRefExpr *RefA, - const MCSymbol *Sym, uint64_t C, - unsigned Type) const; + // Fixup offset and size of each section + typedef std::map> + SectionSizesTy; void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, bool &IsPCRel, uint64_t &FixedValue) override; - // Map from a signature symbol to the group section index - typedef DenseMap RevGroupMapTy; - - /// Compute the symbol table data - /// - /// \param Asm - The assembler. - /// \param SectionIndexMap - Maps a section to its index. - /// \param RevGroupMap - Maps a signature symbol to the group section. - void computeSymbolTable(MCAssembler &Asm, const MCAsmLayout &Layout, - const SectionIndexMapTy &SectionIndexMap, - const RevGroupMapTy &RevGroupMap, - SectionOffsetsTy &SectionOffsets); - - MCSectionELF *createRelocationSection(MCContext &Ctx, - const MCSectionELF &Sec); - - const MCSectionELF *createStringTable(MCContext &Ctx); - void executePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout) override; - void writeSectionHeader(const MCAsmLayout &Layout, - const SectionIndexMapTy &SectionIndexMap, - const SectionOffsetsTy &SectionOffsets); - - void writeSectionData(const MCAssembler &Asm, MCSection &Sec, - const MCAsmLayout &Layout); - - void WriteSecHdrEntry(uint32_t Name, uint32_t Type, uint64_t Flags, - uint64_t Address, uint64_t Offset, uint64_t Size, - uint32_t Link, uint32_t Info, uint64_t Alignment, - uint64_t EntrySize); - - void writeRelocations(const MCAssembler &Asm, const MCSectionELF &Sec); - - bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, - const MCSymbol &SymA, - const MCFragment &FB, bool InSet, - bool IsPCRel) const override; - - bool isWeak(const MCSymbol &Sym) const override; - void writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override; - void writeSection(const SectionIndexMapTy &SectionIndexMap, - uint32_t GroupSymbolIndex, uint64_t Offset, uint64_t Size, - const MCSectionELF &Section); }; } // end anonymous namespace -void ELFObjectWriter::align(unsigned Alignment) { - uint64_t Padding = OffsetToAlignment(getStream().tell(), Alignment); - WriteZeros(Padding); -} - -unsigned ELFObjectWriter::addToSectionTable(const MCSectionELF *Sec) { - SectionTable.push_back(Sec); - StrTabBuilder.add(Sec->getSectionName()); - return SectionTable.size(); -} - -void SymbolTableWriter::createSymtabShndx() { - if (!ShndxIndexes.empty()) - return; - - ShndxIndexes.resize(NumWritten); -} - -template void SymbolTableWriter::write(T Value) { - EWriter.write(Value); -} - -SymbolTableWriter::SymbolTableWriter(ELFObjectWriter &EWriter, bool Is64Bit) - : EWriter(EWriter), Is64Bit(Is64Bit), NumWritten(0) {} - -void SymbolTableWriter::writeSymbol(uint32_t name, uint8_t info, uint64_t value, - uint64_t size, uint8_t other, - uint32_t shndx, bool Reserved) { - bool LargeIndex = shndx >= ELF::SHN_LORESERVE && !Reserved; - - if (LargeIndex) - createSymtabShndx(); - - if (!ShndxIndexes.empty()) { - if (LargeIndex) - ShndxIndexes.push_back(shndx); - else - ShndxIndexes.push_back(0); - } - - uint16_t Index = LargeIndex ? uint16_t(ELF::SHN_XINDEX) : shndx; - - if (Is64Bit) { - write(name); // st_name - write(info); // st_info - write(other); // st_other - write(Index); // st_shndx - write(value); // st_value - write(size); // st_size - } else { - write(name); // st_name - write(uint32_t(value)); // st_value - write(uint32_t(size)); // st_size - write(info); // st_info - write(other); // st_other - write(Index); // st_shndx - } - - ++NumWritten; -} - -ELFObjectWriter::~ELFObjectWriter() +WasmObjectWriter::~WasmObjectWriter() {} -// Emit the ELF header. -void ELFObjectWriter::writeHeader(const MCAssembler &Asm) { - // ELF Header - // ---------- - // - // Note - // ---- - // emitWord method behaves differently for ELF32 and ELF64, writing - // 4 bytes in the former and 8 in the latter. - - writeBytes(ELF::ElfMagic); // e_ident[EI_MAG0] to e_ident[EI_MAG3] - - write8(is64Bit() ? ELF::ELFCLASS64 : ELF::ELFCLASS32); // e_ident[EI_CLASS] - - // e_ident[EI_DATA] - write8(isLittleEndian() ? ELF::ELFDATA2LSB : ELF::ELFDATA2MSB); - - write8(ELF::EV_CURRENT); // e_ident[EI_VERSION] - // e_ident[EI_OSABI] - write8(TargetObjectWriter->getOSABI()); - write8(0); // e_ident[EI_ABIVERSION] - - WriteZeros(ELF::EI_NIDENT - ELF::EI_PAD); - - write16(ELF::ET_REL); // e_type - - write16(TargetObjectWriter->getEMachine()); // e_machine = target - - write32(ELF::EV_CURRENT); // e_version - WriteWord(0); // e_entry, no entry point in .o file - WriteWord(0); // e_phoff, no program header for .o - WriteWord(0); // e_shoff = sec hdr table off in bytes - - // e_flags = whatever the target wants - write32(Asm.getELFHeaderEFlags()); - - // e_ehsize = ELF header size - write16(is64Bit() ? sizeof(ELF::Elf64_Ehdr) : sizeof(ELF::Elf32_Ehdr)); - - write16(0); // e_phentsize = prog header entry size - write16(0); // e_phnum = # prog header entries = 0 - - // e_shentsize = Section header entry size - write16(is64Bit() ? sizeof(ELF::Elf64_Shdr) : sizeof(ELF::Elf32_Shdr)); - - // e_shnum = # of section header ents - write16(0); - - // e_shstrndx = Section # of '.shstrtab' - assert(StringTableIndex < ELF::SHN_LORESERVE); - write16(StringTableIndex); -} - -uint64_t ELFObjectWriter::SymbolValue(const MCSymbol &Sym, - const MCAsmLayout &Layout) { - if (Sym.isCommon() && Sym.isExternal()) - return Sym.getCommonAlignment(); - - uint64_t Res; - if (!Layout.getSymbolOffset(Sym, Res)) - return 0; - - if (Layout.getAssembler().isThumbFunc(&Sym)) - Res |= 1; - - return Res; +// Emit the Wasm header. +void WasmObjectWriter::writeHeader(const MCAssembler &Asm) { + // TODO: write the magic cookie and the version. } -void ELFObjectWriter::executePostLayoutBinding(MCAssembler &Asm, - const MCAsmLayout &Layout) { +void WasmObjectWriter::executePostLayoutBinding(MCAssembler &Asm, + const MCAsmLayout &Layout) { // Section symbols are used as definitions for undefined symbols with matching // names. If there are multiple sections with the same name, the first one is // used. @@ -383,20 +127,20 @@ continue; Renames.insert( - std::make_pair(cast(Alias), cast(Begin))); + std::make_pair(cast(Alias), cast(Begin))); } // The presence of symbol versions causes undefined symbols and // versions declared with @@@ to be renamed. for (const MCSymbol &A : Asm.symbols()) { - const auto &Alias = cast(A); + const auto &Alias = cast(A); // Not an alias. if (!Alias.isVariable()) continue; auto *Ref = dyn_cast(Alias.getVariableValue()); if (!Ref) continue; - const auto &Symbol = cast(Ref->getSymbol()); + const auto &Symbol = cast(Ref->getSymbol()); StringRef AliasName = Alias.getName(); size_t Pos = AliasName.find('@'); @@ -405,9 +149,6 @@ // Aliases defined with .symvar copy the binding from the symbol they alias. // This is the first place we are able to copy this information. - Alias.setExternal(Symbol.isExternal()); - Alias.setBinding(Symbol.getBinding()); - StringRef Rest = AliasName.substr(Pos); if (!Symbol.isUndefined() && !Rest.startswith("@@@")) continue; @@ -421,964 +162,23 @@ } } -static uint8_t mergeTypeForSet(uint8_t origType, uint8_t newType) { - uint8_t Type = newType; - - // Propagation rules: - // IFUNC > FUNC > OBJECT > NOTYPE - // TLS_OBJECT > OBJECT > NOTYPE - // - // dont let the new type degrade the old type - switch (origType) { - default: - break; - case ELF::STT_GNU_IFUNC: - if (Type == ELF::STT_FUNC || Type == ELF::STT_OBJECT || - Type == ELF::STT_NOTYPE || Type == ELF::STT_TLS) - Type = ELF::STT_GNU_IFUNC; - break; - case ELF::STT_FUNC: - if (Type == ELF::STT_OBJECT || Type == ELF::STT_NOTYPE || - Type == ELF::STT_TLS) - Type = ELF::STT_FUNC; - break; - case ELF::STT_OBJECT: - if (Type == ELF::STT_NOTYPE) - Type = ELF::STT_OBJECT; - break; - case ELF::STT_TLS: - if (Type == ELF::STT_OBJECT || Type == ELF::STT_NOTYPE || - Type == ELF::STT_GNU_IFUNC || Type == ELF::STT_FUNC) - Type = ELF::STT_TLS; - break; - } - - return Type; -} - -void ELFObjectWriter::writeSymbol(SymbolTableWriter &Writer, - uint32_t StringIndex, ELFSymbolData &MSD, - const MCAsmLayout &Layout) { - const auto &Symbol = cast(*MSD.Symbol); - const MCSymbolELF *Base = - cast_or_null(Layout.getBaseSymbol(Symbol)); - - // This has to be in sync with when computeSymbolTable uses SHN_ABS or - // SHN_COMMON. - bool IsReserved = !Base || Symbol.isCommon(); - - // Binding and Type share the same byte as upper and lower nibbles - uint8_t Binding = Symbol.getBinding(); - uint8_t Type = Symbol.getType(); - if (Base) { - Type = mergeTypeForSet(Type, Base->getType()); - } - uint8_t Info = (Binding << 4) | Type; - - // Other and Visibility share the same byte with Visibility using the lower - // 2 bits - uint8_t Visibility = Symbol.getVisibility(); - uint8_t Other = Symbol.getOther() | Visibility; - - uint64_t Value = SymbolValue(*MSD.Symbol, Layout); - uint64_t Size = 0; - - const MCExpr *ESize = MSD.Symbol->getSize(); - if (!ESize && Base) - ESize = Base->getSize(); - - if (ESize) { - int64_t Res; - if (!ESize->evaluateKnownAbsolute(Res, Layout)) - report_fatal_error("Size expression must be absolute."); - Size = Res; - } - - // Write out the symbol table entry - Writer.writeSymbol(StringIndex, Info, Value, Size, Other, MSD.SectionIndex, - IsReserved); -} - -// It is always valid to create a relocation with a symbol. It is preferable -// to use a relocation with a section if that is possible. Using the section -// allows us to omit some local symbols from the symbol table. -bool ELFObjectWriter::shouldRelocateWithSymbol(const MCAssembler &Asm, - const MCSymbolRefExpr *RefA, - const MCSymbol *S, uint64_t C, - unsigned Type) const { - const auto *Sym = cast_or_null(S); - // A PCRel relocation to an absolute value has no symbol (or section). We - // represent that with a relocation to a null section. - if (!RefA) - return false; - - MCSymbolRefExpr::VariantKind Kind = RefA->getKind(); - switch (Kind) { - default: - break; - // The .odp creation emits a relocation against the symbol ".TOC." which - // create a R_PPC64_TOC relocation. However the relocation symbol name - // in final object creation should be NULL, since the symbol does not - // really exist, it is just the reference to TOC base for the current - // object file. Since the symbol is undefined, returning false results - // in a relocation with a null section which is the desired result. - case MCSymbolRefExpr::VK_PPC_TOCBASE: - return false; - - // These VariantKind cause the relocation to refer to something other than - // the symbol itself, like a linker generated table. Since the address of - // symbol is not relevant, we cannot replace the symbol with the - // section and patch the difference in the addend. - case MCSymbolRefExpr::VK_GOT: - case MCSymbolRefExpr::VK_PLT: - case MCSymbolRefExpr::VK_GOTPCREL: - case MCSymbolRefExpr::VK_PPC_GOT_LO: - case MCSymbolRefExpr::VK_PPC_GOT_HI: - case MCSymbolRefExpr::VK_PPC_GOT_HA: - return true; - } - - // An undefined symbol is not in any section, so the relocation has to point - // to the symbol itself. - assert(Sym && "Expected a symbol"); - if (Sym->isUndefined()) - return true; - - unsigned Binding = Sym->getBinding(); - switch(Binding) { - default: - llvm_unreachable("Invalid Binding"); - case ELF::STB_LOCAL: - break; - case ELF::STB_WEAK: - // If the symbol is weak, it might be overridden by a symbol in another - // file. The relocation has to point to the symbol so that the linker - // can update it. - return true; - case ELF::STB_GLOBAL: - // Global ELF symbols can be preempted by the dynamic linker. The relocation - // has to point to the symbol for a reason analogous to the STB_WEAK case. - return true; - } - - // If a relocation points to a mergeable section, we have to be careful. - // If the offset is zero, a relocation with the section will encode the - // same information. With a non-zero offset, the situation is different. - // For example, a relocation can point 42 bytes past the end of a string. - // If we change such a relocation to use the section, the linker would think - // that it pointed to another string and subtracting 42 at runtime will - // produce the wrong value. - auto &Sec = cast(Sym->getSection()); - unsigned Flags = Sec.getFlags(); - if (Flags & ELF::SHF_MERGE) { - if (C != 0) - return true; - - // It looks like gold has a bug (http://sourceware.org/PR16794) and can - // only handle section relocations to mergeable sections if using RELA. - if (!hasRelocationAddend()) - return true; - } - - // Most TLS relocations use a got, so they need the symbol. Even those that - // are just an offset (@tpoff), require a symbol in gold versions before - // 5efeedf61e4fe720fd3e9a08e6c91c10abb66d42 (2014-09-26) which fixed - // http://sourceware.org/PR16773. - if (Flags & ELF::SHF_TLS) - return true; - - // If the symbol is a thumb function the final relocation must set the lowest - // bit. With a symbol that is done by just having the symbol have that bit - // set, so we would lose the bit if we relocated with the section. - // FIXME: We could use the section but add the bit to the relocation value. - if (Asm.isThumbFunc(Sym)) - return true; - - if (TargetObjectWriter->needsRelocateWithSymbol(*Sym, Type)) - return true; - return false; -} - -// True if the assembler knows nothing about the final value of the symbol. -// This doesn't cover the comdat issues, since in those cases the assembler -// can at least know that all symbols in the section will move together. -static bool isWeak(const MCSymbolELF &Sym) { - if (Sym.getType() == ELF::STT_GNU_IFUNC) - return true; - - switch (Sym.getBinding()) { - default: - llvm_unreachable("Unknown binding"); - case ELF::STB_LOCAL: - return false; - case ELF::STB_GLOBAL: - return false; - case ELF::STB_WEAK: - case ELF::STB_GNU_UNIQUE: - return true; - } -} - -void ELFObjectWriter::recordRelocation(MCAssembler &Asm, - const MCAsmLayout &Layout, - const MCFragment *Fragment, - const MCFixup &Fixup, MCValue Target, - bool &IsPCRel, uint64_t &FixedValue) { - const MCSectionELF &FixupSection = cast(*Fragment->getParent()); - uint64_t C = Target.getConstant(); - uint64_t FixupOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); - MCContext &Ctx = Asm.getContext(); - - if (const MCSymbolRefExpr *RefB = Target.getSymB()) { - assert(RefB->getKind() == MCSymbolRefExpr::VK_None && - "Should not have constructed this"); - - // Let A, B and C being the components of Target and R be the location of - // the fixup. If the fixup is not pcrel, we want to compute (A - B + C). - // If it is pcrel, we want to compute (A - B + C - R). - - // In general, ELF has no relocations for -B. It can only represent (A + C) - // or (A + C - R). If B = R + K and the relocation is not pcrel, we can - // replace B to implement it: (A - R - K + C) - if (IsPCRel) { - Ctx.reportError( - Fixup.getLoc(), - "No relocation available to represent this relative expression"); - return; - } - - const auto &SymB = cast(RefB->getSymbol()); - - if (SymB.isUndefined()) { - Ctx.reportError(Fixup.getLoc(), - Twine("symbol '") + SymB.getName() + - "' can not be undefined in a subtraction expression"); - return; - } - - assert(!SymB.isAbsolute() && "Should have been folded"); - const MCSection &SecB = SymB.getSection(); - if (&SecB != &FixupSection) { - Ctx.reportError(Fixup.getLoc(), - "Cannot represent a difference across sections"); - return; - } - - uint64_t SymBOffset = Layout.getSymbolOffset(SymB); - uint64_t K = SymBOffset - FixupOffset; - IsPCRel = true; - C -= K; - } - - // We either rejected the fixup or folded B into C at this point. - const MCSymbolRefExpr *RefA = Target.getSymA(); - const auto *SymA = RefA ? cast(&RefA->getSymbol()) : nullptr; - - bool ViaWeakRef = false; - if (SymA && SymA->isVariable()) { - const MCExpr *Expr = SymA->getVariableValue(); - if (const auto *Inner = dyn_cast(Expr)) { - if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF) { - SymA = cast(&Inner->getSymbol()); - ViaWeakRef = true; - } - } - } - - unsigned Type = getRelocType(Ctx, Target, Fixup, IsPCRel); - uint64_t OriginalC = C; - bool RelocateWithSymbol = shouldRelocateWithSymbol(Asm, RefA, SymA, C, Type); - if (!RelocateWithSymbol && SymA && !SymA->isUndefined()) - C += Layout.getSymbolOffset(*SymA); - - uint64_t Addend = 0; - if (hasRelocationAddend()) { - Addend = C; - C = 0; - } - - FixedValue = C; - - if (!RelocateWithSymbol) { - const MCSection *SecA = - (SymA && !SymA->isUndefined()) ? &SymA->getSection() : nullptr; - auto *ELFSec = cast_or_null(SecA); - const auto *SectionSymbol = - ELFSec ? cast(ELFSec->getBeginSymbol()) : nullptr; - if (SectionSymbol) - SectionSymbol->setUsedInReloc(); - ELFRelocationEntry Rec(FixupOffset, SectionSymbol, Type, Addend, SymA, - OriginalC); - Relocations[&FixupSection].push_back(Rec); - return; - } - - const auto *RenamedSymA = SymA; - if (SymA) { - if (const MCSymbolELF *R = Renames.lookup(SymA)) - RenamedSymA = R; - - if (ViaWeakRef) - RenamedSymA->setIsWeakrefUsedInReloc(); - else - RenamedSymA->setUsedInReloc(); - } - ELFRelocationEntry Rec(FixupOffset, RenamedSymA, Type, Addend, SymA, - OriginalC); - Relocations[&FixupSection].push_back(Rec); -} - -bool ELFObjectWriter::isInSymtab(const MCAsmLayout &Layout, - const MCSymbolELF &Symbol, bool Used, - bool Renamed) { - if (Symbol.isVariable()) { - const MCExpr *Expr = Symbol.getVariableValue(); - if (const MCSymbolRefExpr *Ref = dyn_cast(Expr)) { - if (Ref->getKind() == MCSymbolRefExpr::VK_WEAKREF) - return false; - } - } - - if (Used) - return true; - - if (Renamed) - return false; - - if (Symbol.isVariable() && Symbol.isUndefined()) { - // FIXME: this is here just to diagnose the case of a var = commmon_sym. - Layout.getBaseSymbol(Symbol); - return false; - } - - if (Symbol.isUndefined() && !Symbol.isBindingSet()) - return false; - - if (Symbol.isTemporary()) - return false; - - if (Symbol.getType() == ELF::STT_SECTION) - return false; - - return true; -} - -void ELFObjectWriter::computeSymbolTable( - MCAssembler &Asm, const MCAsmLayout &Layout, - const SectionIndexMapTy &SectionIndexMap, const RevGroupMapTy &RevGroupMap, - SectionOffsetsTy &SectionOffsets) { - MCContext &Ctx = Asm.getContext(); - SymbolTableWriter Writer(*this, is64Bit()); - - // Symbol table - unsigned EntrySize = is64Bit() ? ELF::SYMENTRY_SIZE64 : ELF::SYMENTRY_SIZE32; - MCSectionELF *SymtabSection = - Ctx.getELFSection(".symtab", ELF::SHT_SYMTAB, 0, EntrySize, ""); - SymtabSection->setAlignment(is64Bit() ? 8 : 4); - SymbolTableIndex = addToSectionTable(SymtabSection); - - align(SymtabSection->getAlignment()); - uint64_t SecStart = getStream().tell(); - - // The first entry is the undefined symbol entry. - Writer.writeSymbol(0, 0, 0, 0, 0, 0, false); - - std::vector LocalSymbolData; - std::vector ExternalSymbolData; - - // Add the data for the symbols. - bool HasLargeSectionIndex = false; - for (const MCSymbol &S : Asm.symbols()) { - const auto &Symbol = cast(S); - bool Used = Symbol.isUsedInReloc(); - bool WeakrefUsed = Symbol.isWeakrefUsedInReloc(); - bool isSignature = Symbol.isSignature(); - - if (!isInSymtab(Layout, Symbol, Used || WeakrefUsed || isSignature, - Renames.count(&Symbol))) - continue; - - if (Symbol.isTemporary() && Symbol.isUndefined()) { - Ctx.reportError(SMLoc(), "Undefined temporary symbol"); - continue; - } - - ELFSymbolData MSD; - MSD.Symbol = cast(&Symbol); - - bool Local = Symbol.getBinding() == ELF::STB_LOCAL; - assert(Local || !Symbol.isTemporary()); - - if (Symbol.isAbsolute()) { - MSD.SectionIndex = ELF::SHN_ABS; - } else if (Symbol.isCommon()) { - assert(!Local); - MSD.SectionIndex = ELF::SHN_COMMON; - } else if (Symbol.isUndefined()) { - if (isSignature && !Used) { - MSD.SectionIndex = RevGroupMap.lookup(&Symbol); - if (MSD.SectionIndex >= ELF::SHN_LORESERVE) - HasLargeSectionIndex = true; - } else { - MSD.SectionIndex = ELF::SHN_UNDEF; - } - } else { - const MCSectionELF &Section = - static_cast(Symbol.getSection()); - MSD.SectionIndex = SectionIndexMap.lookup(&Section); - assert(MSD.SectionIndex && "Invalid section index!"); - if (MSD.SectionIndex >= ELF::SHN_LORESERVE) - HasLargeSectionIndex = true; - } - - // The @@@ in symbol version is replaced with @ in undefined symbols and @@ - // in defined ones. - // - // FIXME: All name handling should be done before we get to the writer, - // including dealing with GNU-style version suffixes. Fixing this isn't - // trivial. - // - // We thus have to be careful to not perform the symbol version replacement - // blindly: - // - // The ELF format is used on Windows by the MCJIT engine. Thus, on - // Windows, the ELFObjectWriter can encounter symbols mangled using the MS - // Visual Studio C++ name mangling scheme. Symbols mangled using the MSVC - // C++ name mangling can legally have "@@@" as a sub-string. In that case, - // the EFLObjectWriter should not interpret the "@@@" sub-string as - // specifying GNU-style symbol versioning. The ELFObjectWriter therefore - // checks for the MSVC C++ name mangling prefix which is either "?", "@?", - // "__imp_?" or "__imp_@?". - // - // It would have been interesting to perform the MS mangling prefix check - // only when the target triple is of the form *-pc-windows-elf. But, it - // seems that this information is not easily accessible from the - // ELFObjectWriter. - StringRef Name = Symbol.getName(); - SmallString<32> Buf; - if (!Name.startswith("?") && !Name.startswith("@?") && - !Name.startswith("__imp_?") && !Name.startswith("__imp_@?")) { - // This symbol isn't following the MSVC C++ name mangling convention. We - // can thus safely interpret the @@@ in symbol names as specifying symbol - // versioning. - size_t Pos = Name.find("@@@"); - if (Pos != StringRef::npos) { - Buf += Name.substr(0, Pos); - unsigned Skip = MSD.SectionIndex == ELF::SHN_UNDEF ? 2 : 1; - Buf += Name.substr(Pos + Skip); - Name = VersionSymSaver.save(Buf.c_str()); - } - } - - // Sections have their own string table - if (Symbol.getType() != ELF::STT_SECTION) { - MSD.Name = Name; - StrTabBuilder.add(Name); - } - - if (Local) - LocalSymbolData.push_back(MSD); - else - ExternalSymbolData.push_back(MSD); - } - - // This holds the .symtab_shndx section index. - unsigned SymtabShndxSectionIndex = 0; - - if (HasLargeSectionIndex) { - MCSectionELF *SymtabShndxSection = - Ctx.getELFSection(".symtab_shndxr", ELF::SHT_SYMTAB_SHNDX, 0, 4, ""); - SymtabShndxSectionIndex = addToSectionTable(SymtabShndxSection); - SymtabShndxSection->setAlignment(4); - } - - ArrayRef FileNames = Asm.getFileNames(); - for (const std::string &Name : FileNames) - StrTabBuilder.add(Name); - - StrTabBuilder.finalize(); - - for (const std::string &Name : FileNames) - Writer.writeSymbol(StrTabBuilder.getOffset(Name), - ELF::STT_FILE | ELF::STB_LOCAL, 0, 0, ELF::STV_DEFAULT, - ELF::SHN_ABS, true); - - // Symbols are required to be in lexicographic order. - array_pod_sort(LocalSymbolData.begin(), LocalSymbolData.end()); - array_pod_sort(ExternalSymbolData.begin(), ExternalSymbolData.end()); - - // Set the symbol indices. Local symbols must come before all other - // symbols with non-local bindings. - unsigned Index = FileNames.size() + 1; - - for (ELFSymbolData &MSD : LocalSymbolData) { - unsigned StringIndex = MSD.Symbol->getType() == ELF::STT_SECTION - ? 0 - : StrTabBuilder.getOffset(MSD.Name); - MSD.Symbol->setIndex(Index++); - writeSymbol(Writer, StringIndex, MSD, Layout); - } - - // Write the symbol table entries. - LastLocalSymbolIndex = Index; - - for (ELFSymbolData &MSD : ExternalSymbolData) { - unsigned StringIndex = StrTabBuilder.getOffset(MSD.Name); - MSD.Symbol->setIndex(Index++); - writeSymbol(Writer, StringIndex, MSD, Layout); - assert(MSD.Symbol->getBinding() != ELF::STB_LOCAL); - } - - uint64_t SecEnd = getStream().tell(); - SectionOffsets[SymtabSection] = std::make_pair(SecStart, SecEnd); - - ArrayRef ShndxIndexes = Writer.getShndxIndexes(); - if (ShndxIndexes.empty()) { - assert(SymtabShndxSectionIndex == 0); - return; - } - assert(SymtabShndxSectionIndex != 0); - - SecStart = getStream().tell(); - const MCSectionELF *SymtabShndxSection = - SectionTable[SymtabShndxSectionIndex - 1]; - for (uint32_t Index : ShndxIndexes) - write(Index); - SecEnd = getStream().tell(); - SectionOffsets[SymtabShndxSection] = std::make_pair(SecStart, SecEnd); -} - -MCSectionELF * -ELFObjectWriter::createRelocationSection(MCContext &Ctx, - const MCSectionELF &Sec) { - if (Relocations[&Sec].empty()) - return nullptr; - - const StringRef SectionName = Sec.getSectionName(); - std::string RelaSectionName = hasRelocationAddend() ? ".rela" : ".rel"; - RelaSectionName += SectionName; - - unsigned EntrySize; - if (hasRelocationAddend()) - EntrySize = is64Bit() ? sizeof(ELF::Elf64_Rela) : sizeof(ELF::Elf32_Rela); - else - EntrySize = is64Bit() ? sizeof(ELF::Elf64_Rel) : sizeof(ELF::Elf32_Rel); - - unsigned Flags = 0; - if (Sec.getFlags() & ELF::SHF_GROUP) - Flags = ELF::SHF_GROUP; - - MCSectionELF *RelaSection = Ctx.createELFRelSection( - RelaSectionName, hasRelocationAddend() ? ELF::SHT_RELA : ELF::SHT_REL, - Flags, EntrySize, Sec.getGroup(), &Sec); - RelaSection->setAlignment(is64Bit() ? 8 : 4); - return RelaSection; -} - -// Include the debug info compression header. -bool ELFObjectWriter::maybeWriteCompression( - uint64_t Size, SmallVectorImpl &CompressedContents, bool ZLibStyle, - unsigned Alignment) { - if (ZLibStyle) { - uint64_t HdrSize = - is64Bit() ? sizeof(ELF::Elf32_Chdr) : sizeof(ELF::Elf64_Chdr); - if (Size <= HdrSize + CompressedContents.size()) - return false; - // Platform specific header is followed by compressed data. - if (is64Bit()) { - // Write Elf64_Chdr header. - write(static_cast(ELF::ELFCOMPRESS_ZLIB)); - write(static_cast(0)); // ch_reserved field. - write(static_cast(Size)); - write(static_cast(Alignment)); - } else { - // Write Elf32_Chdr header otherwise. - write(static_cast(ELF::ELFCOMPRESS_ZLIB)); - write(static_cast(Size)); - write(static_cast(Alignment)); - } - return true; - } - - // "ZLIB" followed by 8 bytes representing the uncompressed size of the section, - // useful for consumers to preallocate a buffer to decompress into. - const StringRef Magic = "ZLIB"; - if (Size <= Magic.size() + sizeof(Size) + CompressedContents.size()) - return false; - write(ArrayRef(Magic.begin(), Magic.size())); - writeBE64(Size); - return true; -} - -void ELFObjectWriter::writeSectionData(const MCAssembler &Asm, MCSection &Sec, - const MCAsmLayout &Layout) { - MCSectionELF &Section = static_cast(Sec); - StringRef SectionName = Section.getSectionName(); - - // Compressing debug_frame requires handling alignment fragments which is - // more work (possibly generalizing MCAssembler.cpp:writeFragment to allow - // for writing to arbitrary buffers) for little benefit. - bool CompressionEnabled = - Asm.getContext().getAsmInfo()->compressDebugSections() != - DebugCompressionType::DCT_None; - if (!CompressionEnabled || !SectionName.startswith(".debug_") || - SectionName == ".debug_frame") { - Asm.writeSectionData(&Section, Layout); - return; - } - - SmallVector UncompressedData; - raw_svector_ostream VecOS(UncompressedData); - raw_pwrite_stream &OldStream = getStream(); - setStream(VecOS); - Asm.writeSectionData(&Section, Layout); - setStream(OldStream); - - SmallVector CompressedContents; - zlib::Status Success = zlib::compress( - StringRef(UncompressedData.data(), UncompressedData.size()), - CompressedContents); - if (Success != zlib::StatusOK) { - getStream() << UncompressedData; - return; - } - - bool ZlibStyle = Asm.getContext().getAsmInfo()->compressDebugSections() == - DebugCompressionType::DCT_Zlib; - if (!maybeWriteCompression(UncompressedData.size(), CompressedContents, - ZlibStyle, Sec.getAlignment())) { - getStream() << UncompressedData; - return; - } - - if (ZlibStyle) - // Set the compressed flag. That is zlib style. - Section.setFlags(Section.getFlags() | ELF::SHF_COMPRESSED); - else - // Add "z" prefix to section name. This is zlib-gnu style. - Asm.getContext().renameELFSection(&Section, - (".z" + SectionName.drop_front(1)).str()); - getStream() << CompressedContents; -} - -void ELFObjectWriter::WriteSecHdrEntry(uint32_t Name, uint32_t Type, - uint64_t Flags, uint64_t Address, - uint64_t Offset, uint64_t Size, - uint32_t Link, uint32_t Info, - uint64_t Alignment, - uint64_t EntrySize) { - write32(Name); // sh_name: index into string table - write32(Type); // sh_type - WriteWord(Flags); // sh_flags - WriteWord(Address); // sh_addr - WriteWord(Offset); // sh_offset - WriteWord(Size); // sh_size - write32(Link); // sh_link - write32(Info); // sh_info - WriteWord(Alignment); // sh_addralign - WriteWord(EntrySize); // sh_entsize -} - -void ELFObjectWriter::writeRelocations(const MCAssembler &Asm, - const MCSectionELF &Sec) { - std::vector &Relocs = Relocations[&Sec]; - - // We record relocations by pushing to the end of a vector. Reverse the vector - // to get the relocations in the order they were created. - // In most cases that is not important, but it can be for special sections - // (.eh_frame) or specific relocations (TLS optimizations on SystemZ). - std::reverse(Relocs.begin(), Relocs.end()); - - // Sort the relocation entries. MIPS needs this. - TargetObjectWriter->sortRelocs(Asm, Relocs); - - for (unsigned i = 0, e = Relocs.size(); i != e; ++i) { - const ELFRelocationEntry &Entry = Relocs[e - i - 1]; - unsigned Index = Entry.Symbol ? Entry.Symbol->getIndex() : 0; - - if (is64Bit()) { - write(Entry.Offset); - if (TargetObjectWriter->isN64()) { - write(uint32_t(Index)); - - write(TargetObjectWriter->getRSsym(Entry.Type)); - write(TargetObjectWriter->getRType3(Entry.Type)); - write(TargetObjectWriter->getRType2(Entry.Type)); - write(TargetObjectWriter->getRType(Entry.Type)); - } else { - struct ELF::Elf64_Rela ERE64; - ERE64.setSymbolAndType(Index, Entry.Type); - write(ERE64.r_info); - } - if (hasRelocationAddend()) - write(Entry.Addend); - } else { - write(uint32_t(Entry.Offset)); - - struct ELF::Elf32_Rela ERE32; - ERE32.setSymbolAndType(Index, Entry.Type); - write(ERE32.r_info); - - if (hasRelocationAddend()) - write(uint32_t(Entry.Addend)); - } - } -} - -const MCSectionELF *ELFObjectWriter::createStringTable(MCContext &Ctx) { - const MCSectionELF *StrtabSection = SectionTable[StringTableIndex - 1]; - StrTabBuilder.write(getStream()); - return StrtabSection; +void WasmObjectWriter::recordRelocation(MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, MCValue Target, + bool &IsPCRel, uint64_t &FixedValue) { + // TODO: Implement } -void ELFObjectWriter::writeSection(const SectionIndexMapTy &SectionIndexMap, - uint32_t GroupSymbolIndex, uint64_t Offset, - uint64_t Size, const MCSectionELF &Section) { - uint64_t sh_link = 0; - uint64_t sh_info = 0; - - switch(Section.getType()) { - default: - // Nothing to do. - break; - - case ELF::SHT_DYNAMIC: - llvm_unreachable("SHT_DYNAMIC in a relocatable object"); - - case ELF::SHT_REL: - case ELF::SHT_RELA: { - sh_link = SymbolTableIndex; - assert(sh_link && ".symtab not found"); - const MCSectionELF *InfoSection = Section.getAssociatedSection(); - sh_info = SectionIndexMap.lookup(InfoSection); - break; - } - - case ELF::SHT_SYMTAB: - case ELF::SHT_DYNSYM: - sh_link = StringTableIndex; - sh_info = LastLocalSymbolIndex; - break; - - case ELF::SHT_SYMTAB_SHNDX: - sh_link = SymbolTableIndex; - break; - - case ELF::SHT_GROUP: - sh_link = SymbolTableIndex; - sh_info = GroupSymbolIndex; - break; - } - - if (TargetObjectWriter->getEMachine() == ELF::EM_ARM && - Section.getType() == ELF::SHT_ARM_EXIDX) - sh_link = SectionIndexMap.lookup(Section.getAssociatedSection()); - - WriteSecHdrEntry(StrTabBuilder.getOffset(Section.getSectionName()), - Section.getType(), Section.getFlags(), 0, Offset, Size, - sh_link, sh_info, Section.getAlignment(), - Section.getEntrySize()); -} - -void ELFObjectWriter::writeSectionHeader( - const MCAsmLayout &Layout, const SectionIndexMapTy &SectionIndexMap, - const SectionOffsetsTy &SectionOffsets) { - const unsigned NumSections = SectionTable.size(); - - // Null section first. - uint64_t FirstSectionSize = - (NumSections + 1) >= ELF::SHN_LORESERVE ? NumSections + 1 : 0; - WriteSecHdrEntry(0, 0, 0, 0, 0, FirstSectionSize, 0, 0, 0, 0); - - for (const MCSectionELF *Section : SectionTable) { - uint32_t GroupSymbolIndex; - unsigned Type = Section->getType(); - if (Type != ELF::SHT_GROUP) - GroupSymbolIndex = 0; - else - GroupSymbolIndex = Section->getGroup()->getIndex(); - - const std::pair &Offsets = - SectionOffsets.find(Section)->second; - uint64_t Size; - if (Type == ELF::SHT_NOBITS) - Size = Layout.getSectionAddressSize(Section); - else - Size = Offsets.second - Offsets.first; - - writeSection(SectionIndexMap, GroupSymbolIndex, Offsets.first, Size, - *Section); - } -} - -void ELFObjectWriter::writeObject(MCAssembler &Asm, - const MCAsmLayout &Layout) { - MCContext &Ctx = Asm.getContext(); - MCSectionELF *StrtabSection = - Ctx.getELFSection(".strtab", ELF::SHT_STRTAB, 0); - StringTableIndex = addToSectionTable(StrtabSection); - - RevGroupMapTy RevGroupMap; - SectionIndexMapTy SectionIndexMap; - - std::map> GroupMembers; - - // Write out the ELF header ... +void WasmObjectWriter::writeObject(MCAssembler &Asm, + const MCAsmLayout &Layout) { + // Write out the Wasm header. writeHeader(Asm); - // ... then the sections ... - SectionOffsetsTy SectionOffsets; - std::vector Groups; - std::vector Relocations; - for (MCSection &Sec : Asm) { - MCSectionELF &Section = static_cast(Sec); - - align(Section.getAlignment()); - - // Remember the offset into the file for this section. - uint64_t SecStart = getStream().tell(); - - const MCSymbolELF *SignatureSymbol = Section.getGroup(); - writeSectionData(Asm, Section, Layout); - - uint64_t SecEnd = getStream().tell(); - SectionOffsets[&Section] = std::make_pair(SecStart, SecEnd); - - MCSectionELF *RelSection = createRelocationSection(Ctx, Section); - - if (SignatureSymbol) { - Asm.registerSymbol(*SignatureSymbol); - unsigned &GroupIdx = RevGroupMap[SignatureSymbol]; - if (!GroupIdx) { - MCSectionELF *Group = Ctx.createELFGroupSection(SignatureSymbol); - GroupIdx = addToSectionTable(Group); - Group->setAlignment(4); - Groups.push_back(Group); - } - std::vector &Members = - GroupMembers[SignatureSymbol]; - Members.push_back(&Section); - if (RelSection) - Members.push_back(RelSection); - } - - SectionIndexMap[&Section] = addToSectionTable(&Section); - if (RelSection) { - SectionIndexMap[RelSection] = addToSectionTable(RelSection); - Relocations.push_back(RelSection); - } - } - - for (MCSectionELF *Group : Groups) { - align(Group->getAlignment()); - - // Remember the offset into the file for this section. - uint64_t SecStart = getStream().tell(); - - const MCSymbol *SignatureSymbol = Group->getGroup(); - assert(SignatureSymbol); - write(uint32_t(ELF::GRP_COMDAT)); - for (const MCSectionELF *Member : GroupMembers[SignatureSymbol]) { - uint32_t SecIndex = SectionIndexMap.lookup(Member); - write(SecIndex); - } - - uint64_t SecEnd = getStream().tell(); - SectionOffsets[Group] = std::make_pair(SecStart, SecEnd); - } - - // Compute symbol table information. - computeSymbolTable(Asm, Layout, SectionIndexMap, RevGroupMap, SectionOffsets); - - for (MCSectionELF *RelSection : Relocations) { - align(RelSection->getAlignment()); - - // Remember the offset into the file for this section. - uint64_t SecStart = getStream().tell(); - - writeRelocations(Asm, *RelSection->getAssociatedSection()); - - uint64_t SecEnd = getStream().tell(); - SectionOffsets[RelSection] = std::make_pair(SecStart, SecEnd); - } - - { - uint64_t SecStart = getStream().tell(); - const MCSectionELF *Sec = createStringTable(Ctx); - uint64_t SecEnd = getStream().tell(); - SectionOffsets[Sec] = std::make_pair(SecStart, SecEnd); - } - - uint64_t NaturalAlignment = is64Bit() ? 8 : 4; - align(NaturalAlignment); - - const uint64_t SectionHeaderOffset = getStream().tell(); - - // ... then the section header table ... - writeSectionHeader(Layout, SectionIndexMap, SectionOffsets); - - uint16_t NumSections = (SectionTable.size() + 1 >= ELF::SHN_LORESERVE) - ? (uint16_t)ELF::SHN_UNDEF - : SectionTable.size() + 1; - if (sys::IsLittleEndianHost != IsLittleEndian) - sys::swapByteOrder(NumSections); - unsigned NumSectionsOffset; - - if (is64Bit()) { - uint64_t Val = SectionHeaderOffset; - if (sys::IsLittleEndianHost != IsLittleEndian) - sys::swapByteOrder(Val); - getStream().pwrite(reinterpret_cast(&Val), sizeof(Val), - offsetof(ELF::Elf64_Ehdr, e_shoff)); - NumSectionsOffset = offsetof(ELF::Elf64_Ehdr, e_shnum); - } else { - uint32_t Val = SectionHeaderOffset; - if (sys::IsLittleEndianHost != IsLittleEndian) - sys::swapByteOrder(Val); - getStream().pwrite(reinterpret_cast(&Val), sizeof(Val), - offsetof(ELF::Elf32_Ehdr, e_shoff)); - NumSectionsOffset = offsetof(ELF::Elf32_Ehdr, e_shnum); - } - getStream().pwrite(reinterpret_cast(&NumSections), - sizeof(NumSections), NumSectionsOffset); -} - -bool ELFObjectWriter::isSymbolRefDifferenceFullyResolvedImpl( - const MCAssembler &Asm, const MCSymbol &SA, const MCFragment &FB, - bool InSet, bool IsPCRel) const { - const auto &SymA = cast(SA); - if (IsPCRel) { - assert(!InSet); - if (::isWeak(SymA)) - return false; - } - return MCObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(Asm, SymA, FB, - InSet, IsPCRel); -} - -bool ELFObjectWriter::isWeak(const MCSymbol &S) const { - const auto &Sym = cast(S); - if (::isWeak(Sym)) - return true; - - // It is invalid to replace a reference to a global in a comdat - // with a reference to a local since out of comdat references - // to a local are forbidden. - // We could try to return false for more cases, like the reference - // being in the same comdat or Sym being an alias to another global, - // but it is not clear if it is worth the effort. - if (Sym.getBinding() != ELF::STB_GLOBAL) - return false; - - if (!Sym.isInSection()) - return false; - - const auto &Sec = cast(Sym.getSection()); - return Sec.getGroup(); + // TODO: Write the contents. } -MCObjectWriter *llvm::createELFObjectWriter(MCELFObjectTargetWriter *MOTW, - raw_pwrite_stream &OS, - bool IsLittleEndian) { - return new ELFObjectWriter(MOTW, OS, IsLittleEndian); +MCObjectWriter *llvm::createWasmObjectWriter(MCWasmObjectTargetWriter *MOTW, + raw_pwrite_stream &OS) { + return new WasmObjectWriter(MOTW, OS); } Index: lib/Target/ARM/AsmParser/ARMAsmParser.cpp =================================================================== --- lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -5480,7 +5480,8 @@ 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; @@ -5514,6 +5515,9 @@ case MCObjectFileInfo::IsCOFF: CurrentFormat = COFF; break; + case MCObjectFileInfo::IsWasm: + CurrentFormat = WASM; + break; } if (~Prefix->SupportedFormats & CurrentFormat) { Index: lib/Target/WebAssembly/MCTargetDesc/CMakeLists.txt =================================================================== --- lib/Target/WebAssembly/MCTargetDesc/CMakeLists.txt +++ lib/Target/WebAssembly/MCTargetDesc/CMakeLists.txt @@ -1,8 +1,8 @@ add_llvm_library(LLVMWebAssemblyDesc WebAssemblyAsmBackend.cpp - WebAssemblyELFObjectWriter.cpp WebAssemblyMCAsmInfo.cpp WebAssemblyMCCodeEmitter.cpp WebAssemblyMCTargetDesc.cpp WebAssemblyTargetStreamer.cpp + WebAssemblyWasmObjectWriter.cpp ) Index: lib/Target/WebAssembly/MCTargetDesc/WebAssemblyAsmBackend.cpp =================================================================== --- lib/Target/WebAssembly/MCTargetDesc/WebAssemblyAsmBackend.cpp +++ lib/Target/WebAssembly/MCTargetDesc/WebAssemblyAsmBackend.cpp @@ -16,7 +16,7 @@ #include "llvm/MC/MCAsmBackend.h" #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" @@ -96,7 +96,7 @@ MCObjectWriter * WebAssemblyAsmBackend::createObjectWriter(raw_pwrite_stream &OS) const { - return createWebAssemblyELFObjectWriter(OS, Is64Bit, 0); + return createWebAssemblyWasmObjectWriter(OS, Is64Bit); } } // end anonymous namespace Index: lib/Target/WebAssembly/MCTargetDesc/WebAssemblyELFObjectWriter.cpp =================================================================== --- lib/Target/WebAssembly/MCTargetDesc/WebAssemblyELFObjectWriter.cpp +++ lib/Target/WebAssembly/MCTargetDesc/WebAssemblyELFObjectWriter.cpp @@ -1,67 +0,0 @@ -//===-- WebAssemblyELFObjectWriter.cpp - WebAssembly ELF 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 ELF-specific object emission, converting LLVM's -/// internal fixups into the appropriate relocations. -/// -//===----------------------------------------------------------------------===// - -#include "MCTargetDesc/WebAssemblyMCTargetDesc.h" -#include "llvm/MC/MCELFObjectWriter.h" -#include "llvm/MC/MCFixup.h" -#include "llvm/Support/ErrorHandling.h" -using namespace llvm; - -namespace { -class WebAssemblyELFObjectWriter final : public MCELFObjectTargetWriter { -public: - WebAssemblyELFObjectWriter(bool Is64Bit, uint8_t OSABI); - -protected: - unsigned getRelocType(MCContext &Ctx, const MCValue &Target, - const MCFixup &Fixup, bool IsPCRel) const override; -}; -} // end anonymous namespace - -WebAssemblyELFObjectWriter::WebAssemblyELFObjectWriter(bool Is64Bit, - uint8_t OSABI) - : MCELFObjectTargetWriter(Is64Bit, OSABI, ELF::EM_WEBASSEMBLY, - /*HasRelocationAddend=*/false) {} - -unsigned WebAssemblyELFObjectWriter::getRelocType(MCContext &Ctx, - const MCValue &Target, - const MCFixup &Fixup, - bool IsPCRel) const { - // WebAssembly functions are not allocated in the address space. To resolve a - // pointer to a function, we must use a special relocation type. - if (const MCSymbolRefExpr *SyExp = - dyn_cast(Fixup.getValue())) - if (SyExp->getKind() == MCSymbolRefExpr::VK_WebAssembly_FUNCTION) - return ELF::R_WEBASSEMBLY_FUNCTION; - - switch (Fixup.getKind()) { - case FK_Data_4: - assert(!is64Bit() && "4-byte relocations only supported on wasm32"); - return ELF::R_WEBASSEMBLY_DATA; - case FK_Data_8: - assert(is64Bit() && "8-byte relocations only supported on wasm64"); - return ELF::R_WEBASSEMBLY_DATA; - default: - llvm_unreachable("unimplemented fixup kind"); - } -} - -MCObjectWriter *llvm::createWebAssemblyELFObjectWriter(raw_pwrite_stream &OS, - bool Is64Bit, - uint8_t OSABI) { - MCELFObjectTargetWriter *MOTW = - new WebAssemblyELFObjectWriter(Is64Bit, OSABI); - return createELFObjectWriter(MOTW, OS, /*IsLittleEndian=*/true); -} Index: lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCAsmInfo.h =================================================================== --- lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCAsmInfo.h +++ lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCAsmInfo.h @@ -15,13 +15,13 @@ #ifndef LLVM_LIB_TARGET_WEBASSEMBLY_MCTARGETDESC_WEBASSEMBLYMCASMINFO_H #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 WebAssemblyMCAsmInfo final : public MCAsmInfoWasm { public: explicit WebAssemblyMCAsmInfo(const Triple &T); ~WebAssemblyMCAsmInfo() override; Index: lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCAsmInfo.cpp =================================================================== --- lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCAsmInfo.cpp +++ lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCAsmInfo.cpp @@ -47,7 +47,4 @@ ExceptionsType = ExceptionHandling::None; // TODO: UseIntegratedAssembler? - - // WebAssembly's stack is never executable. - UsesNonexecutableStackSection = false; } Index: lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h =================================================================== --- lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h +++ lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h @@ -38,8 +38,8 @@ 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 { Index: lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.cpp =================================================================== --- lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.cpp +++ lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.cpp @@ -89,7 +89,7 @@ static MCTargetStreamer * createObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo & /*STI*/) { - return new WebAssemblyTargetELFStreamer(S); + return new WebAssemblyTargetWasmStreamer(S); } static MCTargetStreamer *createAsmTargetStreamer(MCStreamer &S, Index: lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h =================================================================== --- lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h +++ lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h @@ -21,7 +21,7 @@ namespace llvm { -class MCELFStreamer; +class MCWasmStreamer; /// WebAssembly-specific streamer interface, to implement support /// WebAssembly-specific assembly directives. @@ -64,10 +64,10 @@ void emitIndIdx(const MCExpr *Value) override; }; -/// This part is for ELF object output -class WebAssemblyTargetELFStreamer final : public WebAssemblyTargetStreamer { +/// This part is for Wasm object output +class WebAssemblyTargetWasmStreamer final : public WebAssemblyTargetStreamer { public: - explicit WebAssemblyTargetELFStreamer(MCStreamer &S); + explicit WebAssemblyTargetWasmStreamer(MCStreamer &S); void emitParam(ArrayRef Types) override; void emitResult(ArrayRef Types) override; Index: lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp =================================================================== --- lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp +++ lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp @@ -17,10 +17,9 @@ #include "InstPrinter/WebAssemblyInstPrinter.h" #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; @@ -32,7 +31,7 @@ MCStreamer &S, formatted_raw_ostream &OS) : WebAssemblyTargetStreamer(S), OS(OS) {} -WebAssemblyTargetELFStreamer::WebAssemblyTargetELFStreamer(MCStreamer &S) +WebAssemblyTargetWasmStreamer::WebAssemblyTargetWasmStreamer(MCStreamer &S) : WebAssemblyTargetStreamer(S) {} static void PrintTypes(formatted_raw_ostream &OS, ArrayRef Types) { @@ -84,29 +83,29 @@ OS << "\t.indidx \t" << *Value << '\n'; } -void WebAssemblyTargetELFStreamer::emitParam(ArrayRef Types) { +void WebAssemblyTargetWasmStreamer::emitParam(ArrayRef Types) { // Nothing to emit; params are declared as part of the function signature. } -void WebAssemblyTargetELFStreamer::emitResult(ArrayRef Types) { +void WebAssemblyTargetWasmStreamer::emitResult(ArrayRef Types) { // Nothing to emit; results are declared as part of the function signature. } -void WebAssemblyTargetELFStreamer::emitLocal(ArrayRef Types) { +void WebAssemblyTargetWasmStreamer::emitLocal(ArrayRef Types) { Streamer.EmitULEB128IntValue(Types.size()); for (MVT Type : Types) Streamer.EmitIntValue(int64_t(WebAssembly::toValType(Type)), 1); } -void WebAssemblyTargetELFStreamer::emitEndFunc() { +void WebAssemblyTargetWasmStreamer::emitEndFunc() { Streamer.EmitIntValue(WebAssembly::End, 1); } -void WebAssemblyTargetELFStreamer::emitIndIdx(const MCExpr *Value) { +void WebAssemblyTargetWasmStreamer::emitIndIdx(const MCExpr *Value) { llvm_unreachable(".indidx encoding not yet implemented"); } -void WebAssemblyTargetELFStreamer::emitIndirectFunctionType( +void WebAssemblyTargetWasmStreamer::emitIndirectFunctionType( StringRef name, SmallVectorImpl &Params, SmallVectorImpl &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. Index: lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp =================================================================== --- lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp +++ lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp @@ -1,4 +1,4 @@ -//===-- WebAssemblyELFObjectWriter.cpp - WebAssembly ELF Writer -----------===// +//===-- WebAssemblyWasmObjectWriter.cpp - WebAssembly Wasm Writer ---------===// // // The LLVM Compiler Infrastructure // @@ -8,21 +8,21 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief This file handles ELF-specific object emission, converting LLVM's +/// \brief This file handles Wasm-specific object emission, converting LLVM's /// internal fixups into the appropriate relocations. /// //===----------------------------------------------------------------------===// #include "MCTargetDesc/WebAssemblyMCTargetDesc.h" -#include "llvm/MC/MCELFObjectWriter.h" +#include "llvm/MC/MCWasmObjectWriter.h" #include "llvm/MC/MCFixup.h" #include "llvm/Support/ErrorHandling.h" using namespace llvm; namespace { -class WebAssemblyELFObjectWriter final : public MCELFObjectTargetWriter { +class WebAssemblyWasmObjectWriter final : public MCWasmObjectTargetWriter { public: - WebAssemblyELFObjectWriter(bool Is64Bit, uint8_t OSABI); + explicit WebAssemblyWasmObjectWriter(bool Is64Bit); protected: unsigned getRelocType(MCContext &Ctx, const MCValue &Target, @@ -30,38 +30,20 @@ }; } // end anonymous namespace -WebAssemblyELFObjectWriter::WebAssemblyELFObjectWriter(bool Is64Bit, - uint8_t OSABI) - : MCELFObjectTargetWriter(Is64Bit, OSABI, ELF::EM_WEBASSEMBLY, - /*HasRelocationAddend=*/false) {} - -unsigned WebAssemblyELFObjectWriter::getRelocType(MCContext &Ctx, - const MCValue &Target, - const MCFixup &Fixup, - bool IsPCRel) const { - // WebAssembly functions are not allocated in the address space. To resolve a - // pointer to a function, we must use a special relocation type. - if (const MCSymbolRefExpr *SyExp = - dyn_cast(Fixup.getValue())) - if (SyExp->getKind() == MCSymbolRefExpr::VK_WebAssembly_FUNCTION) - return ELF::R_WEBASSEMBLY_FUNCTION; - - switch (Fixup.getKind()) { - case FK_Data_4: - assert(!is64Bit() && "4-byte relocations only supported on wasm32"); - return ELF::R_WEBASSEMBLY_DATA; - case FK_Data_8: - assert(is64Bit() && "8-byte relocations only supported on wasm64"); - return ELF::R_WEBASSEMBLY_DATA; - default: - llvm_unreachable("unimplemented fixup kind"); - } +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::createWebAssemblyELFObjectWriter(raw_pwrite_stream &OS, - bool Is64Bit, - uint8_t OSABI) { - MCELFObjectTargetWriter *MOTW = - new WebAssemblyELFObjectWriter(Is64Bit, OSABI); - return createELFObjectWriter(MOTW, OS, /*IsLittleEndian=*/true); +MCObjectWriter *llvm::createWebAssemblyWasmObjectWriter(raw_pwrite_stream &OS, + bool Is64Bit) { + MCWasmObjectTargetWriter *MOTW = + new WebAssemblyWasmObjectWriter(Is64Bit); + return createWasmObjectWriter(MOTW, OS); } Index: lib/Target/WebAssembly/WebAssemblyTargetObjectFile.h =================================================================== --- lib/Target/WebAssembly/WebAssemblyTargetObjectFile.h +++ lib/Target/WebAssembly/WebAssemblyTargetObjectFile.h @@ -20,7 +20,7 @@ namespace llvm { -class WebAssemblyTargetObjectFile final : public TargetLoweringObjectFileELF { +class WebAssemblyTargetObjectFile final : public TargetLoweringObjectFileWasm { public: void Initialize(MCContext &Ctx, const TargetMachine &TM) override; }; Index: lib/Target/WebAssembly/WebAssemblyTargetObjectFile.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblyTargetObjectFile.cpp +++ lib/Target/WebAssembly/WebAssemblyTargetObjectFile.cpp @@ -19,6 +19,6 @@ void WebAssemblyTargetObjectFile::Initialize(MCContext &Ctx, const TargetMachine &TM) { - TargetLoweringObjectFileELF::Initialize(Ctx, TM); - InitializeELF(TM.Options.UseInitArray); + TargetLoweringObjectFileWasm::Initialize(Ctx, TM); + InitializeWasm(); } Index: lib/Target/XCore/XCoreAsmPrinter.cpp =================================================================== --- lib/Target/XCore/XCoreAsmPrinter.cpp +++ lib/Target/XCore/XCoreAsmPrinter.cpp @@ -153,7 +153,7 @@ unsigned Size = DL.getTypeAllocSize(C->getType()); if (MAI->hasDotTypeDotSizeDirective()) { OutStreamer->EmitSymbolAttribute(GVSym, MCSA_ELF_TypeObject); - OutStreamer->emitELFSize(cast(GVSym), + OutStreamer->emitELFSize(GVSym, MCConstantExpr::create(Size, OutContext)); } OutStreamer->EmitLabel(GVSym); Index: test/CodeGen/WebAssembly/global.ll =================================================================== --- test/CodeGen/WebAssembly/global.ll +++ test/CodeGen/WebAssembly/global.ll @@ -42,14 +42,20 @@ @ud = internal global i32 undef ; CHECK: .type nil,@object -; CHECK-NEXT: .lcomm nil,4,2{{$}} +; CHECK-NEXT: .p2align 2{{$}} +; CHECK-NEXT: nil: +; CHECK-NEXT: .int32 0{{$}} +; CHECK-NEXT: .size nil, 4{{$}} @nil = internal global i32 zeroinitializer ; CHECK: .type z,@object -; CHECK-NEXT: .lcomm z,4,2{{$}} +; CHECK-NEXT: .p2align 2{{$}} +; CHECK-NEXT: z: +; CHECK-NEXT: .int32 0{{$}} +; CHECK-NEXT: .size z, 4{{$}} @z = internal global i32 0 -; CHECK-NEXT: .type one,@object +; CHECK: .type one,@object ; CHECK-NEXT: .p2align 2{{$}} ; CHECK-NEXT: one: ; CHECK-NEXT: .int32 1{{$}} @@ -57,32 +63,38 @@ @one = internal global i32 1 ; CHECK: .type answer,@object -; CHECK: .p2align 2{{$}} +; CHECK-NEXT: .p2align 2{{$}} ; CHECK-NEXT: answer: ; CHECK-NEXT: .int32 42{{$}} ; CHECK-NEXT: .size answer, 4{{$}} @answer = internal global i32 42 ; CHECK: .type u32max,@object -; CHECK: .p2align 2{{$}} +; CHECK-NEXT: .p2align 2{{$}} ; CHECK-NEXT: u32max: ; CHECK-NEXT: .int32 4294967295{{$}} ; CHECK-NEXT: .size u32max, 4{{$}} @u32max = internal global i32 -1 ; CHECK: .type ud64,@object -; CHECK: .p2align 3{{$}} +; CHECK-NEXT: .p2align 3{{$}} ; CHECK-NEXT: ud64: ; CHECK-NEXT: .skip 8{{$}} ; CHECK-NEXT: .size ud64, 8{{$}} @ud64 = internal global i64 undef ; CHECK: .type nil64,@object -; CHECK: .lcomm nil64,8,3{{$}} +; CHECK-NEXT: .p2align 3{{$}} +; CHECK-NEXT: nil64: +; CHECK-NEXT: .int64 0{{$}} +; CHECK-NEXT: .size nil64, 8{{$}} @nil64 = internal global i64 zeroinitializer ; CHECK: .type z64,@object -; CHECK: .lcomm z64,8,3{{$}} +; CHECK-NEXT: .p2align 3{{$}} +; CHECK-NEXT: z64: +; CHECK-NEXT: .int64 0{{$}} +; CHECK-NEXT: .size z64, 8{{$}} @z64 = internal global i64 0 ; CHECK: .type twoP32,@object @@ -100,18 +112,24 @@ @u64max = internal global i64 -1 ; CHECK: .type f32ud,@object -; CHECK: .p2align 2{{$}} +; CHECK-NEXT: .p2align 2{{$}} ; CHECK-NEXT: f32ud: ; CHECK-NEXT: .skip 4{{$}} ; CHECK-NEXT: .size f32ud, 4{{$}} @f32ud = internal global float undef ; CHECK: .type f32nil,@object -; CHECK: .lcomm f32nil,4,2{{$}} +; CHECK-NEXT: .p2align 2{{$}} +; CHECK-NEXT: f32nil: +; CHECK-NEXT: .int32 0{{$}} +; CHECK-NEXT: .size f32nil, 4{{$}} @f32nil = internal global float zeroinitializer ; CHECK: .type f32z,@object -; CHECK: .lcomm f32z,4,2{{$}} +; CHECK-NEXT: .p2align 2{{$}} +; CHECK-NEXT: f32z: +; CHECK-NEXT: .int32 0{{$}} +; CHECK-NEXT: .size f32z, 4{{$}} @f32z = internal global float 0.0 ; CHECK: .type f32nz,@object @@ -129,18 +147,24 @@ @f32two = internal global float 2.0 ; CHECK: .type f64ud,@object -; CHECK: .p2align 3{{$}} +; CHECK-NEXT: .p2align 3{{$}} ; CHECK-NEXT: f64ud: ; CHECK-NEXT: .skip 8{{$}} ; CHECK-NEXT: .size f64ud, 8{{$}} @f64ud = internal global double undef ; CHECK: .type f64nil,@object -; CHECK: .lcomm f64nil,8,3{{$}} +; CHECK-NEXT: .p2align 3{{$}} +; CHECK-NEXT: f64nil: +; CHECK-NEXT: .int64 0{{$}} +; CHECK-NEXT: .size f64nil, 8{{$}} @f64nil = internal global double zeroinitializer ; CHECK: .type f64z,@object -; CHECK: .lcomm f64z,8,3{{$}} +; CHECK-NEXT: .p2align 3{{$}} +; CHECK-NEXT: f64z: +; CHECK-NEXT: .int64 0{{$}} +; CHECK-NEXT: .size f64z, 8{{$}} @f64z = internal global double 0.0 ; CHECK: .type f64nz,@object @@ -168,7 +192,6 @@ ; Constant global. ; CHECK: .type rom,@object{{$}} -; CHECK: .section .rodata,"a",@progbits{{$}} ; CHECK: .globl rom{{$}} ; CHECK: .p2align 4{{$}} ; CHECK: rom: @@ -181,7 +204,6 @@ ; CHECK-NEXT: .skip 8 ; CHECK-NEXT: .size array, 8 ; CHECK: .type pointer_to_array,@object -; CHECK-NEXT: .section .data.rel.ro,"aw",@progbits ; CHECK-NEXT: .globl pointer_to_array ; CHECK-NEXT: .p2align 2 ; CHECK-NEXT: pointer_to_array: Index: test/CodeGen/WebAssembly/vtable.ll =================================================================== --- test/CodeGen/WebAssembly/vtable.ll +++ test/CodeGen/WebAssembly/vtable.ll @@ -36,7 +36,6 @@ @_ZTS1D = constant [3 x i8] c"1D\00" ; VTABLE: .type _ZTV1A,@object -; VTABLE-NEXT: .section .data.rel.ro,"aw",@progbits ; VTABLE-NEXT: .globl _ZTV1A ; VTABLE-LABEL: _ZTV1A: ; VTABLE-NEXT: .int32 0