File: PPCELFStreamer.cpp

package info (click to toggle)
llvm-toolchain-11 1%3A11.0.1-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 995,808 kB
  • sloc: cpp: 4,767,656; ansic: 760,916; asm: 477,436; python: 170,940; objc: 69,804; lisp: 29,914; sh: 23,855; f90: 18,173; pascal: 7,551; perl: 7,471; ml: 5,603; awk: 3,489; makefile: 2,573; xml: 915; cs: 573; fortran: 503; javascript: 452
file content (112 lines) | stat: -rw-r--r-- 4,700 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
//===-------- PPCELFStreamer.cpp - ELF Object Output ---------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This is a custom MCELFStreamer for PowerPC.
//
// The purpose of the custom ELF streamer is to allow us to intercept
// instructions as they are being emitted and align all 8 byte instructions
// to a 64 byte boundary if required (by adding a 4 byte nop). This is important
// because 8 byte instructions are not allowed to cross 64 byte boundaries
// and by aliging anything that is within 4 bytes of the boundary we can
// guarantee that the 8 byte instructions do not cross that boundary.
//
//===----------------------------------------------------------------------===//


#include "PPCELFStreamer.h"
#include "PPCInstrInfo.h"
#include "PPCMCCodeEmitter.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstrDesc.h"
#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCSymbolELF.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/SourceMgr.h"

using namespace llvm;

PPCELFStreamer::PPCELFStreamer(MCContext &Context,
                               std::unique_ptr<MCAsmBackend> MAB,
                               std::unique_ptr<MCObjectWriter> OW,
                               std::unique_ptr<MCCodeEmitter> Emitter)
    : MCELFStreamer(Context, std::move(MAB), std::move(OW),
                    std::move(Emitter)), LastLabel(NULL) {
}

void PPCELFStreamer::emitPrefixedInstruction(const MCInst &Inst,
                                             const MCSubtargetInfo &STI) {
  // Prefixed instructions must not cross a 64-byte boundary (i.e. prefix is
  // before the boundary and the remaining 4-bytes are after the boundary). In
  // order to achieve this, a nop is added prior to any such boundary-crossing
  // prefixed instruction. Align to 64 bytes if possible but add a maximum of 4
  // bytes when trying to do that. If alignment requires adding more than 4
  // bytes then the instruction won't be aligned. When emitting a code alignment
  // a new fragment is created for this alignment. This fragment will contain
  // all of the nops required as part of the alignment operation. In the cases
  // when no nops are added then The fragment is still created but it remains
  // empty.
  emitCodeAlignment(64, 4);

  // Emit the instruction.
  // Since the previous emit created a new fragment then adding this instruction
  // also forces the addition of a new fragment. Inst is now the first
  // instruction in that new fragment.
  MCELFStreamer::emitInstruction(Inst, STI);

  // The above instruction is forced to start a new fragment because it
  // comes after a code alignment fragment. Get that new fragment.
  MCFragment *InstructionFragment = getCurrentFragment();
  SMLoc InstLoc = Inst.getLoc();
  // Check if there was a last label emitted.
  if (LastLabel && !LastLabel->isUnset() && LastLabelLoc.isValid() &&
      InstLoc.isValid()) {
    const SourceMgr *SourceManager = getContext().getSourceManager();
    unsigned InstLine = SourceManager->FindLineNumber(InstLoc);
    unsigned LabelLine = SourceManager->FindLineNumber(LastLabelLoc);
    // If the Label and the Instruction are on the same line then move the
    // label to the top of the fragment containing the aligned instruction that
    // was just added.
    if (InstLine == LabelLine) {
      AssignFragment(LastLabel, InstructionFragment);
      LastLabel->setOffset(0);
    }
  }
}

void PPCELFStreamer::emitInstruction(const MCInst &Inst,
                                     const MCSubtargetInfo &STI) {
  PPCMCCodeEmitter *Emitter =
      static_cast<PPCMCCodeEmitter*>(getAssembler().getEmitterPtr());

  // Special handling is only for prefixed instructions.
  if (!Emitter->isPrefixedInstruction(Inst)) {
    MCELFStreamer::emitInstruction(Inst, STI);
    return;
  }
  emitPrefixedInstruction(Inst, STI);
}

void PPCELFStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
  LastLabel = Symbol;
  LastLabelLoc = Loc;
  MCELFStreamer::emitLabel(Symbol);
}

MCELFStreamer *llvm::createPPCELFStreamer(
    MCContext &Context, std::unique_ptr<MCAsmBackend> MAB,
    std::unique_ptr<MCObjectWriter> OW,
    std::unique_ptr<MCCodeEmitter> Emitter) {
  return new PPCELFStreamer(Context, std::move(MAB), std::move(OW),
                            std::move(Emitter));
}