Skip to content

Commit

Permalink
[Nios2] final infrastructure to provide compilation of a return from …
Browse files Browse the repository at this point in the history
…a function

This patch includes all missing functionality needed to provide first
compilation of a simple program that just returns from a function.
I've added a test case that checks for "ret" instruction printed in assembly
output.

Patch by Andrei Grischenko (andrei.l.grischenko@intel.com)
Differential revision: https://reviews.llvm.org/D39688

llvm-svn: 320035
  • Loading branch information
Nikolai Bozhenov committed Dec 7, 2017
1 parent 44cfc51 commit 1cf9c54
Show file tree
Hide file tree
Showing 47 changed files with 1,876 additions and 109 deletions.
16 changes: 13 additions & 3 deletions llvm/lib/Target/Nios2/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ set(LLVM_TARGET_DEFINITIONS Nios2.td)
#your hand code C++ files.
#Nios2GenRegisterInfo.inc came from Nios2RegisterInfo.td, Nios2GenInstrInfo.inc
#came from Nios2InstrInfo.td.
tablegen(LLVM Nios2GenAsmWriter.inc -gen-asm-writer)
tablegen(LLVM Nios2GenDAGISel.inc -gen-dag-isel)
tablegen(LLVM Nios2GenRegisterInfo.inc -gen-register-info)
tablegen(LLVM Nios2GenCallingConv.inc -gen-callingconv)
tablegen(LLVM Nios2GenInstrInfo.inc -gen-instr-info)
tablegen(LLVM Nios2GenSubtargetInfo.inc -gen-subtarget)

Expand All @@ -13,13 +16,20 @@ add_public_tablegen_target(Nios2CommonTableGen)

#Nios2CodeGen should match with LLVMBuild.txt Nios2CodeGen
add_llvm_target(Nios2CodeGen
Nios2InstrInfo.cpp
Nios2AsmPrinter.cpp
Nios2FrameLowering.cpp
Nios2InstrInfo.cpp
Nios2ISelDAGToDAG.cpp
Nios2ISelLowering.cpp
Nios2MachineFunction.cpp
Nios2MCInstLower.cpp
Nios2RegisterInfo.cpp
Nios2Subtarget.cpp
Nios2TargetMachine.cpp
Nios2TargetObjectFile.cpp
)

#Should match with "subdirectories = MCTargetDesc TargetInfo" in LLVMBuild.txt
add_subdirectory(TargetInfo)
#Should match with "subdirectories = InstPrinter MCTargetDesc TargetInfo" in LLVMBuild.txt
add_subdirectory(InstPrinter)
add_subdirectory(MCTargetDesc)
add_subdirectory(TargetInfo)
1 change: 1 addition & 0 deletions llvm/lib/Target/Nios2/InstPrinter/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
add_llvm_library(LLVMNios2AsmPrinter Nios2InstPrinter.cpp)
23 changes: 23 additions & 0 deletions llvm/lib/Target/Nios2/InstPrinter/LLVMBuild.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
;===- ./lib/Target/Nios2/InstPrinter/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 = Nios2AsmPrinter
parent = Nios2
required_libraries = MC Support
add_to_library_groups = Nios2
66 changes: 66 additions & 0 deletions llvm/lib/Target/Nios2/InstPrinter/Nios2InstPrinter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
//===-- Nios2InstPrinter.cpp - Convert Nios2 MCInst to assembly syntax-----===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This class prints an Nios2 MCInst to a .s file.
//
//===----------------------------------------------------------------------===//

#include "Nios2InstPrinter.h"

#include "Nios2InstrInfo.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;

#define DEBUG_TYPE "asm-printer"

#define PRINT_ALIAS_INSTR
#include "Nios2GenAsmWriter.inc"

void Nios2InstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
OS << getRegisterName(RegNo);
}

void Nios2InstPrinter::printInst(const MCInst *MI, raw_ostream &O,
StringRef Annot, const MCSubtargetInfo &STI) {
// Try to print any aliases first.
if (!printAliasInstr(MI, STI, O))
printInstruction(MI, STI, O);
printAnnotation(O, Annot);
}

void Nios2InstPrinter::printOperand(const MCInst *MI, int OpNo,
const MCSubtargetInfo &STI,
raw_ostream &O) {
const MCOperand &Op = MI->getOperand(OpNo);
if (Op.isReg()) {
printRegName(O, Op.getReg());
return;
}

if (Op.isImm()) {
O << Op.getImm();
return;
}

assert(Op.isExpr() && "unknown operand kind in printOperand");
Op.getExpr()->print(O, &MAI, true);
}

void Nios2InstPrinter::printMemOperand(const MCInst *MI, int opNum,
const MCSubtargetInfo &STI,
raw_ostream &O, const char *Modifier) {
// Load/Store memory operands -- imm($reg)
printOperand(MI, opNum + 1, STI, O);
O << "(";
printOperand(MI, opNum, STI, O);
O << ")";
}
49 changes: 49 additions & 0 deletions llvm/lib/Target/Nios2/InstPrinter/Nios2InstPrinter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
//= Nios2InstPrinter.h - Convert Nios2 MCInst to assembly syntax -*- C++ -*-==//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This class prints a Nios2 MCInst to a .s file.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIB_TARGET_NIOS2_INSTPRINTER_NIOS2INSTPRINTER_H
#define LLVM_LIB_TARGET_NIOS2_INSTPRINTER_NIOS2INSTPRINTER_H

#include "llvm/MC/MCInstPrinter.h"

namespace llvm {

class Nios2InstPrinter : public MCInstPrinter {
public:
Nios2InstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII,
const MCRegisterInfo &MRI)
: MCInstPrinter(MAI, MII, MRI) {}

void printRegName(raw_ostream &OS, unsigned RegNo) const override;
void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot,
const MCSubtargetInfo &STI) override;

// Autogenerated by tblgen.
void printInstruction(const MCInst *MI, const MCSubtargetInfo &STI,
raw_ostream &O);
static const char *getRegisterName(unsigned RegNo);

bool printAliasInstr(const MCInst *MI, const MCSubtargetInfo &STI,
raw_ostream &O);

void printCustomAliasOperand(const MCInst *MI, unsigned OpIdx,
unsigned PrintMethodIdx,
const MCSubtargetInfo &STI, raw_ostream &O);
void printOperand(const MCInst *MI, int opNum, const MCSubtargetInfo &STI,
raw_ostream &OS);
void printMemOperand(const MCInst *MI, int opNum, const MCSubtargetInfo &STI,
raw_ostream &OS, const char *Modifier = nullptr);
};
} // end namespace llvm

#endif
6 changes: 5 additions & 1 deletion llvm/lib/Target/Nios2/LLVMBuild.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

[common]
subdirectories =
InstPrinter
MCTargetDesc
TargetInfo

Expand All @@ -33,6 +34,7 @@ name = Nios2
parent = Target
#Whether this target defines an assembly parser, assembly printer, disassembler
#, and supports JIT compilation.They are optional.
has_asmprinter = 1

[component_1]
#component_1 is a Library type and name is Nios2CodeGen.After build it will
Expand All @@ -46,12 +48,14 @@ parent = Nios2
#dependencies for this component.When tools are built, the build system will
#include the transitive closure of all required_libraries for the components
#the tool needs.
required_libraries = CodeGen
required_libraries = AsmPrinter
CodeGen
Core
GlobalISel
MC
Nios2Desc
Nios2Info
SelectionDAG
Support
Target
#end of required_libraries
Expand Down
9 changes: 8 additions & 1 deletion llvm/lib/Target/Nios2/MCTargetDesc/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,9 @@
#MCTargetDesc / CMakeLists.txt
add_llvm_library(LLVMNios2Desc Nios2MCTargetDesc.cpp)
add_llvm_library(LLVMNios2Desc
Nios2AsmBackend.cpp
Nios2ELFObjectWriter.cpp
Nios2MCAsmInfo.cpp
Nios2MCExpr.cpp
Nios2MCTargetDesc.cpp
Nios2TargetStreamer.cpp)

5 changes: 3 additions & 2 deletions llvm/lib/Target/Nios2/MCTargetDesc/LLVMBuild.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
type = Library
name = Nios2Desc
parent = Nios2
required_libraries = MC
Nios2Info
required_libraries = MC
Nios2AsmPrinter
Nios2Info
Support
add_to_library_groups = Nios2
131 changes: 131 additions & 0 deletions llvm/lib/Target/Nios2/MCTargetDesc/Nios2AsmBackend.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
//===-- Nios2AsmBackend.cpp - Nios2 Asm Backend --------------------------===//
//
// 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 Nios2AsmBackend class.
//
//===----------------------------------------------------------------------===//
//

#include "MCTargetDesc/Nios2AsmBackend.h"
#include "MCTargetDesc/Nios2FixupKinds.h"
#include "MCTargetDesc/Nios2MCTargetDesc.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCELFObjectWriter.h"
#include "llvm/MC/MCFixupKindInfo.h"
#include "llvm/MC/MCObjectWriter.h"

using namespace llvm;

// Prepare value for the target space for it
static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value) {

unsigned Kind = Fixup.getKind();

// Add/subtract and shift
switch (Kind) {
default:
return 0;
case Nios2::fixup_Nios2_LO16:
break;
case Nios2::fixup_Nios2_HI16:
// Get the higher 16-bits. Also add 1 if bit 15 is 1.
Value = ((Value + 0x8000) >> 16) & 0xffff;
break;
}

return Value;
}

// Calculate index for Nios2 specific little endian byte order
static unsigned calculateLEIndex(unsigned i) {
assert(i <= 3 && "Index out of range!");

return (1 - i / 2) * 2 + i % 2;
}

/// ApplyFixup - Apply the \p Value for given \p Fixup into the provided
/// data fragment, at the offset specified by the fixup and following the
/// fixup kind as appropriate.
void Nios2AsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
const MCValue &Target,
MutableArrayRef<char> Data, uint64_t Value,
bool IsResolved) const {
MCFixupKind Kind = Fixup.getKind();
Value = adjustFixupValue(Fixup, Value);

if (!Value)
return; // Doesn't change encoding.

// Where do we start in the object
unsigned Offset = Fixup.getOffset();
// Number of bytes we need to fixup
unsigned NumBytes = (getFixupKindInfo(Kind).TargetSize + 7) / 8;
// Grab current value, if any, from bits.
uint64_t CurVal = 0;

for (unsigned i = 0; i != NumBytes; ++i) {
unsigned Idx = calculateLEIndex(i);
CurVal |= (uint64_t)((uint8_t)Data[Offset + Idx]) << (i * 8);
}

uint64_t Mask = ((uint64_t)(-1) >> (64 - getFixupKindInfo(Kind).TargetSize));
CurVal |= Value & Mask;

// Write out the fixed up bytes back to the code/data bits.
for (unsigned i = 0; i != NumBytes; ++i) {
unsigned Idx = calculateLEIndex(i);
Data[Offset + Idx] = (uint8_t)((CurVal >> (i * 8)) & 0xff);
}
}

Optional<MCFixupKind> Nios2AsmBackend::getFixupKind(StringRef Name) const {
return StringSwitch<Optional<MCFixupKind>>(Name)
.Case("R_NIOS2_NONE", (MCFixupKind)Nios2::fixup_Nios2_32)
.Case("R_NIOS2_32", FK_Data_4)
.Default(MCAsmBackend::getFixupKind(Name));
}

//@getFixupKindInfo {
const MCFixupKindInfo &
Nios2AsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
const static MCFixupKindInfo Infos[Nios2::NumTargetFixupKinds] = {
// This table *must* be in same the order of fixup_* kinds in
// Nios2FixupKinds.h.
//
// name offset bits flags
{"fixup_Nios2_32", 0, 32, 0},
{"fixup_Nios2_HI16", 0, 16, 0},
{"fixup_Nios2_LO16", 0, 16, 0}};

if (Kind < FirstTargetFixupKind)
return MCAsmBackend::getFixupKindInfo(Kind);

assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
"Invalid kind!");
return Infos[Kind - FirstTargetFixupKind];
}

std::unique_ptr<MCObjectWriter>
Nios2AsmBackend::createObjectWriter(raw_pwrite_stream &OS) const {
return createNios2ELFObjectWriter(OS,
MCELFObjectTargetWriter::getOSABI(OSType));
}

bool Nios2AsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const {
return true;
}

// MCAsmBackend
MCAsmBackend *llvm::createNios2AsmBackend(const Target &T,
const MCRegisterInfo &MRI,
const Triple &TT, StringRef CPU,
const MCTargetOptions &Options) {

return new Nios2AsmBackend(T, TT.getOS());
}
Loading

0 comments on commit 1cf9c54

Please sign in to comment.