From 7bc59bc3952ad7842b1e079753deb32217a768a3 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Sun, 14 May 2006 22:18:28 +0000 Subject: [PATCH] added a skeleton of the ARM backend git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@28301 91177308-0d34-0410-b5e6-96231b3b80d8 --- autoconf/configure.ac | 2 +- configure | 2 +- lib/Target/ARM/ARM.h | 40 ++++++++ lib/Target/ARM/ARM.td | 51 +++++++++++ lib/Target/ARM/ARMAsmPrinter.cpp | 115 +++++++++++++++++++++++ lib/Target/ARM/ARMISelDAGToDAG.cpp | 137 ++++++++++++++++++++++++++++ lib/Target/ARM/ARMInstrInfo.cpp | 58 ++++++++++++ lib/Target/ARM/ARMInstrInfo.h | 57 ++++++++++++ lib/Target/ARM/ARMInstrInfo.td | 54 +++++++++++ lib/Target/ARM/ARMRegisterInfo.cpp | 91 ++++++++++++++++++ lib/Target/ARM/ARMRegisterInfo.h | 66 ++++++++++++++ lib/Target/ARM/ARMRegisterInfo.td | 56 ++++++++++++ lib/Target/ARM/ARMTargetMachine.cpp | 99 ++++++++++++++++++++ lib/Target/ARM/ARMTargetMachine.h | 49 ++++++++++ lib/Target/ARM/Makefile | 21 +++++ tools/llc/Makefile | 5 + 16 files changed, 901 insertions(+), 2 deletions(-) create mode 100644 lib/Target/ARM/ARM.h create mode 100644 lib/Target/ARM/ARM.td create mode 100644 lib/Target/ARM/ARMAsmPrinter.cpp create mode 100644 lib/Target/ARM/ARMISelDAGToDAG.cpp create mode 100644 lib/Target/ARM/ARMInstrInfo.cpp create mode 100644 lib/Target/ARM/ARMInstrInfo.h create mode 100644 lib/Target/ARM/ARMInstrInfo.td create mode 100644 lib/Target/ARM/ARMRegisterInfo.cpp create mode 100644 lib/Target/ARM/ARMRegisterInfo.h create mode 100644 lib/Target/ARM/ARMRegisterInfo.td create mode 100644 lib/Target/ARM/ARMTargetMachine.cpp create mode 100644 lib/Target/ARM/ARMTargetMachine.h create mode 100644 lib/Target/ARM/Makefile diff --git a/autoconf/configure.ac b/autoconf/configure.ac index 3917db0a104..b29ce31f964 100644 --- a/autoconf/configure.ac +++ b/autoconf/configure.ac @@ -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" ;; diff --git a/configure b/configure index 351cdd540b7..b235fcd95c0 100755 --- 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 index 00000000000..167d71eab67 --- /dev/null +++ b/lib/Target/ARM/ARM.h @@ -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 +#include + +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 index 00000000000..a7b7e6ed603 --- /dev/null +++ b/lib/Target/ARM/ARM.td @@ -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 index 00000000000..612540d13ef --- /dev/null +++ b/lib/Target/ARM/ARMAsmPrinter.cpp @@ -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 +#include +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 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 index 00000000000..f7611b65d1e --- /dev/null +++ b/lib/Target/ARM/ARMISelDAGToDAG.cpp @@ -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 +#include +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 + 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 +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 index 00000000000..2ae23c78739 --- /dev/null +++ b/lib/Target/ARM/ARMInstrInfo.cpp @@ -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 index 00000000000..b203b2235f0 --- /dev/null +++ b/lib/Target/ARM/ARMInstrInfo.h @@ -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 index 00000000000..318c230586b --- /dev/null +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -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 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 index 00000000000..db5ce68f4be --- /dev/null +++ b/lib/Target/ARM/ARMRegisterInfo.cpp @@ -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 +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 index 00000000000..a2fa7b9af0d --- /dev/null +++ b/lib/Target/ARM/ARMRegisterInfo.h @@ -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 index 00000000000..e53ab8bfe7e --- /dev/null +++ b/lib/Target/ARM/ARMRegisterInfo.td @@ -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 num, string n> : Register { + 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 index 00000000000..7520cdc5e8b --- /dev/null +++ b/lib/Target/ARM/ARMTargetMachine.cpp @@ -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 +using namespace llvm; + +namespace { + // Register the target. + RegisterTarget 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 index 00000000000..97d1f22d0c9 --- /dev/null +++ b/lib/Target/ARM/ARMTargetMachine.h @@ -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 index 00000000000..4310b8c8e4f --- /dev/null +++ b/lib/Target/ARM/Makefile @@ -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 + diff --git a/tools/llc/Makefile b/tools/llc/Makefile index d4277159a7c..ed48accf2be 100644 --- a/tools/llc/Makefile +++ b/tools/llc/Makefile @@ -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 \ -- 2.34.1