|  | #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::BRTWOWAY_CC,  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) | 
|  | { | 
|  | static const unsigned IncomingArgRegs[] = | 
|  | { V8::I0, V8::I1, V8::I2, V8::I3, V8::I4, V8::I5 }; | 
|  | std::vector<SDOperand> ArgValues; | 
|  |  | 
|  | MachineFunction &MF = DAG.getMachineFunction(); | 
|  | MachineFrameInfo*MFI = MF.getFrameInfo(); | 
|  |  | 
|  | MachineBasicBlock& BB = MF.front(); | 
|  |  | 
|  | unsigned ArgNo = 0; | 
|  | unsigned ArgOffset = 92; | 
|  | for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); | 
|  | I != E; ++I, ++ArgNo) { | 
|  | MVT::ValueType VT = getValueType(I->getType()); | 
|  | SDOperand argt; | 
|  | if (ArgNo < 6) { | 
|  | switch(VT) { | 
|  | default: | 
|  | std::cerr << "Unknown Type " << VT << "\n"; | 
|  | abort(); | 
|  | case MVT::f64: | 
|  | case MVT::i64: | 
|  | //FIXME: figure out the build pair thing | 
|  | assert(0 && "doubles and longs not supported yet"); | 
|  | case MVT::f32: | 
|  | argt = DAG.getCopyFromReg(AddLiveIn(MF, IncomingArgRegs[ArgNo], | 
|  | MVT::i32), | 
|  | VT, DAG.getRoot()); | 
|  | //copy out of Int reg | 
|  | argt = DAG.getNode(ISD::FP_TO_UINT, MVT::f32, argt); | 
|  | break; | 
|  | case MVT::i1: | 
|  | case MVT::i8: | 
|  | case MVT::i16: | 
|  | case MVT::i32: | 
|  | argt = DAG.getCopyFromReg(AddLiveIn(MF, IncomingArgRegs[ArgNo], | 
|  | getRegClassFor(MVT::i32)), | 
|  | VT, DAG.getRoot()); | 
|  | if (VT != MVT::i32) | 
|  | argt = DAG.getNode(ISD::TRUNCATE, VT, argt); | 
|  | break; | 
|  | } | 
|  | DAG.setRoot(argt.getValue(1)); | 
|  | } else { | 
|  | //stack passed | 
|  | switch(VT) { | 
|  | default: | 
|  | std::cerr << "Unknown Type " << VT << "\n"; | 
|  | abort(); | 
|  | case MVT::f64: | 
|  | case MVT::i64: | 
|  | //FIXME: figure out the build pair thing | 
|  | assert(0 && "doubles and longs not supported yet"); | 
|  | case MVT::f32: | 
|  | case MVT::i1: | 
|  | case MVT::i8: | 
|  | case MVT::i16: | 
|  | case MVT::i32: | 
|  | // Create the frame index object for this incoming parameter... | 
|  | int FI = MFI->CreateFixedObject(4, ArgOffset); | 
|  | argt = DAG.getLoad(VT, | 
|  | DAG.getEntryNode(), | 
|  | DAG.getFramIndex(FI, MVT::i32), | 
|  | DAG.getSrcValue(NULL)); | 
|  | ArgOffset += 4; | 
|  | break; | 
|  | } | 
|  | ArgValues.push_back(argt); | 
|  | } | 
|  | } | 
|  |  | 
|  | //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<VTSDNode>(Node->getOperand(3))->getVT()) { | 
|  | 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<VTSDNode>(Node->getOperand(4))->getVT(); | 
|  | 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 |