aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Target/PIC16/PIC16ISelDAGToDAG.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/PIC16/PIC16ISelDAGToDAG.cpp')
-rw-r--r--lib/Target/PIC16/PIC16ISelDAGToDAG.cpp291
1 files changed, 291 insertions, 0 deletions
diff --git a/lib/Target/PIC16/PIC16ISelDAGToDAG.cpp b/lib/Target/PIC16/PIC16ISelDAGToDAG.cpp
new file mode 100644
index 0000000..07ebd99
--- /dev/null
+++ b/lib/Target/PIC16/PIC16ISelDAGToDAG.cpp
@@ -0,0 +1,291 @@
+//===-- PIC16ISelDAGToDAG.cpp - A dag to dag inst selector for PIC16 ------===//
+//
+// 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 PIC16 target.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "pic16-isel"
+
+#include "PIC16.h"
+#include "PIC16ISelLowering.h"
+#include "PIC16RegisterInfo.h"
+#include "PIC16Subtarget.h"
+#include "PIC16TargetMachine.h"
+#include "llvm/GlobalValue.h"
+#include "llvm/Instructions.h"
+#include "llvm/Intrinsics.h"
+#include "llvm/Type.h"
+#include "llvm/CodeGen/MachineConstantPool.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineFrameInfo.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/SelectionDAGISel.h"
+#include "llvm/CodeGen/SelectionDAGNodes.h"
+#include "llvm/Support/CFG.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Target/TargetMachine.h"
+#include <queue>
+#include <set>
+
+using namespace llvm;
+
+//===----------------------------------------------------------------------===//
+// Instruction Selector Implementation
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// PIC16DAGToDAGISel - PIC16 specific code to select PIC16 machine
+// instructions for SelectionDAG operations.
+//===----------------------------------------------------------------------===//
+namespace {
+
+class VISIBILITY_HIDDEN PIC16DAGToDAGISel : public SelectionDAGISel {
+
+ /// TM - Keep a reference to PIC16TargetMachine.
+ PIC16TargetMachine &TM;
+
+ /// PIC16Lowering - This object fully describes how to lower LLVM code to an
+ /// PIC16-specific SelectionDAG.
+ PIC16TargetLowering PIC16Lowering;
+
+ /// Subtarget - Keep a pointer to the PIC16Subtarget around so that we can
+ /// make the right decision when generating code for different targets.
+ //TODO: add initialization on constructor
+ //const PIC16Subtarget *Subtarget;
+
+public:
+ PIC16DAGToDAGISel(PIC16TargetMachine &tm) :
+ SelectionDAGISel(PIC16Lowering),
+ TM(tm), PIC16Lowering(*TM.getTargetLowering()) {}
+
+ virtual void InstructionSelectBasicBlock(SelectionDAG &SD);
+
+ // Pass Name
+ virtual const char *getPassName() const {
+ return "PIC16 DAG->DAG Pattern Instruction Selection";
+ }
+
+private:
+ // Include the pieces autogenerated from the target description.
+ #include "PIC16GenDAGISel.inc"
+
+ SDNode *Select(SDOperand N);
+
+ // Select addressing mode. currently assume base + offset addr mode.
+ bool SelectAM(SDOperand Op, SDOperand N, SDOperand &Base, SDOperand &Offset);
+ bool SelectDirectAM(SDOperand Op, SDOperand N, SDOperand &Base,
+ SDOperand &Offset);
+ bool StoreInDirectAM(SDOperand Op, SDOperand N, SDOperand &fsr);
+ bool LoadFSR(SDOperand Op, SDOperand N, SDOperand &Base, SDOperand &Offset);
+ bool LoadNothing(SDOperand Op, SDOperand N, SDOperand &Base,
+ SDOperand &Offset);
+
+ // getI8Imm - Return a target constant with the specified
+ // value, of type i8.
+ inline SDOperand getI8Imm(unsigned Imm) {
+ return CurDAG->getTargetConstant(Imm, MVT::i8);
+ }
+
+
+ #ifndef NDEBUG
+ unsigned Indent;
+ #endif
+};
+
+}
+
+/// InstructionSelectBasicBlock - This callback is invoked by
+/// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
+void PIC16DAGToDAGISel::InstructionSelectBasicBlock(SelectionDAG &SD)
+{
+ DEBUG(BB->dump());
+ // Codegen the basic block.
+ #ifndef NDEBUG
+ DOUT << "===== Instruction selection begins:\n";
+ Indent = 0;
+ #endif
+
+ // Select target instructions for the DAG.
+ SD.setRoot(SelectRoot(SD.getRoot()));
+
+ #ifndef NDEBUG
+ DOUT << "===== Instruction selection ends:\n";
+ #endif
+
+ SD.RemoveDeadNodes();
+
+ // Emit machine code to BB.
+ ScheduleAndEmitDAG(SD);
+}
+
+
+bool PIC16DAGToDAGISel::
+SelectDirectAM (SDOperand Op, SDOperand N, SDOperand &Base, SDOperand &Offset)
+{
+ GlobalAddressSDNode *GA;
+ ConstantSDNode *GC;
+
+ // if Address is FI, get the TargetFrameIndex.
+ if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(N)) {
+ cout << "--------- its frame Index\n";
+ Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
+ Offset = CurDAG->getTargetConstant(0, MVT::i32);
+ return true;
+ }
+
+ if (N.getOpcode() == ISD::GlobalAddress) {
+ GA = dyn_cast<GlobalAddressSDNode>(N);
+ Offset = CurDAG->getTargetConstant((unsigned char)GA->getOffset(), MVT::i8);
+ Base = CurDAG->getTargetGlobalAddress(GA->getGlobal(), MVT::i16,
+ GA->getOffset());
+ return true;
+ }
+
+ if (N.getOpcode() == ISD::ADD) {
+ GC = dyn_cast<ConstantSDNode>(N.getOperand(1));
+ Offset = CurDAG->getTargetConstant((unsigned char)GC->getValue(), MVT::i8);
+ if ((GA = dyn_cast<GlobalAddressSDNode>(N.getOperand(0)))) {
+ Base = CurDAG->getTargetGlobalAddress(GA->getGlobal(), MVT::i16,
+ GC->getValue());
+ return true;
+ }
+ else if (FrameIndexSDNode *FIN
+ = dyn_cast<FrameIndexSDNode>(N.getOperand(0))) {
+ Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+//FIXME: must also account for preinc/predec/postinc/postdec
+bool PIC16DAGToDAGISel::
+StoreInDirectAM (SDOperand Op, SDOperand N, SDOperand &fsr)
+{
+ RegisterSDNode *Reg;
+ if (N.getOpcode() == ISD::LOAD) {
+ LoadSDNode *LD = dyn_cast<LoadSDNode>(N);
+ if (LD) {
+ fsr = LD->getBasePtr();
+ }
+ else if (isa<RegisterSDNode>(N.Val)) {
+ //FIXME an attempt to retrieve the register number
+ //but does not work
+ cout << "this is a register\n";
+ Reg = dyn_cast<RegisterSDNode>(N.Val);
+ fsr = CurDAG->getRegister(Reg->getReg(),MVT::i16);
+ }
+ else {
+ cout << "this is not a register\n";
+ // FIXME must use whatever load is using
+ fsr = CurDAG->getRegister(1,MVT::i16);
+ }
+ return true;
+ }
+ return false;
+}
+
+bool PIC16DAGToDAGISel::
+LoadFSR (SDOperand Op, SDOperand N, SDOperand &Base, SDOperand &Offset)
+{
+ GlobalAddressSDNode *GA;
+
+ if (N.getOpcode() == ISD::GlobalAddress) {
+ GA = dyn_cast<GlobalAddressSDNode>(N);
+ Offset = CurDAG->getTargetConstant((unsigned char)GA->getOffset(), MVT::i8);
+ Base = CurDAG->getTargetGlobalAddress(GA->getGlobal(), MVT::i16,
+ GA->getOffset());
+ return true;
+ }
+ else if (N.getOpcode() == PIC16ISD::Package) {
+ CurDAG->setGraphColor(Op.Val, "blue");
+ CurDAG->viewGraph();
+ }
+
+ return false;
+}
+
+//don't thake this seriously, it will change
+bool PIC16DAGToDAGISel::
+LoadNothing (SDOperand Op, SDOperand N, SDOperand &Base, SDOperand &Offset)
+{
+ GlobalAddressSDNode *GA;
+ if (N.getOpcode() == ISD::GlobalAddress) {
+ GA = dyn_cast<GlobalAddressSDNode>(N);
+ cout << "==========" << GA->getOffset() << "\n";
+ Offset = CurDAG->getTargetConstant((unsigned char)GA->getOffset(), MVT::i8);
+ Base = CurDAG->getTargetGlobalAddress(GA->getGlobal(), MVT::i16,
+ GA->getOffset());
+ return true;
+ }
+
+ return false;
+}
+
+
+/// Select instructions not customized! Used for
+/// expanded, promoted and normal instructions
+SDNode* PIC16DAGToDAGISel::Select(SDOperand N)
+{
+ SDNode *Node = N.Val;
+ unsigned Opcode = Node->getOpcode();
+
+ // Dump information about the Node being selected
+ #ifndef NDEBUG
+ DOUT << std::string(Indent, ' ') << "Selecting: ";
+ DEBUG(Node->dump(CurDAG));
+ DOUT << "\n";
+ Indent += 2;
+ #endif
+
+ // If we have a custom node, we already have selected!
+ if (Opcode >= ISD::BUILTIN_OP_END && Opcode < PIC16ISD::FIRST_NUMBER) {
+ #ifndef NDEBUG
+ DOUT << std::string(Indent-2, ' ') << "== ";
+ DEBUG(Node->dump(CurDAG));
+ DOUT << "\n";
+ Indent -= 2;
+ #endif
+ return NULL;
+ }
+
+ ///
+ // Instruction Selection not handled by custom or by the
+ // auto-generated tablegen selection should be handled here.
+ ///
+ switch(Opcode) {
+ default: break;
+ }
+
+ // Select the default instruction.
+ SDNode *ResNode = SelectCode(N);
+
+ #ifndef NDEBUG
+ DOUT << std::string(Indent-2, ' ') << "=> ";
+ if (ResNode == NULL || ResNode == N.Val)
+ DEBUG(N.Val->dump(CurDAG));
+ else
+ DEBUG(ResNode->dump(CurDAG));
+ DOUT << "\n";
+ Indent -= 2;
+ #endif
+
+ return ResNode;
+}
+
+/// createPIC16ISelDag - This pass converts a legalized DAG into a
+/// PIC16-specific DAG, ready for instruction scheduling.
+FunctionPass *llvm::createPIC16ISelDag(PIC16TargetMachine &TM) {
+ return new PIC16DAGToDAGISel(TM);
+}
+