Skip to content

Commit

Permalink
[RISCV] Add bare-bones RISC-V MCTargetDesc
Browse files Browse the repository at this point in the history
This is enough to compile and link but doesn't yet do anything particularly 
useful. Once an ASM parser and printer are added in the next two patches, the 
whole thing can be usefully tested.

Differential Revision: https://reviews.llvm.org/D23562

llvm-svn: 285770
  • Loading branch information
asb committed Nov 1, 2016
1 parent 24d9b13 commit 6b2cca7
Show file tree
Hide file tree
Showing 13 changed files with 441 additions and 9 deletions.
2 changes: 2 additions & 0 deletions llvm/lib/Target/RISCV/CMakeLists.txt
Expand Up @@ -2,6 +2,7 @@ set(LLVM_TARGET_DEFINITIONS RISCV.td)

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)

Expand All @@ -10,3 +11,4 @@ add_llvm_target(RISCVCodeGen
)

add_subdirectory(TargetInfo)
add_subdirectory(MCTargetDesc)
2 changes: 1 addition & 1 deletion llvm/lib/Target/RISCV/LLVMBuild.txt
Expand Up @@ -16,7 +16,7 @@
;===------------------------------------------------------------------------===;

[common]
subdirectories = TargetInfo
subdirectories = TargetInfo MCTargetDesc

[component_0]
type = TargetGroup
Expand Down
7 changes: 7 additions & 0 deletions llvm/lib/Target/RISCV/MCTargetDesc/CMakeLists.txt
@@ -0,0 +1,7 @@
add_llvm_library(LLVMRISCVDesc
RISCVAsmBackend.cpp
RISCVELFObjectWriter.cpp
RISCVMCAsmInfo.cpp
RISCVMCTargetDesc.cpp
RISCVMCCodeEmitter.cpp
)
23 changes: 23 additions & 0 deletions llvm/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
91 changes: 91 additions & 0 deletions llvm/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());
}
51 changes: 51 additions & 0 deletions llvm/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);
}
25 changes: 25 additions & 0 deletions llvm/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;
}
31 changes: 31 additions & 0 deletions llvm/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
91 changes: 91 additions & 0 deletions llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
@@ -0,0 +1,91 @@
//===-- 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<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const override;

/// TableGen'erated function for getting the binary encoding for an
/// instruction.
uint64_t getBinaryCodeForInstr(const MCInst &MI,
SmallVectorImpl<MCFixup> &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<MCFixup> &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<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
// For now, we only support RISC-V instructions with 32-bit length
uint32_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
support::endian::Writer<support::little>(OS).write(Bits);
++MCNumEmitted; // Keep track of the # of mi's emitted.
}

unsigned
RISCVMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {

if (MO.isReg())
return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());

if (MO.isImm())
return static_cast<unsigned>(MO.getImm());

llvm_unreachable("Unhandled expression!");
return 0;
}

#include "RISCVGenMCCodeEmitter.inc"

0 comments on commit 6b2cca7

Please sign in to comment.