llvm-project/llvm/lib/Target/ARM/ARMAsmPrinter.h

159 lines
5.7 KiB
C
Raw Normal View History

//===-- 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;
/// OptimizationGoals - Maintain a combined optimization goal for all
/// functions in a module: one of Tag_ABI_optimization_goals values,
/// -1 if uninitialized, 0 if conflicting goals
int OptimizationGoals;
/// List of globals that have had their storage promoted to a constant
/// pool. This lives between calls to runOnMachineFunction and collects
/// data from every MachineFunction. It is used during doFinalization
/// when all non-function globals are emitted.
SmallPtrSet<const GlobalVariable*,2> PromotedGlobals;
/// Set of globals in PromotedGlobals that we've emitted labels for.
/// We need to emit labels even for promoted globals so that DWARF
/// debug info can link properly.
SmallPtrSet<const GlobalVariable*,2> EmittedPromotedGlobalLabels;
public:
explicit ARMAsmPrinter(TargetMachine &TM,
std::unique_ptr<MCStreamer> Streamer);
StringRef getPassName() const override {
return "ARM Assembly Printer";
}
void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O);
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 EmitJumpTableAddrs(const MachineInstr *MI);
void EmitJumpTableInsts(const MachineInstr *MI);
void EmitJumpTableTBInst(const MachineInstr *MI, unsigned OffsetWidth);
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 DataLayout &DL, const Constant *CV) override;
void EmitGlobalVariable(const GlobalVariable *GV) override;
// lowerOperand - Convert a MachineOperand into the equivalent MCOperand.
bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp);
//===------------------------------------------------------------------===//
// XRay implementation
//===------------------------------------------------------------------===//
public:
// XRay-specific lowering for ARM.
void LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI);
void LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI);
[XRay] Support for for tail calls for ARM no-Thumb This patch adds simplified support for tail calls on ARM with XRay instrumentation. Known issue: compiled with generic flags: `-O3 -g -fxray-instrument -Wall -std=c++14 -ffunction-sections -fdata-sections` (this list doesn't include my specific flags like --target=armv7-linux-gnueabihf etc.), the following program #include <cstdio> #include <cassert> #include <xray/xray_interface.h> [[clang::xray_always_instrument]] void __attribute__ ((noinline)) fC() { std::printf("In fC()\n"); } [[clang::xray_always_instrument]] void __attribute__ ((noinline)) fB() { std::printf("In fB()\n"); fC(); } [[clang::xray_always_instrument]] void __attribute__ ((noinline)) fA() { std::printf("In fA()\n"); fB(); } // Avoid infinite recursion in case the logging function is instrumented (so calls logging // function again). [[clang::xray_never_instrument]] void simplyPrint(int32_t functionId, XRayEntryType xret) { printf("XRay: functionId=%d type=%d.\n", int(functionId), int(xret)); } int main(int argc, char* argv[]) { __xray_set_handler(simplyPrint); printf("Patching...\n"); __xray_patch(); fA(); printf("Unpatching...\n"); __xray_unpatch(); fA(); return 0; } gives the following output: Patching... XRay: functionId=3 type=0. In fA() XRay: functionId=3 type=1. XRay: functionId=2 type=0. In fB() XRay: functionId=2 type=1. XRay: functionId=1 type=0. XRay: functionId=1 type=1. In fC() Unpatching... In fA() In fB() In fC() So for function fC() the exit sled seems to be called too much before function exit: before printing In fC(). Debugging shows that the above happens because printf from fC is also called as a tail call. So first the exit sled of fC is executed, and only then printf is jumped into. So it seems we can't do anything about this with the current approach (i.e. within the simplification described in https://reviews.llvm.org/D23988 ). Differential Revision: https://reviews.llvm.org/D25030 llvm-svn: 284456
2016-10-18 13:54:15 +08:00
void LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI);
private:
void EmitSled(const MachineInstr &MI, SledKind Kind);
// 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.
const Triple &TT = TM.getTargetTriple();
if (!TT.isOSBinFormatMachO())
return 0;
bool isThumb = TT.getArch() == Triple::thumb ||
TT.getArch() == Triple::thumbeb ||
TT.getSubArch() == Triple::ARMSubArch_v7m ||
TT.getSubArch() == Triple::ARMSubArch_v6m;
return isThumb ? ARM::DW_ISA_ARM_thumb : ARM::DW_ISA_ARM_arm;
}
private:
MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol);
MCSymbol *GetARMJTIPICJumpTableLabel(unsigned uid) 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