diff options
author | Venkatraman Govindaraju <venkatra@cs.wisc.edu> | 2014-01-05 02:13:48 +0000 |
---|---|---|
committer | Venkatraman Govindaraju <venkatra@cs.wisc.edu> | 2014-01-05 02:13:48 +0000 |
commit | 5d02c84191f0aea5b35b810a30edce97dd24bffc (patch) | |
tree | f85a779fe4bc6f61ee045429343197f67d9a4687 /lib/Target | |
parent | 478ea5d37d15733feee5ea50f689302e0d44cebb (diff) | |
download | llvm-5d02c84191f0aea5b35b810a30edce97dd24bffc.tar.gz llvm-5d02c84191f0aea5b35b810a30edce97dd24bffc.tar.bz2 llvm-5d02c84191f0aea5b35b810a30edce97dd24bffc.tar.xz |
[Sparc] Add initial implementation of MC Code emitter for sparc.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@198533 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target')
-rw-r--r-- | lib/Target/Sparc/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lib/Target/Sparc/MCTargetDesc/CMakeLists.txt | 4 | ||||
-rw-r--r-- | lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp | 101 | ||||
-rw-r--r-- | lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h | 36 | ||||
-rw-r--r-- | lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp | 131 | ||||
-rw-r--r-- | lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp | 12 | ||||
-rw-r--r-- | lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h | 16 | ||||
-rw-r--r-- | lib/Target/Sparc/Makefile | 2 | ||||
-rw-r--r-- | lib/Target/Sparc/SparcCodeEmitter.cpp | 17 | ||||
-rw-r--r-- | lib/Target/Sparc/SparcInstrInfo.td | 9 |
10 files changed, 325 insertions, 4 deletions
diff --git a/lib/Target/Sparc/CMakeLists.txt b/lib/Target/Sparc/CMakeLists.txt index 1795beee3b..9fad0e8561 100644 --- a/lib/Target/Sparc/CMakeLists.txt +++ b/lib/Target/Sparc/CMakeLists.txt @@ -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) diff --git a/lib/Target/Sparc/MCTargetDesc/CMakeLists.txt b/lib/Target/Sparc/MCTargetDesc/CMakeLists.txt index 3a40fcaba4..2619f9db26 100644 --- a/lib/Target/Sparc/MCTargetDesc/CMakeLists.txt +++ b/lib/Target/Sparc/MCTargetDesc/CMakeLists.txt @@ -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 index 0000000000..e86b3c89d2 --- /dev/null +++ b/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp @@ -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 index 0000000000..1b56f1266b --- /dev/null +++ b/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h @@ -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 index 0000000000..641aed429b --- /dev/null +++ b/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp @@ -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" diff --git a/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp b/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp index a98e240fe0..0322ddcf4d 100644 --- a/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp +++ b/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp @@ -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, diff --git a/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h b/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h index cba775adb1..5b3f7448ec 100644 --- a/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h +++ b/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h @@ -15,11 +15,27 @@ #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 diff --git a/lib/Target/Sparc/Makefile b/lib/Target/Sparc/Makefile index 6b563e907e..94a8dd01d4 100644 --- a/lib/Target/Sparc/Makefile +++ b/lib/Target/Sparc/Makefile @@ -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 diff --git a/lib/Target/Sparc/SparcCodeEmitter.cpp b/lib/Target/Sparc/SparcCodeEmitter.cpp index 9bfe31fe49..f4a2c73949 100644 --- a/lib/Target/Sparc/SparcCodeEmitter.cpp +++ b/lib/Target/Sparc/SparcCodeEmitter.cpp @@ -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 { diff --git a/lib/Target/Sparc/SparcInstrInfo.td b/lib/Target/Sparc/SparcInstrInfo.td index d3c8e4ad78..43d9bc9531 100644 --- a/lib/Target/Sparc/SparcInstrInfo.td +++ b/lib/Target/Sparc/SparcInstrInfo.td @@ -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 |