#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Target/MRegisterInfo.h"
+#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
#include <set>
bool printInstruction(const MachineInstr *MI);
void printMachineInstruction(const MachineInstr *MI);
- void printOp(const MachineOperand &MO, bool LoadAddrOp = false);
+ void printOp(const MachineOperand &MO, bool IsCallOp = false);
void printOperand(const MachineInstr *MI, unsigned OpNo, MVT::ValueType VT){
const MachineOperand &MO = MI->getOperand(OpNo);
// Branches can take an immediate operand. This is used by the branch
// selection pass to print $+8, an eight byte displacement from the PC.
if (MI->getOperand(OpNo).isImmediate()) {
- O << "$+" << MI->getOperand(OpNo).getImmedValue() << '\n';
+ O << "$+" << MI->getOperand(OpNo).getImmedValue();
} else {
- printOp(MI->getOperand(OpNo));
+ printOp(MI->getOperand(OpNo),
+ TM.getInstrInfo()->isCall(MI->getOpcode()));
}
}
void printPICLabel(const MachineInstr *MI, unsigned OpNo,
void printSymbolHi(const MachineInstr *MI, unsigned OpNo,
MVT::ValueType VT) {
O << "ha16(";
- printOp(MI->getOperand(OpNo), true /* LoadAddrOp */);
+ printOp(MI->getOperand(OpNo));
O << "-\"L0000" << LabelNumber << "$pb\")";
}
void printSymbolLo(const MachineInstr *MI, unsigned OpNo,
O << (short)MI->getOperand(OpNo).getImmedValue();
} else {
O << "lo16(";
- printOp(MI->getOperand(OpNo), true /* LoadAddrOp */);
+ printOp(MI->getOperand(OpNo));
O << "-\"L0000" << LabelNumber << "$pb\")";
}
}
+ void printcrbit(const MachineInstr *MI, unsigned OpNo,
+ MVT::ValueType VT) {
+ unsigned char value = MI->getOperand(OpNo).getImmedValue();
+ assert(value <= 3 && "Invalid crbit argument!");
+ unsigned RegNo, CCReg = MI->getOperand(OpNo-1).getReg();
+ switch (CCReg) {
+ case PPC::CR0: RegNo = 0; break;
+ case PPC::CR1: RegNo = 1; break;
+ case PPC::CR2: RegNo = 2; break;
+ case PPC::CR3: RegNo = 3; break;
+ case PPC::CR4: RegNo = 4; break;
+ case PPC::CR5: RegNo = 5; break;
+ case PPC::CR6: RegNo = 6; break;
+ case PPC::CR7: RegNo = 7; break;
+ default:
+ std::cerr << "Unhandled reg in enumRegToRealReg!\n";
+ abort();
+ }
+ O << 4 * RegNo + value;
+ }
virtual void printConstantPool(MachineConstantPool *MCP) = 0;
virtual bool runOnMachineFunction(MachineFunction &F) = 0;
// Include the auto-generated portion of the assembly writer
#include "PowerPCGenAsmWriter.inc"
-void PowerPCAsmPrinter::printOp(const MachineOperand &MO,
- bool LoadAddrOp /* = false */) {
+void PowerPCAsmPrinter::printOp(const MachineOperand &MO, bool IsCallOp) {
const MRegisterInfo &RI = *TM.getRegisterInfo();
int new_symbol;
return;
case MachineOperand::MO_ExternalSymbol:
- O << MO.getSymbolName();
+ if (IsCallOp) {
+ std::string Name(GlobalPrefix); Name += MO.getSymbolName();
+ FnStubs.insert(Name);
+ O << "L" << Name << "$stub";
+ return;
+ }
+ O << GlobalPrefix << MO.getSymbolName();
return;
case MachineOperand::MO_GlobalAddress: {
// wary however not to output $stub for external functions whose addresses
// are taken. Those should be emitted as $non_lazy_ptr below.
Function *F = dyn_cast<Function>(GV);
- if (F && F->isExternal() && !LoadAddrOp &&
- getTM().CalledFunctions.count(F)) {
+ if (F && IsCallOp && F->isExternal()) {
FnStubs.insert(Name);
O << "L" << Name << "$stub";
return;
}
// External or weakly linked global variables need non-lazily-resolved stubs
- if ((GV->isExternal() || GV->hasWeakLinkage() || GV->hasLinkOnceLinkage())
- && getTM().AddressTaken.count(GV)) {
- GVStubs.insert(Name);
+ if ((GV->isExternal() || GV->hasWeakLinkage() || GV->hasLinkOnceLinkage())){
+ if (GV->hasLinkOnceLinkage())
+ LinkOnceStubs.insert(Name);
+ else
+ GVStubs.insert(Name);
O << "L" << Name << "$non_lazy_ptr";
return;
}
-
- if (F && LoadAddrOp && getTM().AddressTaken.count(GV)) {
- LinkOnceStubs.insert(Name);
- O << "L" << Name << "$non_lazy_ptr";
- return;
- }
-
+
O << Mang->getValueName(GV);
return;
}
///
void PowerPCAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
++EmittedInsts;
+ // Check for slwi/srwi mnemonics.
+ if (MI->getOpcode() == PPC::RLWINM) {
+ bool FoundMnemonic = false;
+ unsigned char SH = MI->getOperand(2).getImmedValue();
+ unsigned char MB = MI->getOperand(3).getImmedValue();
+ unsigned char ME = MI->getOperand(4).getImmedValue();
+ if (SH <= 31 && MB == 0 && ME == (31-SH)) {
+ O << "slwi "; FoundMnemonic = true;
+ }
+ if (SH <= 31 && MB == (32-SH) && ME == 31) {
+ O << "srwi "; FoundMnemonic = true;
+ SH = 32-SH;
+ }
+ if (FoundMnemonic) {
+ printOperand(MI, 0, MVT::i64);
+ O << ", ";
+ printOperand(MI, 1, MVT::i64);
+ O << ", " << (unsigned int)SH << "\n";
+ return;
+ }
+ }
+
if (printInstruction(MI))
return; // Printer was automatically generated
std::string CurSection;
// Print out module-level global variables here.
- for (Module::const_giterator I = M.gbegin(), E = M.gend(); I != E; ++I)
+ for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I)
if (I->hasInitializer()) { // External global require no code
O << '\n';
std::string name = Mang->getValueName(I);
(I->hasInternalLinkage() || I->hasWeakLinkage() ||
I->hasLinkOnceLinkage())) {
SwitchSection(O, CurSection, ".data");
+ if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
if (I->hasInternalLinkage())
- O << ".lcomm " << name << "," << TD.getTypeSize(C->getType())
- << "," << Align;
+ O << ".lcomm " << name << "," << Size << "," << Align;
else
- O << ".comm " << name << "," << TD.getTypeSize(C->getType());
+ O << ".comm " << name << "," << Size;
O << "\t\t; ";
WriteAsOperand(O, I, true, true, &M);
O << '\n';
case GlobalValue::InternalLinkage:
SwitchSection(O, CurSection, ".data");
break;
+ case GlobalValue::GhostLinkage:
+ std::cerr << "Error: unmaterialized (GhostLinkage) function in asm!";
+ abort();
}
emitAlignment(Align);
<< "\t.csect .text[PR]\n";
// Print out module-level global variables
- for (Module::const_giterator I = M.gbegin(), E = M.gend(); I != E; ++I) {
+ for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) {
if (!I->hasInitializer())
continue;
}
// Output labels for globals
- if (M.gbegin() != M.gend()) O << "\t.toc\n";
- for (Module::const_giterator I = M.gbegin(), E = M.gend(); I != E; ++I) {
+ if (M.global_begin() != M.global_end()) O << "\t.toc\n";
+ for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) {
const GlobalVariable *GV = I;
// Do not output labels for unused variables
if (GV->isExternal() && GV->use_begin() == GV->use_end())
bool AIXAsmPrinter::doFinalization(Module &M) {
const TargetData &TD = TM.getTargetData();
// Print out module-level global variables
- for (Module::const_giterator I = M.gbegin(), E = M.gend(); I != E; ++I) {
+ for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) {
if (I->hasInitializer() || I->hasExternalLinkage())
continue;