aboutsummaryrefslogtreecommitdiff
path: root/lib/Target/ARM/ARMAsmPrinter.h
blob: b2d31244c5fe22b983782b36999b1c38b0f50b9e (plain)
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
//===-- ARMAsmPrinter.h - Print machine code to an ARM .s file --*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// ARM Assembly printer class.
//
//===----------------------------------------------------------------------===//

#ifndef ARMASMPRINTER_H
#define ARMASMPRINTER_H

#include "ARM.h"
#include "ARMTargetMachine.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/Support/Compiler.h"

namespace llvm {

class MCOperand;

namespace ARM {
  enum DW_ISA {
    DW_ISA_ARM_thumb = 1,
    DW_ISA_ARM_arm = 2
  };
}

class LLVM_LIBRARY_VISIBILITY ARMAsmPrinter : public AsmPrinter {

  /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can
  /// make the right decision when printing asm code for different targets.
  const ARMSubtarget *Subtarget;

  /// AFI - Keep a pointer to ARMFunctionInfo for the current
  /// MachineFunction.
  ARMFunctionInfo *AFI;

  /// MCP - Keep a pointer to constantpool entries of the current
  /// MachineFunction.
  const MachineConstantPool *MCP;

  /// InConstantPool - Maintain state when emitting a sequence of constant
  /// pool entries so we can properly mark them as data regions.
  bool InConstantPool;
public:
  explicit ARMAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
    : AsmPrinter(TM, Streamer), AFI(NULL), MCP(NULL), InConstantPool(false) {
      Subtarget = &TM.getSubtarget<ARMSubtarget>();
    }

  virtual const char *getPassName() const LLVM_OVERRIDE {
    return "ARM Assembly Printer";
  }

  void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O,
                    const char *Modifier = 0);

  virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
                               unsigned AsmVariant, const char *ExtraCode,
                               raw_ostream &O) LLVM_OVERRIDE;
  virtual bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum,
                                     unsigned AsmVariant, const char *ExtraCode,
                                     raw_ostream &O) LLVM_OVERRIDE;

  void EmitJumpTable(const MachineInstr *MI);
  void EmitJump2Table(const MachineInstr *MI);
  virtual void EmitInstruction(const MachineInstr *MI) LLVM_OVERRIDE;
  virtual bool runOnMachineFunction(MachineFunction &F) LLVM_OVERRIDE;

  // @LOCALMOD-START
  // usually this does nothing on ARM as constants pools
  // are handled with custom code.
  // For the sfi case we do not use the custom logic and fall back
  // to the default implementation.
  virtual void EmitConstantPool() LLVM_OVERRIDE {
    if (FlagSfiDisableCP) AsmPrinter::EmitConstantPool();
  }
  // @LOCALMOD-END

  virtual void EmitFunctionBodyEnd() LLVM_OVERRIDE;
  virtual void EmitFunctionEntryLabel() LLVM_OVERRIDE;
  virtual void EmitStartOfAsmFile(Module &M) LLVM_OVERRIDE;
  virtual void EmitEndOfAsmFile(Module &M) LLVM_OVERRIDE;
  virtual void EmitXXStructor(const Constant *CV) LLVM_OVERRIDE;

  // lowerOperand - Convert a MachineOperand into the equivalent MCOperand.
  bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp);
  
  // @LOCALMOD-START
  /// UseReadOnlyJumpTables - true if JumpTableInfo must be in rodata.
  virtual bool UseReadOnlyJumpTables() const;
  /// GetTargetBasicBlockAlign - Get the target alignment for basic blocks.
  virtual unsigned GetTargetBasicBlockAlign() const;
  /// GetTargetLabelAlign - Get optional alignment for TargetOpcode
  /// labels E.g., EH_LABEL.
  /// TODO(sehr,robertm): remove this if the labeled block has address taken.
  virtual unsigned GetTargetLabelAlign(const MachineInstr *MI) const;
  // @LOCALMOD-END

private:
  // Helpers for EmitStartOfAsmFile() and EmitEndOfAsmFile()
  void emitAttributes();

  // Helper for ELF .o only
  void emitARMAttributeSection();

  // Generic helper used to emit e.g. ARMv5 mul pseudos
  void EmitPatchedInstruction(const MachineInstr *MI, unsigned TargetOpc);

  void EmitUnwindingInstruction(const MachineInstr *MI);

  // emitPseudoExpansionLowering - tblgen'erated.
  bool emitPseudoExpansionLowering(MCStreamer &OutStreamer,
                                   const MachineInstr *MI);

public:
  void PrintDebugValueComment(const MachineInstr *MI, raw_ostream &OS);

  virtual MachineLocation
    getDebugValueLocation(const MachineInstr *MI) const LLVM_OVERRIDE;

  /// EmitDwarfRegOp - Emit dwarf register operation.
  virtual void EmitDwarfRegOp(const MachineLocation &MLoc) const LLVM_OVERRIDE;

  virtual unsigned getISAEncoding() LLVM_OVERRIDE {
    // ARM/Darwin adds ISA to the DWARF info for each function.
    if (!Subtarget->isTargetDarwin())
      return 0;
    return Subtarget->isThumb() ?
      ARM::DW_ISA_ARM_thumb : ARM::DW_ISA_ARM_arm;
  }

private:
  MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol);
  MCSymbol *GetARMJTIPICJumpTableLabel2(unsigned uid, unsigned uid2) const;

  MCSymbol *GetARMSJLJEHLabel() const;

  MCSymbol *GetARMGVSymbol(const GlobalValue *GV);

public:
  /// EmitMachineConstantPoolValue - Print a machine constantpool value to
  /// the .s file.
  virtual void
    EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) LLVM_OVERRIDE;
};
} // end namespace llvm

#endif