Index: lib/Target/RISCV/CMakeLists.txt =================================================================== --- lib/Target/RISCV/CMakeLists.txt +++ lib/Target/RISCV/CMakeLists.txt @@ -2,6 +2,7 @@ tablegen(LLVM RISCVGenRegisterInfo.inc -gen-register-info) tablegen(LLVM RISCVGenInstrInfo.inc -gen-instr-info) +tablegen(LLVM RISCVGenMCCodeEmitter.inc -gen-emitter) add_public_tablegen_target(RISCVCommonTableGen) @@ -10,3 +11,4 @@ ) add_subdirectory(TargetInfo) +add_subdirectory(MCTargetDesc) Index: lib/Target/RISCV/LLVMBuild.txt =================================================================== --- lib/Target/RISCV/LLVMBuild.txt +++ lib/Target/RISCV/LLVMBuild.txt @@ -16,7 +16,7 @@ ;===------------------------------------------------------------------------===; [common] -subdirectories = TargetInfo +subdirectories = TargetInfo MCTargetDesc [component_0] type = TargetGroup Index: lib/Target/RISCV/MCTargetDesc/CMakeLists.txt =================================================================== --- /dev/null +++ lib/Target/RISCV/MCTargetDesc/CMakeLists.txt @@ -0,0 +1,7 @@ +add_llvm_library(LLVMRISCVDesc + RISCVAsmBackend.cpp + RISCVELFObjectWriter.cpp + RISCVMCAsmInfo.cpp + RISCVMCTargetDesc.cpp + RISCVMCCodeEmitter.cpp +) Index: lib/Target/RISCV/MCTargetDesc/LLVMBuild.txt =================================================================== --- /dev/null +++ lib/Target/RISCV/MCTargetDesc/LLVMBuild.txt @@ -0,0 +1,23 @@ +;===- ./lib/Target/RISCV/MCTargetDesc/LLVMBuild.txt ------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Library +name = RISCVDesc +parent = RISCV +required_libraries = MC RISCVInfo Support +add_to_library_groups = RISCV Index: lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp =================================================================== --- /dev/null +++ lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp @@ -0,0 +1,91 @@ +//===-- RISCVAsmBackend.cpp - RISCV Assembler Backend ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "MCTargetDesc/RISCVMCTargetDesc.h" +#include "llvm/MC/MCAsmBackend.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCDirectives.h" +#include "llvm/MC/MCELFObjectWriter.h" +#include "llvm/MC/MCFixupKindInfo.h" +#include "llvm/MC/MCObjectWriter.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +namespace { +class RISCVAsmBackend : public MCAsmBackend { + uint8_t OSABI; + bool Is64Bit; + +public: + RISCVAsmBackend(uint8_t OSABI, bool Is64Bit) + : MCAsmBackend(), OSABI(OSABI), Is64Bit(Is64Bit) {} + ~RISCVAsmBackend() override {} + + void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, + uint64_t Value, bool IsPCRel) const override; + + MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override; + + bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, + const MCRelaxableFragment *DF, + const MCAsmLayout &Layout) const override { + return false; + } + + unsigned getNumFixupKinds() const override { return 1; } + + bool mayNeedRelaxation(const MCInst &Inst) const override { return false; } + + void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI, + MCInst &Res) const override { + + llvm_unreachable("RISCVAsmBackend::relaxInstruction() unimplemented"); + } + + bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override; +}; + +bool RISCVAsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const { + // Once support for the compressed instruction set is added, we will be able + // to conditionally support 16-bit NOPs + if ((Count % 4) != 0) + return false; + + // The canonical nop on RISC-V is addi x0, x0, 0 + for (uint64_t i = 0; i < Count; i += 4) + OW->write32(0x13); + + return true; +} + +void RISCVAsmBackend::applyFixup(const MCFixup &Fixup, char *Data, + unsigned DataSize, uint64_t Value, + bool IsPCRel) const { + return; +} + +MCObjectWriter * +RISCVAsmBackend::createObjectWriter(raw_pwrite_stream &OS) const { + return createRISCVELFObjectWriter(OS, OSABI, Is64Bit); +} + +} // end anonymous namespace + +MCAsmBackend *llvm::createRISCVAsmBackend(const Target &T, + const MCRegisterInfo &MRI, + const Triple &TT, StringRef CPU, + const MCTargetOptions &Options) { + uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TT.getOS()); + return new RISCVAsmBackend(OSABI, TT.isArch64Bit()); +} Index: lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp =================================================================== --- /dev/null +++ lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp @@ -0,0 +1,51 @@ +//===-- RISCVELFObjectWriter.cpp - RISCV ELF Writer -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "MCTargetDesc/RISCVMCTargetDesc.h" +#include "llvm/MC/MCELFObjectWriter.h" +#include "llvm/MC/MCFixup.h" +#include "llvm/Support/ErrorHandling.h" + +using namespace llvm; + +namespace { +class RISCVELFObjectWriter : public MCELFObjectTargetWriter { +public: + RISCVELFObjectWriter(uint8_t OSABI, bool Is64Bit); + + ~RISCVELFObjectWriter() override; + +protected: + unsigned getRelocType(MCContext &Ctx, const MCValue &Target, + const MCFixup &Fixup, bool IsPCRel) const override; +}; +} + +RISCVELFObjectWriter::RISCVELFObjectWriter(uint8_t OSABI, bool Is64Bit) + : MCELFObjectTargetWriter(Is64Bit, OSABI, ELF::EM_RISCV, + /*HasRelocationAddend*/ false) {} + +RISCVELFObjectWriter::~RISCVELFObjectWriter() {} + +unsigned RISCVELFObjectWriter::getRelocType(MCContext &Ctx, + const MCValue &Target, + const MCFixup &Fixup, + bool IsPCRel) const { + // Determine the type of the relocation + switch ((unsigned)Fixup.getKind()) { + default: + llvm_unreachable("invalid fixup kind!"); + } +} + +MCObjectWriter *llvm::createRISCVELFObjectWriter(raw_pwrite_stream &OS, + uint8_t OSABI, bool Is64Bit) { + MCELFObjectTargetWriter *MOTW = new RISCVELFObjectWriter(OSABI, Is64Bit); + return createELFObjectWriter(MOTW, OS, /*IsLittleEndian*/ true); +} Index: lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.h =================================================================== --- /dev/null +++ lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.h @@ -0,0 +1,31 @@ +//===-- RISCVMCAsmInfo.h - RISCV Asm Info ----------------------*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the RISCVMCAsmInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_RISCV_MCTARGETDESC_RISCVMCASMINFO_H +#define LLVM_LIB_TARGET_RISCV_MCTARGETDESC_RISCVMCASMINFO_H + +#include "llvm/MC/MCAsmInfoELF.h" + +namespace llvm { +class Triple; + +class RISCVMCAsmInfo : public MCAsmInfoELF { + void anchor() override; + +public: + explicit RISCVMCAsmInfo(const Triple &TargetTriple); +}; + +} // namespace llvm + +#endif Index: lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp =================================================================== --- /dev/null +++ lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp @@ -0,0 +1,25 @@ +//===-- RISCVMCAsmInfo.cpp - RISCV Asm properties -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declarations of the RISCVMCAsmInfo properties. +// +//===----------------------------------------------------------------------===// + +#include "RISCVMCAsmInfo.h" +#include "llvm/ADT/Triple.h" +using namespace llvm; + +void RISCVMCAsmInfo::anchor() {} + +RISCVMCAsmInfo::RISCVMCAsmInfo(const Triple &TT) { + PointerSize = CalleeSaveStackSlotSize = TT.isArch64Bit() ? 8 : 4; + CommentString = "#"; + AlignmentIsInBytes = false; + SupportsDebugInformation = true; +} Index: lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp =================================================================== --- /dev/null +++ lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp @@ -0,0 +1,90 @@ +//===-- RISCVMCCodeEmitter.cpp - Convert RISCV 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 RISCVMCCodeEmitter class. +// +//===----------------------------------------------------------------------===// + +#include "MCTargetDesc/RISCVMCTargetDesc.h" +#include "llvm/ADT/Statistic.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/MC/MCSymbol.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/Support/EndianStream.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +#define DEBUG_TYPE "mccodeemitter" + +STATISTIC(MCNumEmitted, "Number of MC instructions emitted"); + +namespace { +class RISCVMCCodeEmitter : public MCCodeEmitter { + RISCVMCCodeEmitter(const RISCVMCCodeEmitter &) = delete; + void operator=(const RISCVMCCodeEmitter &) = delete; + MCContext &Ctx; + +public: + RISCVMCCodeEmitter(MCContext &ctx) : Ctx(ctx) {} + + ~RISCVMCCodeEmitter() override {} + + void encodeInstruction(const MCInst &MI, raw_ostream &OS, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const override; + + /// TableGen'erated function for getting the binary encoding for an + /// instruction. + uint64_t getBinaryCodeForInstr(const MCInst &MI, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + + /// 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 MCSubtargetInfo &STI) const; +}; +} // end anonymous namespace + +MCCodeEmitter *llvm::createRISCVMCCodeEmitter(const MCInstrInfo &MCII, + const MCRegisterInfo &MRI, + MCContext &Ctx) { + return new RISCVMCCodeEmitter(Ctx); +} + +void RISCVMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + unsigned Bits = getBinaryCodeForInstr(MI, Fixups, STI); + support::endian::Writer(OS).write(Bits); + ++MCNumEmitted; // Keep track of the # of mi's emitted. +} + +unsigned +RISCVMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + + if (MO.isReg()) + return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); + + if (MO.isImm()) + return static_cast(MO.getImm()); + + llvm_unreachable("Unhandled expression!"); + return 0; +} + +#include "RISCVGenMCCodeEmitter.inc" Index: lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.h =================================================================== --- /dev/null +++ lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.h @@ -0,0 +1,58 @@ +//===-- RISCVMCTargetDesc.h - RISCV Target Descriptions ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides RISCV specific target descriptions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_RISCV_MCTARGETDESC_RISCVMCTARGETDESC_H +#define LLVM_LIB_TARGET_RISCV_MCTARGETDESC_RISCVMCTARGETDESC_H + +#include "llvm/MC/MCTargetOptions.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Config/config.h" + +namespace llvm { +class MCAsmBackend; +class MCCodeEmitter; +class MCContext; +class MCInstrInfo; +class MCObjectWriter; +class MCRegisterInfo; +class MCSubtargetInfo; +class StringRef; +class Target; +class Triple; +class raw_ostream; +class raw_pwrite_stream; + +extern Target TheRISCV32Target; +extern Target TheRISCV64Target; + +MCCodeEmitter *createRISCVMCCodeEmitter(const MCInstrInfo &MCII, + const MCRegisterInfo &MRI, + MCContext &Ctx); + +MCAsmBackend *createRISCVAsmBackend(const Target &T, const MCRegisterInfo &MRI, + const Triple &TT, StringRef CPU, + const MCTargetOptions &Options); + +MCObjectWriter *createRISCVELFObjectWriter(raw_pwrite_stream &OS, uint8_t OSABI, + bool Is64Bit); +} + +// Defines symbolic names for RISC-V registers. +#define GET_REGINFO_ENUM +#include "RISCVGenRegisterInfo.inc" + +// Defines symbolic names for RISC-V instructions. +#define GET_INSTRINFO_ENUM +#include "RISCVGenInstrInfo.inc" + +#endif Index: lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp =================================================================== --- /dev/null +++ lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp @@ -0,0 +1,59 @@ +//===-- RISCVMCTargetDesc.cpp - RISCV Target Descriptions -----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// This file provides RISCV-specific target descriptions. +/// +//===----------------------------------------------------------------------===// + +#include "RISCVMCTargetDesc.h" +#include "RISCVMCAsmInfo.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/TargetRegistry.h" + +#define GET_INSTRINFO_MC_DESC +#include "RISCVGenInstrInfo.inc" + +#define GET_REGINFO_MC_DESC +#include "RISCVGenRegisterInfo.inc" + +using namespace llvm; + +static MCInstrInfo *createRISCVMCInstrInfo() { + MCInstrInfo *X = new MCInstrInfo(); + InitRISCVMCInstrInfo(X); + return X; +} + +static MCRegisterInfo *createRISCVMCRegisterInfo(const Triple &TT) { + MCRegisterInfo *X = new MCRegisterInfo(); + InitRISCVMCRegisterInfo(X, RISCV::X1); + return X; +} + +static MCAsmInfo *createRISCVMCAsmInfo(const MCRegisterInfo &MRI, + const Triple &TT) { + MCAsmInfo *MAI = new RISCVMCAsmInfo(TT); + return MAI; +} + +extern "C" void LLVMInitializeRISCVTargetMC() { + for (Target *T : {&TheRISCV32Target, &TheRISCV64Target}) { + RegisterMCAsmInfoFn X(*T, createRISCVMCAsmInfo); + TargetRegistry::RegisterMCInstrInfo(*T, createRISCVMCInstrInfo); + TargetRegistry::RegisterMCRegInfo(*T, createRISCVMCRegisterInfo); + TargetRegistry::RegisterMCAsmBackend(*T, createRISCVAsmBackend); + TargetRegistry::RegisterMCCodeEmitter(*T, createRISCVMCCodeEmitter); + } +} Index: lib/Target/RISCV/TargetInfo/RISCVTargetInfo.cpp =================================================================== --- lib/Target/RISCV/TargetInfo/RISCVTargetInfo.cpp +++ lib/Target/RISCV/TargetInfo/RISCVTargetInfo.cpp @@ -21,8 +21,3 @@ RegisterTarget Y(TheRISCV64Target, "riscv64", "64-bit RISC-V"); } - -// FIXME: Temporary stub - this function must be defined for linking -// to succeed and will be called unconditionally by llc, so must be a no-op. -// Remove once this function is properly implemented. -extern "C" void LLVMInitializeRISCVTargetMC() {}