2005-01-24 18:37:48 +00:00
|
|
|
//===-- AlphaAsmPrinter.cpp - Alpha LLVM assembly writer ------------------===//
|
2005-04-21 23:13:11 +00:00
|
|
|
//
|
2005-01-22 23:41:55 +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-04-21 23:13:11 +00:00
|
|
|
//
|
2005-01-22 23:41:55 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file contains a printer that converts from our internal representation
|
|
|
|
// of machine-dependent LLVM code to GAS-format Alpha assembly language.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2006-12-19 22:59:26 +00:00
|
|
|
#define DEBUG_TYPE "asm-printer"
|
2005-01-22 23:41:55 +00:00
|
|
|
#include "Alpha.h"
|
|
|
|
#include "AlphaInstrInfo.h"
|
2005-09-29 22:54:56 +00:00
|
|
|
#include "AlphaTargetMachine.h"
|
2005-01-22 23:41:55 +00:00
|
|
|
#include "llvm/Module.h"
|
2009-06-25 00:47:42 +00:00
|
|
|
#include "llvm/MDNode.h"
|
2005-03-17 15:38:16 +00:00
|
|
|
#include "llvm/Type.h"
|
2005-01-22 23:41:55 +00:00
|
|
|
#include "llvm/Assembly/Writer.h"
|
|
|
|
#include "llvm/CodeGen/AsmPrinter.h"
|
2009-02-18 23:12:06 +00:00
|
|
|
#include "llvm/CodeGen/DwarfWriter.h"
|
2006-09-06 18:34:40 +00:00
|
|
|
#include "llvm/Target/TargetAsmInfo.h"
|
2005-01-22 23:41:55 +00:00
|
|
|
#include "llvm/Target/TargetMachine.h"
|
2006-12-06 18:19:53 +00:00
|
|
|
#include "llvm/Support/Compiler.h"
|
2009-07-08 19:04:27 +00:00
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
2005-01-22 23:41:55 +00:00
|
|
|
#include "llvm/Support/Mangler.h"
|
2008-08-21 00:14:44 +00:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2005-01-22 23:41:55 +00:00
|
|
|
#include "llvm/ADT/Statistic.h"
|
|
|
|
using namespace llvm;
|
|
|
|
|
2006-12-19 22:59:26 +00:00
|
|
|
STATISTIC(EmittedInsts, "Number of machine instrs printed");
|
|
|
|
|
2005-01-22 23:41:55 +00:00
|
|
|
namespace {
|
2006-09-06 18:34:40 +00:00
|
|
|
struct VISIBILITY_HIDDEN AlphaAsmPrinter : public AsmPrinter {
|
2005-01-22 23:41:55 +00:00
|
|
|
/// Unique incrementer for label values for referencing Global values.
|
|
|
|
///
|
2005-04-21 23:13:11 +00:00
|
|
|
|
2009-04-29 00:15:41 +00:00
|
|
|
explicit AlphaAsmPrinter(raw_ostream &o, TargetMachine &tm,
|
2009-07-01 01:48:54 +00:00
|
|
|
const TargetAsmInfo *T, bool V)
|
|
|
|
: AsmPrinter(o, tm, T, V) {}
|
2005-01-22 23:41:55 +00:00
|
|
|
|
|
|
|
virtual const char *getPassName() const {
|
|
|
|
return "Alpha Assembly Printer";
|
|
|
|
}
|
|
|
|
bool printInstruction(const MachineInstr *MI);
|
|
|
|
void printOp(const MachineOperand &MO, bool IsCallOp = false);
|
2005-11-30 18:54:35 +00:00
|
|
|
void printOperand(const MachineInstr *MI, int opNum);
|
2005-01-22 23:41:55 +00:00
|
|
|
void printBaseOffsetPair (const MachineInstr *MI, int i, bool brackets=true);
|
2008-08-07 09:53:57 +00:00
|
|
|
void printModuleLevelGV(const GlobalVariable* GVar);
|
2005-04-21 23:13:11 +00:00
|
|
|
bool runOnMachineFunction(MachineFunction &F);
|
2005-01-22 23:41:55 +00:00
|
|
|
bool doInitialization(Module &M);
|
|
|
|
bool doFinalization(Module &M);
|
2008-08-07 09:53:57 +00:00
|
|
|
|
2006-06-21 13:37:27 +00:00
|
|
|
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
|
|
|
|
unsigned AsmVariant, const char *ExtraCode);
|
2008-08-07 09:53:57 +00:00
|
|
|
bool PrintAsmMemoryOperand(const MachineInstr *MI,
|
2007-04-16 18:10:23 +00:00
|
|
|
unsigned OpNo,
|
2008-08-07 09:53:57 +00:00
|
|
|
unsigned AsmVariant,
|
2007-04-16 18:10:23 +00:00
|
|
|
const char *ExtraCode);
|
2005-01-22 23:41:55 +00:00
|
|
|
};
|
|
|
|
} // end of anonymous namespace
|
|
|
|
|
|
|
|
/// createAlphaCodePrinterPass - Returns a pass that prints the Alpha
|
|
|
|
/// assembly code for a MachineFunction to the given output stream,
|
|
|
|
/// using the given target machine description. This should work
|
|
|
|
/// regardless of whether the function is in SSA form.
|
|
|
|
///
|
2008-08-21 00:14:44 +00:00
|
|
|
FunctionPass *llvm::createAlphaCodePrinterPass(raw_ostream &o,
|
2009-02-24 08:30:20 +00:00
|
|
|
TargetMachine &tm,
|
2009-04-29 00:15:41 +00:00
|
|
|
bool verbose) {
|
2009-07-01 01:48:54 +00:00
|
|
|
return new AlphaAsmPrinter(o, tm, tm.getTargetAsmInfo(), verbose);
|
2005-01-22 23:41:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#include "AlphaGenAsmWriter.inc"
|
|
|
|
|
2005-11-30 18:54:35 +00:00
|
|
|
void AlphaAsmPrinter::printOperand(const MachineInstr *MI, int opNum)
|
2005-01-22 23:41:55 +00:00
|
|
|
{
|
|
|
|
const MachineOperand &MO = MI->getOperand(opNum);
|
2006-05-04 18:05:43 +00:00
|
|
|
if (MO.getType() == MachineOperand::MO_Register) {
|
2008-02-10 18:45:23 +00:00
|
|
|
assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg()) &&
|
|
|
|
"Not physreg??");
|
2008-02-26 21:11:01 +00:00
|
|
|
O << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
|
2008-10-03 15:45:36 +00:00
|
|
|
} else if (MO.isImm()) {
|
2007-12-30 20:49:49 +00:00
|
|
|
O << MO.getImm();
|
|
|
|
assert(MO.getImm() < (1 << 30));
|
2005-01-22 23:41:55 +00:00
|
|
|
} else {
|
|
|
|
printOp(MO);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void AlphaAsmPrinter::printOp(const MachineOperand &MO, bool IsCallOp) {
|
2008-02-10 18:45:23 +00:00
|
|
|
const TargetRegisterInfo &RI = *TM.getRegisterInfo();
|
2005-04-21 23:13:11 +00:00
|
|
|
|
2005-01-22 23:41:55 +00:00
|
|
|
switch (MO.getType()) {
|
2006-05-04 18:05:43 +00:00
|
|
|
case MachineOperand::MO_Register:
|
2008-02-26 21:11:01 +00:00
|
|
|
O << RI.get(MO.getReg()).AsmName;
|
2005-01-22 23:41:55 +00:00
|
|
|
return;
|
|
|
|
|
2006-05-04 17:21:20 +00:00
|
|
|
case MachineOperand::MO_Immediate:
|
2009-07-08 20:53:28 +00:00
|
|
|
LLVM_UNREACHABLE("printOp() does not handle immediate values");
|
2005-01-22 23:41:55 +00:00
|
|
|
return;
|
|
|
|
|
2006-04-22 18:53:45 +00:00
|
|
|
case MachineOperand::MO_MachineBasicBlock:
|
2007-12-30 23:10:15 +00:00
|
|
|
printBasicBlockLabel(MO.getMBB());
|
2005-01-22 23:41:55 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
case MachineOperand::MO_ConstantPoolIndex:
|
2007-10-14 05:57:21 +00:00
|
|
|
O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_"
|
2007-12-30 23:10:15 +00:00
|
|
|
<< MO.getIndex();
|
2005-01-22 23:41:55 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
case MachineOperand::MO_ExternalSymbol:
|
|
|
|
O << MO.getSymbolName();
|
|
|
|
return;
|
|
|
|
|
2009-07-14 06:18:50 +00:00
|
|
|
case MachineOperand::MO_GlobalAddress:
|
|
|
|
O << Mang->getMangledName(MO.getGlobal());
|
2005-01-22 23:41:55 +00:00
|
|
|
return;
|
2005-04-21 23:13:11 +00:00
|
|
|
|
2006-09-18 18:01:03 +00:00
|
|
|
case MachineOperand::MO_JumpTableIndex:
|
2007-10-14 05:57:21 +00:00
|
|
|
O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
|
2007-12-30 23:10:15 +00:00
|
|
|
<< '_' << MO.getIndex();
|
2006-09-18 18:01:03 +00:00
|
|
|
return;
|
|
|
|
|
2005-01-22 23:41:55 +00:00
|
|
|
default:
|
|
|
|
O << "<unknown operand type: " << MO.getType() << ">";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// runOnMachineFunction - This uses the printMachineInstruction()
|
|
|
|
/// method to print assembly for each instruction.
|
|
|
|
///
|
|
|
|
bool AlphaAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
|
2009-02-24 08:30:20 +00:00
|
|
|
this->MF = &MF;
|
|
|
|
|
2005-11-21 07:51:23 +00:00
|
|
|
SetupMachineFunction(MF);
|
2005-01-22 23:41:55 +00:00
|
|
|
O << "\n\n";
|
|
|
|
|
|
|
|
// Print out constants referenced by the function
|
2005-11-21 08:29:17 +00:00
|
|
|
EmitConstantPool(MF.getConstantPool());
|
2005-01-22 23:41:55 +00:00
|
|
|
|
2006-09-18 18:01:03 +00:00
|
|
|
// Print out jump tables referenced by the function
|
2006-10-05 03:01:21 +00:00
|
|
|
EmitJumpTableInfo(MF.getJumpTableInfo(), MF);
|
2006-09-18 18:01:03 +00:00
|
|
|
|
2005-01-22 23:41:55 +00:00
|
|
|
// Print out labels for the function.
|
2006-02-04 19:13:09 +00:00
|
|
|
const Function *F = MF.getFunction();
|
2008-09-24 22:14:23 +00:00
|
|
|
SwitchToSection(TAI->SectionForGlobal(F));
|
2008-08-07 09:53:57 +00:00
|
|
|
|
2009-06-30 22:38:32 +00:00
|
|
|
EmitAlignment(MF.getAlignment(), F);
|
2006-02-04 19:13:09 +00:00
|
|
|
switch (F->getLinkage()) {
|
2009-07-11 20:10:48 +00:00
|
|
|
default: LLVM_UNREACHABLE( "Unknown linkage type!");
|
2006-02-04 19:13:09 +00:00
|
|
|
case Function::InternalLinkage: // Symbols default to internal.
|
2009-01-15 21:51:46 +00:00
|
|
|
case Function::PrivateLinkage:
|
2006-02-04 19:13:09 +00:00
|
|
|
break;
|
|
|
|
case Function::ExternalLinkage:
|
|
|
|
O << "\t.globl " << CurrentFnName << "\n";
|
|
|
|
break;
|
Introduce new linkage types linkonce_odr, weak_odr, common_odr
and extern_weak_odr. These are the same as the non-odr versions,
except that they indicate that the global will only be overridden
by an *equivalent* global. In C, a function with weak linkage can
be overridden by a function which behaves completely differently.
This means that IP passes have to skip weak functions, since any
deductions made from the function definition might be wrong, since
the definition could be replaced by something completely different
at link time. This is not allowed in C++, thanks to the ODR
(One-Definition-Rule): if a function is replaced by another at
link-time, then the new function must be the same as the original
function. If a language knows that a function or other global can
only be overridden by an equivalent global, it can give it the
weak_odr linkage type, and the optimizers will understand that it
is alright to make deductions based on the function body. The
code generators on the other hand map weak and weak_odr linkage
to the same thing.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@66339 91177308-0d34-0410-b5e6-96231b3b80d8
2009-03-07 15:45:40 +00:00
|
|
|
case Function::WeakAnyLinkage:
|
|
|
|
case Function::WeakODRLinkage:
|
|
|
|
case Function::LinkOnceAnyLinkage:
|
|
|
|
case Function::LinkOnceODRLinkage:
|
2006-12-07 23:55:55 +00:00
|
|
|
O << TAI->getWeakRefDirective() << CurrentFnName << "\n";
|
2006-02-04 19:13:09 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2008-08-08 18:25:07 +00:00
|
|
|
printVisibility(CurrentFnName, F->getVisibility());
|
|
|
|
|
2005-05-27 03:39:30 +00:00
|
|
|
O << "\t.ent " << CurrentFnName << "\n";
|
2005-01-22 23:41:55 +00:00
|
|
|
|
|
|
|
O << CurrentFnName << ":\n";
|
|
|
|
|
|
|
|
// Print out code for the function.
|
|
|
|
for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
|
|
|
|
I != E; ++I) {
|
2006-12-07 23:55:55 +00:00
|
|
|
if (I != MF.begin()) {
|
2008-02-28 00:43:03 +00:00
|
|
|
printBasicBlockLabel(I, true, true);
|
2006-12-07 23:55:55 +00:00
|
|
|
O << '\n';
|
|
|
|
}
|
2005-01-22 23:41:55 +00:00
|
|
|
for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
|
|
|
|
II != E; ++II) {
|
|
|
|
// Print the assembly for the instruction.
|
2006-12-07 23:55:55 +00:00
|
|
|
++EmittedInsts;
|
|
|
|
if (!printInstruction(II)) {
|
2009-07-08 19:04:27 +00:00
|
|
|
LLVM_UNREACHABLE("Unhandled instruction in asm writer!");
|
2006-12-07 23:55:55 +00:00
|
|
|
}
|
2005-01-22 23:41:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-02-25 22:55:15 +00:00
|
|
|
O << "\t.end " << CurrentFnName << "\n";
|
2005-01-22 23:41:55 +00:00
|
|
|
|
|
|
|
// We didn't modify anything.
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool AlphaAsmPrinter::doInitialization(Module &M)
|
|
|
|
{
|
2007-01-24 21:09:16 +00:00
|
|
|
if(TM.getSubtarget<AlphaSubtarget>().hasCT())
|
|
|
|
O << "\t.arch ev6\n"; //This might need to be ev67, so leave this test here
|
2005-04-14 16:24:00 +00:00
|
|
|
else
|
2007-01-24 21:09:16 +00:00
|
|
|
O << "\t.arch ev6\n";
|
2005-07-22 20:52:16 +00:00
|
|
|
O << "\t.set noat\n";
|
2007-07-25 19:33:14 +00:00
|
|
|
return AsmPrinter::doInitialization(M);
|
2005-01-22 23:41:55 +00:00
|
|
|
}
|
2005-04-21 23:13:11 +00:00
|
|
|
|
2008-08-07 09:53:57 +00:00
|
|
|
void AlphaAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) {
|
2006-05-03 01:29:57 +00:00
|
|
|
const TargetData *TD = TM.getTargetData();
|
2005-04-21 23:13:11 +00:00
|
|
|
|
2008-08-07 09:53:57 +00:00
|
|
|
if (!GVar->hasInitializer()) return; // External global require no code
|
|
|
|
|
|
|
|
// Check to see if this is a special global used by LLVM, if so, emit it.
|
|
|
|
if (EmitSpecialLLVMGlobal(GVar))
|
|
|
|
return;
|
|
|
|
|
2009-07-14 06:18:50 +00:00
|
|
|
std::string name = Mang->getMangledName(GVar);
|
2008-08-07 09:53:57 +00:00
|
|
|
Constant *C = GVar->getInitializer();
|
2009-06-26 02:26:12 +00:00
|
|
|
if (isa<MDNode>(C) || isa<MDString>(C))
|
2009-06-25 00:47:42 +00:00
|
|
|
return;
|
2009-05-09 07:06:46 +00:00
|
|
|
unsigned Size = TD->getTypeAllocSize(C->getType());
|
2008-08-07 09:53:57 +00:00
|
|
|
unsigned Align = TD->getPreferredAlignmentLog(GVar);
|
|
|
|
|
|
|
|
// 0: Switch to section
|
2008-09-24 22:14:23 +00:00
|
|
|
SwitchToSection(TAI->SectionForGlobal(GVar));
|
2008-08-07 09:53:57 +00:00
|
|
|
|
|
|
|
// 1: Check visibility
|
2008-08-08 18:25:07 +00:00
|
|
|
printVisibility(name, GVar->getVisibility());
|
2008-08-07 09:53:57 +00:00
|
|
|
|
|
|
|
// 2: Kind
|
|
|
|
switch (GVar->getLinkage()) {
|
Introduce new linkage types linkonce_odr, weak_odr, common_odr
and extern_weak_odr. These are the same as the non-odr versions,
except that they indicate that the global will only be overridden
by an *equivalent* global. In C, a function with weak linkage can
be overridden by a function which behaves completely differently.
This means that IP passes have to skip weak functions, since any
deductions made from the function definition might be wrong, since
the definition could be replaced by something completely different
at link time. This is not allowed in C++, thanks to the ODR
(One-Definition-Rule): if a function is replaced by another at
link-time, then the new function must be the same as the original
function. If a language knows that a function or other global can
only be overridden by an equivalent global, it can give it the
weak_odr linkage type, and the optimizers will understand that it
is alright to make deductions based on the function body. The
code generators on the other hand map weak and weak_odr linkage
to the same thing.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@66339 91177308-0d34-0410-b5e6-96231b3b80d8
2009-03-07 15:45:40 +00:00
|
|
|
case GlobalValue::LinkOnceAnyLinkage:
|
|
|
|
case GlobalValue::LinkOnceODRLinkage:
|
|
|
|
case GlobalValue::WeakAnyLinkage:
|
|
|
|
case GlobalValue::WeakODRLinkage:
|
2009-03-11 20:14:15 +00:00
|
|
|
case GlobalValue::CommonLinkage:
|
2008-08-07 09:53:57 +00:00
|
|
|
O << TAI->getWeakRefDirective() << name << '\n';
|
|
|
|
break;
|
|
|
|
case GlobalValue::AppendingLinkage:
|
|
|
|
case GlobalValue::ExternalLinkage:
|
|
|
|
O << TAI->getGlobalDirective() << name << "\n";
|
2007-02-13 23:41:16 +00:00
|
|
|
break;
|
|
|
|
case GlobalValue::InternalLinkage:
|
2009-01-15 21:51:46 +00:00
|
|
|
case GlobalValue::PrivateLinkage:
|
2007-02-13 23:41:16 +00:00
|
|
|
break;
|
|
|
|
default:
|
2009-07-08 19:04:27 +00:00
|
|
|
LLVM_UNREACHABLE("Unknown linkage type!");
|
2007-02-13 23:41:16 +00:00
|
|
|
}
|
2008-08-07 09:53:57 +00:00
|
|
|
|
|
|
|
// 3: Type, Size, Align
|
|
|
|
if (TAI->hasDotTypeDotSizeDirective()) {
|
2007-02-13 23:41:16 +00:00
|
|
|
O << "\t.type\t" << name << ", @object\n";
|
|
|
|
O << "\t.size\t" << name << ", " << Size << "\n";
|
|
|
|
}
|
2006-12-07 17:39:14 +00:00
|
|
|
|
2008-08-07 09:53:57 +00:00
|
|
|
EmitAlignment(Align, GVar);
|
|
|
|
|
|
|
|
O << name << ":\n";
|
|
|
|
|
|
|
|
EmitGlobalConstant(C);
|
|
|
|
O << '\n';
|
|
|
|
}
|
|
|
|
|
|
|
|
bool AlphaAsmPrinter::doFinalization(Module &M) {
|
|
|
|
for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
|
|
|
|
I != E; ++I)
|
|
|
|
printModuleLevelGV(I);
|
|
|
|
|
2007-07-25 19:33:14 +00:00
|
|
|
return AsmPrinter::doFinalization(M);
|
2005-01-22 23:41:55 +00:00
|
|
|
}
|
2006-06-21 13:37:27 +00:00
|
|
|
|
|
|
|
/// PrintAsmOperand - Print out an operand for an inline asm expression.
|
|
|
|
///
|
|
|
|
bool AlphaAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
|
2008-08-07 09:53:57 +00:00
|
|
|
unsigned AsmVariant,
|
2007-04-16 18:10:23 +00:00
|
|
|
const char *ExtraCode) {
|
2006-06-21 13:37:27 +00:00
|
|
|
printOperand(MI, OpNo);
|
|
|
|
return false;
|
|
|
|
}
|
2006-06-21 15:42:36 +00:00
|
|
|
|
2008-08-07 09:53:57 +00:00
|
|
|
bool AlphaAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
|
2007-04-16 18:10:23 +00:00
|
|
|
unsigned OpNo,
|
2008-08-07 09:53:57 +00:00
|
|
|
unsigned AsmVariant,
|
2007-04-16 18:10:23 +00:00
|
|
|
const char *ExtraCode) {
|
2006-06-21 15:42:36 +00:00
|
|
|
if (ExtraCode && ExtraCode[0])
|
|
|
|
return true; // Unknown modifier.
|
2006-07-03 17:57:34 +00:00
|
|
|
O << "0(";
|
2006-06-21 15:42:36 +00:00
|
|
|
printOperand(MI, OpNo);
|
2006-07-03 17:57:34 +00:00
|
|
|
O << ")";
|
2006-06-21 15:42:36 +00:00
|
|
|
return false;
|
|
|
|
}
|
2009-06-16 20:12:29 +00:00
|
|
|
|
2009-06-23 23:59:40 +00:00
|
|
|
// Force static initialization.
|
|
|
|
extern "C" void LLVMInitializeAlphaAsmPrinter() { }
|
2009-06-19 19:36:55 +00:00
|
|
|
|
|
|
|
namespace {
|
|
|
|
static struct Register {
|
|
|
|
Register() {
|
|
|
|
AlphaTargetMachine::registerAsmPrinter(createAlphaCodePrinterPass);
|
|
|
|
}
|
|
|
|
} Registrator;
|
|
|
|
}
|