Pull in r198533 from upstream llvm trunk (by Venkatraman Govindaraju): [Sparc] Add initial implementation of MC Code emitter for sparc. Introduced here: http://svnweb.freebsd.org/changeset/base/262261 Index: lib/Target/Sparc/SparcInstrInfo.td =================================================================== --- lib/Target/Sparc/SparcInstrInfo.td +++ lib/Target/Sparc/SparcInstrInfo.td @@ -100,9 +100,14 @@ def MEMri : Operand { def TLSSym : Operand; // Branch targets have OtherVT type. -def brtarget : Operand; -def calltarget : Operand; +def brtarget : Operand { + let EncoderMethod = "getBranchTargetOpValue"; +} +def calltarget : Operand { + let EncoderMethod = "getCallTargetOpValue"; +} + // Operand for printing out a condition code. let PrintMethod = "printCCOperand" in def CCOp : Operand; Index: lib/Target/Sparc/MCTargetDesc/CMakeLists.txt =================================================================== --- lib/Target/Sparc/MCTargetDesc/CMakeLists.txt +++ lib/Target/Sparc/MCTargetDesc/CMakeLists.txt @@ -1,6 +1,8 @@ add_llvm_library(LLVMSparcDesc + SparcAsmBackend.cpp + SparcMCAsmInfo.cpp + SparcMCCodeEmitter.cpp SparcMCTargetDesc.cpp - SparcMCAsmInfo.cpp SparcMCExpr.cpp SparcTargetStreamer.cpp ) Index: lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp =================================================================== --- lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp +++ 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 &Fixups) const; + + // getBinaryCodeForInstr - TableGen'erated function for getting the + // binary encoding for an instruction. + uint64_t getBinaryCodeForInstr(const MCInst &MI, + SmallVectorImpl &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 &Fixups) const; + + unsigned getCallTargetOpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups) const; + unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &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 &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 &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 &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 &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: lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp =================================================================== --- lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp +++ 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, Index: lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp =================================================================== --- lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp +++ 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()); +} Index: lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h =================================================================== --- lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h +++ 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 Index: lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h =================================================================== --- lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h +++ 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 Index: lib/Target/Sparc/Makefile =================================================================== --- lib/Target/Sparc/Makefile +++ lib/Target/Sparc/Makefile @@ -16,7 +16,7 @@ BUILT_SOURCES = SparcGenRegisterInfo.inc SparcGenI SparcGenAsmWriter.inc SparcGenAsmMatcher.inc \ SparcGenDAGISel.inc \ SparcGenSubtargetInfo.inc SparcGenCallingConv.inc \ - SparcGenCodeEmitter.inc + SparcGenCodeEmitter.inc SparcGenMCCodeEmitter.inc DIRS = InstPrinter AsmParser TargetInfo MCTargetDesc Index: lib/Target/Sparc/CMakeLists.txt =================================================================== --- lib/Target/Sparc/CMakeLists.txt +++ 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) Index: lib/Target/Sparc/SparcCodeEmitter.cpp =================================================================== --- lib/Target/Sparc/SparcCodeEmitter.cpp +++ lib/Target/Sparc/SparcCodeEmitter.cpp @@ -72,6 +72,11 @@ class SparcCodeEmitter : public MachineFunctionPas 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 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: test/MC/Sparc/sparc-alu-instructions.s =================================================================== --- test/MC/Sparc/sparc-alu-instructions.s +++ test/MC/Sparc/sparc-alu-instructions.s @@ -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 +