2007-06-25 15:11:25 +00:00
|
|
|
//===-- X86ATTAsmPrinter.h - Convert X86 LLVM code to AT&T assembly -------===//
|
2005-07-01 22:44:09 +00:00
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
2007-12-29 20:36:04 +00:00
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
2005-07-01 22:44:09 +00:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// AT&T assembly code printer class.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#ifndef X86ATTASMPRINTER_H
|
|
|
|
#define X86ATTASMPRINTER_H
|
|
|
|
|
2008-08-17 18:24:26 +00:00
|
|
|
#include "../X86.h"
|
|
|
|
#include "../X86MachineFunctionInfo.h"
|
|
|
|
#include "../X86TargetMachine.h"
|
2008-06-28 11:08:27 +00:00
|
|
|
#include "llvm/ADT/StringSet.h"
|
|
|
|
#include "llvm/CodeGen/AsmPrinter.h"
|
|
|
|
#include "llvm/CodeGen/DwarfWriter.h"
|
|
|
|
#include "llvm/CodeGen/MachineModuleInfo.h"
|
2005-07-01 22:44:09 +00:00
|
|
|
#include "llvm/CodeGen/ValueTypes.h"
|
2008-06-28 11:08:27 +00:00
|
|
|
#include "llvm/Support/Compiler.h"
|
2005-07-01 22:44:09 +00:00
|
|
|
|
|
|
|
namespace llvm {
|
|
|
|
|
2009-05-12 21:55:29 +00:00
|
|
|
class MachineJumpTableInfo;
|
2009-06-24 05:46:28 +00:00
|
|
|
class MCContext;
|
2009-06-19 00:47:33 +00:00
|
|
|
class MCInst;
|
2009-06-24 05:46:28 +00:00
|
|
|
class MCStreamer;
|
2008-06-28 11:08:27 +00:00
|
|
|
|
2009-02-24 08:30:20 +00:00
|
|
|
class VISIBILITY_HIDDEN X86ATTAsmPrinter : public AsmPrinter {
|
2008-06-28 11:08:27 +00:00
|
|
|
const X86Subtarget *Subtarget;
|
2009-06-24 05:46:28 +00:00
|
|
|
|
|
|
|
MCContext *Context;
|
|
|
|
MCStreamer *Streamer;
|
2009-02-24 08:30:20 +00:00
|
|
|
public:
|
2009-07-14 20:18:05 +00:00
|
|
|
explicit X86ATTAsmPrinter(formatted_raw_ostream &O, X86TargetMachine &TM,
|
2009-07-01 01:48:54 +00:00
|
|
|
const TargetAsmInfo *T, bool V)
|
|
|
|
: AsmPrinter(O, TM, T, V) {
|
2008-06-28 11:08:27 +00:00
|
|
|
Subtarget = &TM.getSubtarget<X86Subtarget>();
|
2009-06-24 05:46:28 +00:00
|
|
|
Context = 0;
|
|
|
|
Streamer = 0;
|
2008-06-28 11:08:27 +00:00
|
|
|
}
|
2005-07-01 22:44:09 +00:00
|
|
|
|
|
|
|
virtual const char *getPassName() const {
|
|
|
|
return "X86 AT&T-Style Assembly Printer";
|
|
|
|
}
|
|
|
|
|
2008-06-28 11:08:27 +00:00
|
|
|
void getAnalysisUsage(AnalysisUsage &AU) const {
|
|
|
|
AU.setPreservesAll();
|
|
|
|
if (Subtarget->isTargetDarwin() ||
|
|
|
|
Subtarget->isTargetELF() ||
|
|
|
|
Subtarget->isTargetCygMing()) {
|
|
|
|
AU.addRequired<MachineModuleInfo>();
|
|
|
|
}
|
2009-01-08 23:40:34 +00:00
|
|
|
AU.addRequired<DwarfWriter>();
|
2008-06-28 11:08:27 +00:00
|
|
|
AsmPrinter::getAnalysisUsage(AU);
|
|
|
|
}
|
|
|
|
|
2009-06-20 01:00:07 +00:00
|
|
|
bool doInitialization(Module &M);
|
2008-06-28 11:08:27 +00:00
|
|
|
bool doFinalization(Module &M);
|
|
|
|
|
2005-07-01 22:44:09 +00:00
|
|
|
/// printInstruction - This method is automatically generated by tablegen
|
|
|
|
/// from the instruction set description. This method returns true if the
|
|
|
|
/// machine instruction was sufficiently described to print it, otherwise it
|
|
|
|
/// returns false.
|
|
|
|
bool printInstruction(const MachineInstr *MI);
|
2009-06-19 00:47:33 +00:00
|
|
|
|
2009-06-19 23:59:57 +00:00
|
|
|
|
|
|
|
// New MCInst printing stuff.
|
|
|
|
bool printInstruction(const MCInst *MI);
|
|
|
|
|
2009-07-13 21:41:08 +00:00
|
|
|
void printSymbolOperand(const MachineOperand &MO);
|
2009-06-19 23:59:57 +00:00
|
|
|
void printOperand(const MCInst *MI, unsigned OpNo,
|
Reimplement rip-relative addressing in the X86-64 backend. The new
implementation primarily differs from the former in that the asmprinter
doesn't make a zillion decisions about whether or not something will be
RIP relative or not. Instead, those decisions are made by isel lowering
and propagated through to the asm printer. To achieve this, we:
1. Represent RIP relative addresses by setting the base of the X86 addr
mode to X86::RIP.
2. When ISel Lowering decides that it is safe to use RIP, it lowers to
X86ISD::WrapperRIP. When it is unsafe to use RIP, it lowers to
X86ISD::Wrapper as before.
3. This removes isRIPRel from X86ISelAddressMode, representing it with
a basereg of RIP instead.
4. The addressing mode matching logic in isel is greatly simplified.
5. The asmprinter is greatly simplified, notably the "NotRIPRel" predicate
passed through various printoperand routines is gone now.
6. The various symbol printing routines in asmprinter now no longer infer
when to emit (%rip), they just print the symbol.
I think this is a big improvement over the previous situation. It does have
two small caveats though: 1. I implemented a horrible "no-rip" modifier for
the inline asm "P" constraint modifier. This is a short term hack, there is
a much better, but more involved, solution. 2. I had to xfail an
-aggressive-remat testcase because it isn't handling the use of RIP in the
constant-pool reading instruction. This specific test is easy to fix without
-aggressive-remat, which I intend to do next.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@74372 91177308-0d34-0410-b5e6-96231b3b80d8
2009-06-27 04:16:01 +00:00
|
|
|
const char *Modifier = 0);
|
2009-06-20 07:03:18 +00:00
|
|
|
void printMemReference(const MCInst *MI, unsigned Op);
|
|
|
|
void printLeaMemReference(const MCInst *MI, unsigned Op);
|
2009-06-19 23:59:57 +00:00
|
|
|
void printSSECC(const MCInst *MI, unsigned Op);
|
|
|
|
void printPICLabel(const MCInst *MI, unsigned Op);
|
2009-06-20 19:34:09 +00:00
|
|
|
void print_pcrel_imm(const MCInst *MI, unsigned OpNo);
|
|
|
|
|
2009-06-19 23:59:57 +00:00
|
|
|
void printi8mem(const MCInst *MI, unsigned OpNo) {
|
|
|
|
printMemReference(MI, OpNo);
|
|
|
|
}
|
|
|
|
void printi16mem(const MCInst *MI, unsigned OpNo) {
|
|
|
|
printMemReference(MI, OpNo);
|
|
|
|
}
|
|
|
|
void printi32mem(const MCInst *MI, unsigned OpNo) {
|
|
|
|
printMemReference(MI, OpNo);
|
|
|
|
}
|
|
|
|
void printi64mem(const MCInst *MI, unsigned OpNo) {
|
|
|
|
printMemReference(MI, OpNo);
|
|
|
|
}
|
|
|
|
void printi128mem(const MCInst *MI, unsigned OpNo) {
|
|
|
|
printMemReference(MI, OpNo);
|
|
|
|
}
|
|
|
|
void printf32mem(const MCInst *MI, unsigned OpNo) {
|
|
|
|
printMemReference(MI, OpNo);
|
|
|
|
}
|
|
|
|
void printf64mem(const MCInst *MI, unsigned OpNo) {
|
|
|
|
printMemReference(MI, OpNo);
|
|
|
|
}
|
|
|
|
void printf80mem(const MCInst *MI, unsigned OpNo) {
|
|
|
|
printMemReference(MI, OpNo);
|
|
|
|
}
|
|
|
|
void printf128mem(const MCInst *MI, unsigned OpNo) {
|
|
|
|
printMemReference(MI, OpNo);
|
|
|
|
}
|
|
|
|
void printlea32mem(const MCInst *MI, unsigned OpNo) {
|
|
|
|
printLeaMemReference(MI, OpNo);
|
|
|
|
}
|
|
|
|
void printlea64mem(const MCInst *MI, unsigned OpNo) {
|
|
|
|
printLeaMemReference(MI, OpNo);
|
|
|
|
}
|
|
|
|
void printlea64_32mem(const MCInst *MI, unsigned OpNo) {
|
2009-06-20 07:03:18 +00:00
|
|
|
printLeaMemReference(MI, OpNo);
|
2009-06-19 23:59:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-07-01 22:44:09 +00:00
|
|
|
|
2006-02-06 23:41:19 +00:00
|
|
|
// These methods are used by the tablegen'erated instruction printer.
|
|
|
|
void printOperand(const MachineInstr *MI, unsigned OpNo,
|
Reimplement rip-relative addressing in the X86-64 backend. The new
implementation primarily differs from the former in that the asmprinter
doesn't make a zillion decisions about whether or not something will be
RIP relative or not. Instead, those decisions are made by isel lowering
and propagated through to the asm printer. To achieve this, we:
1. Represent RIP relative addresses by setting the base of the X86 addr
mode to X86::RIP.
2. When ISel Lowering decides that it is safe to use RIP, it lowers to
X86ISD::WrapperRIP. When it is unsafe to use RIP, it lowers to
X86ISD::Wrapper as before.
3. This removes isRIPRel from X86ISelAddressMode, representing it with
a basereg of RIP instead.
4. The addressing mode matching logic in isel is greatly simplified.
5. The asmprinter is greatly simplified, notably the "NotRIPRel" predicate
passed through various printoperand routines is gone now.
6. The various symbol printing routines in asmprinter now no longer infer
when to emit (%rip), they just print the symbol.
I think this is a big improvement over the previous situation. It does have
two small caveats though: 1. I implemented a horrible "no-rip" modifier for
the inline asm "P" constraint modifier. This is a short term hack, there is
a much better, but more involved, solution. 2. I had to xfail an
-aggressive-remat testcase because it isn't handling the use of RIP in the
constant-pool reading instruction. This specific test is easy to fix without
-aggressive-remat, which I intend to do next.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@74372 91177308-0d34-0410-b5e6-96231b3b80d8
2009-06-27 04:16:01 +00:00
|
|
|
const char *Modifier = 0);
|
2009-06-20 19:34:09 +00:00
|
|
|
void print_pcrel_imm(const MachineInstr *MI, unsigned OpNo);
|
2005-11-30 18:54:35 +00:00
|
|
|
void printi8mem(const MachineInstr *MI, unsigned OpNo) {
|
2005-07-01 22:44:09 +00:00
|
|
|
printMemReference(MI, OpNo);
|
|
|
|
}
|
2005-11-30 18:54:35 +00:00
|
|
|
void printi16mem(const MachineInstr *MI, unsigned OpNo) {
|
|
|
|
printMemReference(MI, OpNo);
|
|
|
|
}
|
|
|
|
void printi32mem(const MachineInstr *MI, unsigned OpNo) {
|
|
|
|
printMemReference(MI, OpNo);
|
|
|
|
}
|
|
|
|
void printi64mem(const MachineInstr *MI, unsigned OpNo) {
|
|
|
|
printMemReference(MI, OpNo);
|
|
|
|
}
|
2006-02-22 02:26:30 +00:00
|
|
|
void printi128mem(const MachineInstr *MI, unsigned OpNo) {
|
|
|
|
printMemReference(MI, OpNo);
|
|
|
|
}
|
2009-06-30 19:24:59 +00:00
|
|
|
void printi256mem(const MachineInstr *MI, unsigned OpNo) {
|
|
|
|
printMemReference(MI, OpNo);
|
|
|
|
}
|
2005-11-30 18:54:35 +00:00
|
|
|
void printf32mem(const MachineInstr *MI, unsigned OpNo) {
|
|
|
|
printMemReference(MI, OpNo);
|
|
|
|
}
|
|
|
|
void printf64mem(const MachineInstr *MI, unsigned OpNo) {
|
|
|
|
printMemReference(MI, OpNo);
|
|
|
|
}
|
2007-08-05 18:49:15 +00:00
|
|
|
void printf80mem(const MachineInstr *MI, unsigned OpNo) {
|
|
|
|
printMemReference(MI, OpNo);
|
|
|
|
}
|
2006-01-31 22:28:30 +00:00
|
|
|
void printf128mem(const MachineInstr *MI, unsigned OpNo) {
|
2005-11-30 18:54:35 +00:00
|
|
|
printMemReference(MI, OpNo);
|
|
|
|
}
|
2009-06-30 19:24:59 +00:00
|
|
|
void printf256mem(const MachineInstr *MI, unsigned OpNo) {
|
|
|
|
printMemReference(MI, OpNo);
|
|
|
|
}
|
2009-04-08 21:14:34 +00:00
|
|
|
void printlea32mem(const MachineInstr *MI, unsigned OpNo) {
|
|
|
|
printLeaMemReference(MI, OpNo);
|
|
|
|
}
|
|
|
|
void printlea64mem(const MachineInstr *MI, unsigned OpNo) {
|
|
|
|
printLeaMemReference(MI, OpNo);
|
|
|
|
}
|
2006-09-08 06:48:29 +00:00
|
|
|
void printlea64_32mem(const MachineInstr *MI, unsigned OpNo) {
|
2009-04-08 21:14:34 +00:00
|
|
|
printLeaMemReference(MI, OpNo, "subreg64");
|
2006-09-08 06:48:29 +00:00
|
|
|
}
|
2008-06-28 11:08:27 +00:00
|
|
|
|
2009-06-15 04:42:32 +00:00
|
|
|
bool printAsmMRegister(const MachineOperand &MO, char Mode);
|
2008-06-28 11:09:48 +00:00
|
|
|
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
|
2006-04-28 21:19:05 +00:00
|
|
|
unsigned AsmVariant, const char *ExtraCode);
|
2008-06-28 11:09:48 +00:00
|
|
|
bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
|
2006-04-28 21:19:05 +00:00
|
|
|
unsigned AsmVariant, const char *ExtraCode);
|
2008-06-28 11:08:27 +00:00
|
|
|
|
2006-04-28 23:11:40 +00:00
|
|
|
void printMachineInstruction(const MachineInstr *MI);
|
2005-11-30 18:54:35 +00:00
|
|
|
void printSSECC(const MachineInstr *MI, unsigned Op);
|
2006-09-08 06:48:29 +00:00
|
|
|
void printMemReference(const MachineInstr *MI, unsigned Op,
|
Reimplement rip-relative addressing in the X86-64 backend. The new
implementation primarily differs from the former in that the asmprinter
doesn't make a zillion decisions about whether or not something will be
RIP relative or not. Instead, those decisions are made by isel lowering
and propagated through to the asm printer. To achieve this, we:
1. Represent RIP relative addresses by setting the base of the X86 addr
mode to X86::RIP.
2. When ISel Lowering decides that it is safe to use RIP, it lowers to
X86ISD::WrapperRIP. When it is unsafe to use RIP, it lowers to
X86ISD::Wrapper as before.
3. This removes isRIPRel from X86ISelAddressMode, representing it with
a basereg of RIP instead.
4. The addressing mode matching logic in isel is greatly simplified.
5. The asmprinter is greatly simplified, notably the "NotRIPRel" predicate
passed through various printoperand routines is gone now.
6. The various symbol printing routines in asmprinter now no longer infer
when to emit (%rip), they just print the symbol.
I think this is a big improvement over the previous situation. It does have
two small caveats though: 1. I implemented a horrible "no-rip" modifier for
the inline asm "P" constraint modifier. This is a short term hack, there is
a much better, but more involved, solution. 2. I had to xfail an
-aggressive-remat testcase because it isn't handling the use of RIP in the
constant-pool reading instruction. This specific test is easy to fix without
-aggressive-remat, which I intend to do next.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@74372 91177308-0d34-0410-b5e6-96231b3b80d8
2009-06-27 04:16:01 +00:00
|
|
|
const char *Modifier=NULL);
|
2009-04-08 21:14:34 +00:00
|
|
|
void printLeaMemReference(const MachineInstr *MI, unsigned Op,
|
Reimplement rip-relative addressing in the X86-64 backend. The new
implementation primarily differs from the former in that the asmprinter
doesn't make a zillion decisions about whether or not something will be
RIP relative or not. Instead, those decisions are made by isel lowering
and propagated through to the asm printer. To achieve this, we:
1. Represent RIP relative addresses by setting the base of the X86 addr
mode to X86::RIP.
2. When ISel Lowering decides that it is safe to use RIP, it lowers to
X86ISD::WrapperRIP. When it is unsafe to use RIP, it lowers to
X86ISD::Wrapper as before.
3. This removes isRIPRel from X86ISelAddressMode, representing it with
a basereg of RIP instead.
4. The addressing mode matching logic in isel is greatly simplified.
5. The asmprinter is greatly simplified, notably the "NotRIPRel" predicate
passed through various printoperand routines is gone now.
6. The various symbol printing routines in asmprinter now no longer infer
when to emit (%rip), they just print the symbol.
I think this is a big improvement over the previous situation. It does have
two small caveats though: 1. I implemented a horrible "no-rip" modifier for
the inline asm "P" constraint modifier. This is a short term hack, there is
a much better, but more involved, solution. 2. I had to xfail an
-aggressive-remat testcase because it isn't handling the use of RIP in the
constant-pool reading instruction. This specific test is easy to fix without
-aggressive-remat, which I intend to do next.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@74372 91177308-0d34-0410-b5e6-96231b3b80d8
2009-06-27 04:16:01 +00:00
|
|
|
const char *Modifier=NULL);
|
Much improved pic jumptable codegen:
Then:
call "L1$pb"
"L1$pb":
popl %eax
...
LBB1_1: # entry
imull $4, %ecx, %ecx
leal LJTI1_0-"L1$pb"(%eax), %edx
addl LJTI1_0-"L1$pb"(%ecx,%eax), %edx
jmpl *%edx
.align 2
.set L1_0_set_3,LBB1_3-LJTI1_0
.set L1_0_set_2,LBB1_2-LJTI1_0
.set L1_0_set_5,LBB1_5-LJTI1_0
.set L1_0_set_4,LBB1_4-LJTI1_0
LJTI1_0:
.long L1_0_set_3
.long L1_0_set_2
Now:
call "L1$pb"
"L1$pb":
popl %eax
...
LBB1_1: # entry
addl LJTI1_0-"L1$pb"(%eax,%ecx,4), %eax
jmpl *%eax
.align 2
.set L1_0_set_3,LBB1_3-"L1$pb"
.set L1_0_set_2,LBB1_2-"L1$pb"
.set L1_0_set_5,LBB1_5-"L1$pb"
.set L1_0_set_4,LBB1_4-"L1$pb"
LJTI1_0:
.long L1_0_set_3
.long L1_0_set_2
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@43924 91177308-0d34-0410-b5e6-96231b3b80d8
2007-11-09 01:32:10 +00:00
|
|
|
void printPICJumpTableSetLabel(unsigned uid,
|
|
|
|
const MachineBasicBlock *MBB) const;
|
|
|
|
void printPICJumpTableSetLabel(unsigned uid, unsigned uid2,
|
|
|
|
const MachineBasicBlock *MBB) const {
|
|
|
|
AsmPrinter::printPICJumpTableSetLabel(uid, uid2, MBB);
|
|
|
|
}
|
2007-11-14 09:18:41 +00:00
|
|
|
void printPICJumpTableEntry(const MachineJumpTableInfo *MJTI,
|
|
|
|
const MachineBasicBlock *MBB,
|
|
|
|
unsigned uid) const;
|
2008-06-28 11:08:27 +00:00
|
|
|
|
2006-02-18 00:15:05 +00:00
|
|
|
void printPICLabel(const MachineInstr *MI, unsigned Op);
|
2008-06-28 11:09:32 +00:00
|
|
|
void printModuleLevelGV(const GlobalVariable* GVar);
|
|
|
|
|
2009-06-24 19:19:16 +00:00
|
|
|
void PrintPICBaseSymbol() const;
|
|
|
|
|
2005-07-01 22:44:09 +00:00
|
|
|
bool runOnMachineFunction(MachineFunction &F);
|
2008-06-28 11:08:27 +00:00
|
|
|
|
2008-06-28 11:09:01 +00:00
|
|
|
void emitFunctionHeader(const MachineFunction &MF);
|
|
|
|
|
2008-06-28 11:08:27 +00:00
|
|
|
// Necessary for Darwin to print out the apprioriate types of linker stubs
|
2009-07-14 18:17:16 +00:00
|
|
|
StringMap<std::string> FnStubs, GVStubs, HiddenGVStubs;
|
2008-06-28 11:08:27 +00:00
|
|
|
|
|
|
|
// Necessary for dllexport support
|
2009-07-14 18:17:16 +00:00
|
|
|
StringSet<> CygMingStubs, DLLExportedFns, DLLExportedGVs;
|
2008-06-28 11:08:27 +00:00
|
|
|
|
|
|
|
// We have to propagate some information about MachineFunction to
|
|
|
|
// AsmPrinter. It's ok, when we're printing the function, since we have
|
|
|
|
// access to MachineFunction and can get the appropriate MachineFunctionInfo.
|
|
|
|
// Unfortunately, this is not possible when we're printing reference to
|
|
|
|
// Function (e.g. calling it and so on). Even more, there is no way to get the
|
|
|
|
// corresponding MachineFunctions: it can even be not created at all. That's
|
|
|
|
// why we should use additional structure, when we're collecting all necessary
|
|
|
|
// information.
|
|
|
|
//
|
|
|
|
// This structure is using e.g. for name decoration for stdcall & fastcall'ed
|
|
|
|
// function, since we have to use arguments' size for decoration.
|
|
|
|
typedef std::map<const Function*, X86MachineFunctionInfo> FMFInfoMap;
|
|
|
|
FMFInfoMap FunctionInfoMap;
|
|
|
|
|
|
|
|
void decorateName(std::string& Name, const GlobalValue* GV);
|
2005-07-01 22:44:09 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
} // end namespace llvm
|
|
|
|
|
|
|
|
#endif
|