//===-- ARMISelDAGToDAG.cpp - A dag to dag inst selector for ARM ----------===// // // The LLVM Compiler Infrastructure // // This file was developed by Chris Lattner and is distributed under // the University of Illinois Open Source License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file defines an instruction selector for the ARM target. // //===----------------------------------------------------------------------===// #include "ARM.h" #include "ARMTargetMachine.h" #include "llvm/DerivedTypes.h" #include "llvm/Function.h" #include "llvm/Intrinsics.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/CodeGen/SelectionDAGISel.h" #include "llvm/CodeGen/SSARegMap.h" #include "llvm/Target/TargetLowering.h" #include "llvm/Support/Debug.h" #include #include using namespace llvm; namespace ARMISD { enum { FIRST_NUMBER = ISD::BUILTIN_OP_END+ARM::INSTRUCTION_LIST_END, RET_FLAG, }; } namespace { class ARMTargetLowering : public TargetLowering { public: ARMTargetLowering(TargetMachine &TM); virtual SDOperand LowerOperation(SDOperand Op, SelectionDAG &DAG); virtual std::pair LowerCallTo(SDOperand Chain, const Type *RetTy, bool isVarArg, unsigned CC, bool isTailCall, SDOperand Callee, ArgListTy &Args, SelectionDAG &DAG); }; } ARMTargetLowering::ARMTargetLowering(TargetMachine &TM) : TargetLowering(TM) { setOperationAction(ISD::RET, MVT::Other, Custom); } std::pair ARMTargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy, bool isVarArg, unsigned CC, bool isTailCall, SDOperand Callee, ArgListTy &Args, SelectionDAG &DAG) { assert(0 && "Not implemented"); abort(); } static SDOperand LowerRET(SDOperand Op, SelectionDAG &DAG) { SDOperand Copy; switch(Op.getNumOperands()) { default: assert(0 && "Do not know how to return this many arguments!"); abort(); case 1: return SDOperand(); // ret void is legal case 2: Copy = DAG.getCopyToReg(Op.getOperand(0), ARM::R0, Op.getOperand(1), SDOperand()); break; } return DAG.getNode(ARMISD::RET_FLAG, MVT::Other, Copy, Copy.getValue(1)); } SDOperand ARMTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { switch (Op.getOpcode()) { default: assert(0 && "Should not custom lower this!"); abort(); case ISD::RET: return LowerRET(Op, DAG); } } //===----------------------------------------------------------------------===// // Instruction Selector Implementation //===----------------------------------------------------------------------===// //===--------------------------------------------------------------------===// /// ARMDAGToDAGISel - ARM specific code to select ARM machine /// instructions for SelectionDAG operations. /// namespace { class ARMDAGToDAGISel : public SelectionDAGISel { ARMTargetLowering Lowering; public: ARMDAGToDAGISel(TargetMachine &TM) : SelectionDAGISel(Lowering), Lowering(TM) { } void Select(SDOperand &Result, SDOperand Op); virtual void InstructionSelectBasicBlock(SelectionDAG &DAG); // Include the pieces autogenerated from the target description. #include "ARMGenDAGISel.inc" }; void ARMDAGToDAGISel::InstructionSelectBasicBlock(SelectionDAG &DAG) { DEBUG(BB->dump()); DAG.setRoot(SelectRoot(DAG.getRoot())); CodeGenMap.clear(); DAG.RemoveDeadNodes(); ScheduleAndEmitDAG(DAG); } void ARMDAGToDAGISel::Select(SDOperand &Result, SDOperand Op) { SelectCode(Result, Op); } } // end anonymous namespace /// createARMISelDag - This pass converts a legalized DAG into a /// ARM-specific DAG, ready for instruction scheduling. /// FunctionPass *llvm::createARMISelDag(TargetMachine &TM) { return new ARMDAGToDAGISel(TM); }