added a skeleton of the ARM backend
authorRafael Espindola <rafael.espindola@gmail.com>
Sun, 14 May 2006 22:18:28 +0000 (22:18 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Sun, 14 May 2006 22:18:28 +0000 (22:18 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@28301 91177308-0d34-0410-b5e6-96231b3b80d8

16 files changed:
autoconf/configure.ac
configure
lib/Target/ARM/ARM.h [new file with mode: 0644]
lib/Target/ARM/ARM.td [new file with mode: 0644]
lib/Target/ARM/ARMAsmPrinter.cpp [new file with mode: 0644]
lib/Target/ARM/ARMISelDAGToDAG.cpp [new file with mode: 0644]
lib/Target/ARM/ARMInstrInfo.cpp [new file with mode: 0644]
lib/Target/ARM/ARMInstrInfo.h [new file with mode: 0644]
lib/Target/ARM/ARMInstrInfo.td [new file with mode: 0644]
lib/Target/ARM/ARMRegisterInfo.cpp [new file with mode: 0644]
lib/Target/ARM/ARMRegisterInfo.h [new file with mode: 0644]
lib/Target/ARM/ARMRegisterInfo.td [new file with mode: 0644]
lib/Target/ARM/ARMTargetMachine.cpp [new file with mode: 0644]
lib/Target/ARM/ARMTargetMachine.h [new file with mode: 0644]
lib/Target/ARM/Makefile [new file with mode: 0644]
tools/llc/Makefile

index 3917db0a10475a1e15b4f4d89a7244f25c2a61f1..b29ce31f964db366a5b98d2adca6d6f2fc01392a 100644 (file)
@@ -285,7 +285,7 @@ AC_ARG_ENABLE([targets],AS_HELP_STRING([--enable-target],
     [Build specific host targets: all,host-only,{target-name} (default=all)]),,
     enableval=all)
 case "$enableval" in
-  all) TARGETS_TO_BUILD="X86 Sparc PowerPC Alpha IA64" ;;
+  all) TARGETS_TO_BUILD="X86 Sparc PowerPC Alpha IA64 ARM" ;;
   host-only)
     case "$llvm_cv_target_arch" in
       x86)     TARGETS_TO_BUILD="X86" ;;
index 351cdd540b7d3e0e18c7e48136ff9b6eeb04c7e5..b235fcd95c07ec2a6448ded6c4f27e0897af5080 100755 (executable)
--- a/configure
+++ b/configure
@@ -3107,7 +3107,7 @@ else
   enableval=all
 fi;
 case "$enableval" in
-  all) TARGETS_TO_BUILD="X86 Sparc PowerPC Alpha IA64" ;;
+  all) TARGETS_TO_BUILD="X86 Sparc PowerPC Alpha IA64 ARM" ;;
   host-only)
     case "$llvm_cv_target_arch" in
       x86)     TARGETS_TO_BUILD="X86" ;;
diff --git a/lib/Target/ARM/ARM.h b/lib/Target/ARM/ARM.h
new file mode 100644 (file)
index 0000000..167d71e
--- /dev/null
@@ -0,0 +1,40 @@
+//===-- ARM.h - Top-level interface for ARM representation---- --*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by the "Instituto Nokia de Tecnologia" and
+// is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the entry points for global functions defined in the LLVM
+// ARM back-end.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef TARGET_ARM_H
+#define TARGET_ARM_H
+
+#include <iosfwd>
+#include <cassert>
+
+namespace llvm {
+  class FunctionPass;
+  class TargetMachine;
+
+  FunctionPass *createARMISelDag(TargetMachine &TM);
+  FunctionPass *createARMCodePrinterPass(std::ostream &OS, TargetMachine &TM);
+} // end namespace llvm;
+
+// Defines symbolic names for ARM registers.  This defines a mapping from
+// register name to register number.
+//
+#include "ARMGenRegisterNames.inc"
+
+// Defines symbolic names for the ARM instructions.
+//
+#include "ARMGenInstrNames.inc"
+
+
+#endif
diff --git a/lib/Target/ARM/ARM.td b/lib/Target/ARM/ARM.td
new file mode 100644 (file)
index 0000000..a7b7e6e
--- /dev/null
@@ -0,0 +1,51 @@
+//===- ARM.td - Describe the ARM Target Machine -----------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by the "Instituto Nokia de Tecnologia" and
+// is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// Target-independent interfaces which we are implementing
+//===----------------------------------------------------------------------===//
+
+include "../Target.td"
+
+//===----------------------------------------------------------------------===//
+// Register File Description
+//===----------------------------------------------------------------------===//
+
+include "ARMRegisterInfo.td"
+
+//===----------------------------------------------------------------------===//
+// Instruction Descriptions
+//===----------------------------------------------------------------------===//
+
+include "ARMInstrInfo.td"
+
+def ARMInstrInfo : InstrInfo {
+  // Define how we want to layout our target-specific information field.
+  let TSFlagsFields = [];
+  let TSFlagsShifts = [];
+}
+
+//===----------------------------------------------------------------------===//
+// Declare the target which we are implementing
+//===----------------------------------------------------------------------===//
+
+def ARM : Target {
+  // Pointers are 32-bits in size.
+  let PointerType = i32;
+
+  // FIXME: Specify callee-saved registers
+  let CalleeSavedRegisters = [];
+
+  // Pull in Instruction Info:
+  let InstructionSet = ARMInstrInfo;
+}
diff --git a/lib/Target/ARM/ARMAsmPrinter.cpp b/lib/Target/ARM/ARMAsmPrinter.cpp
new file mode 100644 (file)
index 0000000..612540d
--- /dev/null
@@ -0,0 +1,115 @@
+//===-- ARMAsmPrinter.cpp - ARM LLVM assembly writer ----------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by the "Instituto Nokia de Tecnologia" and
+// is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains a printer that converts from our internal representation
+// of machine-dependent LLVM code to GAS-format ARM assembly language.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ARM.h"
+#include "ARMInstrInfo.h"
+#include "llvm/Constants.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/Module.h"
+#include "llvm/Assembly/Writer.h"
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineConstantPool.h"
+#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Support/Mangler.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/MathExtras.h"
+#include <cctype>
+#include <iostream>
+using namespace llvm;
+
+namespace {
+  Statistic<> EmittedInsts("asm-printer", "Number of machine instrs printed");
+
+  struct ARMAsmPrinter : public AsmPrinter {
+    ARMAsmPrinter(std::ostream &O, TargetMachine &TM) : AsmPrinter(O, TM) {
+      Data16bitsDirective = "\t.half\t";
+      Data32bitsDirective = "\t.word\t";
+      Data64bitsDirective = 0;
+      ZeroDirective = "\t.skip\t";
+      CommentString = "!";
+      ConstantPoolSection = "\t.section \".rodata\",#alloc\n";
+    }
+
+    /// We name each basic block in a Function with a unique number, so
+    /// that we can consistently refer to them later. This is cleared
+    /// at the beginning of each call to runOnMachineFunction().
+    ///
+    typedef std::map<const Value *, unsigned> ValueMapTy;
+    ValueMapTy NumberForBB;
+
+    virtual const char *getPassName() const {
+      return "ARM Assembly Printer";
+    }
+
+    void printOperand(const MachineInstr *MI, int opNum);
+    void printMemOperand(const MachineInstr *MI, int opNum,
+                         const char *Modifier = 0);
+    void printCCOperand(const MachineInstr *MI, int opNum);
+
+    bool printInstruction(const MachineInstr *MI);  // autogenerated.
+    bool runOnMachineFunction(MachineFunction &F);
+    bool doInitialization(Module &M);
+    bool doFinalization(Module &M);
+  };
+} // end of anonymous namespace
+
+#include "ARMGenAsmWriter.inc"
+
+/// createARMCodePrinterPass - Returns a pass that prints the ARM
+/// assembly code for a MachineFunction to the given output stream,
+/// using the given target machine description.  This should work
+/// regardless of whether the function is in SSA form.
+///
+FunctionPass *llvm::createARMCodePrinterPass(std::ostream &o,
+                                               TargetMachine &tm) {
+  return new ARMAsmPrinter(o, tm);
+}
+
+/// runOnMachineFunction - This uses the printMachineInstruction()
+/// method to print assembly for each instruction.
+///
+bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
+  assert(0 && "not implemented");
+  // We didn't modify anything.
+  return false;
+}
+
+void ARMAsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
+  assert(0 && "not implemented");
+}
+
+void ARMAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum,
+                                      const char *Modifier) {
+  assert(0 && "not implemented");
+}
+
+void ARMAsmPrinter::printCCOperand(const MachineInstr *MI, int opNum) {
+  assert(0 && "not implemented");
+}
+
+bool ARMAsmPrinter::doInitialization(Module &M) {
+  Mang = new Mangler(M);
+  return false; // success
+}
+
+bool ARMAsmPrinter::doFinalization(Module &M) {
+  assert(0 && "not implemented");
+  AsmPrinter::doFinalization(M);
+  return false; // success
+}
diff --git a/lib/Target/ARM/ARMISelDAGToDAG.cpp b/lib/Target/ARM/ARMISelDAGToDAG.cpp
new file mode 100644 (file)
index 0000000..f7611b6
--- /dev/null
@@ -0,0 +1,137 @@
+//===-- 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 <iostream>
+#include <set>
+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<SDOperand, SDOperand>
+      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<SDOperand, SDOperand>
+ARMTargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy,
+                                 bool isVarArg, unsigned CC,
+                                 bool isTailCall, SDOperand Callee,
+                                 ArgListTy &Args, SelectionDAG &DAG) {
+  assert(0 && "Not implemented");
+}
+
+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!");
+  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);
+}
diff --git a/lib/Target/ARM/ARMInstrInfo.cpp b/lib/Target/ARM/ARMInstrInfo.cpp
new file mode 100644 (file)
index 0000000..2ae23c7
--- /dev/null
@@ -0,0 +1,58 @@
+//===- ARMInstrInfo.cpp - ARM Instruction Information -----------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by the "Instituto Nokia de Tecnologia" and
+// is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the ARM implementation of the TargetInstrInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ARMInstrInfo.h"
+#include "ARM.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "ARMGenInstrInfo.inc"
+using namespace llvm;
+
+ARMInstrInfo::ARMInstrInfo()
+  : TargetInstrInfo(ARMInsts, sizeof(ARMInsts)/sizeof(ARMInsts[0])) {
+}
+
+/// Return true if the instruction is a register to register move and
+/// leave the source and dest operands in the passed parameters.
+///
+bool ARMInstrInfo::isMoveInstr(const MachineInstr &MI,
+                                 unsigned &SrcReg, unsigned &DstReg) const {
+  // We look for 3 kinds of patterns here:
+  // or with G0 or 0
+  // add with G0 or 0
+  // fmovs or FpMOVD (pseudo double move).
+  assert(0 && "not implemented");
+  return false;
+}
+
+/// isLoadFromStackSlot - If the specified machine instruction is a direct
+/// load from a stack slot, return the virtual or physical register number of
+/// the destination along with the FrameIndex of the loaded stack slot.  If
+/// not, return 0.  This predicate must return 0 if the instruction has
+/// any side effects other than loading from the stack slot.
+unsigned ARMInstrInfo::isLoadFromStackSlot(MachineInstr *MI,
+                                             int &FrameIndex) const {
+  assert(0 && "not implemented");
+  return 0;
+}
+
+/// isStoreToStackSlot - If the specified machine instruction is a direct
+/// store to a stack slot, return the virtual or physical register number of
+/// the source reg along with the FrameIndex of the loaded stack slot.  If
+/// not, return 0.  This predicate must return 0 if the instruction has
+/// any side effects other than storing to the stack slot.
+unsigned ARMInstrInfo::isStoreToStackSlot(MachineInstr *MI,
+                                            int &FrameIndex) const {
+  assert(0 && "not implemented");
+  return 0;
+}
diff --git a/lib/Target/ARM/ARMInstrInfo.h b/lib/Target/ARM/ARMInstrInfo.h
new file mode 100644 (file)
index 0000000..b203b22
--- /dev/null
@@ -0,0 +1,57 @@
+//===- ARMInstrInfo.h - ARM Instruction Information --------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by the "Instituto Nokia de Tecnologia" and
+// is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the ARM implementation of the TargetInstrInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef ARMINSTRUCTIONINFO_H
+#define ARMINSTRUCTIONINFO_H
+
+#include "llvm/Target/TargetInstrInfo.h"
+#include "ARMRegisterInfo.h"
+
+namespace llvm {
+
+class ARMInstrInfo : public TargetInstrInfo {
+  const ARMRegisterInfo RI;
+public:
+  ARMInstrInfo();
+
+  /// getRegisterInfo - TargetInstrInfo is a superset of MRegister info.  As
+  /// such, whenever a client has an instance of instruction info, it should
+  /// always be able to get register info as well (through this method).
+  ///
+  virtual const MRegisterInfo &getRegisterInfo() const { return RI; }
+
+  /// Return true if the instruction is a register to register move and
+  /// leave the source and dest operands in the passed parameters.
+  ///
+  virtual bool isMoveInstr(const MachineInstr &MI,
+                           unsigned &SrcReg, unsigned &DstReg) const;
+
+  /// isLoadFromStackSlot - If the specified machine instruction is a direct
+  /// load from a stack slot, return the virtual or physical register number of
+  /// the destination along with the FrameIndex of the loaded stack slot.  If
+  /// not, return 0.  This predicate must return 0 if the instruction has
+  /// any side effects other than loading from the stack slot.
+  virtual unsigned isLoadFromStackSlot(MachineInstr *MI, int &FrameIndex) const;
+
+  /// isStoreToStackSlot - If the specified machine instruction is a direct
+  /// store to a stack slot, return the virtual or physical register number of
+  /// the source reg along with the FrameIndex of the loaded stack slot.  If
+  /// not, return 0.  This predicate must return 0 if the instruction has
+  /// any side effects other than storing to the stack slot.
+  virtual unsigned isStoreToStackSlot(MachineInstr *MI, int &FrameIndex) const;
+};
+
+}
+
+#endif
diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td
new file mode 100644 (file)
index 0000000..318c230
--- /dev/null
@@ -0,0 +1,54 @@
+//===- ARMInstrInfo.td - Target Description for ARM Target ----------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by the "Instituto Nokia de Tecnologia" and
+// is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file describes the ARM instructions in TableGen format.
+//
+//===----------------------------------------------------------------------===//
+
+
+
+//===----------------------------------------------------------------------===//
+// Instructions
+//===----------------------------------------------------------------------===//
+
+class InstARM<dag ops, string asmstr, list<dag> pattern> : Instruction {
+  let Namespace = "ARM";
+
+  dag OperandList = ops;
+  let AsmString   = asmstr;
+  let Pattern = pattern;
+}
+
+def SDT_ARMCallSeq : SDTypeProfile<0, 1, [ SDTCisVT<0, i32> ]>;
+def callseq_start  : SDNode<"ISD::CALLSEQ_START", SDT_ARMCallSeq, [SDNPHasChain]>;
+def callseq_end    : SDNode<"ISD::CALLSEQ_END",   SDT_ARMCallSeq, [SDNPHasChain]>;
+
+def SDT_ARMRetFlag : SDTypeProfile<0, 0, []>;
+def retflag        : SDNode<"ARMISD::RET_FLAG", SDT_ARMRetFlag,
+                           [SDNPHasChain, SDNPOptInFlag]>;
+
+def ADJCALLSTACKUP : InstARM<(ops i32imm:$amt),
+                            "!ADJCALLSTACKUP $amt",
+                            [(callseq_end imm:$amt)]>;
+
+def ADJCALLSTACKDOWN : InstARM<(ops i32imm:$amt),
+                               "!ADJCALLSTACKDOWN $amt",
+                               [(callseq_start imm:$amt)]>;
+
+def ldr   : InstARM<(ops IntRegs:$dst, IntRegs:$addr),
+                     "ldr $dst, [$addr]",
+                     [(set IntRegs:$dst, (load IntRegs:$addr))]>;
+
+def str  : InstARM<(ops IntRegs:$src, IntRegs:$addr),
+                    "str $src, [$addr]",
+                    [(store IntRegs:$src, IntRegs:$addr)]>;
+
+def mov   : InstARM<(ops IntRegs:$dst, IntRegs:$b),
+                    "mov $dst, $b", []>;
diff --git a/lib/Target/ARM/ARMRegisterInfo.cpp b/lib/Target/ARM/ARMRegisterInfo.cpp
new file mode 100644 (file)
index 0000000..db5ce68
--- /dev/null
@@ -0,0 +1,91 @@
+//===- ARMRegisterInfo.cpp - ARM Register Information -----------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by the "Instituto Nokia de Tecnologia" and
+// is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the ARM implementation of the MRegisterInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ARM.h"
+#include "ARMRegisterInfo.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineFrameInfo.h"
+#include "llvm/CodeGen/MachineLocation.h"
+#include "llvm/Type.h"
+#include "llvm/ADT/STLExtras.h"
+#include <iostream>
+using namespace llvm;
+
+ARMRegisterInfo::ARMRegisterInfo()
+  : ARMGenRegisterInfo(ARM::ADJCALLSTACKDOWN, ARM::ADJCALLSTACKUP) {
+}
+
+void ARMRegisterInfo::
+storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
+                    unsigned SrcReg, int FI,
+                    const TargetRegisterClass *RC) const {
+  // On the order of operands here: think "[FI + 0] = SrcReg".
+  assert (RC == ARM::IntRegsRegisterClass);
+  BuildMI(MBB, I, ARM::str, 3).addFrameIndex(FI).addImm(0).addReg(SrcReg);
+}
+
+void ARMRegisterInfo::
+loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
+                     unsigned DestReg, int FI,
+                     const TargetRegisterClass *RC) const {
+  assert (RC == ARM::IntRegsRegisterClass);
+  BuildMI(MBB, I, ARM::ldr, 2, DestReg).addFrameIndex(FI).addImm(0);
+}
+
+void ARMRegisterInfo::copyRegToReg(MachineBasicBlock &MBB,
+                                     MachineBasicBlock::iterator I,
+                                     unsigned DestReg, unsigned SrcReg,
+                                     const TargetRegisterClass *RC) const {
+  assert (RC == ARM::IntRegsRegisterClass);
+  BuildMI(MBB, I, ARM::mov, 1, DestReg).addReg(SrcReg);
+}
+
+MachineInstr *ARMRegisterInfo::foldMemoryOperand(MachineInstr* MI,
+                                                   unsigned OpNum,
+                                                   int FI) const {
+  return NULL;
+}
+
+void ARMRegisterInfo::
+eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
+                              MachineBasicBlock::iterator I) const {
+  MBB.erase(I);
+}
+
+void
+ARMRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II) const {
+  assert(0 && "Not Implemented");
+}
+
+void ARMRegisterInfo::
+processFunctionBeforeFrameFinalized(MachineFunction &MF) const {}
+
+void ARMRegisterInfo::emitPrologue(MachineFunction &MF) const {
+}
+
+void ARMRegisterInfo::emitEpilogue(MachineFunction &MF,
+                                  MachineBasicBlock &MBB) const {
+}
+
+unsigned ARMRegisterInfo::getRARegister() const {
+  return ARM::R14;
+}
+
+unsigned ARMRegisterInfo::getFrameRegister(MachineFunction &MF) const {
+  return ARM::R13;
+}
+
+#include "ARMGenRegisterInfo.inc"
+
diff --git a/lib/Target/ARM/ARMRegisterInfo.h b/lib/Target/ARM/ARMRegisterInfo.h
new file mode 100644 (file)
index 0000000..a2fa7b9
--- /dev/null
@@ -0,0 +1,66 @@
+//===- ARMRegisterInfo.h - ARM Register Information Impl --------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by the "Instituto Nokia de Tecnologia" and
+// is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the ARM implementation of the MRegisterInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef ARMREGISTERINFO_H
+#define ARMREGISTERINFO_H
+
+#include "llvm/Target/MRegisterInfo.h"
+#include "ARMGenRegisterInfo.h.inc"
+
+namespace llvm {
+
+class Type;
+
+struct ARMRegisterInfo : public ARMGenRegisterInfo {
+
+  ARMRegisterInfo();
+
+  /// Code Generation virtual methods...
+  void storeRegToStackSlot(MachineBasicBlock &MBB,
+                           MachineBasicBlock::iterator MBBI,
+                           unsigned SrcReg, int FrameIndex,
+                           const TargetRegisterClass *RC) const;
+
+  void loadRegFromStackSlot(MachineBasicBlock &MBB,
+                            MachineBasicBlock::iterator MBBI,
+                            unsigned DestReg, int FrameIndex,
+                            const TargetRegisterClass *RC) const;
+
+  void copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
+                    unsigned DestReg, unsigned SrcReg,
+                    const TargetRegisterClass *RC) const;
+
+  virtual MachineInstr* foldMemoryOperand(MachineInstr* MI,
+                                          unsigned OpNum,
+                                          int FrameIndex) const;
+
+  void eliminateCallFramePseudoInstr(MachineFunction &MF,
+                                     MachineBasicBlock &MBB,
+                                     MachineBasicBlock::iterator I) const;
+
+  void eliminateFrameIndex(MachineBasicBlock::iterator II) const;
+
+  void processFunctionBeforeFrameFinalized(MachineFunction &MF) const;
+
+  void emitPrologue(MachineFunction &MF) const;
+  void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
+
+  // Debug information queries.
+  unsigned getRARegister() const;
+  unsigned getFrameRegister(MachineFunction &MF) const;
+};
+
+} // end namespace llvm
+
+#endif
diff --git a/lib/Target/ARM/ARMRegisterInfo.td b/lib/Target/ARM/ARMRegisterInfo.td
new file mode 100644 (file)
index 0000000..e53ab8b
--- /dev/null
@@ -0,0 +1,56 @@
+//===- ARMRegisterInfo.td - ARM Register defs ----------*- tablegen -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by the "Instituto Nokia de Tecnologia" and
+// is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+//  Declarations that describe the ARM register file
+//===----------------------------------------------------------------------===//
+
+// Registers are identified with 4-bit ID numbers.
+class ARMReg<bits<4> num, string n> : Register<n> {
+  field bits<4> Num;
+  let Namespace = "ARM";
+}
+
+// Integer registers
+def R0  : ARMReg< 0, "R0">,  DwarfRegNum<0>;
+def R1  : ARMReg< 1, "R1">,  DwarfRegNum<1>;
+def R2  : ARMReg< 2, "R2">,  DwarfRegNum<2>;
+def R3  : ARMReg< 3, "R3">,  DwarfRegNum<3>;
+def R4  : ARMReg< 4, "R4">,  DwarfRegNum<4>;
+def R5  : ARMReg< 5, "R5">,  DwarfRegNum<5>;
+def R6  : ARMReg< 6, "R6">,  DwarfRegNum<6>;
+def R7  : ARMReg< 7, "R7">,  DwarfRegNum<7>;
+def R8  : ARMReg< 8, "R8">,  DwarfRegNum<8>;
+def R9  : ARMReg< 9, "R9">,  DwarfRegNum<9>;
+def R10 : ARMReg<10, "R10">, DwarfRegNum<10>;
+def R11 : ARMReg<11, "R11">, DwarfRegNum<11>;
+def R12 : ARMReg<12, "R12">, DwarfRegNum<12>;
+def R13 : ARMReg<13, "R13">, DwarfRegNum<13>;
+def R14 : ARMReg<14, "R14">, DwarfRegNum<14>;
+def R15 : ARMReg<15, "R15">, DwarfRegNum<15>;
+
+// Register classes.
+//
+// FIXME: the register order should be defined in terms of the preferred
+// allocation order...
+//
+def IntRegs : RegisterClass<"ARM", [i32], 32, [R0, R1, R2, R3, R4, R5, R6,
+                                              R7, R8, R9, R10, R11, R12,
+                                               R13, R14, R15]> {
+  let MethodProtos = [{
+    iterator allocation_order_end(MachineFunction &MF) const;
+  }];
+  let MethodBodies = [{
+    IntRegsClass::iterator
+    IntRegsClass::allocation_order_end(MachineFunction &MF) const {
+      return end() - 1;
+    }
+  }];
+}
diff --git a/lib/Target/ARM/ARMTargetMachine.cpp b/lib/Target/ARM/ARMTargetMachine.cpp
new file mode 100644 (file)
index 0000000..7520cdc
--- /dev/null
@@ -0,0 +1,99 @@
+//===-- ARMTargetMachine.cpp - Define TargetMachine for ARM ---------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by the "Instituto Nokia de Tecnologia" and
+// is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//
+//===----------------------------------------------------------------------===//
+
+#include "ARMTargetMachine.h"
+#include "ARM.h"
+#include "llvm/Assembly/PrintModulePass.h"
+#include "llvm/Module.h"
+#include "llvm/PassManager.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/Target/TargetOptions.h"
+#include "llvm/Target/TargetMachineRegistry.h"
+#include "llvm/Transforms/Scalar.h"
+#include <iostream>
+using namespace llvm;
+
+namespace {
+  // Register the target.
+  RegisterTarget<ARMTargetMachine> X("arm", "  ARM");
+}
+
+/// TargetMachine ctor - Create an ILP32 architecture model
+///
+ARMTargetMachine::ARMTargetMachine(const Module &M, const std::string &FS)
+  : TargetMachine("ARM"),
+    DataLayout("ARM", false, 4, 4),
+    InstrInfo(),
+    FrameInfo(TargetFrameInfo::StackGrowsDown, 8, 0) {
+}
+
+unsigned ARMTargetMachine::getModuleMatchQuality(const Module &M) {
+  std::string TT = M.getTargetTriple();
+  if (TT.size() >= 4 && std::string(TT.begin(), TT.begin()+4) == "arm-")
+    return 20;
+
+  if (M.getPointerSize() == Module::Pointer32)
+    return 1;
+  else
+    return 0;
+}
+
+/// addPassesToEmitFile - Add passes to the specified pass manager
+/// to implement a static compiler for this target.
+///
+bool ARMTargetMachine::addPassesToEmitFile(PassManager &PM, std::ostream &Out,
+                                             CodeGenFileType FileType,
+                                             bool Fast) {
+  if (FileType != TargetMachine::AssemblyFile)
+    return true;
+
+  // Run loop strength reduction before anything else.
+  if (!Fast)
+    PM.add(createLoopStrengthReducePass());
+
+  // FIXME: Implement efficient support for garbage collection intrinsics.
+  PM.add(createLowerGCPass());
+
+  // FIXME: implement the invoke/unwind instructions!
+  PM.add(createLowerInvokePass());
+
+  // Print LLVM code input to instruction selector:
+  if (PrintMachineCode)
+    PM.add(new PrintFunctionPass());
+
+  // Make sure that no unreachable blocks are instruction selected.
+  PM.add(createUnreachableBlockEliminationPass());
+
+  PM.add(createARMISelDag(*this));
+
+  // Print machine instructions as they were initially generated.
+  if (PrintMachineCode)
+    PM.add(createMachineFunctionPrinterPass(&std::cerr));
+
+  PM.add(createRegisterAllocator());
+  PM.add(createPrologEpilogCodeInserter());
+
+  // Print machine instructions after register allocation and prolog/epilog
+  // insertion.
+  if (PrintMachineCode)
+    PM.add(createMachineFunctionPrinterPass(&std::cerr));
+
+  // Output assembly language.
+  PM.add(createARMCodePrinterPass(Out, *this));
+
+  // Delete the MachineInstrs we generated, since they're no longer needed.
+  PM.add(createMachineCodeDeleter());
+  return false;
+}
+
diff --git a/lib/Target/ARM/ARMTargetMachine.h b/lib/Target/ARM/ARMTargetMachine.h
new file mode 100644 (file)
index 0000000..97d1f22
--- /dev/null
@@ -0,0 +1,49 @@
+//===-- ARMTargetMachine.h - Define TargetMachine for ARM -------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by the "Instituto Nokia de Tecnologia" and
+// is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the ARM specific subclass of TargetMachine.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef ARMTARGETMACHINE_H
+#define ARMTARGETMACHINE_H
+
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Target/TargetFrameInfo.h"
+#include "llvm/PassManager.h"
+#include "ARMInstrInfo.h"
+
+namespace llvm {
+
+class Module;
+
+class ARMTargetMachine : public TargetMachine {
+  const TargetData DataLayout;       // Calculates type size & alignment
+  ARMInstrInfo InstrInfo;
+  TargetFrameInfo FrameInfo;
+public:
+  ARMTargetMachine(const Module &M, const std::string &FS);
+
+  virtual const ARMInstrInfo *getInstrInfo() const { return &InstrInfo; }
+  virtual const TargetFrameInfo  *getFrameInfo() const { return &FrameInfo; }
+  virtual const MRegisterInfo *getRegisterInfo() const {
+    return &InstrInfo.getRegisterInfo();
+  }
+  virtual const TargetData       *getTargetData() const { return &DataLayout; }
+  static unsigned getModuleMatchQuality(const Module &M);
+
+  virtual bool addPassesToEmitFile(PassManager &PM, std::ostream &Out,
+                                   CodeGenFileType FileType, bool Fast);
+};
+
+} // end namespace llvm
+
+#endif
diff --git a/lib/Target/ARM/Makefile b/lib/Target/ARM/Makefile
new file mode 100644 (file)
index 0000000..4310b8c
--- /dev/null
@@ -0,0 +1,21 @@
+##===- lib/Target/ARM/Makefile -----------------------------*- Makefile -*-===##
+#
+#                     The LLVM Compiler Infrastructure
+#
+# This file was developed by the "Instituto Nokia de Tecnologia" and
+# is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+LEVEL = ../../..
+LIBRARYNAME = LLVMARM
+TARGET = ARM
+
+# Make sure that tblgen is run, first thing.
+BUILT_SOURCES = ARMGenRegisterInfo.h.inc ARMGenRegisterNames.inc \
+                ARMGenRegisterInfo.inc ARMGenInstrNames.inc \
+                ARMGenInstrInfo.inc ARMGenAsmWriter.inc \
+                ARMGenDAGISel.inc
+
+include $(LEVEL)/Makefile.common
+
index d4277159a7c52b25102c26eeea2a84b24edab69a..ed48accf2beadc0bfb0003de7e931eb6194a574e 100644 (file)
@@ -48,6 +48,11 @@ ifneq ($(strip $(filter IA64,$(TARGETS_TO_BUILD))),)
 USEDLIBS += LLVMIA64
 endif
 
+#Check for ARM Target
+ifneq ($(strip $(filter ARM,$(TARGETS_TO_BUILD))),)
+USEDLIBS += LLVMARM
+endif
+
 USEDLIBS += \
        LLVMSelectionDAG \
        LLVMCodeGen \