Initial revision

llvm-svn: 14283
This commit is contained in:
Misha Brukman 2004-06-21 16:55:25 +00:00
parent e54cbdd478
commit e05203fb40
20 changed files with 9690 additions and 0 deletions

View File

@ -0,0 +1,55 @@
##===- lib/Target/PowerPC/Makefile -------------------------*- Makefile -*-===##
#
# The LLVM Compiler Infrastructure
#
# This file was developed by the LLVM research group and is distributed under
# the University of Illinois Open Source License. See LICENSE.TXT for details.
#
##===----------------------------------------------------------------------===##
LEVEL = ../../..
LIBRARYNAME = powerpc
include $(LEVEL)/Makefile.common
# Make sure that tblgen is run, first thing.
$(SourceDepend): PowerPCGenRegisterInfo.h.inc PowerPCGenRegisterNames.inc \
PowerPCGenRegisterInfo.inc PowerPCGenInstrNames.inc \
PowerPCGenInstrInfo.inc PowerPCGenInstrSelector.inc
PowerPCGenRegisterNames.inc:: $(SourceDir)/PowerPC.td \
$(SourceDir)/PowerPCReg.td \
$(SourceDir)/../Target.td $(TBLGEN)
@echo "Building PowerPC.td register names with tblgen"
$(VERB) $(TBLGEN) -I $(BUILD_SRC_DIR) $< -gen-register-enums -o $@
PowerPCGenRegisterInfo.h.inc:: $(SourceDir)/PowerPC.td \
$(SourceDir)/PowerPCReg.td \
$(SourceDir)/../Target.td $(TBLGEN)
@echo "Building PowerPC.td register information header with tblgen"
$(VERB) $(TBLGEN) -I $(BUILD_SRC_DIR) $< -gen-register-desc-header -o $@
PowerPCGenRegisterInfo.inc:: $(SourceDir)/PowerPC.td \
$(SourceDir)/PowerPCReg.td \
$(SourceDir)/../Target.td $(TBLGEN)
@echo "Building PowerPC.td register information implementation with tblgen"
$(VERB) $(TBLGEN) -I $(BUILD_SRC_DIR) $< -gen-register-desc -o $@
PowerPCGenInstrNames.inc:: $(SourceDir)/PowerPC.td \
$(SourceDir)/PowerPCInstrs.td \
$(SourceDir)/../Target.td $(TBLGEN)
@echo "Building PowerPC.td instruction names with tblgen"
$(VERB) $(TBLGEN) -I $(BUILD_SRC_DIR) $< -gen-instr-enums -o $@
PowerPCGenInstrInfo.inc:: $(SourceDir)/PowerPC.td \
$(SourceDir)/PowerPCInstrs.td \
$(SourceDir)/../Target.td $(TBLGEN)
@echo "Building PowerPC.td instruction information with tblgen"
$(VERB) $(TBLGEN) -I $(BUILD_SRC_DIR) $< -gen-instr-desc -o $@
PowerPCGenInstrSelector.inc:: $(SourceDir)/PowerPC.td \
$(SourceDir)/PowerPCInstrs.td \
$(SourceDir)/../Target.td $(TBLGEN)
@echo "Building PowerPC.td instruction selector with tblgen"
$(VERB) $(TBLGEN) -I $(BUILD_SRC_DIR) $< -gen-instr-selector -o $@
clean::
$(VERB) rm -f *.inc

View File

@ -0,0 +1,40 @@
//===-- PowerPC.h - Top-level interface for PowerPC representation -*- C++ -*-//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the entry points for global functions defined in the LLVM
// PowerPC back-end.
//
//===----------------------------------------------------------------------===//
#ifndef TARGET_POWERPC_H
#define TARGET_POWERPC_H
#include <iosfwd>
namespace llvm {
class FunctionPass;
class TargetMachine;
// Here is where you would define factory methods for powerpc-specific
// passes. For example:
FunctionPass *createPPCSimpleInstructionSelector (TargetMachine &TM);
FunctionPass *createPPCCodePrinterPass(std::ostream &OS, TargetMachine &TM);
} // end namespace llvm;
// Defines symbolic names for PowerPC registers. This defines a mapping from
// register name to register number.
//
#include "PowerPCGenRegisterNames.inc"
// Defines symbolic names for the PowerPC instructions.
//
#include "PowerPCGenInstrNames.inc"
#endif

View File

@ -0,0 +1,694 @@
//===-- PPC32/Printer.cpp - Convert X86 LLVM code to Intel assembly ---------===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains a printer that converts from our internal
// representation of machine-dependent LLVM code to Intel-format
// assembly language. This printer is the output mechanism used
// by `llc' and `lli -print-machineinstrs' on X86.
//
//===----------------------------------------------------------------------===//
#include <set>
#include "PowerPC.h"
#include "PowerPCInstrInfo.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/Assembly/Writer.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Support/Mangler.h"
#include "Support/Statistic.h"
#include "Support/StringExtras.h"
#include "Support/CommandLine.h"
namespace llvm {
namespace {
Statistic<> EmittedInsts("asm-printer", "Number of machine instrs printed");
struct Printer : public MachineFunctionPass {
/// Output stream on which we're printing assembly code.
///
std::ostream &O;
/// Target machine description which we query for reg. names, data
/// layout, etc.
///
TargetMachine &TM;
/// Name-mangler for global names.
///
Mangler *Mang;
std::set< std::string > Stubs;
std::set<std::string> Strings;
Printer(std::ostream &o, TargetMachine &tm) : O(o), TM(tm) { }
/// We name each basic block in a Function with a unique number, so
/// that we can consistently refer to them later. This is cleared
/// at the beginning of each call to runOnMachineFunction().
///
typedef std::map<const Value *, unsigned> ValueMapTy;
ValueMapTy NumberForBB;
/// Cache of mangled name for current function. This is
/// recalculated at the beginning of each call to
/// runOnMachineFunction().
///
std::string CurrentFnName;
virtual const char *getPassName() const {
return "PowerPC Assembly Printer";
}
void printMachineInstruction(const MachineInstr *MI);
void printOp(const MachineOperand &MO,
bool elideOffsetKeyword = false);
void printConstantPool(MachineConstantPool *MCP);
bool runOnMachineFunction(MachineFunction &F);
bool doInitialization(Module &M);
bool doFinalization(Module &M);
void emitGlobalConstant(const Constant* CV);
void emitConstantValueOnly(const Constant *CV);
};
} // end of anonymous namespace
/// createPPCCodePrinterPass - Returns a pass that prints the X86
/// 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.
///
FunctionPass *createPPCCodePrinterPass(std::ostream &o,TargetMachine &tm){
return new Printer(o, tm);
}
/// isStringCompatible - Can we treat the specified array as a string?
/// Only if it is an array of ubytes or non-negative sbytes.
///
static bool isStringCompatible(const ConstantArray *CVA) {
const Type *ETy = cast<ArrayType>(CVA->getType())->getElementType();
if (ETy == Type::UByteTy) return true;
if (ETy != Type::SByteTy) return false;
for (unsigned i = 0; i < CVA->getNumOperands(); ++i)
if (cast<ConstantSInt>(CVA->getOperand(i))->getValue() < 0)
return false;
return true;
}
/// toOctal - Convert the low order bits of X into an octal digit.
///
static inline char toOctal(int X) {
return (X&7)+'0';
}
/// getAsCString - Return the specified array as a C compatible
/// string, only if the predicate isStringCompatible is true.
///
static void printAsCString(std::ostream &O, const ConstantArray *CVA) {
assert(isStringCompatible(CVA) && "Array is not string compatible!");
O << "\"";
for (unsigned i = 0; i < CVA->getNumOperands(); ++i) {
unsigned char C = cast<ConstantInt>(CVA->getOperand(i))->getRawValue();
if (C == '"') {
O << "\\\"";
} else if (C == '\\') {
O << "\\\\";
} else if (isprint(C)) {
O << C;
} else {
switch(C) {
case '\b': O << "\\b"; break;
case '\f': O << "\\f"; break;
case '\n': O << "\\n"; break;
case '\r': O << "\\r"; break;
case '\t': O << "\\t"; break;
default:
O << '\\';
O << toOctal(C >> 6);
O << toOctal(C >> 3);
O << toOctal(C >> 0);
break;
}
}
}
O << "\"";
}
// Print out the specified constant, without a storage class. Only the
// constants valid in constant expressions can occur here.
void Printer::emitConstantValueOnly(const Constant *CV) {
if (CV->isNullValue())
O << "0";
else if (const ConstantBool *CB = dyn_cast<ConstantBool>(CV)) {
assert(CB == ConstantBool::True);
O << "1";
} else if (const ConstantSInt *CI = dyn_cast<ConstantSInt>(CV))
O << CI->getValue();
else if (const ConstantUInt *CI = dyn_cast<ConstantUInt>(CV))
O << CI->getValue();
else if (const ConstantPointerRef *CPR = dyn_cast<ConstantPointerRef>(CV))
// This is a constant address for a global variable or function. Use the
// name of the variable or function as the address value.
O << Mang->getValueName(CPR->getValue());
else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) {
const TargetData &TD = TM.getTargetData();
switch(CE->getOpcode()) {
case Instruction::GetElementPtr: {
// generate a symbolic expression for the byte address
const Constant *ptrVal = CE->getOperand(0);
std::vector<Value*> idxVec(CE->op_begin()+1, CE->op_end());
if (unsigned Offset = TD.getIndexedOffset(ptrVal->getType(), idxVec)) {
O << "(";
emitConstantValueOnly(ptrVal);
O << ") + " << Offset;
} else {
emitConstantValueOnly(ptrVal);
}
break;
}
case Instruction::Cast: {
// Support only non-converting or widening casts for now, that is, ones
// that do not involve a change in value. This assertion is really gross,
// and may not even be a complete check.
Constant *Op = CE->getOperand(0);
const Type *OpTy = Op->getType(), *Ty = CE->getType();
// Remember, kids, pointers on x86 can be losslessly converted back and
// forth into 32-bit or wider integers, regardless of signedness. :-P
assert(((isa<PointerType>(OpTy)
&& (Ty == Type::LongTy || Ty == Type::ULongTy
|| Ty == Type::IntTy || Ty == Type::UIntTy))
|| (isa<PointerType>(Ty)
&& (OpTy == Type::LongTy || OpTy == Type::ULongTy
|| OpTy == Type::IntTy || OpTy == Type::UIntTy))
|| (((TD.getTypeSize(Ty) >= TD.getTypeSize(OpTy))
&& OpTy->isLosslesslyConvertibleTo(Ty))))
&& "FIXME: Don't yet support this kind of constant cast expr");
O << "(";
emitConstantValueOnly(Op);
O << ")";
break;
}
case Instruction::Add:
O << "(";
emitConstantValueOnly(CE->getOperand(0));
O << ") + (";
emitConstantValueOnly(CE->getOperand(1));
O << ")";
break;
default:
assert(0 && "Unsupported operator!");
}
} else {
assert(0 && "Unknown constant value!");
}
}
// Print a constant value or values, with the appropriate storage class as a
// prefix.
void Printer::emitGlobalConstant(const Constant *CV) {
const TargetData &TD = TM.getTargetData();
if (CV->isNullValue()) {
O << "\t.space\t " << TD.getTypeSize(CV->getType()) << "\n";
return;
} else if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV)) {
if (isStringCompatible(CVA)) {
O << ".ascii";
printAsCString(O, CVA);
O << "\n";
} else { // Not a string. Print the values in successive locations
const std::vector<Use> &constValues = CVA->getValues();
for (unsigned i=0; i < constValues.size(); i++)
emitGlobalConstant(cast<Constant>(constValues[i].get()));
}
return;
} else if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV)) {
// Print the fields in successive locations. Pad to align if needed!
const StructLayout *cvsLayout = TD.getStructLayout(CVS->getType());
const std::vector<Use>& constValues = CVS->getValues();
unsigned sizeSoFar = 0;
for (unsigned i=0, N = constValues.size(); i < N; i++) {
const Constant* field = cast<Constant>(constValues[i].get());
// Check if padding is needed and insert one or more 0s.
unsigned fieldSize = TD.getTypeSize(field->getType());
unsigned padSize = ((i == N-1? cvsLayout->StructSize
: cvsLayout->MemberOffsets[i+1])
- cvsLayout->MemberOffsets[i]) - fieldSize;
sizeSoFar += fieldSize + padSize;
// Now print the actual field value
emitGlobalConstant(field);
// Insert the field padding unless it's zero bytes...
if (padSize)
O << "\t.space\t " << padSize << "\n";
}
assert(sizeSoFar == cvsLayout->StructSize &&
"Layout of constant struct may be incorrect!");
return;
} else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) {
// FP Constants are printed as integer constants to avoid losing
// precision...
double Val = CFP->getValue();
switch (CFP->getType()->getPrimitiveID()) {
default: assert(0 && "Unknown floating point type!");
case Type::FloatTyID: {
union FU { // Abide by C TBAA rules
float FVal;
unsigned UVal;
} U;
U.FVal = Val;
O << ".long\t" << U.UVal << "\t# float " << Val << "\n";
return;
}
case Type::DoubleTyID: {
union DU { // Abide by C TBAA rules
double FVal;
uint64_t UVal;
struct {
uint32_t MSWord;
uint32_t LSWord;
} T;
} U;
U.FVal = Val;
O << ".long\t" << U.T.MSWord << "\t# double most significant word " << Val << "\n";
O << ".long\t" << U.T.LSWord << "\t# double least significant word" << Val << "\n";
return;
}
}
} else if (CV->getType()->getPrimitiveSize() == 64) {
const ConstantInt *CI = dyn_cast<ConstantInt>(CV);
if(CI) {
union DU { // Abide by C TBAA rules
int64_t UVal;
struct {
uint32_t MSWord;
uint32_t LSWord;
} T;
} U;
U.UVal = CI->getRawValue();
O << ".long\t" << U.T.MSWord << "\t# Double-word most significant word " << U.UVal << "\n";
O << ".long\t" << U.T.LSWord << "\t# Double-word least significant word" << U.UVal << "\n";
return;
}
}
const Type *type = CV->getType();
O << "\t";
switch (type->getPrimitiveID()) {
case Type::UByteTyID: case Type::SByteTyID:
O << ".byte";
break;
case Type::UShortTyID: case Type::ShortTyID:
O << ".short";
break;
case Type::BoolTyID:
case Type::PointerTyID:
case Type::UIntTyID: case Type::IntTyID:
O << ".long";
break;
case Type::ULongTyID: case Type::LongTyID:
assert (0 && "Should have already output double-word constant.");
case Type::FloatTyID: case Type::DoubleTyID:
assert (0 && "Should have already output floating point constant.");
default:
assert (0 && "Can't handle printing this type of thing");
break;
}
O << "\t";
emitConstantValueOnly(CV);
O << "\n";
}
/// printConstantPool - Print to the current output stream assembly
/// representations of the constants in the constant pool MCP. This is
/// used to print out constants which have been "spilled to memory" by
/// the code generator.
///
void Printer::printConstantPool(MachineConstantPool *MCP) {
const std::vector<Constant*> &CP = MCP->getConstants();
const TargetData &TD = TM.getTargetData();
if (CP.empty()) return;
for (unsigned i = 0, e = CP.size(); i != e; ++i) {
O << "\t.const\n";
O << "\t.align " << (unsigned)TD.getTypeAlignment(CP[i]->getType())
<< "\n";
O << ".CPI" << CurrentFnName << "_" << i << ":\t\t\t\t\t#"
<< *CP[i] << "\n";
emitGlobalConstant(CP[i]);
}
}
/// runOnMachineFunction - This uses the printMachineInstruction()
/// method to print assembly for each instruction.
///
bool Printer::runOnMachineFunction(MachineFunction &MF) {
// BBNumber is used here so that a given Printer will never give two
// BBs the same name. (If you have a better way, please let me know!)
static unsigned BBNumber = 0;
O << "\n\n";
// What's my mangled name?
CurrentFnName = Mang->getValueName(MF.getFunction());
// Print out constants referenced by the function
printConstantPool(MF.getConstantPool());
// Print out labels for the function.
O << "\t.text\n";
O << "\t.globl\t" << CurrentFnName << "\n";
O << "\t.align 5\n";
O << CurrentFnName << ":\n";
// Number each basic block so that we can consistently refer to them
// in PC-relative references.
NumberForBB.clear();
for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
I != E; ++I) {
NumberForBB[I->getBasicBlock()] = BBNumber++;
}
// Print out code for the function.
for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
I != E; ++I) {
// Print a label for the basic block.
O << "L" << NumberForBB[I->getBasicBlock()] << ":\t# "
<< I->getBasicBlock()->getName() << "\n";
for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
II != E; ++II) {
// Print the assembly for the instruction.
O << "\t";
printMachineInstruction(II);
}
}
// We didn't modify anything.
return false;
}
void Printer::printOp(const MachineOperand &MO,
bool elideOffsetKeyword /* = false */) {
const MRegisterInfo &RI = *TM.getRegisterInfo();
int new_symbol;
switch (MO.getType()) {
case MachineOperand::MO_VirtualRegister:
if (Value *V = MO.getVRegValueOrNull()) {
O << "<" << V->getName() << ">";
return;
}
// FALLTHROUGH
case MachineOperand::MO_MachineRegister:
O << RI.get(MO.getReg()).Name;
return;
case MachineOperand::MO_SignExtendedImmed:
case MachineOperand::MO_UnextendedImmed:
O << (int)MO.getImmedValue();
return;
case MachineOperand::MO_MachineBasicBlock: {
MachineBasicBlock *MBBOp = MO.getMachineBasicBlock();
O << ".LBB" << Mang->getValueName(MBBOp->getParent()->getFunction())
<< "_" << MBBOp->getNumber () << "\t# "
<< MBBOp->getBasicBlock ()->getName ();
return;
}
case MachineOperand::MO_PCRelativeDisp:
std::cerr << "Shouldn't use addPCDisp() when building PPC MachineInstrs";
abort ();
return;
case MachineOperand::MO_GlobalAddress:
if (!elideOffsetKeyword) {
if(isa<Function>(MO.getGlobal())) {
Stubs.insert(Mang->getValueName(MO.getGlobal()));
O << "L" << Mang->getValueName(MO.getGlobal()) << "$stub";
} else {
O << Mang->getValueName(MO.getGlobal());
}
}
return;
case MachineOperand::MO_ExternalSymbol:
O << MO.getSymbolName();
return;
default:
O << "<unknown operand type>"; return;
}
}
#if 0
static inline
unsigned int ValidOpcodes(const MachineInstr *MI, unsigned int ArgType[5]) {
int i;
unsigned int retval = 1;
for(i = 0; i<5; i++) {
switch(ArgType[i]) {
case none:
break;
case Gpr:
case Gpr0:
Type::UIntTy
case Simm16:
case Zimm16:
case PCRelimm24:
case Imm24:
case Imm5:
case PCRelimm14:
case Imm14:
case Imm2:
case Crf:
case Imm3:
case Imm1:
case Fpr:
case Imm4:
case Imm8:
case Disimm16:
case Spr:
case Sgr:
};
}
}
}
#endif
/// printMachineInstruction -- Print out a single PPC32 LLVM instruction
/// MI in Darwin syntax to the current output stream.
///
void Printer::printMachineInstruction(const MachineInstr *MI) {
unsigned Opcode = MI->getOpcode();
const TargetInstrInfo &TII = *TM.getInstrInfo();
const TargetInstrDescriptor &Desc = TII.get(Opcode);
unsigned int i;
unsigned int ArgCount = Desc.TSFlags & PPC32II::ArgCountMask;
unsigned int ArgType[5];
ArgType[0] = (Desc.TSFlags>>PPC32II::Arg0TypeShift) & PPC32II::ArgTypeMask;
ArgType[1] = (Desc.TSFlags>>PPC32II::Arg1TypeShift) & PPC32II::ArgTypeMask;
ArgType[2] = (Desc.TSFlags>>PPC32II::Arg2TypeShift) & PPC32II::ArgTypeMask;
ArgType[3] = (Desc.TSFlags>>PPC32II::Arg3TypeShift) & PPC32II::ArgTypeMask;
ArgType[4] = (Desc.TSFlags>>PPC32II::Arg4TypeShift) & PPC32II::ArgTypeMask;
assert ( ((Desc.TSFlags & PPC32II::VMX) == 0) && "Instruction requires VMX support");
assert ( ((Desc.TSFlags & PPC32II::PPC64) == 0) && "Instruction requires 64 bit support");
//assert ( ValidOpcodes(MI, ArgType) && "Instruction has invalid inputs");
++EmittedInsts;
if(Opcode == PPC32::MovePCtoLR) {
O << "mflr r0\n";
O << "bcl 20,31,L" << CurrentFnName << "$pb\n";
O << "L" << CurrentFnName << "$pb:\n";
return;
}
O << TII.getName(MI->getOpcode()) << " ";
std::cout << TII.getName(MI->getOpcode()) << " expects " << ArgCount << " args\n";
if(Opcode == PPC32::LOADLoAddr) {
printOp(MI->getOperand(0));
O << ", ";
printOp(MI->getOperand(1));
O << ", lo16(";
printOp(MI->getOperand(2));
O << "-L" << CurrentFnName << "$pb)\n";
return;
}
if(Opcode == PPC32::LOADHiAddr) {
printOp(MI->getOperand(0));
O << ", ";
printOp(MI->getOperand(1));
O << ", ha16(" ;
printOp(MI->getOperand(2));
O << "-L" << CurrentFnName << "$pb)\n";
return;
}
if( (ArgCount == 3) && (ArgType[1] == PPC32II::Disimm16) ) {
printOp(MI->getOperand(0));
O << ", ";
printOp(MI->getOperand(1));
O << "(";
if((ArgType[2] == PPC32II::Gpr0) && (MI->getOperand(2).getReg() == PPC32::R0)) {
O << "0";
} else {
printOp(MI->getOperand(2));
}
O << ")\n";
} else {
for(i = 0; i< ArgCount; i++) {
if( (ArgType[i] == PPC32II::Gpr0) && ((MI->getOperand(i).getReg()) == PPC32::R0)) {
O << "0";
} else {
//std::cout << "DEBUG " << (*(TM.getRegisterInfo())).get(MI->getOperand(i).getReg()).Name << "\n";
printOp(MI->getOperand(i));
}
if( ArgCount - 1 == i) {
O << "\n";
} else {
O << ", ";
}
}
}
return;
}
bool Printer::doInitialization(Module &M) {
// Tell gas we are outputting Intel syntax (not AT&T syntax) assembly.
//
// Bug: gas in `intel_syntax noprefix' mode interprets the symbol `Sp' in an
// instruction as a reference to the register named sp, and if you try to
// reference a symbol `Sp' (e.g. `mov ECX, OFFSET Sp') then it gets lowercased
// before being looked up in the symbol table. This creates spurious
// `undefined symbol' errors when linking. Workaround: Do not use `noprefix'
// mode, and decorate all register names with percent signs.
// O << "\t.intel_syntax\n";
Mang = new Mangler(M, true);
return false; // success
}
// SwitchSection - Switch to the specified section of the executable if we are
// not already in it!
//
static void SwitchSection(std::ostream &OS, std::string &CurSection,
const char *NewSection) {
if (CurSection != NewSection) {
CurSection = NewSection;
if (!CurSection.empty())
OS << "\t" << NewSection << "\n";
}
}
bool Printer::doFinalization(Module &M) {
const TargetData &TD = TM.getTargetData();
std::string CurSection;
// Print out module-level global variables here.
for (Module::const_giterator I = M.gbegin(), E = M.gend(); I != E; ++I)
if (I->hasInitializer()) { // External global require no code
O << "\n\n";
std::string name = Mang->getValueName(I);
Constant *C = I->getInitializer();
unsigned Size = TD.getTypeSize(C->getType());
unsigned Align = TD.getTypeAlignment(C->getType());
if (C->isNullValue() &&
(I->hasLinkOnceLinkage() || I->hasInternalLinkage() ||
I->hasWeakLinkage() /* FIXME: Verify correct */)) {
SwitchSection(O, CurSection, ".data");
if (I->hasInternalLinkage())
O << "\t.local " << name << "\n";
O << "\t.comm " << name << "," << TD.getTypeSize(C->getType())
<< "," << (unsigned)TD.getTypeAlignment(C->getType());
O << "\t\t# ";
WriteAsOperand(O, I, true, true, &M);
O << "\n";
} else {
switch (I->getLinkage()) {
case GlobalValue::LinkOnceLinkage:
case GlobalValue::WeakLinkage: // FIXME: Verify correct for weak.
// Nonnull linkonce -> weak
O << "\t.weak " << name << "\n";
SwitchSection(O, CurSection, "");
O << "\t.section\t.llvm.linkonce.d." << name << ",\"aw\",@progbits\n";
break;
case GlobalValue::AppendingLinkage:
// FIXME: appending linkage variables should go into a section of
// their name or something. For now, just emit them as external.
case GlobalValue::ExternalLinkage:
// If external or appending, declare as a global symbol
O << "\t.globl " << name << "\n";
// FALL THROUGH
case GlobalValue::InternalLinkage:
if (C->isNullValue())
SwitchSection(O, CurSection, ".bss");
else
SwitchSection(O, CurSection, ".data");
break;
}
O << "\t.align " << Align << "\n";
O << name << ":\t\t\t\t# ";
WriteAsOperand(O, I, true, true, &M);
O << " = ";
WriteAsOperand(O, C, false, false, &M);
O << "\n";
emitGlobalConstant(C);
}
}
for(std::set<std::string>::iterator i = Stubs.begin(); i != Stubs.end(); ++i) {
O << ".data\n";
O << ".section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32\n";
O << "\t.align 2\n";
O << "L" << *i << "$stub:\n";
O << "\t.indirect_symbol " << *i << "\n";
O << "\tmflr r0\n";
O << "\tbcl 20,31,L0$" << *i << "\n";
O << "L0$" << *i << ":\n";
O << "\tmflr r11\n";
O << "\taddis r11,r11,ha16(L" << *i << "$lazy_ptr-L0$" << *i << ")\n";
O << "\tmtlr r0\n";
O << "\tlwzu r12,lo16(L" << *i << "$lazy_ptr-L0$" << *i << ")(r11)\n";
O << "\tmtctr r12\n";
O << "\tbctr\n";
O << ".data\n";
O << ".lazy_symbol_pointer\n";
O << "L" << *i << "$lazy_ptr:\n";
O << ".indirect_symbol " << *i << "\n";
O << ".long dyld_stub_binding_helper\n";
}
delete Mang;
return false; // success
}
} // End llvm namespace

View File

@ -0,0 +1,43 @@
//===-- PowerPCCodeEmitter.cpp - JIT Code Emitter for PowerPC -----*- C++ -*-=//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//
//===----------------------------------------------------------------------===//
#include "PowerPCTargetMachine.h"
namespace llvm {
/// addPassesToEmitMachineCode - Add passes to the specified pass manager to get
/// machine code emitted. This uses a MachineCodeEmitter object to handle
/// actually outputting the machine code and resolving things like the address
/// of functions. This method should returns true if machine code emission is
/// not supported.
///
bool PowerPCTargetMachine::addPassesToEmitMachineCode(FunctionPassManager &PM,
MachineCodeEmitter &MCE) {
return true;
// It should go something like this:
// PM.add(new Emitter(MCE)); // Machine code emitter pass for PowerPC
// Delete machine code for this function after emitting it:
// PM.add(createMachineCodeDeleter());
}
void *PowerPCJITInfo::getJITStubForFunction(Function *F,
MachineCodeEmitter &MCE) {
assert (0 && "PowerPCJITInfo::getJITStubForFunction not implemented");
return 0;
}
void PowerPCJITInfo::replaceMachineCodeForFunction (void *Old, void *New) {
assert (0 && "PowerPCJITInfo::replaceMachineCodeForFunction not implemented");
}
} // end llvm namespace

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,49 @@
//===- PowerPCJITInfo.h - PowerPC impl. of the JIT interface ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the PowerPC implementation of the TargetJITInfo class.
//
//===----------------------------------------------------------------------===//
#ifndef POWERPCJITINFO_H
#define POWERPCJITINFO_H
#include "llvm/Target/TargetJITInfo.h"
namespace llvm {
class TargetMachine;
class IntrinsicLowering;
class PowerPCJITInfo : public TargetJITInfo {
TargetMachine &TM;
public:
PowerPCJITInfo(TargetMachine &tm) : TM(tm) {}
/// addPassesToJITCompile - Add passes to the specified pass manager to
/// implement a fast dynamic compiler for this target. Return true if this
/// is not supported for this target.
///
virtual void addPassesToJITCompile(FunctionPassManager &PM);
/// replaceMachineCodeForFunction - Make it so that calling the function
/// whose machine code is at OLD turns into a call to NEW, perhaps by
/// overwriting OLD with a branch to NEW. This is used for self-modifying
/// code.
///
virtual void replaceMachineCodeForFunction(void *Old, void *New);
/// getJITStubForFunction - Create or return a stub for the specified
/// function. This stub acts just like the specified function, except that
/// it allows the "address" of the function to be taken without having to
/// generate code for it.
virtual void *getJITStubForFunction(Function *F, MachineCodeEmitter &MCE);
};
}
#endif

View File

@ -0,0 +1,88 @@
//===-- PowerPCTargetMachine.cpp - Define TargetMachine for PowerPC -------===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//
//===----------------------------------------------------------------------===//
#include "PowerPCTargetMachine.h"
#include "PowerPC.h"
#include "llvm/IntrinsicLowering.h"
#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/Target/TargetMachineImpls.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/Transforms/Scalar.h"
using namespace llvm;
// allocatePowerPCTargetMachine - Allocate and return a subclass of
// TargetMachine that implements the PowerPC backend.
//
TargetMachine *llvm::allocatePowerPCTargetMachine(const Module &M,
IntrinsicLowering *IL) {
return new PowerPCTargetMachine(M, IL);
}
/// PowerPCTargetMachine ctor - Create an ILP32 architecture model
///
/// FIXME: Should double alignment be 8 bytes? Then we get a PtrAl != DoubleAl abort
PowerPCTargetMachine::PowerPCTargetMachine(const Module &M,
IntrinsicLowering *IL)
: TargetMachine("PowerPC", IL, false, 4, 4, 4, 4, 4, 4, 4, 4),
FrameInfo(TargetFrameInfo::StackGrowsDown, 16, -4), JITInfo(*this) {
}
/// addPassesToEmitAssembly - Add passes to the specified pass manager
/// to implement a static compiler for this target.
///
bool PowerPCTargetMachine::addPassesToEmitAssembly(PassManager &PM,
std::ostream &Out) {
// FIXME: Implement efficient support for garbage collection intrinsics.
PM.add(createLowerGCPass());
// FIXME: Implement the invoke/unwind instructions!
PM.add(createLowerInvokePass());
// FIXME: The code generator does not properly handle functions with
// unreachable basic blocks.
PM.add(createCFGSimplificationPass());
// FIXME: Implement the switch instruction in the instruction selector!
PM.add(createLowerSwitchPass());
PM.add(createPPCSimpleInstructionSelector(*this));
PM.add(createRegisterAllocator());
PM.add(createPrologEpilogCodeInserter());
PM.add(createPPCCodePrinterPass(Out, *this));
PM.add(createMachineCodeDeleter());
return false;
}
/// addPassesToJITCompile - Add passes to the specified pass manager to
/// implement a fast dynamic compiler for this target.
///
void PowerPCJITInfo::addPassesToJITCompile(FunctionPassManager &PM) {
// FIXME: Implement efficient support for garbage collection intrinsics.
PM.add(createLowerGCPass());
// FIXME: Implement the invoke/unwind instructions!
PM.add(createLowerInvokePass());
// FIXME: The code generator does not properly handle functions with
// unreachable basic blocks.
PM.add(createCFGSimplificationPass());
// FIXME: Implement the switch instruction in the instruction selector!
PM.add(createLowerSwitchPass());
PM.add(createPPCSimpleInstructionSelector(TM));
PM.add(createRegisterAllocator());
PM.add(createPrologEpilogCodeInserter());
}

View File

@ -0,0 +1,44 @@
//===- PowerPC.td - Describe the PowerPC Target Machine ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//
//===----------------------------------------------------------------------===//
// Get the target-independent interfaces which we are implementing...
//
include "../Target.td"
//===----------------------------------------------------------------------===//
// Register File Description
//===----------------------------------------------------------------------===//
include "PowerPCReg.td"
include "PowerPCInstrs.td"
def PowerPCInstrInfo : InstrInfo {
let PHIInst = PHI;
let TSFlagsFields = ["ArgCount", "Arg0Type", "Arg1Type", "Arg2Type", "Arg3Type", "Arg4Type", "VMX", "PPC64"];
let TSFlagsShifts = [ 0, 3, 8, 13, 18, 23, 28, 29 ];
}
def PowerPC : Target {
// Pointers are 32-bits in size.
let PointerType = i32;
// According to the Mach-O Runtime ABI, these regs are nonvolatile across
// calls:
let CalleeSavedRegisters = [R1, R13, R14, R15, R16, R17, R18, R19,
R20, R21, R22, R23, R24, R25, R26, R27, R28, R29, R30, R31, F14, F15,
F16, F17, F18, F19, F20, F21, F22, F23, F24, F25, F26, F27, F28, F29,
F30, F31, CR2, CR3, CR4];
// Pull in Instruction Info:
let InstructionSet = PowerPCInstrInfo;
}

View File

@ -0,0 +1,694 @@
//===-- PPC32/Printer.cpp - Convert X86 LLVM code to Intel assembly ---------===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains a printer that converts from our internal
// representation of machine-dependent LLVM code to Intel-format
// assembly language. This printer is the output mechanism used
// by `llc' and `lli -print-machineinstrs' on X86.
//
//===----------------------------------------------------------------------===//
#include <set>
#include "PowerPC.h"
#include "PowerPCInstrInfo.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/Assembly/Writer.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Support/Mangler.h"
#include "Support/Statistic.h"
#include "Support/StringExtras.h"
#include "Support/CommandLine.h"
namespace llvm {
namespace {
Statistic<> EmittedInsts("asm-printer", "Number of machine instrs printed");
struct Printer : public MachineFunctionPass {
/// Output stream on which we're printing assembly code.
///
std::ostream &O;
/// Target machine description which we query for reg. names, data
/// layout, etc.
///
TargetMachine &TM;
/// Name-mangler for global names.
///
Mangler *Mang;
std::set< std::string > Stubs;
std::set<std::string> Strings;
Printer(std::ostream &o, TargetMachine &tm) : O(o), TM(tm) { }
/// We name each basic block in a Function with a unique number, so
/// that we can consistently refer to them later. This is cleared
/// at the beginning of each call to runOnMachineFunction().
///
typedef std::map<const Value *, unsigned> ValueMapTy;
ValueMapTy NumberForBB;
/// Cache of mangled name for current function. This is
/// recalculated at the beginning of each call to
/// runOnMachineFunction().
///
std::string CurrentFnName;
virtual const char *getPassName() const {
return "PowerPC Assembly Printer";
}
void printMachineInstruction(const MachineInstr *MI);
void printOp(const MachineOperand &MO,
bool elideOffsetKeyword = false);
void printConstantPool(MachineConstantPool *MCP);
bool runOnMachineFunction(MachineFunction &F);
bool doInitialization(Module &M);
bool doFinalization(Module &M);
void emitGlobalConstant(const Constant* CV);
void emitConstantValueOnly(const Constant *CV);
};
} // end of anonymous namespace
/// createPPCCodePrinterPass - Returns a pass that prints the X86
/// 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.
///
FunctionPass *createPPCCodePrinterPass(std::ostream &o,TargetMachine &tm){
return new Printer(o, tm);
}
/// isStringCompatible - Can we treat the specified array as a string?
/// Only if it is an array of ubytes or non-negative sbytes.
///
static bool isStringCompatible(const ConstantArray *CVA) {
const Type *ETy = cast<ArrayType>(CVA->getType())->getElementType();
if (ETy == Type::UByteTy) return true;
if (ETy != Type::SByteTy) return false;
for (unsigned i = 0; i < CVA->getNumOperands(); ++i)
if (cast<ConstantSInt>(CVA->getOperand(i))->getValue() < 0)
return false;
return true;
}
/// toOctal - Convert the low order bits of X into an octal digit.
///
static inline char toOctal(int X) {
return (X&7)+'0';
}
/// getAsCString - Return the specified array as a C compatible
/// string, only if the predicate isStringCompatible is true.
///
static void printAsCString(std::ostream &O, const ConstantArray *CVA) {
assert(isStringCompatible(CVA) && "Array is not string compatible!");
O << "\"";
for (unsigned i = 0; i < CVA->getNumOperands(); ++i) {
unsigned char C = cast<ConstantInt>(CVA->getOperand(i))->getRawValue();
if (C == '"') {
O << "\\\"";
} else if (C == '\\') {
O << "\\\\";
} else if (isprint(C)) {
O << C;
} else {
switch(C) {
case '\b': O << "\\b"; break;
case '\f': O << "\\f"; break;
case '\n': O << "\\n"; break;
case '\r': O << "\\r"; break;
case '\t': O << "\\t"; break;
default:
O << '\\';
O << toOctal(C >> 6);
O << toOctal(C >> 3);
O << toOctal(C >> 0);
break;
}
}
}
O << "\"";
}
// Print out the specified constant, without a storage class. Only the
// constants valid in constant expressions can occur here.
void Printer::emitConstantValueOnly(const Constant *CV) {
if (CV->isNullValue())
O << "0";
else if (const ConstantBool *CB = dyn_cast<ConstantBool>(CV)) {
assert(CB == ConstantBool::True);
O << "1";
} else if (const ConstantSInt *CI = dyn_cast<ConstantSInt>(CV))
O << CI->getValue();
else if (const ConstantUInt *CI = dyn_cast<ConstantUInt>(CV))
O << CI->getValue();
else if (const ConstantPointerRef *CPR = dyn_cast<ConstantPointerRef>(CV))
// This is a constant address for a global variable or function. Use the
// name of the variable or function as the address value.
O << Mang->getValueName(CPR->getValue());
else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) {
const TargetData &TD = TM.getTargetData();
switch(CE->getOpcode()) {
case Instruction::GetElementPtr: {
// generate a symbolic expression for the byte address
const Constant *ptrVal = CE->getOperand(0);
std::vector<Value*> idxVec(CE->op_begin()+1, CE->op_end());
if (unsigned Offset = TD.getIndexedOffset(ptrVal->getType(), idxVec)) {
O << "(";
emitConstantValueOnly(ptrVal);
O << ") + " << Offset;
} else {
emitConstantValueOnly(ptrVal);
}
break;
}
case Instruction::Cast: {
// Support only non-converting or widening casts for now, that is, ones
// that do not involve a change in value. This assertion is really gross,
// and may not even be a complete check.
Constant *Op = CE->getOperand(0);
const Type *OpTy = Op->getType(), *Ty = CE->getType();
// Remember, kids, pointers on x86 can be losslessly converted back and
// forth into 32-bit or wider integers, regardless of signedness. :-P
assert(((isa<PointerType>(OpTy)
&& (Ty == Type::LongTy || Ty == Type::ULongTy
|| Ty == Type::IntTy || Ty == Type::UIntTy))
|| (isa<PointerType>(Ty)
&& (OpTy == Type::LongTy || OpTy == Type::ULongTy
|| OpTy == Type::IntTy || OpTy == Type::UIntTy))
|| (((TD.getTypeSize(Ty) >= TD.getTypeSize(OpTy))
&& OpTy->isLosslesslyConvertibleTo(Ty))))
&& "FIXME: Don't yet support this kind of constant cast expr");
O << "(";
emitConstantValueOnly(Op);
O << ")";
break;
}
case Instruction::Add:
O << "(";
emitConstantValueOnly(CE->getOperand(0));
O << ") + (";
emitConstantValueOnly(CE->getOperand(1));
O << ")";
break;
default:
assert(0 && "Unsupported operator!");
}
} else {
assert(0 && "Unknown constant value!");
}
}
// Print a constant value or values, with the appropriate storage class as a
// prefix.
void Printer::emitGlobalConstant(const Constant *CV) {
const TargetData &TD = TM.getTargetData();
if (CV->isNullValue()) {
O << "\t.space\t " << TD.getTypeSize(CV->getType()) << "\n";
return;
} else if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV)) {
if (isStringCompatible(CVA)) {
O << ".ascii";
printAsCString(O, CVA);
O << "\n";
} else { // Not a string. Print the values in successive locations
const std::vector<Use> &constValues = CVA->getValues();
for (unsigned i=0; i < constValues.size(); i++)
emitGlobalConstant(cast<Constant>(constValues[i].get()));
}
return;
} else if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV)) {
// Print the fields in successive locations. Pad to align if needed!
const StructLayout *cvsLayout = TD.getStructLayout(CVS->getType());
const std::vector<Use>& constValues = CVS->getValues();
unsigned sizeSoFar = 0;
for (unsigned i=0, N = constValues.size(); i < N; i++) {
const Constant* field = cast<Constant>(constValues[i].get());
// Check if padding is needed and insert one or more 0s.
unsigned fieldSize = TD.getTypeSize(field->getType());
unsigned padSize = ((i == N-1? cvsLayout->StructSize
: cvsLayout->MemberOffsets[i+1])
- cvsLayout->MemberOffsets[i]) - fieldSize;
sizeSoFar += fieldSize + padSize;
// Now print the actual field value
emitGlobalConstant(field);
// Insert the field padding unless it's zero bytes...
if (padSize)
O << "\t.space\t " << padSize << "\n";
}
assert(sizeSoFar == cvsLayout->StructSize &&
"Layout of constant struct may be incorrect!");
return;
} else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) {
// FP Constants are printed as integer constants to avoid losing
// precision...
double Val = CFP->getValue();
switch (CFP->getType()->getPrimitiveID()) {
default: assert(0 && "Unknown floating point type!");
case Type::FloatTyID: {
union FU { // Abide by C TBAA rules
float FVal;
unsigned UVal;
} U;
U.FVal = Val;
O << ".long\t" << U.UVal << "\t# float " << Val << "\n";
return;
}
case Type::DoubleTyID: {
union DU { // Abide by C TBAA rules
double FVal;
uint64_t UVal;
struct {
uint32_t MSWord;
uint32_t LSWord;
} T;
} U;
U.FVal = Val;
O << ".long\t" << U.T.MSWord << "\t# double most significant word " << Val << "\n";
O << ".long\t" << U.T.LSWord << "\t# double least significant word" << Val << "\n";
return;
}
}
} else if (CV->getType()->getPrimitiveSize() == 64) {
const ConstantInt *CI = dyn_cast<ConstantInt>(CV);
if(CI) {
union DU { // Abide by C TBAA rules
int64_t UVal;
struct {
uint32_t MSWord;
uint32_t LSWord;
} T;
} U;
U.UVal = CI->getRawValue();
O << ".long\t" << U.T.MSWord << "\t# Double-word most significant word " << U.UVal << "\n";
O << ".long\t" << U.T.LSWord << "\t# Double-word least significant word" << U.UVal << "\n";
return;
}
}
const Type *type = CV->getType();
O << "\t";
switch (type->getPrimitiveID()) {
case Type::UByteTyID: case Type::SByteTyID:
O << ".byte";
break;
case Type::UShortTyID: case Type::ShortTyID:
O << ".short";
break;
case Type::BoolTyID:
case Type::PointerTyID:
case Type::UIntTyID: case Type::IntTyID:
O << ".long";
break;
case Type::ULongTyID: case Type::LongTyID:
assert (0 && "Should have already output double-word constant.");
case Type::FloatTyID: case Type::DoubleTyID:
assert (0 && "Should have already output floating point constant.");
default:
assert (0 && "Can't handle printing this type of thing");
break;
}
O << "\t";
emitConstantValueOnly(CV);
O << "\n";
}
/// printConstantPool - Print to the current output stream assembly
/// representations of the constants in the constant pool MCP. This is
/// used to print out constants which have been "spilled to memory" by
/// the code generator.
///
void Printer::printConstantPool(MachineConstantPool *MCP) {
const std::vector<Constant*> &CP = MCP->getConstants();
const TargetData &TD = TM.getTargetData();
if (CP.empty()) return;
for (unsigned i = 0, e = CP.size(); i != e; ++i) {
O << "\t.const\n";
O << "\t.align " << (unsigned)TD.getTypeAlignment(CP[i]->getType())
<< "\n";
O << ".CPI" << CurrentFnName << "_" << i << ":\t\t\t\t\t#"
<< *CP[i] << "\n";
emitGlobalConstant(CP[i]);
}
}
/// runOnMachineFunction - This uses the printMachineInstruction()
/// method to print assembly for each instruction.
///
bool Printer::runOnMachineFunction(MachineFunction &MF) {
// BBNumber is used here so that a given Printer will never give two
// BBs the same name. (If you have a better way, please let me know!)
static unsigned BBNumber = 0;
O << "\n\n";
// What's my mangled name?
CurrentFnName = Mang->getValueName(MF.getFunction());
// Print out constants referenced by the function
printConstantPool(MF.getConstantPool());
// Print out labels for the function.
O << "\t.text\n";
O << "\t.globl\t" << CurrentFnName << "\n";
O << "\t.align 5\n";
O << CurrentFnName << ":\n";
// Number each basic block so that we can consistently refer to them
// in PC-relative references.
NumberForBB.clear();
for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
I != E; ++I) {
NumberForBB[I->getBasicBlock()] = BBNumber++;
}
// Print out code for the function.
for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
I != E; ++I) {
// Print a label for the basic block.
O << "L" << NumberForBB[I->getBasicBlock()] << ":\t# "
<< I->getBasicBlock()->getName() << "\n";
for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
II != E; ++II) {
// Print the assembly for the instruction.
O << "\t";
printMachineInstruction(II);
}
}
// We didn't modify anything.
return false;
}
void Printer::printOp(const MachineOperand &MO,
bool elideOffsetKeyword /* = false */) {
const MRegisterInfo &RI = *TM.getRegisterInfo();
int new_symbol;
switch (MO.getType()) {
case MachineOperand::MO_VirtualRegister:
if (Value *V = MO.getVRegValueOrNull()) {
O << "<" << V->getName() << ">";
return;
}
// FALLTHROUGH
case MachineOperand::MO_MachineRegister:
O << RI.get(MO.getReg()).Name;
return;
case MachineOperand::MO_SignExtendedImmed:
case MachineOperand::MO_UnextendedImmed:
O << (int)MO.getImmedValue();
return;
case MachineOperand::MO_MachineBasicBlock: {
MachineBasicBlock *MBBOp = MO.getMachineBasicBlock();
O << ".LBB" << Mang->getValueName(MBBOp->getParent()->getFunction())
<< "_" << MBBOp->getNumber () << "\t# "
<< MBBOp->getBasicBlock ()->getName ();
return;
}
case MachineOperand::MO_PCRelativeDisp:
std::cerr << "Shouldn't use addPCDisp() when building PPC MachineInstrs";
abort ();
return;
case MachineOperand::MO_GlobalAddress:
if (!elideOffsetKeyword) {
if(isa<Function>(MO.getGlobal())) {
Stubs.insert(Mang->getValueName(MO.getGlobal()));
O << "L" << Mang->getValueName(MO.getGlobal()) << "$stub";
} else {
O << Mang->getValueName(MO.getGlobal());
}
}
return;
case MachineOperand::MO_ExternalSymbol:
O << MO.getSymbolName();
return;
default:
O << "<unknown operand type>"; return;
}
}
#if 0
static inline
unsigned int ValidOpcodes(const MachineInstr *MI, unsigned int ArgType[5]) {
int i;
unsigned int retval = 1;
for(i = 0; i<5; i++) {
switch(ArgType[i]) {
case none:
break;
case Gpr:
case Gpr0:
Type::UIntTy
case Simm16:
case Zimm16:
case PCRelimm24:
case Imm24:
case Imm5:
case PCRelimm14:
case Imm14:
case Imm2:
case Crf:
case Imm3:
case Imm1:
case Fpr:
case Imm4:
case Imm8:
case Disimm16:
case Spr:
case Sgr:
};
}
}
}
#endif
/// printMachineInstruction -- Print out a single PPC32 LLVM instruction
/// MI in Darwin syntax to the current output stream.
///
void Printer::printMachineInstruction(const MachineInstr *MI) {
unsigned Opcode = MI->getOpcode();
const TargetInstrInfo &TII = *TM.getInstrInfo();
const TargetInstrDescriptor &Desc = TII.get(Opcode);
unsigned int i;
unsigned int ArgCount = Desc.TSFlags & PPC32II::ArgCountMask;
unsigned int ArgType[5];
ArgType[0] = (Desc.TSFlags>>PPC32II::Arg0TypeShift) & PPC32II::ArgTypeMask;
ArgType[1] = (Desc.TSFlags>>PPC32II::Arg1TypeShift) & PPC32II::ArgTypeMask;
ArgType[2] = (Desc.TSFlags>>PPC32II::Arg2TypeShift) & PPC32II::ArgTypeMask;
ArgType[3] = (Desc.TSFlags>>PPC32II::Arg3TypeShift) & PPC32II::ArgTypeMask;
ArgType[4] = (Desc.TSFlags>>PPC32II::Arg4TypeShift) & PPC32II::ArgTypeMask;
assert ( ((Desc.TSFlags & PPC32II::VMX) == 0) && "Instruction requires VMX support");
assert ( ((Desc.TSFlags & PPC32II::PPC64) == 0) && "Instruction requires 64 bit support");
//assert ( ValidOpcodes(MI, ArgType) && "Instruction has invalid inputs");
++EmittedInsts;
if(Opcode == PPC32::MovePCtoLR) {
O << "mflr r0\n";
O << "bcl 20,31,L" << CurrentFnName << "$pb\n";
O << "L" << CurrentFnName << "$pb:\n";
return;
}
O << TII.getName(MI->getOpcode()) << " ";
std::cout << TII.getName(MI->getOpcode()) << " expects " << ArgCount << " args\n";
if(Opcode == PPC32::LOADLoAddr) {
printOp(MI->getOperand(0));
O << ", ";
printOp(MI->getOperand(1));
O << ", lo16(";
printOp(MI->getOperand(2));
O << "-L" << CurrentFnName << "$pb)\n";
return;
}
if(Opcode == PPC32::LOADHiAddr) {
printOp(MI->getOperand(0));
O << ", ";
printOp(MI->getOperand(1));
O << ", ha16(" ;
printOp(MI->getOperand(2));
O << "-L" << CurrentFnName << "$pb)\n";
return;
}
if( (ArgCount == 3) && (ArgType[1] == PPC32II::Disimm16) ) {
printOp(MI->getOperand(0));
O << ", ";
printOp(MI->getOperand(1));
O << "(";
if((ArgType[2] == PPC32II::Gpr0) && (MI->getOperand(2).getReg() == PPC32::R0)) {
O << "0";
} else {
printOp(MI->getOperand(2));
}
O << ")\n";
} else {
for(i = 0; i< ArgCount; i++) {
if( (ArgType[i] == PPC32II::Gpr0) && ((MI->getOperand(i).getReg()) == PPC32::R0)) {
O << "0";
} else {
//std::cout << "DEBUG " << (*(TM.getRegisterInfo())).get(MI->getOperand(i).getReg()).Name << "\n";
printOp(MI->getOperand(i));
}
if( ArgCount - 1 == i) {
O << "\n";
} else {
O << ", ";
}
}
}
return;
}
bool Printer::doInitialization(Module &M) {
// Tell gas we are outputting Intel syntax (not AT&T syntax) assembly.
//
// Bug: gas in `intel_syntax noprefix' mode interprets the symbol `Sp' in an
// instruction as a reference to the register named sp, and if you try to
// reference a symbol `Sp' (e.g. `mov ECX, OFFSET Sp') then it gets lowercased
// before being looked up in the symbol table. This creates spurious
// `undefined symbol' errors when linking. Workaround: Do not use `noprefix'
// mode, and decorate all register names with percent signs.
// O << "\t.intel_syntax\n";
Mang = new Mangler(M, true);
return false; // success
}
// SwitchSection - Switch to the specified section of the executable if we are
// not already in it!
//
static void SwitchSection(std::ostream &OS, std::string &CurSection,
const char *NewSection) {
if (CurSection != NewSection) {
CurSection = NewSection;
if (!CurSection.empty())
OS << "\t" << NewSection << "\n";
}
}
bool Printer::doFinalization(Module &M) {
const TargetData &TD = TM.getTargetData();
std::string CurSection;
// Print out module-level global variables here.
for (Module::const_giterator I = M.gbegin(), E = M.gend(); I != E; ++I)
if (I->hasInitializer()) { // External global require no code
O << "\n\n";
std::string name = Mang->getValueName(I);
Constant *C = I->getInitializer();
unsigned Size = TD.getTypeSize(C->getType());
unsigned Align = TD.getTypeAlignment(C->getType());
if (C->isNullValue() &&
(I->hasLinkOnceLinkage() || I->hasInternalLinkage() ||
I->hasWeakLinkage() /* FIXME: Verify correct */)) {
SwitchSection(O, CurSection, ".data");
if (I->hasInternalLinkage())
O << "\t.local " << name << "\n";
O << "\t.comm " << name << "," << TD.getTypeSize(C->getType())
<< "," << (unsigned)TD.getTypeAlignment(C->getType());
O << "\t\t# ";
WriteAsOperand(O, I, true, true, &M);
O << "\n";
} else {
switch (I->getLinkage()) {
case GlobalValue::LinkOnceLinkage:
case GlobalValue::WeakLinkage: // FIXME: Verify correct for weak.
// Nonnull linkonce -> weak
O << "\t.weak " << name << "\n";
SwitchSection(O, CurSection, "");
O << "\t.section\t.llvm.linkonce.d." << name << ",\"aw\",@progbits\n";
break;
case GlobalValue::AppendingLinkage:
// FIXME: appending linkage variables should go into a section of
// their name or something. For now, just emit them as external.
case GlobalValue::ExternalLinkage:
// If external or appending, declare as a global symbol
O << "\t.globl " << name << "\n";
// FALL THROUGH
case GlobalValue::InternalLinkage:
if (C->isNullValue())
SwitchSection(O, CurSection, ".bss");
else
SwitchSection(O, CurSection, ".data");
break;
}
O << "\t.align " << Align << "\n";
O << name << ":\t\t\t\t# ";
WriteAsOperand(O, I, true, true, &M);
O << " = ";
WriteAsOperand(O, C, false, false, &M);
O << "\n";
emitGlobalConstant(C);
}
}
for(std::set<std::string>::iterator i = Stubs.begin(); i != Stubs.end(); ++i) {
O << ".data\n";
O << ".section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32\n";
O << "\t.align 2\n";
O << "L" << *i << "$stub:\n";
O << "\t.indirect_symbol " << *i << "\n";
O << "\tmflr r0\n";
O << "\tbcl 20,31,L0$" << *i << "\n";
O << "L0$" << *i << ":\n";
O << "\tmflr r11\n";
O << "\taddis r11,r11,ha16(L" << *i << "$lazy_ptr-L0$" << *i << ")\n";
O << "\tmtlr r0\n";
O << "\tlwzu r12,lo16(L" << *i << "$lazy_ptr-L0$" << *i << ")(r11)\n";
O << "\tmtctr r12\n";
O << "\tbctr\n";
O << ".data\n";
O << ".lazy_symbol_pointer\n";
O << "L" << *i << "$lazy_ptr:\n";
O << ".indirect_symbol " << *i << "\n";
O << ".long dyld_stub_binding_helper\n";
}
delete Mang;
return false; // success
}
} // End llvm namespace

View File

@ -0,0 +1,43 @@
//===-- PowerPCCodeEmitter.cpp - JIT Code Emitter for PowerPC -----*- C++ -*-=//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//
//===----------------------------------------------------------------------===//
#include "PowerPCTargetMachine.h"
namespace llvm {
/// addPassesToEmitMachineCode - Add passes to the specified pass manager to get
/// machine code emitted. This uses a MachineCodeEmitter object to handle
/// actually outputting the machine code and resolving things like the address
/// of functions. This method should returns true if machine code emission is
/// not supported.
///
bool PowerPCTargetMachine::addPassesToEmitMachineCode(FunctionPassManager &PM,
MachineCodeEmitter &MCE) {
return true;
// It should go something like this:
// PM.add(new Emitter(MCE)); // Machine code emitter pass for PowerPC
// Delete machine code for this function after emitting it:
// PM.add(createMachineCodeDeleter());
}
void *PowerPCJITInfo::getJITStubForFunction(Function *F,
MachineCodeEmitter &MCE) {
assert (0 && "PowerPCJITInfo::getJITStubForFunction not implemented");
return 0;
}
void PowerPCJITInfo::replaceMachineCodeForFunction (void *Old, void *New) {
assert (0 && "PowerPCJITInfo::replaceMachineCodeForFunction not implemented");
}
} // end llvm namespace

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,53 @@
//===-- PowerPCInstrBuilder.h - Functions to aid building PPC insts -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file exposes functions that may be used with BuildMI from the
// MachineInstrBuilder.h file to simplify generating frame and constant pool
// references.
//
// For reference, the order of operands for memory references is:
// (Operand), Dest Reg, Base Reg, and either Reg Index or Immediate Displacement.
//
//===----------------------------------------------------------------------===//
#ifndef PPCINSTRBUILDER_H
#define PPCINSTRBUILDER_H
#include "llvm/CodeGen/MachineInstrBuilder.h"
namespace llvm {
/// addFrameReference - This function is used to add a reference to the base of
/// an abstract object on the stack frame of the current function. This
/// reference has base register as the FrameIndex offset until it is resolved.
/// This allows a constant offset to be specified as well...
///
inline const MachineInstrBuilder &
addFrameReference(const MachineInstrBuilder &MIB, int FI, int Offset = 0, bool mem = true) {
if (mem)
return MIB.addSImm(Offset).addFrameIndex(FI);
else
return MIB.addFrameIndex(FI).addSImm(Offset);
}
/// addConstantPoolReference - This function is used to add a reference to the
/// base of a constant value spilled to the per-function constant pool. The
/// reference has base register ConstantPoolIndex offset which is retained until
/// either machine code emission or assembly output. This allows an optional
/// offset to be added as well.
///
inline const MachineInstrBuilder &
addConstantPoolReference(const MachineInstrBuilder &MIB, unsigned CPI,
int Offset = 0) {
return MIB.addSImm(Offset).addConstantPoolIndex(CPI);
}
} // End llvm namespace
#endif

View File

@ -0,0 +1,22 @@
//===- PowerPCInstrInfo.cpp - PowerPC Instruction Information ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the PowerPC implementation of the TargetInstrInfo class.
//
//===----------------------------------------------------------------------===//
#include "PowerPCInstrInfo.h"
#include "PowerPC.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "PowerPCGenInstrInfo.inc"
using namespace llvm;
PowerPCInstrInfo::PowerPCInstrInfo()
: TargetInstrInfo(PowerPCInsts, sizeof(PowerPCInsts)/sizeof(PowerPCInsts[0])){
}

View File

@ -0,0 +1,78 @@
//===- PowerPCInstrInfo.h - PowerPC Instruction Information -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the PowerPC implementation of the TargetInstrInfo class.
//
//===----------------------------------------------------------------------===//
#ifndef POWERPCINSTRUCTIONINFO_H
#define POWERPCINSTRUCTIONINFO_H
#include "llvm/Target/TargetInstrInfo.h"
#include "PowerPCRegisterInfo.h"
namespace llvm {
namespace PPC32II {
enum {
ArgCountShift = 0,
ArgCountMask = 7,
Arg0TypeShift = 3,
Arg1TypeShift = 8,
Arg2TypeShift = 13,
Arg3TypeShift = 18,
Arg4TypeShift = 23,
VMX = 1<<28,
PPC64 = 1<<29,
ArgTypeMask = 31
};
enum {
None = 0,
Gpr = 1,
Gpr0 = 2,
Simm16 = 3,
Zimm16 = 4,
PCRelimm24 = 5,
Imm24 = 6,
Imm5 = 7,
PCRelimm14 = 8,
Imm14 = 9,
Imm2 = 10,
Crf = 11,
Imm3 = 12,
Imm1 = 13,
Fpr = 14,
Imm4 = 15,
Imm8 = 16,
Disimm16 = 17,
Disimm14 = 18,
Spr = 19,
Sgr = 20,
Imm15 = 21,
Vpr = 22
};
}
class PowerPCInstrInfo : public TargetInstrInfo {
const PowerPCRegisterInfo RI;
public:
PowerPCInstrInfo();
/// getRegisterInfo - TargetInstrInfo is a superset of MRegister info. As
/// such, whenever a client has an instance of instruction info, it should
/// always be able to get register info as well (through this method).
///
virtual const MRegisterInfo &getRegisterInfo() const { return RI; }
};
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,268 @@
//===- PowerPCRegisterInfo.cpp - PowerPC Register Information ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the PowerPC implementation of the MRegisterInfo class.
//
//===----------------------------------------------------------------------===//
#include "PowerPC.h"
#include "PowerPCRegisterInfo.h"
#include "PowerPCInstrBuilder.h"
#include "llvm/Constants.h"
#include "llvm/Type.h"
#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetFrameInfo.h"
#include "Support/CommandLine.h"
#include "Support/STLExtras.h"
using namespace llvm;
namespace {
cl::opt<bool>
NoFPElim("disable-fp-elim",cl::desc("Disable frame pointer elimination optimization"));
}
PowerPCRegisterInfo::PowerPCRegisterInfo()
: PowerPCGenRegisterInfo(PPC32::ADJCALLSTACKDOWN,
PPC32::ADJCALLSTACKUP) {}
static unsigned getIdx(const TargetRegisterClass *RC) {
if (RC == PowerPC::GPRCRegisterClass) {
switch (RC->getSize()) {
default: assert(0 && "Invalid data size!");
case 1: return 0;
case 2: return 1;
case 4: return 2;
}
}
else if (RC == PowerPC::FPRCRegisterClass) {
switch (RC->getSize()) {
default: assert(0 && "Invalid data size!");
case 4: return 3;
case 8: return 4;
}
}
abort();
}
int PowerPCRegisterInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
unsigned SrcReg, int FrameIdx,
const TargetRegisterClass *RC) const {
static const unsigned Opcode[] =
{ PPC32::STB, PPC32::STH, PPC32::STW, PPC32::STFS, PPC32::STFD };
unsigned OC = Opcode[getIdx(RC)];
MBB.insert(MI, addFrameReference(BuildMI(OC, 3).addReg(SrcReg),FrameIdx));
return 1;
}
int PowerPCRegisterInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
unsigned DestReg, int FrameIdx,
const TargetRegisterClass *RC) const{
static const unsigned Opcode[] =
{ PPC32::LBZ, PPC32::LHZ, PPC32::LWZ, PPC32::LFS, PPC32::LFD };
unsigned OC = Opcode[getIdx(RC)];
MBB.insert(MI, addFrameReference(BuildMI(OC, 2, DestReg), FrameIdx));
return 1;
}
int PowerPCRegisterInfo::copyRegToReg(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
unsigned DestReg, unsigned SrcReg,
const TargetRegisterClass *RC) const {
MachineInstr *I;
if(RC == PowerPC::GPRCRegisterClass) {
I = BuildMI(PPC32::OR, 2, DestReg).addReg(SrcReg).addReg(SrcReg);
} else if (RC == PowerPC::FPRCRegisterClass) {
I = BuildMI(PPC32::FMR, 1, DestReg).addReg(SrcReg);
} else {
std::cerr << "Attempt to copy register that is not GPR or FPR";
abort();
}
MBB.insert(MI, I);
return 1;
}
//===----------------------------------------------------------------------===//
// Stack Frame Processing methods
//===----------------------------------------------------------------------===//
// hasFP - Return true if the specified function should have a dedicated frame
// pointer register. This is true if the function has variable sized allocas or
// if frame pointer elimination is disabled.
//
static bool hasFP(MachineFunction &MF) {
return NoFPElim || MF.getFrameInfo()->hasVarSizedObjects();
}
void PowerPCRegisterInfo::
eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
MachineBasicBlock::iterator I) const {
if (hasFP(MF)) {
// If we have a frame pointer, turn the adjcallstackdown instruction into a
// 'sub r1, r1, <amt>' and the adjcallstackup instruction into 'add r1, r1, <amt>'
MachineInstr *Old = I;
int Amount = Old->getOperand(0).getImmedValue();
if (Amount != 0) {
// We need to keep the stack aligned properly. To do this, we round the
// amount of space needed for the outgoing arguments up to the next
// alignment boundary.
unsigned Align = MF.getTarget().getFrameInfo()->getStackAlignment();
Amount = (Amount+Align-1)/Align*Align;
MachineInstr *New;
if (Old->getOpcode() == PPC32::ADJCALLSTACKDOWN) {
New=BuildMI(PPC32::ADDI, 2, PPC32::R1).addReg(PPC32::R1).addSImm(-Amount);
} else {
assert(Old->getOpcode() == PPC32::ADJCALLSTACKUP);
New=BuildMI(PPC32::ADDI, 2, PPC32::R1).addReg(PPC32::R1).addSImm(Amount);
}
// Replace the pseudo instruction with a new instruction...
MBB.insert(I, New);
}
}
MBB.erase(I);
}
void
PowerPCRegisterInfo::eliminateFrameIndex(MachineFunction &MF,
MachineBasicBlock::iterator II) const {
unsigned i = 0;
MachineInstr &MI = *II;
while (!MI.getOperand(i).isFrameIndex()) {
++i;
assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!");
}
int FrameIndex = MI.getOperand(i).getFrameIndex();
// This must be part of a four operand memory reference. Replace the
// FrameIndex with base register with GPR1.
MI.SetMachineOperandReg(i, PPC32::R1);
// Take into account whether its an add or mem instruction
if (i == 2) i--;
// Now add the frame object offset to the offset from r1.
int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex) +
MI.getOperand(i).getImmedValue()+4;
if (!hasFP(MF))
Offset += MF.getFrameInfo()->getStackSize();
MI.SetMachineOperandConst(i-1, MachineOperand::MO_SignExtendedImmed, Offset);
std::cout << "offset = " << Offset << std::endl;
}
void PowerPCRegisterInfo::processFunctionBeforeFrameFinalized(
MachineFunction &MF) const {
// Do Nothing
}
void PowerPCRegisterInfo::emitPrologue(MachineFunction &MF) const {
MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB
MachineBasicBlock::iterator MBBI = MBB.begin();
MachineFrameInfo *MFI = MF.getFrameInfo();
MachineInstr *MI;
// Get the number of bytes to allocate from the FrameInfo
unsigned NumBytes = MFI->getStackSize();
if (MFI->hasCalls()) {
// When we have no frame pointer, we reserve argument space for call sites
// in the function immediately on entry to the current function. This
// eliminates the need for add/sub brackets around call sites.
//
NumBytes += MFI->getMaxCallFrameSize();
// Round the size to a multiple of the alignment (don't forget the 4 byte
// offset though).
unsigned Align = MF.getTarget().getFrameInfo()->getStackAlignment();
NumBytes = ((NumBytes+4)+Align-1)/Align*Align - 4;
// Store the incoming LR so it is preserved across calls
MI= BuildMI(PPC32::MovePCtoLR, 0, PPC32::LR).addReg(PPC32::LR);
MBB.insert(MBBI, MI);
MI= BuildMI(PPC32::MFSPR, 1, PPC32::R0).addImm(8);
MBB.insert(MBBI, MI);
MI= BuildMI(PPC32::STW, 3).addReg(PPC32::R0).addSImm(8).addReg(PPC32::R1);
MBB.insert(MBBI, MI);
}
// Update frame info to pretend that this is part of the stack...
MFI->setStackSize(NumBytes);
// adjust stack pointer: r1 -= numbytes
if (NumBytes) {
MI= BuildMI(PPC32::STWU, 2, PPC32::R1).addImm(-NumBytes).addReg(PPC32::R1);
MBB.insert(MBBI, MI);
}
}
void PowerPCRegisterInfo::emitEpilogue(MachineFunction &MF,
MachineBasicBlock &MBB) const {
const MachineFrameInfo *MFI = MF.getFrameInfo();
MachineBasicBlock::iterator MBBI = prior(MBB.end());
MachineInstr *MI;
assert(MBBI->getOpcode() == PPC32::BLR &&
"Can only insert epilog into returning blocks");
// Get the number of bytes allocated from the FrameInfo...
unsigned NumBytes = MFI->getStackSize();
// adjust stack pointer back: r1 += numbytes
if (NumBytes) {
MI =BuildMI(PPC32::ADDI, 2, PPC32::R1)
.addReg(PPC32::R1)
.addSImm(NumBytes);
MBB.insert(MBBI, MI);
}
// If we have calls, restore the LR value before we branch to it
if (MFI->hasCalls()) {
MI = BuildMI(PPC32::LWZ, 2, PPC32::R0).addSImm(8).addReg(PPC32::R1);
MBB.insert(MBBI, MI);
MI = BuildMI(PPC32::MTLR, 1).addReg(PPC32::R0);
MBB.insert(MBBI, MI);
}
}
#include "PowerPCGenRegisterInfo.inc"
const TargetRegisterClass*
PowerPCRegisterInfo::getRegClassForType(const Type* Ty) const {
switch (Ty->getPrimitiveID()) {
case Type::LongTyID:
case Type::ULongTyID: assert(0 && "Long values can't fit in registers!");
default: assert(0 && "Invalid type to getClass!");
case Type::BoolTyID:
case Type::SByteTyID:
case Type::UByteTyID:
case Type::ShortTyID:
case Type::UShortTyID:
case Type::IntTyID:
case Type::UIntTyID:
case Type::PointerTyID: return &GPRCInstance;
case Type::FloatTyID:
case Type::DoubleTyID: return &FPRCInstance;
}
}

View File

@ -0,0 +1,58 @@
//===- PowerPCRegisterInfo.h - PowerPC Register Information Impl -*- C++ -*-==//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the PowerPC implementation of the MRegisterInfo class.
//
//===----------------------------------------------------------------------===//
#ifndef POWERPCREGISTERINFO_H
#define POWERPCREGISTERINFO_H
#include "llvm/Target/MRegisterInfo.h"
#include "PowerPCGenRegisterInfo.h.inc"
namespace llvm {
class Type;
struct PowerPCRegisterInfo : public PowerPCGenRegisterInfo {
PowerPCRegisterInfo();
const TargetRegisterClass* getRegClassForType(const Type* Ty) const;
/// Code Generation virtual methods...
int storeRegToStackSlot(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
unsigned SrcReg, int FrameIndex,
const TargetRegisterClass *RC) const;
int loadRegFromStackSlot(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
unsigned DestReg, int FrameIndex,
const TargetRegisterClass *RC) const;
int copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
unsigned DestReg, unsigned SrcReg,
const TargetRegisterClass *RC) const;
void eliminateCallFramePseudoInstr(MachineFunction &MF,
MachineBasicBlock &MBB,
MachineBasicBlock::iterator I) const;
void eliminateFrameIndex(MachineFunction &MF,
MachineBasicBlock::iterator II) const;
void processFunctionBeforeFrameFinalized(MachineFunction &MF) const;
void emitPrologue(MachineFunction &MF) const;
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
};
} // end namespace llvm
#endif

View File

@ -0,0 +1,82 @@
//===- PowerPCReg.td - Describe the PowerPC Register File -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//
//===----------------------------------------------------------------------===//
class PPCReg : Register {
let Namespace = "PPC32";
}
// We identify all our registers with a 5-bit ID, for consistency's sake.
// GPR - One of the 32 32-bit general-purpose registers
class GPR<bits<5> num> : PPCReg {
field bits<5> Num = num;
}
// SPR - One of the 32-bit special-purpose registers
class SPR<bits<5> num> : PPCReg {
field bits<5> Num = num;
}
// FPR - One of the 32 64-bit floating-point registers
class FPR<bits<5> num> : PPCReg {
field bits<5> Num = num;
}
// CR - One of the 8 4-bit condition registers
class CR<bits<5> num> : PPCReg {
field bits<5> Num = num;
}
// General-purpose registers
def R0 : GPR< 0>; def R1 : GPR< 1>; def R2 : GPR< 2>; def R3 : GPR< 3>;
def R4 : GPR< 4>; def R5 : GPR< 5>; def R6 : GPR< 6>; def R7 : GPR< 7>;
def R8 : GPR< 8>; def R9 : GPR< 9>; def R10 : GPR<10>; def R11 : GPR<11>;
def R12 : GPR<12>; def R13 : GPR<13>; def R14 : GPR<14>; def R15 : GPR<15>;
def R16 : GPR<16>; def R17 : GPR<17>; def R18 : GPR<18>; def R19 : GPR<19>;
def R20 : GPR<20>; def R21 : GPR<21>; def R22 : GPR<22>; def R23 : GPR<23>;
def R24 : GPR<24>; def R25 : GPR<25>; def R26 : GPR<26>; def R27 : GPR<27>;
def R28 : GPR<28>; def R29 : GPR<29>; def R30 : GPR<30>; def R31 : GPR<31>;
// Floating-point registers
def F0 : FPR< 0>; def F1 : FPR< 1>; def F2 : FPR< 2>; def F3 : FPR< 3>;
def F4 : FPR< 4>; def F5 : FPR< 5>; def F6 : FPR< 6>; def F7 : FPR< 7>;
def F8 : FPR< 8>; def F9 : FPR< 9>; def F10 : FPR<10>; def F11 : FPR<11>;
def F12 : FPR<12>; def F13 : FPR<13>; def F14 : FPR<14>; def F15 : FPR<15>;
def F16 : FPR<16>; def F17 : FPR<17>; def F18 : FPR<18>; def F19 : FPR<19>;
def F20 : FPR<20>; def F21 : FPR<21>; def F22 : FPR<22>; def F23 : FPR<23>;
def F24 : FPR<24>; def F25 : FPR<25>; def F26 : FPR<26>; def F27 : FPR<27>;
def F28 : FPR<28>; def F29 : FPR<29>; def F30 : FPR<30>; def F31 : FPR<31>;
// Condition registers
def CR0 : CR<0>; def CR1 : CR<1>; def CR2 : CR<2>; def CR3 : CR<3>;
def CR4 : CR<4>; def CR5 : CR<5>; def CR6 : CR<6>; def CR7 : CR<7>;
// Floating-point status and control register
def FPSCR : SPR<0>;
// fiXed-point Exception Register? :-)
def XER : SPR<1>;
// Link register
def LR : SPR<2>;
// Count register
def CTR : SPR<3>;
// These are the "time base" registers which are read-only in user mode.
def TBL : SPR<4>;
def TBU : SPR<5>;
/// Register classes: one for floats and another for non-floats.
def GPRC : RegisterClass<i32, 4, [R0, R1, R2, R3, R4, R5, R6, R7,
R8, R9, R10, R11, R12, R13, R14, R15, R16, R17, R18, R19, R20, R21,
R22, R23, R24, R25, R26, R27, R28, R29, R30, R31]>;
def FPRC : RegisterClass<f64, 8, [F0, F1, F2, F3, F4, F5, F6, F7,
F8, F9, F10, F11, F12, F13, F14, F15, F16, F17, F18, F19, F20, F21,
F22, F23, F24, F25, F26, F27, F28, F29, F30, F31]>;

View File

@ -0,0 +1,57 @@
//===-- PowerPCTargetMachine.h - Define TargetMachine for PowerPC -*- C++ -*-=//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file declares the PowerPC specific subclass of TargetMachine.
//
//===----------------------------------------------------------------------===//
#ifndef POWERPCTARGETMACHINE_H
#define POWERPCTARGETMACHINE_H
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetFrameInfo.h"
#include "llvm/PassManager.h"
#include "PowerPCInstrInfo.h"
#include "PowerPCJITInfo.h"
namespace llvm {
class IntrinsicLowering;
class PowerPCTargetMachine : public TargetMachine {
PowerPCInstrInfo InstrInfo;
TargetFrameInfo FrameInfo;
PowerPCJITInfo JITInfo;
public:
PowerPCTargetMachine(const Module &M, IntrinsicLowering *IL);
virtual const PowerPCInstrInfo *getInstrInfo() const { return &InstrInfo; }
virtual const TargetFrameInfo *getFrameInfo() const { return &FrameInfo; }
virtual const MRegisterInfo *getRegisterInfo() const {
return &InstrInfo.getRegisterInfo();
}
virtual TargetJITInfo *getJITInfo() {
return &JITInfo;
}
/// addPassesToEmitMachineCode - Add passes to the specified pass manager to
/// get machine code emitted. This uses a MachineCodeEmitter object to handle
/// actually outputting the machine code and resolving things like the address
/// of functions. This method should returns true if machine code emission is
/// not supported.
///
virtual bool addPassesToEmitMachineCode(FunctionPassManager &PM,
MachineCodeEmitter &MCE);
virtual bool addPassesToEmitAssembly(PassManager &PM, std::ostream &Out);
};
} // end namespace llvm
#endif

View File

@ -0,0 +1,26 @@
PowerPC backend skeleton
------------------------
Someday we'd like to have a PowerPC backend. Unfortunately, this
is not yet that day.
This directory contains mainly stubs and placeholders; there is no
binary machine code emitter, no assembly writer, and no instruction
selector here. Most of the functions in these files call abort()
or fail assertions on purpose, just to reinforce the fact that they
don't work.
If you want to use LLVM on the PowerPC *today*, use the C Backend
(llc -march=c). It generates C code that you can compile with the
native GCC compiler and run. A distant second choice would be the
Interpreter (lli --force-interpreter=true).
A few things *are* really here, including:
* PowerPC register file definition in TableGen format
* PowerPC definitions of TargetMachine and other target-specific classes
"Patches," as they say, "are accepted."
$Date$