Add an instruction selector capable of selecting 'ret void'


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@11973 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Target/Sparc/InstSelectSimple.cpp b/lib/Target/Sparc/InstSelectSimple.cpp
new file mode 100644
index 0000000..c195611
--- /dev/null
+++ b/lib/Target/Sparc/InstSelectSimple.cpp
@@ -0,0 +1,152 @@
+//===-- InstSelectSimple.cpp - A simple instruction selector 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 simple peephole instruction selector for the V8 target
+//
+//===----------------------------------------------------------------------===//
+
+#include "SparcV8.h"
+#include "llvm/Instructions.h"
+#include "llvm/IntrinsicLowering.h"
+#include "llvm/Pass.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Support/GetElementPtrTypeIterator.h"
+#include "llvm/Support/InstVisitor.h"
+#include "llvm/Support/CFG.h"
+using namespace llvm;
+
+namespace {
+  struct V8ISel : public FunctionPass, public InstVisitor<V8ISel> {
+    TargetMachine &TM;
+    MachineFunction *F;                 // The function we are compiling into
+    MachineBasicBlock *BB;              // The current MBB we are compiling
+
+    std::map<Value*, unsigned> RegMap;  // Mapping between Val's and SSA Regs
+
+    // MBBMap - Mapping between LLVM BB -> Machine BB
+    std::map<const BasicBlock*, MachineBasicBlock*> MBBMap;
+
+    V8ISel(TargetMachine &tm) : TM(tm), F(0), BB(0) {}
+
+    /// runOnFunction - Top level implementation of instruction selection for
+    /// the entire function.
+    ///
+    bool runOnFunction(Function &Fn);
+
+    virtual const char *getPassName() const {
+      return "SparcV8 Simple Instruction Selection";
+    }
+
+    /// visitBasicBlock - This method is called when we are visiting a new basic
+    /// block.  This simply creates a new MachineBasicBlock to emit code into
+    /// and adds it to the current MachineFunction.  Subsequent visit* for
+    /// instructions will be invoked for all instructions in the basic block.
+    ///
+    void visitBasicBlock(BasicBlock &LLVM_BB) {
+      BB = MBBMap[&LLVM_BB];
+    }
+
+    void visitReturnInst(ReturnInst &RI);
+
+    void visitInstruction(Instruction &I) {
+      std::cerr << "Unhandled instruction: " << I;
+      abort();
+    }
+
+    /// LowerUnknownIntrinsicFunctionCalls - This performs a prepass over the
+    /// function, lowering any calls to unknown intrinsic functions into the
+    /// equivalent LLVM code.
+    void LowerUnknownIntrinsicFunctionCalls(Function &F);
+
+
+    void visitIntrinsicCall(Intrinsic::ID ID, CallInst &CI);
+
+  };
+}
+
+FunctionPass *llvm::createSparcV8SimpleInstructionSelector(TargetMachine &TM) {
+  return new V8ISel(TM);
+}
+
+
+bool V8ISel::runOnFunction(Function &Fn) {
+  // First pass over the function, lower any unknown intrinsic functions
+  // with the IntrinsicLowering class.
+  LowerUnknownIntrinsicFunctionCalls(Fn);
+  
+  F = &MachineFunction::construct(&Fn, TM);
+  
+  // Create all of the machine basic blocks for the function...
+  for (Function::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I)
+    F->getBasicBlockList().push_back(MBBMap[I] = new MachineBasicBlock(I));
+  
+  BB = &F->front();
+  
+  // Set up a frame object for the return address.  This is used by the
+  // llvm.returnaddress & llvm.frameaddress intrinisics.
+  //ReturnAddressIndex = F->getFrameInfo()->CreateFixedObject(4, -4);
+  
+  // Copy incoming arguments off of the stack and out of fixed registers.
+  //LoadArgumentsToVirtualRegs(Fn);
+  
+  // Instruction select everything except PHI nodes
+  visit(Fn);
+  
+  // Select the PHI nodes
+  //SelectPHINodes();
+  
+  RegMap.clear();
+  MBBMap.clear();
+  F = 0;
+  // We always build a machine code representation for the function
+  return true;
+}
+
+
+void V8ISel::visitReturnInst(ReturnInst &I) {
+  if (I.getNumOperands() == 0) {
+    // Just emit a 'ret' instruction
+    BuildMI(BB, V8::JMPLi, 2, V8::G0).addZImm(8).addReg(V8::I7);
+    return;
+  }
+  visitInstruction(I);
+}
+
+
+/// LowerUnknownIntrinsicFunctionCalls - This performs a prepass over the
+/// function, lowering any calls to unknown intrinsic functions into the
+/// equivalent LLVM code.
+void V8ISel::LowerUnknownIntrinsicFunctionCalls(Function &F) {
+  for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
+    for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; )
+      if (CallInst *CI = dyn_cast<CallInst>(I++))
+        if (Function *F = CI->getCalledFunction())
+          switch (F->getIntrinsicID()) {
+          case Intrinsic::not_intrinsic: break;
+          default:
+            // All other intrinsic calls we must lower.
+            Instruction *Before = CI->getPrev();
+            TM.getIntrinsicLowering().LowerIntrinsicCall(CI);
+            if (Before) {        // Move iterator to instruction after call
+              I = Before;  ++I;
+            } else {
+              I = BB->begin();
+            }
+          }
+}
+
+
+void V8ISel::visitIntrinsicCall(Intrinsic::ID ID, CallInst &CI) {
+  unsigned TmpReg1, TmpReg2;
+  switch (ID) {
+  default: assert(0 && "Intrinsic not supported!");
+  }
+}