diff options
Diffstat (limited to 'lib')
29 files changed, 3790 insertions, 0 deletions
diff --git a/lib/Support/Triple.cpp b/lib/Support/Triple.cpp index af372e2da6..391c98656d 100644 --- a/lib/Support/Triple.cpp +++ b/lib/Support/Triple.cpp @@ -23,6 +23,7 @@ const char *Triple::getArchTypeName(ArchType Kind) { case alpha: return "alpha"; case arm: return "arm"; + case bfin: return "bfin"; case cellspu: return "cellspu"; case mips: return "mips"; case mipsel: return "mipsel"; @@ -107,6 +108,8 @@ void Triple::Parse() const { Arch = sparc; else if (ArchName == "s390x") Arch = systemz; + else if (ArchName == "bfin") + Arch = bfin; else Arch = UnknownArch; diff --git a/lib/Target/Blackfin/AsmPrinter/BlackfinAsmPrinter.cpp b/lib/Target/Blackfin/AsmPrinter/BlackfinAsmPrinter.cpp new file mode 100644 index 0000000000..60744ddfff --- /dev/null +++ b/lib/Target/Blackfin/AsmPrinter/BlackfinAsmPrinter.cpp @@ -0,0 +1,237 @@ +//===-- BlackfinAsmPrinter.cpp - Blackfin LLVM assembly writer ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file 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 GAS-format BLACKFIN assembly language. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "asm-printer" +#include "Blackfin.h" +#include "BlackfinInstrInfo.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Module.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/DwarfWriter.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/Target/TargetAsmInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetRegistry.h" +#include "llvm/Support/Mangler.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/FormattedStream.h" + +using namespace llvm; + +STATISTIC(EmittedInsts, "Number of machine instrs printed"); + +namespace { + class VISIBILITY_HIDDEN BlackfinAsmPrinter : public AsmPrinter { + public: + BlackfinAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM, + const TargetAsmInfo *TAI, bool V) + : AsmPrinter(O, TM, TAI, V) {} + + virtual const char *getPassName() const { + return "Blackfin Assembly Printer"; + } + + void printOperand(const MachineInstr *MI, int opNum); + void printMemoryOperand(const MachineInstr *MI, int opNum); + bool printInstruction(const MachineInstr *MI); // autogenerated. + void emitLinkage(const std::string &n, GlobalValue::LinkageTypes l); + bool runOnMachineFunction(MachineFunction &F); + bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, const char *ExtraCode); + bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, const char *ExtraCode); + void PrintGlobalVariable(const GlobalVariable* GVar); + }; +} // end of anonymous namespace + +#include "BlackfinGenAsmWriter.inc" + +extern "C" void LLVMInitializeBlackfinAsmPrinter() { + RegisterAsmPrinter<BlackfinAsmPrinter> X(TheBlackfinTarget); +} + +void BlackfinAsmPrinter::emitLinkage(const std::string &name, + GlobalValue::LinkageTypes l) { + switch (l) { + default: llvm_unreachable("Unknown linkage type!"); + case GlobalValue::InternalLinkage: // Symbols default to internal. + case GlobalValue::PrivateLinkage: + case GlobalValue::LinkerPrivateLinkage: + break; + case GlobalValue::ExternalLinkage: + O << TAI->getGlobalDirective() << name << "\n"; + break; + case GlobalValue::LinkOnceAnyLinkage: + case GlobalValue::LinkOnceODRLinkage: + case GlobalValue::WeakAnyLinkage: + case GlobalValue::WeakODRLinkage: + O << TAI->getGlobalDirective() << name << "\n"; + O << TAI->getWeakDefDirective() << name << "\n"; + break; + } +} + +void BlackfinAsmPrinter::PrintGlobalVariable(const GlobalVariable* GV) { + const TargetData *TD = TM.getTargetData(); + + if (!GV->hasInitializer() || EmitSpecialLLVMGlobal(GV)) + return; + + std::string name = Mang->getMangledName(GV); + Constant *C = GV->getInitializer(); + + SwitchToSection(getObjFileLowering().SectionForGlobal(GV, Mang, TM)); + emitLinkage(name, GV->getLinkage()); + EmitAlignment(TD->getPreferredAlignmentLog(GV), GV); + printVisibility(name, GV->getVisibility()); + + O << "\t.type " << name << ", STT_OBJECT\n"; + O << "\t.size " << name << ',' << TD->getTypeAllocSize(C->getType()) << '\n'; + O << name << ":\n"; + EmitGlobalConstant(C); +} + +/// runOnMachineFunction - This uses the printInstruction() +/// method to print assembly for each instruction. +/// +bool BlackfinAsmPrinter::runOnMachineFunction(MachineFunction &MF) { + SetupMachineFunction(MF); + EmitConstantPool(MF.getConstantPool()); + EmitJumpTableInfo(MF.getJumpTableInfo(), MF); + + const Function *F = MF.getFunction(); + SwitchToSection(getObjFileLowering().SectionForGlobal(F, Mang, TM)); + EmitAlignment(2, F); + emitLinkage(CurrentFnName, F->getLinkage()); + printVisibility(CurrentFnName, F->getVisibility()); + + O << "\t.type\t" << CurrentFnName << ", STT_FUNC\n" + << CurrentFnName << ":\n"; + + if (DW) + DW->BeginFunction(&MF); + + // 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. + if (!VerboseAsm && (I->pred_empty() || I->isOnlyReachableByFallthrough())) { + // This is an entry block or a block that's only reachable via a + // fallthrough edge. In non-VerboseAsm mode, don't print the label. + } else { + printBasicBlockLabel(I, true, true, VerboseAsm); + O << '\n'; + } + + for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); + II != E; ++II) { + // Print the assembly for the instruction. + printInstruction(II); + ++EmittedInsts; + } + } + + O << "\t.size " << CurrentFnName << ", .-" << CurrentFnName << "\n"; + + if (DW) + DW->EndFunction(&MF); + + return false; +} + +void BlackfinAsmPrinter::printOperand(const MachineInstr *MI, int opNum) { + const MachineOperand &MO = MI->getOperand (opNum); + const TargetRegisterInfo &RI = *TM.getRegisterInfo(); + switch (MO.getType()) { + case MachineOperand::MO_Register: + assert (TargetRegisterInfo::isPhysicalRegister(MO.getReg()) && + "Virtual registers should be already mapped!"); + O << RI.get(MO.getReg()).AsmName; + break; + + case MachineOperand::MO_Immediate: + O << MO.getImm(); + break; + case MachineOperand::MO_MachineBasicBlock: + printBasicBlockLabel(MO.getMBB(), false, false, false); + return; + case MachineOperand::MO_GlobalAddress: + O << Mang->getMangledName(MO.getGlobal()); + printOffset(MO.getOffset()); + break; + case MachineOperand::MO_ExternalSymbol: + O << Mang->makeNameProper(MO.getSymbolName()); + break; + case MachineOperand::MO_ConstantPoolIndex: + O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_" + << MO.getIndex(); + break; + case MachineOperand::MO_JumpTableIndex: + O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() + << '_' << MO.getIndex(); + break; + default: + llvm_unreachable("<unknown operand type>"); + break; + } +} + +void BlackfinAsmPrinter::printMemoryOperand(const MachineInstr *MI, int opNum) { + printOperand(MI, opNum); + + if (MI->getOperand(opNum+1).isImm() && MI->getOperand(opNum+1).getImm() == 0) + return; + + O << " + "; + printOperand(MI, opNum+1); +} + +/// PrintAsmOperand - Print out an operand for an inline asm expression. +/// +bool BlackfinAsmPrinter::PrintAsmOperand(const MachineInstr *MI, + unsigned OpNo, + unsigned AsmVariant, + const char *ExtraCode) { + if (ExtraCode && ExtraCode[0]) { + if (ExtraCode[1] != 0) return true; // Unknown modifier. + + switch (ExtraCode[0]) { + default: return true; // Unknown modifier. + case 'r': + break; + } + } + + printOperand(MI, OpNo); + + return false; +} + +bool BlackfinAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, + unsigned OpNo, + unsigned AsmVariant, + const char *ExtraCode) { + if (ExtraCode && ExtraCode[0]) + return true; // Unknown modifier + + O << '['; + printOperand(MI, OpNo); + O << ']'; + + return false; +} diff --git a/lib/Target/Blackfin/AsmPrinter/CMakeLists.txt b/lib/Target/Blackfin/AsmPrinter/CMakeLists.txt new file mode 100644 index 0000000000..cd20f0754b --- /dev/null +++ b/lib/Target/Blackfin/AsmPrinter/CMakeLists.txt @@ -0,0 +1,3 @@ +include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/.. ) +add_llvm_library(LLVMBlackfinAsmPrinter BlackfinAsmPrinter.cpp) +add_dependencies(LLVMBlackfinAsmPrinter BlackfinCodeGenTable_gen) diff --git a/lib/Target/Blackfin/AsmPrinter/Makefile b/lib/Target/Blackfin/AsmPrinter/Makefile new file mode 100644 index 0000000000..a2b0d1d1a1 --- /dev/null +++ b/lib/Target/Blackfin/AsmPrinter/Makefile @@ -0,0 +1,16 @@ +##===- lib/Target/Blackfin/Makefile ------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../../../.. +LIBRARYNAME = LLVMBlackfinAsmPrinter + +# Hack: we need to include 'main' Blackfin target directory to grab private +# headers +CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. + +include $(LEVEL)/Makefile.common diff --git a/lib/Target/Blackfin/Blackfin.h b/lib/Target/Blackfin/Blackfin.h new file mode 100644 index 0000000000..ec1fa8689d --- /dev/null +++ b/lib/Target/Blackfin/Blackfin.h @@ -0,0 +1,38 @@ +//=== Blackfin.h - Top-level interface for Blackfin backend -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file 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 +// Blackfin back-end. +// +//===----------------------------------------------------------------------===// + +#ifndef TARGET_BLACKFIN_H +#define TARGET_BLACKFIN_H + +#include "llvm/Target/TargetMachine.h" + +namespace llvm { + + class FunctionPass; + class BlackfinTargetMachine; + + FunctionPass *createBlackfinISelDag(BlackfinTargetMachine &TM, + CodeGenOpt::Level OptLevel); + extern Target TheBlackfinTarget; + +} // end namespace llvm + +// Defines symbolic names for Blackfin registers. This defines a mapping from +// register name to register number. +#include "BlackfinGenRegisterNames.inc" + +// Defines symbolic names for the Blackfin instructions. +#include "BlackfinGenInstrNames.inc" + +#endif diff --git a/lib/Target/Blackfin/Blackfin.td b/lib/Target/Blackfin/Blackfin.td new file mode 100644 index 0000000000..0b73d1f4db --- /dev/null +++ b/lib/Target/Blackfin/Blackfin.td @@ -0,0 +1,52 @@ +//===- Blackfin.td - Describe the Blackfin Target Machine --*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Target-independent interfaces which we are implementing +//===----------------------------------------------------------------------===// + +include "llvm/Target/Target.td" + +//===----------------------------------------------------------------------===// +// Blackfin Subtarget features. +//===----------------------------------------------------------------------===// + +def FeatureSSYNC : SubtargetFeature<"ssync","ssyncWorkaround", "true", + "Work around SSYNC bugs">; + +//===----------------------------------------------------------------------===// +// Register File, Calling Conv, Instruction Descriptions +//===----------------------------------------------------------------------===// + +include "BlackfinRegisterInfo.td" +include "BlackfinCallingConv.td" +include "BlackfinInstrInfo.td" + +def BlackfinInstrInfo : InstrInfo {} + +//===----------------------------------------------------------------------===// +// Blackfin processors supported. +//===----------------------------------------------------------------------===// + +class Proc<string Name, list<SubtargetFeature> Features> + : Processor<Name, NoItineraries, Features>; + +def : Proc<"generic", [FeatureSSYNC]>; + +//===----------------------------------------------------------------------===// +// Declare the target which we are implementing +//===----------------------------------------------------------------------===// + +def Blackfin : Target { + // Pull in Instruction Info: + let InstructionSet = BlackfinInstrInfo; +} diff --git a/lib/Target/Blackfin/BlackfinCallingConv.td b/lib/Target/Blackfin/BlackfinCallingConv.td new file mode 100644 index 0000000000..0abc84c3c4 --- /dev/null +++ b/lib/Target/Blackfin/BlackfinCallingConv.td @@ -0,0 +1,30 @@ +//===--- BlackfinCallingConv.td - Calling Conventions ------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This describes the calling conventions for the Blackfin architectures. +// +//===----------------------------------------------------------------------===// + +// Blackfin C Calling convention. +def CC_Blackfin : CallingConv<[ + CCIfType<[i16], CCPromoteToType<i32>>, + CCIfSRet<CCAssignToReg<[P0]>>, + CCAssignToReg<[R0, R1, R2]>, + CCAssignToStack<4, 4> +]>; + +//===----------------------------------------------------------------------===// +// Return Value Calling Conventions +//===----------------------------------------------------------------------===// + +// Blackfin C return-value convention. +def RetCC_Blackfin : CallingConv<[ + CCIfType<[i16], CCPromoteToType<i32>>, + CCAssignToReg<[R0, R1]> +]>; diff --git a/lib/Target/Blackfin/BlackfinISelDAGToDAG.cpp b/lib/Target/Blackfin/BlackfinISelDAGToDAG.cpp new file mode 100644 index 0000000000..062b22abe6 --- /dev/null +++ b/lib/Target/Blackfin/BlackfinISelDAGToDAG.cpp @@ -0,0 +1,191 @@ +//===- BlackfinISelDAGToDAG.cpp - A dag to dag inst selector for Blackfin -===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines an instruction selector for the Blackfin target. +// +//===----------------------------------------------------------------------===// + +#include "Blackfin.h" +#include "BlackfinISelLowering.h" +#include "BlackfinTargetMachine.h" +#include "BlackfinRegisterInfo.h" +#include "llvm/Intrinsics.h" +#include "llvm/CodeGen/SelectionDAGISel.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Instruction Selector Implementation +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +/// BlackfinDAGToDAGISel - Blackfin specific code to select blackfin machine +/// instructions for SelectionDAG operations. +namespace { + class BlackfinDAGToDAGISel : public SelectionDAGISel { + /// Subtarget - Keep a pointer to the Blackfin Subtarget around so that we + /// can make the right decision when generating code for different targets. + //const BlackfinSubtarget &Subtarget; + public: + BlackfinDAGToDAGISel(BlackfinTargetMachine &TM, CodeGenOpt::Level OptLevel) + : SelectionDAGISel(TM, OptLevel) {} + + virtual void InstructionSelect(); + + virtual const char *getPassName() const { + return "Blackfin DAG->DAG Pattern Instruction Selection"; + } + + // Include the pieces autogenerated from the target description. +#include "BlackfinGenDAGISel.inc" + + private: + SDNode *Select(SDValue Op); + bool SelectADDRspii(SDValue Op, SDValue Addr, + SDValue &Base, SDValue &Offset); + + // Walk the DAG after instruction selection, fixing register class issues. + void FixRegisterClasses(SelectionDAG &DAG); + + const BlackfinInstrInfo &getInstrInfo() { + return *static_cast<const BlackfinTargetMachine&>(TM).getInstrInfo(); + } + const BlackfinRegisterInfo *getRegisterInfo() { + return static_cast<const BlackfinTargetMachine&>(TM).getRegisterInfo(); + } + }; +} // end anonymous namespace + +FunctionPass *llvm::createBlackfinISelDag(BlackfinTargetMachine &TM, + CodeGenOpt::Level OptLevel) { + return new BlackfinDAGToDAGISel(TM, OptLevel); +} + +/// InstructionSelect - This callback is invoked by +/// SelectionDAGISel when it has created a SelectionDAG for us to codegen. +void BlackfinDAGToDAGISel::InstructionSelect() { + // Select target instructions for the DAG. + SelectRoot(*CurDAG); + DOUT << "Selected selection DAG before regclass fixup:\n"; + DEBUG(CurDAG->dump()); + FixRegisterClasses(*CurDAG); +} + +SDNode *BlackfinDAGToDAGISel::Select(SDValue Op) { + SDNode *N = Op.getNode(); + DebugLoc dl = N->getDebugLoc(); + if (N->isMachineOpcode()) + return NULL; // Already selected. + + switch (N->getOpcode()) { + default: break; + case ISD::FrameIndex: { + // Selects to ADDpp FI, 0 which in turn will become ADDimm7 SP, imm or ADDpp + // SP, Px + int FI = cast<FrameIndexSDNode>(N)->getIndex(); + SDValue TFI = CurDAG->getTargetFrameIndex(FI, MVT::i32); + return CurDAG->SelectNodeTo(N, BF::ADDpp, MVT::i32, TFI, + CurDAG->getTargetConstant(0, MVT::i32)); + } + } + + return SelectCode(Op); +} + +bool BlackfinDAGToDAGISel::SelectADDRspii(SDValue Op, + SDValue Addr, + SDValue &Base, + SDValue &Offset) { + FrameIndexSDNode *FIN = 0; + if ((FIN = dyn_cast<FrameIndexSDNode>(Addr))) { + Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); + Offset = CurDAG->getTargetConstant(0, MVT::i32); + return true; + } + if (Addr.getOpcode() == ISD::ADD) { + ConstantSDNode *CN = 0; + if ((FIN = dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) && + (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) && + (CN->getSExtValue() % 4 == 0 && CN->getSExtValue() >= 0)) { + // Constant positive word offset from frame index + Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); + Offset = CurDAG->getTargetConstant(CN->getSExtValue(), MVT::i32); + return true; + } + } + return false; +} + +static inline bool isCC(const TargetRegisterClass *RC) { + return RC == &BF::AnyCCRegClass || BF::AnyCCRegClass.hasSubClass(RC); +} + +static inline bool isDCC(const TargetRegisterClass *RC) { + return RC == &BF::DRegClass || BF::DRegClass.hasSubClass(RC) || isCC(RC); +} + +static void UpdateNodeOperand(SelectionDAG &DAG, + SDNode *N, + unsigned Num, + SDValue Val) { + SmallVector<SDValue, 8> ops(N->op_begin(), N->op_end()); + ops[Num] = Val; + SDValue New = DAG.UpdateNodeOperands(SDValue(N, 0), ops.data(), ops.size()); + DAG.ReplaceAllUsesWith(N, New.getNode()); +} + +// After instruction selection, insert COPY_TO_REGCLASS nodes to help in +// choosing the proper register classes. +void BlackfinDAGToDAGISel::FixRegisterClasses(SelectionDAG &DAG) { + const BlackfinInstrInfo &TII = getInstrInfo(); + const BlackfinRegisterInfo *TRI = getRegisterInfo(); + DAG.AssignTopologicalOrder(); + HandleSDNode Dummy(DAG.getRoot()); + + for (SelectionDAG::allnodes_iterator NI = DAG.allnodes_begin(); + NI != DAG.allnodes_end(); ++NI) { + if (NI->use_empty() || !NI->isMachineOpcode()) + continue; + const TargetInstrDesc &DefTID = TII.get(NI->getMachineOpcode()); + for (SDNode::use_iterator UI = NI->use_begin(); !UI.atEnd(); ++UI) { + if (!UI->isMachineOpcode()) + continue; + + if (UI.getUse().getResNo() >= DefTID.getNumDefs()) + continue; + const TargetRegisterClass *DefRC = + DefTID.OpInfo[UI.getUse().getResNo()].getRegClass(TRI); + + const TargetInstrDesc &UseTID = TII.get(UI->getMachineOpcode()); + if (UseTID.getNumDefs()+UI.getOperandNo() >= UseTID.getNumOperands()) + continue; + const TargetRegisterClass *UseRC = + UseTID.OpInfo[UseTID.getNumDefs()+UI.getOperandNo()].getRegClass(TRI); + if (!DefRC || !UseRC) + continue; + // We cannot copy CC <-> !(CC/D) + if ((isCC(DefRC) && !isDCC(UseRC)) || (isCC(UseRC) && !isDCC(DefRC))) { + SDNode *Copy = + DAG.getTargetNode(TargetInstrInfo::COPY_TO_REGCLASS, + NI->getDebugLoc(), + MVT::i32, + UI.getUse().get(), + DAG.getTargetConstant(BF::DRegClassID, MVT::i32)); + UpdateNodeOperand(DAG, *UI, UI.getOperandNo(), SDValue(Copy, 0)); + } + } + } + DAG.setRoot(Dummy.getValue()); +} + diff --git a/lib/Target/Blackfin/BlackfinISelLowering.cpp b/lib/Target/Blackfin/BlackfinISelLowering.cpp new file mode 100644 index 0000000000..a4af0ad9e7 --- /dev/null +++ b/lib/Target/Blackfin/BlackfinISelLowering.cpp @@ -0,0 +1,536 @@ +//===- BlackfinISelLowering.cpp - Blackfin DAG Lowering Implementation ----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the interfaces that Blackfin uses to lower LLVM code +// into a selection DAG. +// +//===----------------------------------------------------------------------===// + +#include "BlackfinISelLowering.h" +#include "BlackfinTargetMachine.h" +#include "llvm/Function.h" +#include "llvm/CodeGen/CallingConvLower.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/ADT/VectorExtras.h" +#include "llvm/Support/Debug.h" + +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Calling Convention Implementation +//===----------------------------------------------------------------------===// + +#include "BlackfinGenCallingConv.inc" + +//===----------------------------------------------------------------------===// +// TargetLowering Implementation +//===----------------------------------------------------------------------===// + +BlackfinTargetLowering::BlackfinTargetLowering(TargetMachine &TM) + : TargetLowering(TM, new TargetLoweringObjectFileELF()) { + setShiftAmountType(MVT::i16); + setBooleanContents(ZeroOrOneBooleanContent); + setStackPointerRegisterToSaveRestore(BF::SP); + setIntDivIsCheap(false); + + // Set up the legal register classes. + addRegisterClass(MVT::i32, BF::DRegisterClass); + addRegisterClass(MVT::i16, BF::D16RegisterClass); + + computeRegisterProperties(); + + // Blackfin doesn't have i1 loads or stores + setLoadExtAction(ISD::EXTLOAD, MVT::i1, Promote); + setLoadExtAction(ISD::ZEXTLOAD, MVT::i1, Promote); + setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote); + + setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); + setOperationAction(ISD::JumpTable, MVT::i32, Custom); + + setOperationAction(ISD::SELECT_CC, MVT::Other, Expand); + setOperationAction(ISD::BR_JT, MVT::Other, Expand); + setOperationAction(ISD::BR_CC, MVT::Other, Expand); + + // i16 registers don't do much + setOperationAction(ISD::AND, MVT::i16, Promote); + setOperationAction(ISD::OR, MVT::i16, Promote); + setOperationAction(ISD::XOR, MVT::i16, Promote); + setOperationAction(ISD::CTPOP, MVT::i16, Promote); + // The expansion of CTLZ/CTTZ uses AND/OR, so we might as well promote + // immediately. + setOperationAction(ISD::CTLZ, MVT::i16, Promote); + setOperationAction(ISD::CTTZ, MVT::i16, Promote); + setOperationAction(ISD::SETCC, MVT::i16, Promote); + + // Blackfin has no division + setOperationAction(ISD::SDIV, MVT::i16, Expand); + setOperationAction(ISD::SDIV, MVT::i32, Expand); + setOperationAction(ISD::SDIVREM, MVT::i16, Expand); + setOperationAction(ISD::SDIVREM, MVT::i32, Expand); + setOperationAction(ISD::SREM, MVT::i16, Expand); + setOperationAction(ISD::SREM, MVT::i32, Expand); + setOperationAction(ISD::UDIV, MVT::i16, Expand); + setOperationAction(ISD::UDIV, MVT::i32, Expand); + setOperationAction(ISD::UDIVREM, MVT::i16, Expand); + setOperationAction(ISD::UDIVREM, MVT::i32, Expand); + setOperationAction(ISD::UREM, MVT::i16, Expand); + setOperationAction(ISD::UREM, MVT::i32, Expand); + + setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand); + setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand); + setOperationAction(ISD::MULHU, MVT::i32, Expand); + setOperationAction(ISD::MULHS, MVT::i32, Expand); + + // No carry-in operations. + setOperationAction(ISD::ADDE, MVT::i32, Custom); + setOperationAction(ISD::SUBE, MVT::i32, Custom); + + // Blackfin has no intrinsics for these particular operations. + setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand); + setOperationAction(ISD::BSWAP, MVT::i32, Expand); + + setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand); + setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand); + setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand); + + setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand); + + // i32 has native CTPOP, but not CT |