[Sparc] Add initial implementation of MC Code emitter for sparc.
authorVenkatraman Govindaraju <venkatra@cs.wisc.edu>
Sun, 5 Jan 2014 02:13:48 +0000 (02:13 +0000)
committerVenkatraman Govindaraju <venkatra@cs.wisc.edu>
Sun, 5 Jan 2014 02:13:48 +0000 (02:13 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@198533 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/Sparc/CMakeLists.txt
lib/Target/Sparc/MCTargetDesc/CMakeLists.txt
lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp [new file with mode: 0644]
lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h [new file with mode: 0644]
lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp [new file with mode: 0644]
lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp
lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h
lib/Target/Sparc/Makefile
lib/Target/Sparc/SparcCodeEmitter.cpp
lib/Target/Sparc/SparcInstrInfo.td
test/MC/Sparc/sparc-alu-instructions.s [new file with mode: 0644]

index 1795beee3b2bb8e165d75187f250f7d1cc89cc01..9fad0e85619ad071cbde568ce2ee8180045af9cf 100644 (file)
@@ -3,6 +3,7 @@ set(LLVM_TARGET_DEFINITIONS Sparc.td)
 tablegen(LLVM SparcGenRegisterInfo.inc -gen-register-info)
 tablegen(LLVM SparcGenInstrInfo.inc -gen-instr-info)
 tablegen(LLVM SparcGenCodeEmitter.inc -gen-emitter)
+tablegen(LLVM SparcGenMCCodeEmitter.inc -gen-emitter -mc-emitter)
 tablegen(LLVM SparcGenAsmWriter.inc -gen-asm-writer)
 tablegen(LLVM SparcGenAsmMatcher.inc -gen-asm-matcher)
 tablegen(LLVM SparcGenDAGISel.inc -gen-dag-isel)
index 3a40fcaba47e92468b4ea20a3070044fad9e964f..2619f9db26d4e62d505a9e46cf338c9c70f93c1f 100644 (file)
@@ -1,6 +1,8 @@
 add_llvm_library(LLVMSparcDesc
-  SparcMCTargetDesc.cpp
+  SparcAsmBackend.cpp
   SparcMCAsmInfo.cpp
+  SparcMCCodeEmitter.cpp
+  SparcMCTargetDesc.cpp
   SparcMCExpr.cpp
   SparcTargetStreamer.cpp
   )
diff --git a/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp b/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
new file mode 100644 (file)
index 0000000..e86b3c8
--- /dev/null
@@ -0,0 +1,101 @@
+//===-- SparcAsmBackend.cpp - Sparc Assembler Backend ---------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCAsmBackend.h"
+#include "MCTargetDesc/SparcMCTargetDesc.h"
+#include "MCTargetDesc/SparcFixupKinds.h"
+#include "llvm/MC/MCFixupKindInfo.h"
+#include "llvm/MC/MCObjectWriter.h"
+#include "llvm/Support/TargetRegistry.h"
+
+using namespace llvm;
+
+namespace {
+  class SparcAsmBackend : public MCAsmBackend {
+
+  public:
+    SparcAsmBackend(const Target &T) : MCAsmBackend() {}
+
+    unsigned getNumFixupKinds() const {
+      return Sparc::NumTargetFixupKinds;
+    }
+
+    const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const {
+      const static MCFixupKindInfo Infos[Sparc::NumTargetFixupKinds] = {
+        // name                    offset bits  flags
+        { "fixup_sparc_call30",     0,     30,  MCFixupKindInfo::FKF_IsPCRel },
+        { "fixup_sparc_br22",       0,     22,  MCFixupKindInfo::FKF_IsPCRel },
+        { "fixup_sparc_br19",       0,     19,  MCFixupKindInfo::FKF_IsPCRel }
+      };
+
+      if (Kind < FirstTargetFixupKind)
+        return MCAsmBackend::getFixupKindInfo(Kind);
+
+      assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
+             "Invalid kind!");
+      return Infos[Kind - FirstTargetFixupKind];
+    }
+
+    bool mayNeedRelaxation(const MCInst &Inst) const {
+      // FIXME.
+      return false;
+    }
+
+    /// fixupNeedsRelaxation - Target specific predicate for whether a given
+    /// fixup requires the associated instruction to be relaxed.
+    bool fixupNeedsRelaxation(const MCFixup &Fixup,
+                              uint64_t Value,
+                              const MCRelaxableFragment *DF,
+                              const MCAsmLayout &Layout) const {
+      // FIXME.
+      assert(0 && "fixupNeedsRelaxation() unimplemented");
+      return false;
+    }
+    void relaxInstruction(const MCInst &Inst, MCInst &Res) const {
+      // FIXME.
+      assert(0 && "relaxInstruction() unimplemented");
+    }
+
+    bool writeNopData(uint64_t Count, MCObjectWriter *OW) const {
+      // FIXME: Zero fill for now.
+      for (uint64_t i = 0; i != Count; ++i)
+        OW->Write8(0);
+      return true;
+    }
+  };
+
+  class ELFSparcAsmBackend : public SparcAsmBackend {
+  public:
+    ELFSparcAsmBackend(const Target &T, Triple::OSType OSType) :
+      SparcAsmBackend(T) { }
+
+    void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize,
+                    uint64_t Value) const {
+      assert(0 && "applyFixup not implemented yet");
+    }
+
+    MCObjectWriter *createObjectWriter(raw_ostream &OS) const {
+      assert(0 && "Object Writer not implemented yet");
+      return 0;
+    }
+
+    virtual bool doesSectionRequireSymbols(const MCSection &Section) const {
+      return false;
+    }
+  };
+
+} // end anonymous namespace
+
+
+MCAsmBackend *llvm::createSparcAsmBackend(const Target &T,
+                                          const MCRegisterInfo &MRI,
+                                          StringRef TT,
+                                          StringRef CPU) {
+  return new ELFSparcAsmBackend(T, Triple(TT).getOS());
+}
diff --git a/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h b/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h
new file mode 100644 (file)
index 0000000..1b56f12
--- /dev/null
@@ -0,0 +1,36 @@
+//===-- SparcFixupKinds.h - Sparc Specific Fixup Entries --------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SPARC_FIXUPKINDS_H
+#define LLVM_SPARC_FIXUPKINDS_H
+
+#include "llvm/MC/MCFixup.h"
+
+namespace llvm {
+  namespace Sparc {
+    enum Fixups {
+      // fixup_sparc_call30 - 30-bit PC relative relocation for call
+      fixup_sparc_call30 = FirstTargetFixupKind,
+
+      /// fixup_sparc_br22 - 22-bit PC relative relocation for
+      /// branches
+      fixup_sparc_br22,
+
+      /// fixup_sparc_br22 - 22-bit PC relative relocation for
+      /// branches on icc/xcc
+      fixup_sparc_br19,
+
+      // Marker
+      LastTargetFixupKind,
+      NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind
+    };
+  }
+}
+
+#endif
diff --git a/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp b/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp
new file mode 100644 (file)
index 0000000..641aed4
--- /dev/null
@@ -0,0 +1,131 @@
+//===-- SparcMCCodeEmitter.cpp - Convert Sparc code to machine code -------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the SparcMCCodeEmitter class.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "mccodeemitter"
+#include "SparcMCTargetDesc.h"
+#include "MCTargetDesc/SparcFixupKinds.h"
+#include "llvm/MC/MCCodeEmitter.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
+
+namespace {
+class SparcMCCodeEmitter : public MCCodeEmitter {
+  SparcMCCodeEmitter(const SparcMCCodeEmitter &) LLVM_DELETED_FUNCTION;
+  void operator=(const SparcMCCodeEmitter &) LLVM_DELETED_FUNCTION;
+  MCContext &Ctx;
+
+public:
+  SparcMCCodeEmitter(MCContext &ctx): Ctx(ctx) {}
+
+  ~SparcMCCodeEmitter() {}
+
+  void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
+                         SmallVectorImpl<MCFixup> &Fixups) const;
+
+  // getBinaryCodeForInstr - TableGen'erated function for getting the
+  // binary encoding for an instruction.
+  uint64_t getBinaryCodeForInstr(const MCInst &MI,
+                                 SmallVectorImpl<MCFixup> &Fixups) const;
+
+  /// getMachineOpValue - Return binary encoding of operand. If the machine
+  /// operand requires relocation, record the relocation and return zero.
+  unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,
+                             SmallVectorImpl<MCFixup> &Fixups) const;
+
+  unsigned getCallTargetOpValue(const MCInst &MI, unsigned OpNo,
+                             SmallVectorImpl<MCFixup> &Fixups) const;
+  unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
+                             SmallVectorImpl<MCFixup> &Fixups) const;
+
+};
+} // end anonymous namespace
+
+MCCodeEmitter *llvm::createSparcMCCodeEmitter(const MCInstrInfo &MCII,
+                                              const MCRegisterInfo &MRI,
+                                              const MCSubtargetInfo &STI,
+                                              MCContext &Ctx) {
+  return new SparcMCCodeEmitter(Ctx);
+}
+
+void SparcMCCodeEmitter::
+EncodeInstruction(const MCInst &MI, raw_ostream &OS,
+                  SmallVectorImpl<MCFixup> &Fixups) const {
+  unsigned Bits = getBinaryCodeForInstr(MI, Fixups);
+
+  // Output the constant in big endian byte order.
+  for (unsigned i = 0; i != 4; ++i) {
+    OS << (char)(Bits >> 24);
+    Bits <<= 8;
+  }
+
+  ++MCNumEmitted;  // Keep track of the # of mi's emitted.
+}
+
+
+unsigned SparcMCCodeEmitter::
+getMachineOpValue(const MCInst &MI, const MCOperand &MO,
+                  SmallVectorImpl<MCFixup> &Fixups) const {
+
+  if (MO.isReg())
+    return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
+
+  if (MO.isImm())
+    return MO.getImm();
+
+  assert(MO.isExpr());
+  const MCExpr *Expr = MO.getExpr();
+  int64_t Res;
+  if (Expr->EvaluateAsAbsolute(Res))
+    return Res;
+
+  assert(0 && "Unhandled expression!");
+  return 0;
+}
+
+unsigned SparcMCCodeEmitter::
+getCallTargetOpValue(const MCInst &MI, unsigned OpNo,
+                     SmallVectorImpl<MCFixup> &Fixups) const {
+  const MCOperand &MO = MI.getOperand(OpNo);
+  if (MO.isReg() || MO.isImm())
+    return getMachineOpValue(MI, MO, Fixups);
+
+  Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
+                                   (MCFixupKind)Sparc::fixup_sparc_call30));
+  return 0;
+}
+
+unsigned SparcMCCodeEmitter::
+getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
+                  SmallVectorImpl<MCFixup> &Fixups) const {
+  const MCOperand &MO = MI.getOperand(OpNo);
+  if (MO.isReg() || MO.isImm())
+    return getMachineOpValue(MI, MO, Fixups);
+
+  Sparc::Fixups fixup = Sparc::fixup_sparc_br22;
+  if (MI.getOpcode() == SP::BPXCC)
+    fixup = Sparc::fixup_sparc_br19;
+
+  Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
+                                   (MCFixupKind)fixup));
+  return 0;
+}
+
+#include "SparcGenMCCodeEmitter.inc"
index a98e240fe060e434135cf8b10f6ec339af68b0a6..0322ddcf4d0e2ee92c047154d80e4336bb090947 100644 (file)
@@ -136,6 +136,18 @@ extern "C" void LLVMInitializeSparcTargetMC() {
   TargetRegistry::RegisterMCSubtargetInfo(TheSparcV9Target,
                                           createSparcMCSubtargetInfo);
 
+  // Register the MC Code Emitter.
+  TargetRegistry::RegisterMCCodeEmitter(TheSparcTarget,
+                                        createSparcMCCodeEmitter);
+  TargetRegistry::RegisterMCCodeEmitter(TheSparcV9Target,
+                                        createSparcMCCodeEmitter);
+
+  //Register the asm backend.
+  TargetRegistry::RegisterMCAsmBackend(TheSparcTarget,
+                                       createSparcAsmBackend);
+  TargetRegistry::RegisterMCAsmBackend(TheSparcV9Target,
+                                       createSparcAsmBackend);
+
   TargetRegistry::RegisterAsmStreamer(TheSparcTarget,
                                       createMCAsmStreamer);
   TargetRegistry::RegisterAsmStreamer(TheSparcV9Target,
index cba775adb1a80fcf523f49dbacbaf58e3a335f79..5b3f7448ec9a94e0919427b14a3e716b72f8d978 100644 (file)
 #define SPARCMCTARGETDESC_H
 
 namespace llvm {
+class MCAsmBackend;
+class MCCodeEmitter;
+class MCContext;
+class MCInstrInfo;
+class MCRegisterInfo;
+class MCSubtargetInfo;
 class Target;
+class StringRef;
 
 extern Target TheSparcTarget;
 extern Target TheSparcV9Target;
 
+MCCodeEmitter *createSparcMCCodeEmitter(const MCInstrInfo &MCII,
+                                        const MCRegisterInfo &MRI,
+                                        const MCSubtargetInfo &STI,
+                                        MCContext &Ctx);
+MCAsmBackend *createSparcAsmBackend(const Target &T,
+                                    const MCRegisterInfo &MRI,
+                                    StringRef TT,
+                                    StringRef CPU);
+
 } // End llvm namespace
 
 // Defines symbolic names for Sparc registers.  This defines a mapping from
index 6b563e907e7b0293eb96b5923d43eb42d7daad6a..94a8dd01d47e3d5c8d8863b3de5b655c9dfbb482 100644 (file)
@@ -16,7 +16,7 @@ BUILT_SOURCES = SparcGenRegisterInfo.inc SparcGenInstrInfo.inc \
                SparcGenAsmWriter.inc SparcGenAsmMatcher.inc \
                SparcGenDAGISel.inc \
                SparcGenSubtargetInfo.inc SparcGenCallingConv.inc \
-               SparcGenCodeEmitter.inc
+               SparcGenCodeEmitter.inc SparcGenMCCodeEmitter.inc
 
 DIRS = InstPrinter AsmParser TargetInfo MCTargetDesc
 
index 9bfe31fe496928af651d312b0aa199d666899ed4..f4a2c739494cebce75f3132a97029384e6ace800 100644 (file)
@@ -72,6 +72,11 @@ private:
   unsigned getMachineOpValue(const MachineInstr &MI,
                              const MachineOperand &MO) const;
 
+  unsigned getCallTargetOpValue(const MachineInstr &MI,
+                                unsigned) const;
+  unsigned getBranchTargetOpValue(const MachineInstr &MI,
+                                  unsigned) const;
+
   void emitWord(unsigned Word);
 
   unsigned getRelocation(const MachineInstr &MI,
@@ -181,6 +186,18 @@ unsigned SparcCodeEmitter::getMachineOpValue(const MachineInstr &MI,
     llvm_unreachable("Unable to encode MachineOperand!");
   return 0;
 }
+unsigned SparcCodeEmitter::getCallTargetOpValue(const MachineInstr &MI,
+                                                unsigned opIdx) const {
+  const MachineOperand MO = MI.getOperand(opIdx);
+  return getMachineOpValue(MI, MO);
+}
+
+unsigned SparcCodeEmitter::getBranchTargetOpValue(const MachineInstr &MI,
+                                                  unsigned opIdx) const {
+  const MachineOperand MO = MI.getOperand(opIdx);
+  return getMachineOpValue(MI, MO);
+}
+
 unsigned SparcCodeEmitter::getRelocation(const MachineInstr &MI,
                                          const MachineOperand &MO) const {
 
index d3c8e4ad7885d528a0d5d1e705ed80af938c2c42..43d9bc953144e8f1374bd00abde516b4868962e9 100644 (file)
@@ -100,8 +100,13 @@ def MEMri : Operand<iPTR> {
 def TLSSym : Operand<iPTR>;
 
 // Branch targets have OtherVT type.
-def brtarget : Operand<OtherVT>;
-def calltarget : Operand<i32>;
+def brtarget : Operand<OtherVT> {
+  let EncoderMethod = "getBranchTargetOpValue";
+}
+
+def calltarget : Operand<i32> {
+  let EncoderMethod = "getCallTargetOpValue";
+}
 
 // Operand for printing out a condition code.
 let PrintMethod = "printCCOperand" in
diff --git a/test/MC/Sparc/sparc-alu-instructions.s b/test/MC/Sparc/sparc-alu-instructions.s
new file mode 100644 (file)
index 0000000..393b5df
--- /dev/null
@@ -0,0 +1,72 @@
+! RUN: llvm-mc %s -arch=sparc   -show-encoding | FileCheck %s
+! RUN: llvm-mc %s -arch=sparcv9 -show-encoding | FileCheck %s
+
+        ! CHECK: add %g0, %g0, %g0    ! encoding: [0x80,0x00,0x00,0x00]
+        add %g0, %g0, %g0
+        ! CHECK: add %g1, %g2, %g3    ! encoding: [0x86,0x00,0x40,0x02]
+        add %g1, %g2, %g3
+        ! CHECK: add %o0, %o1, %l0    ! encoding: [0xa0,0x02,0x00,0x09]
+        add %r8, %r9, %l0
+        ! CHECK: add %o0, 10,  %l0    ! encoding: [0xa0,0x02,0x20,0x0a]
+        add %o0, 10, %l0
+
+        ! CHECK: addcc %g1, %g2, %g3  ! encoding: [0x86,0x80,0x40,0x02]
+        addcc %g1, %g2, %g3
+
+        ! CHECK: addxcc %g1, %g2, %g3 ! encoding: [0x86,0xc0,0x40,0x02]
+        addxcc %g1, %g2, %g3
+
+        ! CHECK: udiv %g1, %g2, %g3   ! encoding: [0x86,0x70,0x40,0x02]
+        udiv %g1, %g2, %g3
+
+        ! CHECK: sdiv %g1, %g2, %g3   ! encoding: [0x86,0x78,0x40,0x02]
+        sdiv %g1, %g2, %g3
+
+        ! CHECK: and %g1, %g2, %g3    ! encoding: [0x86,0x08,0x40,0x02]
+        and %g1, %g2, %g3
+        ! CHECK: andn %g1, %g2, %g3   ! encoding: [0x86,0x28,0x40,0x02]
+        andn %g1, %g2, %g3
+        ! CHECK: or %g1, %g2, %g3     ! encoding: [0x86,0x10,0x40,0x02]
+        or  %g1, %g2, %g3
+        ! CHECK: orn %g1, %g2, %g3    ! encoding: [0x86,0x30,0x40,0x02]
+        orn %g1, %g2, %g3
+        ! CHECK: xor %g1, %g2, %g3    ! encoding: [0x86,0x18,0x40,0x02]
+        xor %g1, %g2, %g3
+        ! CHECK: xnor %g1, %g2, %g3   ! encoding: [0x86,0x38,0x40,0x02]
+        xnor %g1, %g2, %g3
+
+        ! CHECK: umul %g1, %g2, %g3   ! encoding: [0x86,0x50,0x40,0x02]
+        umul %g1, %g2, %g3
+
+        ! CHECK: smul %g1, %g2, %g3   ! encoding: [0x86,0x58,0x40,0x02]
+        smul %g1, %g2, %g3
+
+        ! CHECK: nop                  ! encoding: [0x01,0x00,0x00,0x00]
+        nop
+
+        ! CHECK: sethi 10, %l0        ! encoding: [0x21,0x00,0x00,0x0a]
+        sethi 10, %l0
+
+        ! CHECK: sll %g1, %g2, %g3    ! encoding: [0x87,0x28,0x40,0x02]
+        sll %g1, %g2, %g3
+        ! CHECK: sll %g1, 31, %g3     ! encoding: [0x87,0x28,0x60,0x1f]
+        sll %g1, 31, %g3
+
+        ! CHECK: srl %g1, %g2, %g3    ! encoding: [0x87,0x30,0x40,0x02]
+        srl %g1, %g2, %g3
+        ! CHECK: srl %g1, 31, %g3     ! encoding: [0x87,0x30,0x60,0x1f]
+        srl %g1, 31, %g3
+
+        ! CHECK: sra %g1, %g2, %g3    ! encoding: [0x87,0x38,0x40,0x02]
+        sra %g1, %g2, %g3
+        ! CHECK: sra %g1, 31, %g3     ! encoding: [0x87,0x38,0x60,0x1f]
+        sra %g1, 31, %g3
+
+        ! CHECK: sub %g1, %g2, %g3    ! encoding: [0x86,0x20,0x40,0x02]
+        sub %g1, %g2, %g3
+        ! CHECK: subcc %g1, %g2, %g3  ! encoding: [0x86,0xa0,0x40,0x02]
+        subcc %g1, %g2, %g3
+
+        ! CHECK: subxcc %g1, %g2, %g3 ! encoding: [0x86,0xe0,0x40,0x02]
+        subxcc %g1, %g2, %g3
+