From c9da0caf08e55e4dccb07814644bf5ac8f4a2555 Mon Sep 17 00:00:00 2001 From: Colin LeMahieu Date: Wed, 17 Jun 2015 03:06:16 +0000 Subject: [PATCH] [Hexagon] Adding MC ELF streamer and updating addend relocation test which shows correct ELF symbol. llvm-svn: 239876 --- lib/Target/Hexagon/HexagonTargetStreamer.h | 31 ++++ .../Hexagon/MCTargetDesc/CMakeLists.txt | 1 + .../MCTargetDesc/HexagonMCELFStreamer.cpp | 152 ++++++++++++++++++ .../MCTargetDesc/HexagonMCELFStreamer.h | 45 ++++++ .../MCTargetDesc/HexagonMCInstrInfo.cpp | 15 ++ .../Hexagon/MCTargetDesc/HexagonMCInstrInfo.h | 5 +- .../MCTargetDesc/HexagonMCTargetDesc.cpp | 62 ++++++- test/CodeGen/Hexagon/simple_addend.ll | 2 +- 8 files changed, 308 insertions(+), 5 deletions(-) create mode 100644 lib/Target/Hexagon/HexagonTargetStreamer.h create mode 100644 lib/Target/Hexagon/MCTargetDesc/HexagonMCELFStreamer.cpp create mode 100644 lib/Target/Hexagon/MCTargetDesc/HexagonMCELFStreamer.h diff --git a/lib/Target/Hexagon/HexagonTargetStreamer.h b/lib/Target/Hexagon/HexagonTargetStreamer.h new file mode 100644 index 00000000000..e19c404450e --- /dev/null +++ b/lib/Target/Hexagon/HexagonTargetStreamer.h @@ -0,0 +1,31 @@ +//===-- HexagonTargetStreamer.h - Hexagon Target Streamer ------*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef HEXAGONTARGETSTREAMER_H +#define HEXAGONTARGETSTREAMER_H + +#include "llvm/MC/MCStreamer.h" + +namespace llvm { +class HexagonTargetStreamer : public MCTargetStreamer { +public: + HexagonTargetStreamer(MCStreamer &S) : MCTargetStreamer(S) {} + virtual void EmitCodeAlignment(unsigned ByteAlignment, + unsigned MaxBytesToEmit = 0){}; + virtual void emitFAlign(unsigned Size, unsigned MaxBytesToEmit){}; + virtual void EmitCommonSymbolSorted(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment, + unsigned AccessGranularity){}; + virtual void EmitLocalCommonSymbolSorted(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlign, + unsigned AccessGranularity){}; +}; +} + +#endif diff --git a/lib/Target/Hexagon/MCTargetDesc/CMakeLists.txt b/lib/Target/Hexagon/MCTargetDesc/CMakeLists.txt index 6253686b499..5403b106cbb 100644 --- a/lib/Target/Hexagon/MCTargetDesc/CMakeLists.txt +++ b/lib/Target/Hexagon/MCTargetDesc/CMakeLists.txt @@ -6,6 +6,7 @@ add_llvm_library(LLVMHexagonDesc HexagonMCCodeEmitter.cpp HexagonMCCompound.cpp HexagonMCDuplexInfo.cpp + HexagonMCELFStreamer.cpp HexagonMCInstrInfo.cpp HexagonMCShuffler.cpp HexagonMCTargetDesc.cpp diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCELFStreamer.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonMCELFStreamer.cpp new file mode 100644 index 00000000000..bf51c3515e9 --- /dev/null +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCELFStreamer.cpp @@ -0,0 +1,152 @@ +//=== HexagonMCELFStreamer.cpp - Hexagon subclass of MCELFStreamer -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a stub that parses a MCInst bundle and passes the +// instructions on to the real streamer. +// +//===----------------------------------------------------------------------===// +#define DEBUG_TYPE "hexagonmcelfstreamer" + +#include "Hexagon.h" +#include "HexagonMCELFStreamer.h" +#include "MCTargetDesc/HexagonBaseInfo.h" +#include "MCTargetDesc/HexagonMCShuffler.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCSectionELF.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCSymbolELF.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +static cl::opt + GPSize("gpsize", cl::NotHidden, + cl::desc("Global Pointer Addressing Size. The default size is 8."), + cl::Prefix, cl::init(8)); + +void HexagonMCELFStreamer::EmitInstruction(const MCInst &MCK, + const MCSubtargetInfo &STI) { + MCInst HMI; + HMI.setOpcode(Hexagon::BUNDLE); + HMI.addOperand(MCOperand::createImm(0)); + MCInst *MCB; + + if (MCK.getOpcode() != Hexagon::BUNDLE) { + HMI.addOperand(MCOperand::createInst(&MCK)); + MCB = &HMI; + } else + MCB = const_cast(&MCK); + + // Examines packet and pad the packet, if needed, when an + // end-loop is in the bundle. + HexagonMCInstrInfo::padEndloop(*MCB); + HexagonMCShuffle(*MCII, STI, *MCB); + + assert(HexagonMCInstrInfo::bundleSize(*MCB) <= HEXAGON_PACKET_SIZE); + bool Extended = false; + for (auto &I : HexagonMCInstrInfo::bundleInstructions(*MCB)) { + MCInst *MCI = const_cast(I.getInst()); + if (Extended) { + if (HexagonMCInstrInfo::isDuplex(*MCII, *MCI)) { + MCInst *SubInst = const_cast(MCI->getOperand(1).getInst()); + HexagonMCInstrInfo::clampExtended(*MCII, *SubInst); + } else { + HexagonMCInstrInfo::clampExtended(*MCII, *MCI); + } + Extended = false; + } else { + Extended = HexagonMCInstrInfo::isImmext(*MCI); + } + } + + // At this point, MCB is a bundle + // Iterate through the bundle and assign addends for the instructions + for (auto const &I : HexagonMCInstrInfo::bundleInstructions(*MCB)) { + MCInst *MCI = const_cast(I.getInst()); + EmitSymbol(*MCI); + } + MCObjectStreamer::EmitInstruction(*MCB, STI); +} + +void HexagonMCELFStreamer::EmitSymbol(const MCInst &Inst) { + // Scan for values. + for (unsigned i = Inst.getNumOperands(); i--;) + if (Inst.getOperand(i).isExpr()) + visitUsedExpr(*Inst.getOperand(i).getExpr()); +} + +// EmitCommonSymbol and EmitLocalCommonSymbol are extended versions of the +// functions found in MCELFStreamer.cpp taking AccessSize as an additional +// parameter. +void HexagonMCELFStreamer::HexagonMCEmitCommonSymbol(MCSymbol *Symbol, + uint64_t Size, + unsigned ByteAlignment, + unsigned AccessSize) { + getAssembler().registerSymbol(*Symbol); + StringRef sbss[4] = {".sbss.1", ".sbss.2", ".sbss.4", ".sbss.8"}; + + auto ELFSymbol = cast(Symbol); + if (!ELFSymbol->isBindingSet()) { + ELFSymbol->setBinding(ELF::STB_GLOBAL); + ELFSymbol->setExternal(true); + } + + ELFSymbol->setType(ELF::STT_OBJECT); + + if (ELFSymbol->getBinding() == ELF::STB_LOCAL) { + StringRef SectionName = + ((AccessSize == 0) || (Size == 0) || (Size > GPSize)) + ? ".bss" + : sbss[(Log2_64(AccessSize))]; + + MCSection *CrntSection = getCurrentSection().first; + MCSection *Section = getAssembler().getContext().getELFSection( + SectionName, ELF::SHT_NOBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC); + SwitchSection(Section); + AssignSection(Symbol, Section); + + MCELFStreamer::EmitCommonSymbol(Symbol, Size, ByteAlignment); + SwitchSection(CrntSection); + } else { + if (ELFSymbol->declareCommon(Size, ByteAlignment)) + report_fatal_error("Symbol: " + Symbol->getName() + + " redeclared as different type"); + if ((AccessSize) && (Size <= GPSize)) { + uint64_t SectionIndex = + (AccessSize <= GPSize) + ? ELF::SHN_HEXAGON_SCOMMON + (Log2_64(AccessSize) + 1) + : (unsigned)ELF::SHN_HEXAGON_SCOMMON; + ELFSymbol->setIndex(SectionIndex); + } + } + + ELFSymbol->setSize(MCConstantExpr::create(Size, getContext())); +} + +void HexagonMCELFStreamer::HexagonMCEmitLocalCommonSymbol( + MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment, + unsigned AccessSize) { + getAssembler().registerSymbol(*Symbol); + auto ELFSymbol = cast(Symbol); + ELFSymbol->setBinding(ELF::STB_LOCAL); + ELFSymbol->setExternal(false); + HexagonMCEmitCommonSymbol(Symbol, Size, ByteAlignment, AccessSize); +} + +namespace llvm { +MCStreamer *createHexagonELFStreamer(MCContext &Context, MCAsmBackend &MAB, + raw_pwrite_stream &OS, MCCodeEmitter *CE) { + return new HexagonMCELFStreamer(Context, MAB, OS, CE); +} +} diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCELFStreamer.h b/lib/Target/Hexagon/MCTargetDesc/HexagonMCELFStreamer.h new file mode 100644 index 00000000000..d77c0cd16b3 --- /dev/null +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCELFStreamer.h @@ -0,0 +1,45 @@ +//===- HexagonMCELFStreamer.h - Hexagon subclass of MCElfStreamer ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef HEXAGONMCELFSTREAMER_H +#define HEXAGONMCELFSTREAMER_H + +#include "MCTargetDesc/HexagonMCCodeEmitter.h" +#include "MCTargetDesc/HexagonMCInstrInfo.h" +#include "MCTargetDesc/HexagonMCTargetDesc.h" +#include "llvm/MC/MCELFStreamer.h" +#include "HexagonTargetStreamer.h" + +namespace llvm { + +class HexagonMCELFStreamer : public MCELFStreamer { + std::unique_ptr MCII; + +public: + HexagonMCELFStreamer(MCContext &Context, MCAsmBackend &TAB, + raw_pwrite_stream &OS, MCCodeEmitter *Emitter) + : MCELFStreamer(Context, TAB, OS, Emitter), + MCII(createHexagonMCInstrInfo()) {} + + virtual void EmitInstruction(const MCInst &Inst, + const MCSubtargetInfo &STI) override; + void EmitSymbol(const MCInst &Inst); + void HexagonMCEmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment, + unsigned AccessSize); + void HexagonMCEmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment, unsigned AccessSize); +}; + +MCStreamer *createHexagonELFStreamer(MCContext &Context, MCAsmBackend &MAB, + raw_pwrite_stream &OS, MCCodeEmitter *CE); + +} // namespace llvm + +#endif diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.cpp index 2731278f0e4..48b15f85a78 100644 --- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.cpp +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.cpp @@ -35,6 +35,21 @@ size_t HexagonMCInstrInfo::bundleSize(MCInst const &MCI) { return (1); } +void HexagonMCInstrInfo::clampExtended(MCInstrInfo const &MCII, MCInst &MCI) { + assert(HexagonMCInstrInfo::isExtendable(MCII, MCI) || + HexagonMCInstrInfo::isExtended(MCII, MCI)); + MCOperand &exOp = + MCI.getOperand(HexagonMCInstrInfo::getExtendableOp(MCII, MCI)); + // If the extended value is a constant, then use it for the extended and + // for the extender instructions, masking off the lower 6 bits and + // including the assumed bits. + if (exOp.isImm()) { + unsigned Shift = HexagonMCInstrInfo::getExtentAlignment(MCII, MCI); + int64_t Bits = exOp.getImm(); + exOp.setImm((Bits & 0x3f) << Shift); + } +} + MCInst *HexagonMCInstrInfo::deriveDuplex(MCContext &Context, unsigned iClass, MCInst const &inst0, MCInst const &inst1) { diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.h b/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.h index 40d3b075e27..32d61a4a7be 100644 --- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.h +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.h @@ -47,6 +47,9 @@ iterator_range bundleInstructions(MCInst const &MCI); // Returns the number of instructions in the bundle size_t bundleSize(MCInst const &MCI); +// Clamp off upper 26 bits of extendable operand for emission +void clampExtended(MCInstrInfo const &MCII, MCInst &MCI); + // Create a duplex instruction given the two subinsts MCInst *deriveDuplex(MCContext &Context, unsigned iClass, MCInst const &inst0, MCInst const &inst1); @@ -224,7 +227,7 @@ void setOuterLoop(MCInst &MCI); // Would duplexing this instruction create a requirement to extend bool subInstWouldBeExtended(MCInst const &potentialDuplex); -// Attempt to find and replace compound pairs +// Attempt to find and replace compound pairs void tryCompound(MCInstrInfo const &MCII, MCContext &Context, MCInst &MCI); } } diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp index 8fb9b5c4b32..4e7bca634e3 100644 --- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp @@ -11,16 +11,20 @@ // //===----------------------------------------------------------------------===// -#include "HexagonMCTargetDesc.h" #include "HexagonMCAsmInfo.h" +#include "HexagonMCELFStreamer.h" +#include "HexagonMCTargetDesc.h" #include "MCTargetDesc/HexagonInstPrinter.h" #include "llvm/MC/MCCodeGenInfo.h" +#include "llvm/MC/MCContext.h" #include "llvm/MC/MCELFStreamer.h" #include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCObjectStreamer.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MachineLocation.h" +#include "llvm/Support/ELF.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/TargetRegistry.h" @@ -54,6 +58,41 @@ createHexagonMCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS) { return X; } +namespace { +class HexagonTargetELFStreamer : public HexagonTargetStreamer { +public: + MCELFStreamer &getStreamer() { + return static_cast(Streamer); + } + HexagonTargetELFStreamer(MCStreamer &S, MCSubtargetInfo const &STI) + : HexagonTargetStreamer(S) { + auto Bits = STI.getFeatureBits(); + unsigned Flags; + if (Bits.to_ullong() & llvm::Hexagon::ArchV5) + Flags = ELF::EF_HEXAGON_MACH_V5; + else + Flags = ELF::EF_HEXAGON_MACH_V4; + getStreamer().getAssembler().setELFHeaderEFlags(Flags); + } + void EmitCommonSymbolSorted(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment, + unsigned AccessSize) override { + HexagonMCELFStreamer &HexagonELFStreamer = + static_cast(getStreamer()); + HexagonELFStreamer.HexagonMCEmitCommonSymbol(Symbol, Size, ByteAlignment, + AccessSize); + } + void EmitLocalCommonSymbolSorted(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment, + unsigned AccessSize) override { + HexagonMCELFStreamer &HexagonELFStreamer = + static_cast(getStreamer()); + HexagonELFStreamer.HexagonMCEmitLocalCommonSymbol( + Symbol, Size, ByteAlignment, AccessSize); + } +}; +} + static MCAsmInfo *createHexagonMCAsmInfo(const MCRegisterInfo &MRI, const Triple &TT) { MCAsmInfo *MAI = new HexagonMCAsmInfo(TT); @@ -82,9 +121,20 @@ static MCInstPrinter *createHexagonMCInstPrinter(const Triple &T, const MCInstrInfo &MII, const MCRegisterInfo &MRI) { if (SyntaxVariant == 0) - return(new HexagonInstPrinter(MAI, MII, MRI)); + return (new HexagonInstPrinter(MAI, MII, MRI)); else - return nullptr; + return nullptr; +} + +static MCStreamer *createMCStreamer(Triple const &T, MCContext &Context, + MCAsmBackend &MAB, raw_pwrite_stream &OS, + MCCodeEmitter *Emitter, bool RelaxAll) { + return createHexagonELFStreamer(Context, MAB, OS, Emitter); +} + +static MCTargetStreamer * +createHexagonObjectTargetStreamer(MCStreamer &S, MCSubtargetInfo const &STI) { + return new HexagonTargetELFStreamer(S, STI); } // Force static initialization. @@ -116,7 +166,13 @@ extern "C" void LLVMInitializeHexagonTargetMC() { TargetRegistry::RegisterMCAsmBackend(TheHexagonTarget, createHexagonAsmBackend); + // Register the obj streamer + TargetRegistry::RegisterELFStreamer(TheHexagonTarget, createMCStreamer); + // Register the MC Inst Printer TargetRegistry::RegisterMCInstPrinter(TheHexagonTarget, createHexagonMCInstPrinter); + + TargetRegistry::RegisterObjectTargetStreamer( + TheHexagonTarget, createHexagonObjectTargetStreamer); } diff --git a/test/CodeGen/Hexagon/simple_addend.ll b/test/CodeGen/Hexagon/simple_addend.ll index 7d300d4afc0..ec3a87f1dcc 100644 --- a/test/CodeGen/Hexagon/simple_addend.ll +++ b/test/CodeGen/Hexagon/simple_addend.ll @@ -7,4 +7,4 @@ define void @foo(i32 %a) { call void @bar(i32 %b) ret void } -; CHECK: 0x8 R_HEX_B22_PCREL - 0x4 +; CHECK: 0x8 R_HEX_B22_PCREL bar 0x4