HexagonMCELFStreamer.cpp revision 360784
1//=== HexagonMCELFStreamer.cpp - Hexagon subclass of MCELFStreamer -------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file is a stub that parses a MCInst bundle and passes the
10// instructions on to the real streamer.
11//
12//===----------------------------------------------------------------------===//
13#define DEBUG_TYPE "hexagonmcelfstreamer"
14
15#include "MCTargetDesc/HexagonMCELFStreamer.h"
16#include "MCTargetDesc/HexagonMCInstrInfo.h"
17#include "MCTargetDesc/HexagonMCShuffler.h"
18#include "llvm/ADT/StringRef.h"
19#include "llvm/BinaryFormat/ELF.h"
20#include "llvm/MC/MCAsmBackend.h"
21#include "llvm/MC/MCAssembler.h"
22#include "llvm/MC/MCCodeEmitter.h"
23#include "llvm/MC/MCContext.h"
24#include "llvm/MC/MCExpr.h"
25#include "llvm/MC/MCInst.h"
26#include "llvm/MC/MCObjectStreamer.h"
27#include "llvm/MC/MCObjectWriter.h"
28#include "llvm/MC/MCSection.h"
29#include "llvm/MC/MCSectionELF.h"
30#include "llvm/MC/MCStreamer.h"
31#include "llvm/MC/MCSymbol.h"
32#include "llvm/MC/MCSymbolELF.h"
33#include "llvm/Support/Casting.h"
34#include "llvm/Support/CommandLine.h"
35#include "llvm/Support/ErrorHandling.h"
36#include "llvm/Support/MathExtras.h"
37#include <cassert>
38#include <cstdint>
39
40using namespace llvm;
41
42static cl::opt<unsigned> GPSize
43  ("gpsize", cl::NotHidden,
44   cl::desc("Global Pointer Addressing Size.  The default size is 8."),
45   cl::Prefix,
46   cl::init(8));
47
48HexagonMCELFStreamer::HexagonMCELFStreamer(
49    MCContext &Context, std::unique_ptr<MCAsmBackend> TAB,
50    std::unique_ptr<MCObjectWriter> OW, std::unique_ptr<MCCodeEmitter> Emitter)
51    : MCELFStreamer(Context, std::move(TAB), std::move(OW), std::move(Emitter)),
52      MCII(createHexagonMCInstrInfo()) {}
53
54HexagonMCELFStreamer::HexagonMCELFStreamer(
55    MCContext &Context, std::unique_ptr<MCAsmBackend> TAB,
56    std::unique_ptr<MCObjectWriter> OW, std::unique_ptr<MCCodeEmitter> Emitter,
57    MCAssembler *Assembler)
58    : MCELFStreamer(Context, std::move(TAB), std::move(OW), std::move(Emitter)),
59      MCII(createHexagonMCInstrInfo()) {}
60
61void HexagonMCELFStreamer::EmitInstruction(const MCInst &MCB,
62                                           const MCSubtargetInfo &STI) {
63  assert(MCB.getOpcode() == Hexagon::BUNDLE);
64  assert(HexagonMCInstrInfo::bundleSize(MCB) <= HEXAGON_PACKET_SIZE);
65  assert(HexagonMCInstrInfo::bundleSize(MCB) > 0);
66
67  // At this point, MCB is a bundle
68  // Iterate through the bundle and assign addends for the instructions
69  for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCB)) {
70    MCInst *MCI = const_cast<MCInst *>(I.getInst());
71    EmitSymbol(*MCI);
72  }
73
74  MCObjectStreamer::EmitInstruction(MCB, STI);
75}
76
77void HexagonMCELFStreamer::EmitSymbol(const MCInst &Inst) {
78  // Scan for values.
79  for (unsigned i = Inst.getNumOperands(); i--;)
80    if (Inst.getOperand(i).isExpr())
81      visitUsedExpr(*Inst.getOperand(i).getExpr());
82}
83
84// EmitCommonSymbol and EmitLocalCommonSymbol are extended versions of the
85// functions found in MCELFStreamer.cpp taking AccessSize as an additional
86// parameter.
87void HexagonMCELFStreamer::HexagonMCEmitCommonSymbol(MCSymbol *Symbol,
88                                                     uint64_t Size,
89                                                     unsigned ByteAlignment,
90                                                     unsigned AccessSize) {
91  getAssembler().registerSymbol(*Symbol);
92  StringRef sbss[4] = {".sbss.1", ".sbss.2", ".sbss.4", ".sbss.8"};
93
94  auto ELFSymbol = cast<MCSymbolELF>(Symbol);
95  if (!ELFSymbol->isBindingSet()) {
96    ELFSymbol->setBinding(ELF::STB_GLOBAL);
97    ELFSymbol->setExternal(true);
98  }
99
100  ELFSymbol->setType(ELF::STT_OBJECT);
101
102  if (ELFSymbol->getBinding() == ELF::STB_LOCAL) {
103    StringRef SectionName =
104        ((AccessSize == 0) || (Size == 0) || (Size > GPSize))
105            ? ".bss"
106            : sbss[(Log2_64(AccessSize))];
107    MCSection &Section = *getAssembler().getContext().getELFSection(
108        SectionName, ELF::SHT_NOBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC);
109    MCSectionSubPair P = getCurrentSection();
110    SwitchSection(&Section);
111
112    if (ELFSymbol->isUndefined()) {
113      EmitValueToAlignment(ByteAlignment, 0, 1, 0);
114      EmitLabel(Symbol);
115      EmitZeros(Size);
116    }
117
118    // Update the maximum alignment of the section if necessary.
119    if (Align(ByteAlignment) > Section.getAlignment())
120      Section.setAlignment(Align(ByteAlignment));
121
122    SwitchSection(P.first, P.second);
123  } else {
124    if (ELFSymbol->declareCommon(Size, ByteAlignment))
125      report_fatal_error("Symbol: " + Symbol->getName() +
126                         " redeclared as different type");
127    if ((AccessSize) && (Size <= GPSize)) {
128      uint64_t SectionIndex =
129          (AccessSize <= GPSize)
130              ? ELF::SHN_HEXAGON_SCOMMON + (Log2_64(AccessSize) + 1)
131              : (unsigned)ELF::SHN_HEXAGON_SCOMMON;
132      ELFSymbol->setIndex(SectionIndex);
133    }
134  }
135
136  ELFSymbol->setSize(MCConstantExpr::create(Size, getContext()));
137}
138
139void HexagonMCELFStreamer::HexagonMCEmitLocalCommonSymbol(MCSymbol *Symbol,
140                                                         uint64_t Size,
141                                                         unsigned ByteAlignment,
142                                                         unsigned AccessSize) {
143  getAssembler().registerSymbol(*Symbol);
144  auto ELFSymbol = cast<MCSymbolELF>(Symbol);
145  ELFSymbol->setBinding(ELF::STB_LOCAL);
146  ELFSymbol->setExternal(false);
147  HexagonMCEmitCommonSymbol(Symbol, Size, ByteAlignment, AccessSize);
148}
149
150
151namespace llvm {
152MCStreamer *createHexagonELFStreamer(Triple const &TT, MCContext &Context,
153                                     std::unique_ptr<MCAsmBackend> MAB,
154                                     std::unique_ptr<MCObjectWriter> OW,
155                                     std::unique_ptr<MCCodeEmitter> CE) {
156  return new HexagonMCELFStreamer(Context, std::move(MAB), std::move(OW),
157                                  std::move(CE));
158  }
159
160} // end namespace llvm
161