mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-23 02:29:18 +00:00
So there are a couple of issues with indirect calls on thumbv4t. First, the most 'obvious' instruction, 'blx' isn't available until v5t. And secondly, the next-most-obvious sequence: 'mov lr, pc; bx rN' doesn't DTRT in thumb code because the saved off pc has its thumb bit cleared, so when the callee returns we end up in ARM mode.... yuck. The solution is to 'bl' to a nearby landing pad with a 'bx rN' in it. We could cut down on code size by sharing the landing pads between call sites that are close enough, but for the moment let's do correctness first and look at performance later. Patch by: Iain Sandoe http://reviews.llvm.org/D6519 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@223380 91177308-0d34-0410-b5e6-96231b3b80d8
133 lines
4.3 KiB
C++
133 lines
4.3 KiB
C++
//===-- ARMAsmPrinter.h - ARM implementation of AsmPrinter ------*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_LIB_TARGET_ARM_ARMASMPRINTER_H
|
|
#define LLVM_LIB_TARGET_ARM_ARMASMPRINTER_H
|
|
|
|
#include "ARMSubtarget.h"
|
|
#include "llvm/CodeGen/AsmPrinter.h"
|
|
#include "llvm/Target/TargetMachine.h"
|
|
|
|
namespace llvm {
|
|
|
|
class ARMFunctionInfo;
|
|
class MCOperand;
|
|
class MachineConstantPool;
|
|
class MachineOperand;
|
|
class MCSymbol;
|
|
|
|
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;
|
|
|
|
/// ThumbIndirectPads - These maintain a per-function list of jump pad
|
|
/// labels used for ARMv4t thumb code to make register indirect calls.
|
|
SmallVector<std::pair<unsigned, MCSymbol*>, 4> ThumbIndirectPads;
|
|
|
|
public:
|
|
explicit ARMAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
|
|
: AsmPrinter(TM, Streamer), AFI(nullptr), MCP(nullptr),
|
|
InConstantPool(false) {
|
|
Subtarget = &TM.getSubtarget<ARMSubtarget>();
|
|
}
|
|
|
|
const char *getPassName() const override {
|
|
return "ARM Assembly / Object Emitter";
|
|
}
|
|
|
|
void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O,
|
|
const char *Modifier = nullptr);
|
|
|
|
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
|
|
unsigned AsmVariant, const char *ExtraCode,
|
|
raw_ostream &O) override;
|
|
bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum,
|
|
unsigned AsmVariant, const char *ExtraCode,
|
|
raw_ostream &O) override;
|
|
|
|
void emitInlineAsmEnd(const MCSubtargetInfo &StartInfo,
|
|
const MCSubtargetInfo *EndInfo) const override;
|
|
|
|
void EmitJumpTable(const MachineInstr *MI);
|
|
void EmitJump2Table(const MachineInstr *MI);
|
|
void EmitInstruction(const MachineInstr *MI) override;
|
|
bool runOnMachineFunction(MachineFunction &F) override;
|
|
|
|
void EmitConstantPool() override {
|
|
// we emit constant pools customly!
|
|
}
|
|
void EmitFunctionBodyEnd() override;
|
|
void EmitFunctionEntryLabel() override;
|
|
void EmitStartOfAsmFile(Module &M) override;
|
|
void EmitEndOfAsmFile(Module &M) override;
|
|
void EmitXXStructor(const Constant *CV) override;
|
|
|
|
// lowerOperand - Convert a MachineOperand into the equivalent MCOperand.
|
|
bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp);
|
|
|
|
private:
|
|
// Helpers for EmitStartOfAsmFile() and EmitEndOfAsmFile()
|
|
void emitAttributes();
|
|
|
|
// 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:
|
|
unsigned getISAEncoding() override {
|
|
// ARM/Darwin adds ISA to the DWARF info for each function.
|
|
if (!Subtarget->isTargetMachO())
|
|
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, unsigned char TargetFlags);
|
|
|
|
public:
|
|
/// EmitMachineConstantPoolValue - Print a machine constantpool value to
|
|
/// the .s file.
|
|
void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) override;
|
|
};
|
|
} // end namespace llvm
|
|
|
|
#endif
|