A start at a Sparc V8 Pattern ISel. Anyone want to implement the calling
authorAndrew Lenharth <andrewl@lenharth.org>
Fri, 17 Jun 2005 16:52:12 +0000 (16:52 +0000)
committerAndrew Lenharth <andrewl@lenharth.org>
Fri, 17 Jun 2005 16:52:12 +0000 (16:52 +0000)
convention? ;)

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@22247 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/Sparc/SparcV8ISelPattern.cpp [new file with mode: 0644]
lib/Target/SparcV8/SparcV8ISelPattern.cpp [new file with mode: 0644]

diff --git a/lib/Target/Sparc/SparcV8ISelPattern.cpp b/lib/Target/Sparc/SparcV8ISelPattern.cpp
new file mode 100644 (file)
index 0000000..98d4f93
--- /dev/null
@@ -0,0 +1,479 @@
+#if 0
+//===- SparcV8ISelPattern.cpp - A pattern matching isel for SparcV8 -------===//
+//
+//                     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 defines a pattern matching instruction selector for SparcV8.
+//
+//===----------------------------------------------------------------------===//
+
+//Please note that this file is a work in progress, and not a high
+//priority for anyone.
+
+#include "SparcV8.h"
+#include "SparcV8RegisterInfo.h"
+#include "llvm/Constants.h"                   // FIXME: REMOVE
+#include "llvm/Function.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineConstantPool.h" // FIXME: REMOVE
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineFrameInfo.h"
+#include "llvm/CodeGen/SelectionDAG.h"
+#include "llvm/CodeGen/SelectionDAGISel.h"
+#include "llvm/CodeGen/SSARegMap.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Target/TargetLowering.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/CommandLine.h"
+#include <set>
+#include <algorithm>
+using namespace llvm;
+
+//===----------------------------------------------------------------------===//
+//  V8TargetLowering - SparcV8 Implementation of the TargetLowering interface
+namespace {
+  class V8TargetLowering : public TargetLowering {
+    int VarArgsFrameIndex;            // FrameIndex for start of varargs area.
+  public:
+    V8TargetLowering(TargetMachine &TM) : TargetLowering(TM) {
+      // Set up the TargetLowering object.
+      //I am having problems with shr n ubyte 1
+      setShiftAmountType(MVT::i32);
+      setSetCCResultType(MVT::i32);
+      setSetCCResultContents(ZeroOrOneSetCCResult);
+
+      //FIXME: get these right
+      addRegisterClass(MVT::i64, V8::GPRCRegisterClass);
+      addRegisterClass(MVT::f64, V8::FPRCRegisterClass);
+      addRegisterClass(MVT::f32, V8::FPRCRegisterClass);
+
+      setOperationAction(ISD::BRCONDTWOWAY, MVT::Other, Expand);
+      setOperationAction(ISD::EXTLOAD, MVT::i1,  Promote);
+      setOperationAction(ISD::EXTLOAD, MVT::f32, Promote);
+
+      setOperationAction(ISD::ZEXTLOAD, MVT::i1, Expand);
+      setOperationAction(ISD::SEXTLOAD, MVT::i1, Expand);
+
+      setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1,  Expand);
+      setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8,  Expand);
+      setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16, Expand);
+      setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i32, Expand);
+
+      setOperationAction(ISD::UREM, MVT::i32, Expand);
+      setOperationAction(ISD::SREM, MVT::i32, Expand);
+
+      setOperationAction(ISD::CTPOP, MVT::i32, Expand);
+      setOperationAction(ISD::CTTZ, MVT::i32, Expand);
+      setOperationAction(ISD::CTLZ, MVT::i32, Expand);
+
+      setOperationAction(ISD::MEMMOVE, MVT::Other, Expand);
+      setOperationAction(ISD::MEMSET,  MVT::Other, Expand);
+      setOperationAction(ISD::MEMCPY,  MVT::Other, Expand);
+
+      // We don't support sin/cos/sqrt
+      setOperationAction(ISD::FSIN , MVT::f64, Expand);
+      setOperationAction(ISD::FCOS , MVT::f64, Expand);
+      setOperationAction(ISD::FSQRT, MVT::f64, Expand);
+      setOperationAction(ISD::FSIN , MVT::f32, Expand);
+      setOperationAction(ISD::FCOS , MVT::f32, Expand);
+      setOperationAction(ISD::FSQRT, MVT::f32, Expand);
+
+      computeRegisterProperties();
+
+      addLegalFPImmediate(+0.0); //F31
+      addLegalFPImmediate(-0.0); //-F31
+    }
+
+    /// LowerArguments - This hook must be implemented to indicate how we should
+    /// lower the arguments for the specified function, into the specified DAG.
+    virtual std::vector<SDOperand>
+    LowerArguments(Function &F, SelectionDAG &DAG);
+
+    /// LowerCallTo - This hook lowers an abstract call to a function into an
+    /// actual call.
+    virtual std::pair<SDOperand, SDOperand>
+    LowerCallTo(SDOperand Chain, const Type *RetTy, bool isVarArg, unsigned CC,
+                bool isTailCall, SDOperand Callee, ArgListTy &Args,
+                SelectionDAG &DAG);
+  };
+}
+
+/// AddLiveIn - This helper function adds the specified physical register to the
+/// MachineFunction as a live in value.  It also creates a corresponding virtual
+/// register for it.
+static unsigned AddLiveIn(MachineFunction &MF, unsigned PReg,
+                          TargetRegisterClass *RC) {
+  assert(RC->contains(PReg) && "Not the correct regclass!");
+  unsigned VReg = MF.getSSARegMap()->createVirtualRegister(RC);
+  MF.addLiveIn(PReg, VReg);
+  return VReg;
+}
+
+std::vector<SDOperand>
+V8TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG)
+{
+  //FIXME
+  std::vector<SDOperand> ArgValues;
+
+  MachineFunction &MF = DAG.getMachineFunction();
+  MachineFrameInfo*MFI = MF.getFrameInfo();
+
+  MachineBasicBlock& BB = MF.front();
+
+  //return the arguments
+  return ArgValues;
+}
+
+std::pair<SDOperand, SDOperand>
+V8TargetLowering::LowerCallTo(SDOperand Chain,
+                                 const Type *RetTy, bool isVarArg,
+                                 unsigned CallingConv, bool isTailCall,
+                                 SDOperand Callee, ArgListTy &Args, 
+                                 SelectionDAG &DAG) {
+  //FIXME
+  return std::make_pair(Chain, Chain);
+}
+
+namespace {
+
+//===--------------------------------------------------------------------===//
+/// ISel - V8 specific code to select V8 machine instructions for
+/// SelectionDAG operations.
+//===--------------------------------------------------------------------===//
+class ISel : public SelectionDAGISel {
+
+  /// V8Lowering - This object fully describes how to lower LLVM code to an
+  /// V8-specific SelectionDAG.
+  V8TargetLowering V8Lowering;
+
+  SelectionDAG *ISelDAG;  // Hack to support us having a dag->dag transform
+                          // for sdiv and udiv until it is put into the future
+                          // dag combiner.
+
+  /// ExprMap - As shared expressions are codegen'd, we keep track of which
+  /// vreg the value is produced in, so we only emit one copy of each compiled
+  /// tree.
+  static const unsigned notIn = (unsigned)(-1);
+  std::map<SDOperand, unsigned> ExprMap;
+
+public:
+  ISel(TargetMachine &TM) : SelectionDAGISel(V8Lowering), V8Lowering(TM)
+  {}
+
+  /// InstructionSelectBasicBlock - This callback is invoked by
+  /// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
+  virtual void InstructionSelectBasicBlock(SelectionDAG &DAG) {
+    DEBUG(BB->dump());
+
+    // Codegen the basic block.
+    ISelDAG = &DAG;
+    max_depth = DAG.getRoot().getNodeDepth();
+    Select(DAG.getRoot());
+
+    // Clear state used for selection.
+    ExprMap.clear();
+  }
+  
+  virtual void EmitFunctionEntryCode(Function &Fn, MachineFunction &MF);
+
+  unsigned SelectExpr(SDOperand N);
+  void Select(SDOperand N);
+
+};
+}
+
+void ISel::EmitFunctionEntryCode(Function &Fn, MachineFunction &MF) {
+  // If this function has live-in values, emit the copies from pregs to vregs at
+  // the top of the function, before anything else.
+  MachineBasicBlock *BB = MF.begin();
+  if (MF.livein_begin() != MF.livein_end()) {
+    SSARegMap *RegMap = MF.getSSARegMap();
+    for (MachineFunction::livein_iterator LI = MF.livein_begin(),
+           E = MF.livein_end(); LI != E; ++LI) {
+      const TargetRegisterClass *RC = RegMap->getRegClass(LI->second);
+      if (RC == V8::GPRCRegisterClass) {
+        BuildMI(BB, V8::ORrr, 2, LI->second).addReg(LI->first).addReg(V8::G0);
+      } else if (RC == V8::FPRCRegisterClass) {
+        BuildMI(BB, V8::FMOVSrr, 2, LI->second).addReg(LI->first);
+      } else {
+        assert(0 && "Unknown regclass!");
+      }
+    }
+  }
+}
+
+//These describe LDAx
+static const int IMM_LOW  = -32768;
+static const int IMM_HIGH = 32767;
+static const int IMM_MULT = 65536;
+
+static long getUpper16(long l)
+{
+  long y = l / IMM_MULT;
+  if (l % IMM_MULT > IMM_HIGH)
+    ++y;
+  return y;
+}
+
+static long getLower16(long l)
+{
+  long h = getUpper16(l);
+  return l - h * IMM_MULT;
+}
+
+unsigned ISel::SelectExpr(SDOperand N) {
+  unsigned Result;
+  unsigned Tmp1, Tmp2 = 0, Tmp3;
+  unsigned Opc = 0;
+  unsigned opcode = N.getOpcode();
+
+  SDNode *Node = N.Val;
+  MVT::ValueType DestType = N.getValueType();
+
+  unsigned &Reg = ExprMap[N];
+  if (Reg) return Reg;
+
+  if (N.getOpcode() != ISD::CALL && N.getOpcode() != ISD::TAILCALL)
+    Reg = Result = (N.getValueType() != MVT::Other) ?
+      MakeReg(N.getValueType()) : notIn;
+  else {
+    // If this is a call instruction, make sure to prepare ALL of the result
+    // values as well as the chain.
+    if (Node->getNumValues() == 1)
+      Reg = Result = notIn;  // Void call, just a chain.
+    else {
+      Result = MakeReg(Node->getValueType(0));
+      ExprMap[N.getValue(0)] = Result;
+      for (unsigned i = 1, e = N.Val->getNumValues()-1; i != e; ++i)
+        ExprMap[N.getValue(i)] = MakeReg(Node->getValueType(i));
+      ExprMap[SDOperand(Node, Node->getNumValues()-1)] = notIn;
+    }
+  }
+
+  switch (opcode) {
+  default:
+    Node->dump();
+    assert(0 && "Node not handled!\n");
+
+  case ISD::EXTLOAD:
+  case ISD::ZEXTLOAD:
+  case ISD::SEXTLOAD:
+  case ISD::LOAD:
+    {
+      // Make sure we generate both values.
+      if (Result != notIn)
+        ExprMap[N.getValue(1)] = notIn;   // Generate the token
+      else
+        Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
+
+      SDOperand Chain   = N.getOperand(0);
+      SDOperand Address = N.getOperand(1);
+      Select(Chain);
+      unsigned Adr = SelectExpr(Address);
+      switch(cast<MVTSDNode>(Node)->getExtraValueType()) {
+      case MVT::i32: Opc = V8::LD;
+      case MVT::i16: Opc = opcode == ISD::ZEXTLOAD ? V8::LDUH : V8::LDSH; break;
+      case MVT::i8:  Opc = opcode == ISD::ZEXTLOAD ? V8::LDUB : V8::LDSB; break;
+      case MVT::f64: Opc = V8::LDFSRrr;
+      case MVT::f32: Opc = V8::LDDFrr;
+      default:
+        Node->dump(); 
+        assert(0 && "Bad type!");
+        break;
+      }
+      BuildMI(BB, Opc, 1, Result).addReg(Adr);
+      return Result;
+    }
+
+  case ISD::TAILCALL:
+  case ISD::CALL:
+    {
+      //FIXME:
+      abort();
+      return Result;
+    }
+
+  case ISD::CopyFromReg:
+    {
+      // Make sure we generate both values.
+      if (Result != notIn)
+        ExprMap[N.getValue(1)] = notIn;   // Generate the token
+      else
+        Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
+
+      SDOperand Chain   = N.getOperand(0);
+      Select(Chain);
+      unsigned r = dyn_cast<RegSDNode>(Node)->getReg();
+      
+      BuildMI(BB, V8::ORrr, 2, Result).addReg(r).addReg(V8::G0);
+      return Result;
+    }
+
+    //Most of the plain arithmetic and logic share the same form, and the same
+    //constant immediate test
+  case ISD::XOR:
+  case ISD::AND:
+  case ISD::OR:
+  case ISD::SHL:
+  case ISD::SRL:
+  case ISD::SRA:
+  case ISD::ADD:
+  case ISD::SUB:
+  case ISD::SDIV:
+  case ISD::UDIV:
+  case ISD::SMUL:
+  case ISD::UMUL:
+    switch(opcode) {
+    case ISD::XOR:  Opc = V8::XORrr; break;
+    case ISD::AND:  Opc = V8::ANDrr; break;
+    case ISD::OR:   Opc = V8::ORrr; break;
+    case ISD::SHL:  Opc = V8::SLLrr; break;
+    case ISD::SRL:  Opc = V8::SRLrr; break;
+    case ISD::SRA:  Opc = V8::SRArr; break;
+    case ISD::ADD:  Opc = V8::ADDrr; break;
+    case ISD::SUB:  Opc = V8::SUBrr; break;
+    case ISD::SDIV: Opc = V8::SDIVrr; break;
+    case ISD::UDIV: Opc = V8::UDIVrr; break;
+    case ISD::SMUL: Opc = V8::SMULrr; break;
+    case ISD::UMUL: Opc = V8::UMULrr; break;
+    }
+    Tmp1 = SelectExpr(N.getOperand(0));
+    Tmp2 = SelectExpr(N.getOperand(1));
+    BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
+    return Result;
+   
+  }
+  return 0;
+}
+
+void ISel::Select(SDOperand N) {
+  unsigned Tmp1, Tmp2, Opc;
+  unsigned opcode = N.getOpcode();
+
+  if (!ExprMap.insert(std::make_pair(N, notIn)).second)
+    return;  // Already selected.
+
+  SDNode *Node = N.Val;
+
+  switch (opcode) {
+
+  default:
+    Node->dump(); std::cerr << "\n";
+    assert(0 && "Node not handled yet!");
+
+  case ISD::BRCOND: {
+    //FIXME
+    abort();
+    return;
+  }
+
+  case ISD::BR: {
+    MachineBasicBlock *Dest =
+      cast<BasicBlockSDNode>(N.getOperand(1))->getBasicBlock();
+
+    Select(N.getOperand(0));
+    BuildMI(BB, V8::BA, 1).addMBB(Dest);
+    return;
+  }
+
+  case ISD::ImplicitDef:
+    Select(N.getOperand(0));
+    BuildMI(BB, V8::IMPLICIT_DEF, 0, cast<RegSDNode>(N)->getReg());
+    return;
+
+  case ISD::EntryToken: return;  // Noop
+
+  case ISD::TokenFactor:
+    for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i)
+      Select(Node->getOperand(i));
+    return;
+
+  case ISD::CopyToReg:
+    Select(N.getOperand(0));
+    Tmp1 = SelectExpr(N.getOperand(1));
+    Tmp2 = cast<RegSDNode>(N)->getReg();
+
+    if (Tmp1 != Tmp2) {
+      if (N.getOperand(1).getValueType() == MVT::f64 ||
+          N.getOperand(1).getValueType() == MVT::f32)
+        BuildMI(BB, V8::FMOVS, 2, Tmp2).addReg(Tmp1);
+      else
+        BuildMI(BB, V8::ORrr, 2, Tmp2).addReg(Tmp1).addReg(V8::G0);
+    }
+    return;
+
+  case ISD::RET:
+    //FIXME:
+    abort();
+    return;
+
+  case ISD::TRUNCSTORE:
+  case ISD::STORE:
+    {
+      SDOperand Chain   = N.getOperand(0);
+      SDOperand Value = N.getOperand(1);
+      SDOperand Address = N.getOperand(2);
+      Select(Chain);
+
+      Tmp1 = SelectExpr(Value);
+      Tmp2 = SelectExpr(Address);
+
+      unsigned VT = opcode == ISD::STORE ? 
+        Value.getValueType() : cast<MVTSDNode>(Node)->getExtraValueType();
+      switch(VT) {
+      default: assert(0 && "unknown Type in store");
+      case MVT::f64: Opc = V8::STDFrr; break;
+      case MVT::f32: Opc = V8::STFrr; break;
+      case MVT::i1:  //FIXME: DAG does not promote this load
+      case MVT::i8:  Opc = V8::STBrr; break;
+      case MVT::i16: Opc = V8::STHrr; break;
+      case MVT::i32: Opc = V8::STLrr; break;
+      case MVT::i64: Opc = V8::STDrr; break;
+      }
+
+      BuildMI(BB,Opc,2).addReg(Tmp1).addReg(Tmp2);
+      return;
+    }
+
+  case ISD::EXTLOAD:
+  case ISD::SEXTLOAD:
+  case ISD::ZEXTLOAD:
+  case ISD::LOAD:
+  case ISD::CopyFromReg:
+  case ISD::TAILCALL:
+  case ISD::CALL:
+  case ISD::DYNAMIC_STACKALLOC:
+    ExprMap.erase(N);
+    SelectExpr(N);
+    return;
+
+  case ISD::CALLSEQ_START:
+  case ISD::CALLSEQ_END:
+    Select(N.getOperand(0));
+    Tmp1 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
+
+    Opc = N.getOpcode() == ISD::CALLSEQ_START ? V8::ADJUSTCALLSTACKDOWN :
+      V8::ADJUSTCALLSTACKUP;
+    BuildMI(BB, Opc, 1).addImm(Tmp1);
+    return;
+  }
+  assert(0 && "Should not be reached!");
+}
+
+
+/// createV8PatternInstructionSelector - This pass converts an LLVM function
+/// into a machine code representation using pattern matching and a machine
+/// description file.
+///
+FunctionPass *llvm::createV8PatternInstructionSelector(TargetMachine &TM) {
+  return new ISel(TM);
+}
+
+#endif
diff --git a/lib/Target/SparcV8/SparcV8ISelPattern.cpp b/lib/Target/SparcV8/SparcV8ISelPattern.cpp
new file mode 100644 (file)
index 0000000..98d4f93
--- /dev/null
@@ -0,0 +1,479 @@
+#if 0
+//===- SparcV8ISelPattern.cpp - A pattern matching isel for SparcV8 -------===//
+//
+//                     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 defines a pattern matching instruction selector for SparcV8.
+//
+//===----------------------------------------------------------------------===//
+
+//Please note that this file is a work in progress, and not a high
+//priority for anyone.
+
+#include "SparcV8.h"
+#include "SparcV8RegisterInfo.h"
+#include "llvm/Constants.h"                   // FIXME: REMOVE
+#include "llvm/Function.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineConstantPool.h" // FIXME: REMOVE
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineFrameInfo.h"
+#include "llvm/CodeGen/SelectionDAG.h"
+#include "llvm/CodeGen/SelectionDAGISel.h"
+#include "llvm/CodeGen/SSARegMap.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Target/TargetLowering.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/CommandLine.h"
+#include <set>
+#include <algorithm>
+using namespace llvm;
+
+//===----------------------------------------------------------------------===//
+//  V8TargetLowering - SparcV8 Implementation of the TargetLowering interface
+namespace {
+  class V8TargetLowering : public TargetLowering {
+    int VarArgsFrameIndex;            // FrameIndex for start of varargs area.
+  public:
+    V8TargetLowering(TargetMachine &TM) : TargetLowering(TM) {
+      // Set up the TargetLowering object.
+      //I am having problems with shr n ubyte 1
+      setShiftAmountType(MVT::i32);
+      setSetCCResultType(MVT::i32);
+      setSetCCResultContents(ZeroOrOneSetCCResult);
+
+      //FIXME: get these right
+      addRegisterClass(MVT::i64, V8::GPRCRegisterClass);
+      addRegisterClass(MVT::f64, V8::FPRCRegisterClass);
+      addRegisterClass(MVT::f32, V8::FPRCRegisterClass);
+
+      setOperationAction(ISD::BRCONDTWOWAY, MVT::Other, Expand);
+      setOperationAction(ISD::EXTLOAD, MVT::i1,  Promote);
+      setOperationAction(ISD::EXTLOAD, MVT::f32, Promote);
+
+      setOperationAction(ISD::ZEXTLOAD, MVT::i1, Expand);
+      setOperationAction(ISD::SEXTLOAD, MVT::i1, Expand);
+
+      setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1,  Expand);
+      setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8,  Expand);
+      setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16, Expand);
+      setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i32, Expand);
+
+      setOperationAction(ISD::UREM, MVT::i32, Expand);
+      setOperationAction(ISD::SREM, MVT::i32, Expand);
+
+      setOperationAction(ISD::CTPOP, MVT::i32, Expand);
+      setOperationAction(ISD::CTTZ, MVT::i32, Expand);
+      setOperationAction(ISD::CTLZ, MVT::i32, Expand);
+
+      setOperationAction(ISD::MEMMOVE, MVT::Other, Expand);
+      setOperationAction(ISD::MEMSET,  MVT::Other, Expand);
+      setOperationAction(ISD::MEMCPY,  MVT::Other, Expand);
+
+      // We don't support sin/cos/sqrt
+      setOperationAction(ISD::FSIN , MVT::f64, Expand);
+      setOperationAction(ISD::FCOS , MVT::f64, Expand);
+      setOperationAction(ISD::FSQRT, MVT::f64, Expand);
+      setOperationAction(ISD::FSIN , MVT::f32, Expand);
+      setOperationAction(ISD::FCOS , MVT::f32, Expand);
+      setOperationAction(ISD::FSQRT, MVT::f32, Expand);
+
+      computeRegisterProperties();
+
+      addLegalFPImmediate(+0.0); //F31
+      addLegalFPImmediate(-0.0); //-F31
+    }
+
+    /// LowerArguments - This hook must be implemented to indicate how we should
+    /// lower the arguments for the specified function, into the specified DAG.
+    virtual std::vector<SDOperand>
+    LowerArguments(Function &F, SelectionDAG &DAG);
+
+    /// LowerCallTo - This hook lowers an abstract call to a function into an
+    /// actual call.
+    virtual std::pair<SDOperand, SDOperand>
+    LowerCallTo(SDOperand Chain, const Type *RetTy, bool isVarArg, unsigned CC,
+                bool isTailCall, SDOperand Callee, ArgListTy &Args,
+                SelectionDAG &DAG);
+  };
+}
+
+/// AddLiveIn - This helper function adds the specified physical register to the
+/// MachineFunction as a live in value.  It also creates a corresponding virtual
+/// register for it.
+static unsigned AddLiveIn(MachineFunction &MF, unsigned PReg,
+                          TargetRegisterClass *RC) {
+  assert(RC->contains(PReg) && "Not the correct regclass!");
+  unsigned VReg = MF.getSSARegMap()->createVirtualRegister(RC);
+  MF.addLiveIn(PReg, VReg);
+  return VReg;
+}
+
+std::vector<SDOperand>
+V8TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG)
+{
+  //FIXME
+  std::vector<SDOperand> ArgValues;
+
+  MachineFunction &MF = DAG.getMachineFunction();
+  MachineFrameInfo*MFI = MF.getFrameInfo();
+
+  MachineBasicBlock& BB = MF.front();
+
+  //return the arguments
+  return ArgValues;
+}
+
+std::pair<SDOperand, SDOperand>
+V8TargetLowering::LowerCallTo(SDOperand Chain,
+                                 const Type *RetTy, bool isVarArg,
+                                 unsigned CallingConv, bool isTailCall,
+                                 SDOperand Callee, ArgListTy &Args, 
+                                 SelectionDAG &DAG) {
+  //FIXME
+  return std::make_pair(Chain, Chain);
+}
+
+namespace {
+
+//===--------------------------------------------------------------------===//
+/// ISel - V8 specific code to select V8 machine instructions for
+/// SelectionDAG operations.
+//===--------------------------------------------------------------------===//
+class ISel : public SelectionDAGISel {
+
+  /// V8Lowering - This object fully describes how to lower LLVM code to an
+  /// V8-specific SelectionDAG.
+  V8TargetLowering V8Lowering;
+
+  SelectionDAG *ISelDAG;  // Hack to support us having a dag->dag transform
+                          // for sdiv and udiv until it is put into the future
+                          // dag combiner.
+
+  /// ExprMap - As shared expressions are codegen'd, we keep track of which
+  /// vreg the value is produced in, so we only emit one copy of each compiled
+  /// tree.
+  static const unsigned notIn = (unsigned)(-1);
+  std::map<SDOperand, unsigned> ExprMap;
+
+public:
+  ISel(TargetMachine &TM) : SelectionDAGISel(V8Lowering), V8Lowering(TM)
+  {}
+
+  /// InstructionSelectBasicBlock - This callback is invoked by
+  /// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
+  virtual void InstructionSelectBasicBlock(SelectionDAG &DAG) {
+    DEBUG(BB->dump());
+
+    // Codegen the basic block.
+    ISelDAG = &DAG;
+    max_depth = DAG.getRoot().getNodeDepth();
+    Select(DAG.getRoot());
+
+    // Clear state used for selection.
+    ExprMap.clear();
+  }
+  
+  virtual void EmitFunctionEntryCode(Function &Fn, MachineFunction &MF);
+
+  unsigned SelectExpr(SDOperand N);
+  void Select(SDOperand N);
+
+};
+}
+
+void ISel::EmitFunctionEntryCode(Function &Fn, MachineFunction &MF) {
+  // If this function has live-in values, emit the copies from pregs to vregs at
+  // the top of the function, before anything else.
+  MachineBasicBlock *BB = MF.begin();
+  if (MF.livein_begin() != MF.livein_end()) {
+    SSARegMap *RegMap = MF.getSSARegMap();
+    for (MachineFunction::livein_iterator LI = MF.livein_begin(),
+           E = MF.livein_end(); LI != E; ++LI) {
+      const TargetRegisterClass *RC = RegMap->getRegClass(LI->second);
+      if (RC == V8::GPRCRegisterClass) {
+        BuildMI(BB, V8::ORrr, 2, LI->second).addReg(LI->first).addReg(V8::G0);
+      } else if (RC == V8::FPRCRegisterClass) {
+        BuildMI(BB, V8::FMOVSrr, 2, LI->second).addReg(LI->first);
+      } else {
+        assert(0 && "Unknown regclass!");
+      }
+    }
+  }
+}
+
+//These describe LDAx
+static const int IMM_LOW  = -32768;
+static const int IMM_HIGH = 32767;
+static const int IMM_MULT = 65536;
+
+static long getUpper16(long l)
+{
+  long y = l / IMM_MULT;
+  if (l % IMM_MULT > IMM_HIGH)
+    ++y;
+  return y;
+}
+
+static long getLower16(long l)
+{
+  long h = getUpper16(l);
+  return l - h * IMM_MULT;
+}
+
+unsigned ISel::SelectExpr(SDOperand N) {
+  unsigned Result;
+  unsigned Tmp1, Tmp2 = 0, Tmp3;
+  unsigned Opc = 0;
+  unsigned opcode = N.getOpcode();
+
+  SDNode *Node = N.Val;
+  MVT::ValueType DestType = N.getValueType();
+
+  unsigned &Reg = ExprMap[N];
+  if (Reg) return Reg;
+
+  if (N.getOpcode() != ISD::CALL && N.getOpcode() != ISD::TAILCALL)
+    Reg = Result = (N.getValueType() != MVT::Other) ?
+      MakeReg(N.getValueType()) : notIn;
+  else {
+    // If this is a call instruction, make sure to prepare ALL of the result
+    // values as well as the chain.
+    if (Node->getNumValues() == 1)
+      Reg = Result = notIn;  // Void call, just a chain.
+    else {
+      Result = MakeReg(Node->getValueType(0));
+      ExprMap[N.getValue(0)] = Result;
+      for (unsigned i = 1, e = N.Val->getNumValues()-1; i != e; ++i)
+        ExprMap[N.getValue(i)] = MakeReg(Node->getValueType(i));
+      ExprMap[SDOperand(Node, Node->getNumValues()-1)] = notIn;
+    }
+  }
+
+  switch (opcode) {
+  default:
+    Node->dump();
+    assert(0 && "Node not handled!\n");
+
+  case ISD::EXTLOAD:
+  case ISD::ZEXTLOAD:
+  case ISD::SEXTLOAD:
+  case ISD::LOAD:
+    {
+      // Make sure we generate both values.
+      if (Result != notIn)
+        ExprMap[N.getValue(1)] = notIn;   // Generate the token
+      else
+        Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
+
+      SDOperand Chain   = N.getOperand(0);
+      SDOperand Address = N.getOperand(1);
+      Select(Chain);
+      unsigned Adr = SelectExpr(Address);
+      switch(cast<MVTSDNode>(Node)->getExtraValueType()) {
+      case MVT::i32: Opc = V8::LD;
+      case MVT::i16: Opc = opcode == ISD::ZEXTLOAD ? V8::LDUH : V8::LDSH; break;
+      case MVT::i8:  Opc = opcode == ISD::ZEXTLOAD ? V8::LDUB : V8::LDSB; break;
+      case MVT::f64: Opc = V8::LDFSRrr;
+      case MVT::f32: Opc = V8::LDDFrr;
+      default:
+        Node->dump(); 
+        assert(0 && "Bad type!");
+        break;
+      }
+      BuildMI(BB, Opc, 1, Result).addReg(Adr);
+      return Result;
+    }
+
+  case ISD::TAILCALL:
+  case ISD::CALL:
+    {
+      //FIXME:
+      abort();
+      return Result;
+    }
+
+  case ISD::CopyFromReg:
+    {
+      // Make sure we generate both values.
+      if (Result != notIn)
+        ExprMap[N.getValue(1)] = notIn;   // Generate the token
+      else
+        Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
+
+      SDOperand Chain   = N.getOperand(0);
+      Select(Chain);
+      unsigned r = dyn_cast<RegSDNode>(Node)->getReg();
+      
+      BuildMI(BB, V8::ORrr, 2, Result).addReg(r).addReg(V8::G0);
+      return Result;
+    }
+
+    //Most of the plain arithmetic and logic share the same form, and the same
+    //constant immediate test
+  case ISD::XOR:
+  case ISD::AND:
+  case ISD::OR:
+  case ISD::SHL:
+  case ISD::SRL:
+  case ISD::SRA:
+  case ISD::ADD:
+  case ISD::SUB:
+  case ISD::SDIV:
+  case ISD::UDIV:
+  case ISD::SMUL:
+  case ISD::UMUL:
+    switch(opcode) {
+    case ISD::XOR:  Opc = V8::XORrr; break;
+    case ISD::AND:  Opc = V8::ANDrr; break;
+    case ISD::OR:   Opc = V8::ORrr; break;
+    case ISD::SHL:  Opc = V8::SLLrr; break;
+    case ISD::SRL:  Opc = V8::SRLrr; break;
+    case ISD::SRA:  Opc = V8::SRArr; break;
+    case ISD::ADD:  Opc = V8::ADDrr; break;
+    case ISD::SUB:  Opc = V8::SUBrr; break;
+    case ISD::SDIV: Opc = V8::SDIVrr; break;
+    case ISD::UDIV: Opc = V8::UDIVrr; break;
+    case ISD::SMUL: Opc = V8::SMULrr; break;
+    case ISD::UMUL: Opc = V8::UMULrr; break;
+    }
+    Tmp1 = SelectExpr(N.getOperand(0));
+    Tmp2 = SelectExpr(N.getOperand(1));
+    BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
+    return Result;
+   
+  }
+  return 0;
+}
+
+void ISel::Select(SDOperand N) {
+  unsigned Tmp1, Tmp2, Opc;
+  unsigned opcode = N.getOpcode();
+
+  if (!ExprMap.insert(std::make_pair(N, notIn)).second)
+    return;  // Already selected.
+
+  SDNode *Node = N.Val;
+
+  switch (opcode) {
+
+  default:
+    Node->dump(); std::cerr << "\n";
+    assert(0 && "Node not handled yet!");
+
+  case ISD::BRCOND: {
+    //FIXME
+    abort();
+    return;
+  }
+
+  case ISD::BR: {
+    MachineBasicBlock *Dest =
+      cast<BasicBlockSDNode>(N.getOperand(1))->getBasicBlock();
+
+    Select(N.getOperand(0));
+    BuildMI(BB, V8::BA, 1).addMBB(Dest);
+    return;
+  }
+
+  case ISD::ImplicitDef:
+    Select(N.getOperand(0));
+    BuildMI(BB, V8::IMPLICIT_DEF, 0, cast<RegSDNode>(N)->getReg());
+    return;
+
+  case ISD::EntryToken: return;  // Noop
+
+  case ISD::TokenFactor:
+    for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i)
+      Select(Node->getOperand(i));
+    return;
+
+  case ISD::CopyToReg:
+    Select(N.getOperand(0));
+    Tmp1 = SelectExpr(N.getOperand(1));
+    Tmp2 = cast<RegSDNode>(N)->getReg();
+
+    if (Tmp1 != Tmp2) {
+      if (N.getOperand(1).getValueType() == MVT::f64 ||
+          N.getOperand(1).getValueType() == MVT::f32)
+        BuildMI(BB, V8::FMOVS, 2, Tmp2).addReg(Tmp1);
+      else
+        BuildMI(BB, V8::ORrr, 2, Tmp2).addReg(Tmp1).addReg(V8::G0);
+    }
+    return;
+
+  case ISD::RET:
+    //FIXME:
+    abort();
+    return;
+
+  case ISD::TRUNCSTORE:
+  case ISD::STORE:
+    {
+      SDOperand Chain   = N.getOperand(0);
+      SDOperand Value = N.getOperand(1);
+      SDOperand Address = N.getOperand(2);
+      Select(Chain);
+
+      Tmp1 = SelectExpr(Value);
+      Tmp2 = SelectExpr(Address);
+
+      unsigned VT = opcode == ISD::STORE ? 
+        Value.getValueType() : cast<MVTSDNode>(Node)->getExtraValueType();
+      switch(VT) {
+      default: assert(0 && "unknown Type in store");
+      case MVT::f64: Opc = V8::STDFrr; break;
+      case MVT::f32: Opc = V8::STFrr; break;
+      case MVT::i1:  //FIXME: DAG does not promote this load
+      case MVT::i8:  Opc = V8::STBrr; break;
+      case MVT::i16: Opc = V8::STHrr; break;
+      case MVT::i32: Opc = V8::STLrr; break;
+      case MVT::i64: Opc = V8::STDrr; break;
+      }
+
+      BuildMI(BB,Opc,2).addReg(Tmp1).addReg(Tmp2);
+      return;
+    }
+
+  case ISD::EXTLOAD:
+  case ISD::SEXTLOAD:
+  case ISD::ZEXTLOAD:
+  case ISD::LOAD:
+  case ISD::CopyFromReg:
+  case ISD::TAILCALL:
+  case ISD::CALL:
+  case ISD::DYNAMIC_STACKALLOC:
+    ExprMap.erase(N);
+    SelectExpr(N);
+    return;
+
+  case ISD::CALLSEQ_START:
+  case ISD::CALLSEQ_END:
+    Select(N.getOperand(0));
+    Tmp1 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
+
+    Opc = N.getOpcode() == ISD::CALLSEQ_START ? V8::ADJUSTCALLSTACKDOWN :
+      V8::ADJUSTCALLSTACKUP;
+    BuildMI(BB, Opc, 1).addImm(Tmp1);
+    return;
+  }
+  assert(0 && "Should not be reached!");
+}
+
+
+/// createV8PatternInstructionSelector - This pass converts an LLVM function
+/// into a machine code representation using pattern matching and a machine
+/// description file.
+///
+FunctionPass *llvm::createV8PatternInstructionSelector(TargetMachine &TM) {
+  return new ISel(TM);
+}
+
+#endif