Index: lib/Target/Nios2/CMakeLists.txt =================================================================== --- lib/Target/Nios2/CMakeLists.txt +++ lib/Target/Nios2/CMakeLists.txt @@ -4,7 +4,10 @@ #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) @@ -13,13 +16,20 @@ #Nios2CodeGen should match with LLVMBuild.txt Nios2CodeGen add_llvm_target(Nios2CodeGen + Nios2AsmPrinter.cpp Nios2InstrInfo.cpp + Nios2ISelDAGToDAG.cpp Nios2FrameLowering.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) Index: lib/Target/Nios2/InstPrinter/CMakeLists.txt =================================================================== --- /dev/null +++ lib/Target/Nios2/InstPrinter/CMakeLists.txt @@ -0,0 +1 @@ +add_llvm_library(LLVMNios2AsmPrinter Nios2InstPrinter.cpp) Index: lib/Target/Nios2/InstPrinter/LLVMBuild.txt =================================================================== --- /dev/null +++ lib/Target/Nios2/InstPrinter/LLVMBuild.txt @@ -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 Index: lib/Target/Nios2/InstPrinter/Nios2InstPrinter.h =================================================================== --- /dev/null +++ lib/Target/Nios2/InstPrinter/Nios2InstPrinter.h @@ -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 Index: lib/Target/Nios2/InstPrinter/Nios2InstPrinter.cpp =================================================================== --- /dev/null +++ lib/Target/Nios2/InstPrinter/Nios2InstPrinter.cpp @@ -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 << StringRef(getRegisterName(RegNo)).lower(); +} + +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 << ")"; +} Index: lib/Target/Nios2/LLVMBuild.txt =================================================================== --- lib/Target/Nios2/LLVMBuild.txt +++ lib/Target/Nios2/LLVMBuild.txt @@ -19,6 +19,7 @@ [common] subdirectories = + InstPrinter MCTargetDesc TargetInfo @@ -33,6 +34,7 @@ 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 @@ -46,12 +48,14 @@ #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 Index: lib/Target/Nios2/MCTargetDesc/CMakeLists.txt =================================================================== --- lib/Target/Nios2/MCTargetDesc/CMakeLists.txt +++ lib/Target/Nios2/MCTargetDesc/CMakeLists.txt @@ -1,2 +1,4 @@ #MCTargetDesc / CMakeLists.txt -add_llvm_library(LLVMNios2Desc Nios2MCTargetDesc.cpp) +add_llvm_library(LLVMNios2Desc Nios2MCTargetDesc.cpp Nios2MCExpr.cpp + Nios2MCAsmInfo.cpp Nios2TargetStreamer.cpp Nios2AsmBackend.cpp + Nios2ELFObjectWriter.cpp) Index: lib/Target/Nios2/MCTargetDesc/LLVMBuild.txt =================================================================== --- lib/Target/Nios2/MCTargetDesc/LLVMBuild.txt +++ lib/Target/Nios2/MCTargetDesc/LLVMBuild.txt @@ -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 Index: lib/Target/Nios2/MCTargetDesc/Nios2AsmBackend.h =================================================================== --- /dev/null +++ lib/Target/Nios2/MCTargetDesc/Nios2AsmBackend.h @@ -0,0 +1,81 @@ +//===-- Nios2AsmBackend.h - 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 defines the Nios2AsmBackend class. +// +//===----------------------------------------------------------------------===// +// + +#ifndef LLVM_LIB_TARGET_NIOS2_MCTARGETDESC_NIOS2ASMBACKEND_H +#define LLVM_LIB_TARGET_NIOS2_MCTARGETDESC_NIOS2ASMBACKEND_H + +#include "MCTargetDesc/Nios2FixupKinds.h" +#include "llvm/ADT/Triple.h" +#include "llvm/MC/MCAsmBackend.h" + +namespace llvm { + +class MCAssembler; +struct MCFixupKindInfo; +class Target; +class MCObjectWriter; + +class Nios2AsmBackend : public MCAsmBackend { + Triple::OSType OSType; + +public: + Nios2AsmBackend(const Target &T, Triple::OSType OSType) + : MCAsmBackend(), OSType(OSType) {} + + std::unique_ptr + createObjectWriter(raw_pwrite_stream &OS) const override; + + bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override; + + void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, + const MCValue &Target, MutableArrayRef Data, + uint64_t Value, bool IsResolved) const override; + + Optional getFixupKind(StringRef Name) const override; + const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override; + + unsigned getNumFixupKinds() const override { + return Nios2::NumTargetFixupKinds; + } + + /// MayNeedRelaxation - Check whether the given instruction may need + /// relaxation. + /// + /// \param Inst - The instruction to test. + bool mayNeedRelaxation(const MCInst &Inst) const override { 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 override { + // FIXME. + llvm_unreachable("RelaxInstruction() unimplemented"); + return false; + } + + /// RelaxInstruction - Relax the instruction in the given fragment + /// to the next wider instruction. + /// + /// \param Inst - The instruction to relax, which may be the same + /// as the output. + /// \param [out] Res On return, the relaxed instruction. + void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI, + MCInst &Res) const override {} + +}; // class Nios2AsmBackend + +} // namespace llvm + +#endif Index: lib/Target/Nios2/MCTargetDesc/Nios2AsmBackend.cpp =================================================================== --- /dev/null +++ lib/Target/Nios2/MCTargetDesc/Nios2AsmBackend.cpp @@ -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 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 Nios2AsmBackend::getFixupKind(StringRef Name) const { + return StringSwitch>(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 +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()); +} Index: lib/Target/Nios2/MCTargetDesc/Nios2BaseInfo.h =================================================================== --- /dev/null +++ lib/Target/Nios2/MCTargetDesc/Nios2BaseInfo.h @@ -0,0 +1,38 @@ +//===-- Nios2BaseInfo.h - Top level definitions for NIOS2 MC ----*- 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 small standalone helper functions and enum definitions for +// the Nios2 target useful for the compiler back-end and the MC libraries. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_LIB_TARGET_NIOS2_MCTARGETDESC_NIOS2BASEINFO_H +#define LLVM_LIB_TARGET_NIOS2_MCTARGETDESC_NIOS2BASEINFO_H + +namespace llvm { + +/// Nios2FG - This namespace holds all of the target specific flags that +/// instruction info tracks. +namespace Nios2FG { +/// Target Operand Flag enum. +enum TOF { + //===------------------------------------------------------------------===// + // Nios2 Specific MachineOperand flags. + + MO_NO_FLAG, + + /// MO_ABS_HI/LO - Represents the hi or low part of an absolute symbol + /// address. + MO_ABS_HI, + MO_ABS_LO, + +}; +} // namespace Nios2FG +} // namespace llvm + +#endif Index: lib/Target/Nios2/MCTargetDesc/Nios2ELFObjectWriter.cpp =================================================================== --- /dev/null +++ lib/Target/Nios2/MCTargetDesc/Nios2ELFObjectWriter.cpp @@ -0,0 +1,44 @@ +//===-- Nios2ELFObjectWriter.cpp - Nios2 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/Nios2FixupKinds.h" +#include "MCTargetDesc/Nios2MCExpr.h" +#include "MCTargetDesc/Nios2MCTargetDesc.h" +#include "llvm/MC/MCELFObjectWriter.h" +#include "llvm/MC/MCObjectWriter.h" + +using namespace llvm; + +namespace { +class Nios2ELFObjectWriter : public MCELFObjectTargetWriter { +public: + Nios2ELFObjectWriter(uint8_t OSABI) + : MCELFObjectTargetWriter(false, OSABI, ELF::EM_ALTERA_NIOS2, false) {} + + ~Nios2ELFObjectWriter() override; + + unsigned getRelocType(MCContext &Ctx, const MCValue &Target, + const MCFixup &Fixup, bool IsPCRel) const override; +}; +} // namespace + +Nios2ELFObjectWriter::~Nios2ELFObjectWriter() {} + +unsigned Nios2ELFObjectWriter::getRelocType(MCContext &Ctx, + const MCValue &Target, + const MCFixup &Fixup, + bool IsPCRel) const { + return 0; +} + +std::unique_ptr +llvm::createNios2ELFObjectWriter(raw_pwrite_stream &OS, uint8_t OSABI) { + auto MOTW = llvm::make_unique(OSABI); + return createELFObjectWriter(std::move(MOTW), OS, true); +} Index: lib/Target/Nios2/MCTargetDesc/Nios2FixupKinds.h =================================================================== --- /dev/null +++ lib/Target/Nios2/MCTargetDesc/Nios2FixupKinds.h @@ -0,0 +1,41 @@ +//===-- Nios2FixupKinds.h - Nios2 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_LIB_TARGET_NIOS2_MCTARGETDESC_NIOS2FIXUPKINDS_H +#define LLVM_LIB_TARGET_NIOS2_MCTARGETDESC_NIOS2FIXUPKINDS_H + +#include "llvm/MC/MCFixup.h" + +namespace llvm { +namespace Nios2 { +// Although most of the current fixup types reflect a unique relocation +// one can have multiple fixup types for a given relocation and thus need +// to be uniquely named. +// +// This table *must* be in the save order of +// MCFixupKindInfo Infos[Nios2::NumTargetFixupKinds] +// in Nios2AsmBackend.cpp. +enum Fixups { + // Pure upper 32 bit fixup resulting in - R_NIOS2_32. + fixup_Nios2_32 = FirstTargetFixupKind, + + // Pure upper 16 bit fixup resulting in - R_NIOS2_HI16. + fixup_Nios2_HI16, + + // Pure lower 16 bit fixup resulting in - R_NIOS2_LO16. + fixup_Nios2_LO16, + + // Marker + LastTargetFixupKind, + NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind +}; +} // namespace Nios2 +} // namespace llvm + +#endif // LLVM_NIOS2_NIOS2FIXUPKINDS_H Index: lib/Target/Nios2/MCTargetDesc/Nios2MCAsmInfo.h =================================================================== --- /dev/null +++ lib/Target/Nios2/MCTargetDesc/Nios2MCAsmInfo.h @@ -0,0 +1,31 @@ +//===-- Nios2MCAsmInfo.h - Nios2 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 Nios2MCAsmInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_NIOS2_MCTARGETDESC_NIOS2MCASMINFO_H +#define LLVM_LIB_TARGET_NIOS2_MCTARGETDESC_NIOS2MCASMINFO_H + +#include "llvm/MC/MCAsmInfoELF.h" + +namespace llvm { +class Triple; + +class Nios2MCAsmInfo : public MCAsmInfoELF { + void anchor() override; + +public: + explicit Nios2MCAsmInfo(const Triple &TheTriple); +}; + +} // namespace llvm + +#endif Index: lib/Target/Nios2/MCTargetDesc/Nios2MCAsmInfo.cpp =================================================================== --- /dev/null +++ lib/Target/Nios2/MCTargetDesc/Nios2MCAsmInfo.cpp @@ -0,0 +1,44 @@ +//===-- Nios2MCAsmInfo.cpp - Nios2 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 Nios2MCAsmInfo properties. +// +//===----------------------------------------------------------------------===// + +#include "Nios2MCAsmInfo.h" + +#include "llvm/ADT/Triple.h" + +using namespace llvm; + +void Nios2MCAsmInfo::anchor() {} + +Nios2MCAsmInfo::Nios2MCAsmInfo(const Triple &TheTriple) { + if ((TheTriple.getArch() == Triple::nios2)) + IsLittleEndian = true; // the default of IsLittleEndian is true + + AlignmentIsInBytes = false; + Data16bitsDirective = "\t.2byte\t"; + Data32bitsDirective = "\t.4byte\t"; + Data64bitsDirective = "\t.8byte\t"; + PrivateLabelPrefix = ".LC"; + CommentString = "#"; + ZeroDirective = "\t.space\t"; + GPRel32Directive = "\t.gpword\t"; + GPRel64Directive = "\t.gpdword\t"; + WeakRefDirective = "\t.weak\t"; + GlobalDirective = "\t.global\t"; + AscizDirective = "\t.string\t"; + UseAssignmentForEHBegin = true; + + SupportsDebugInformation = true; + ExceptionsType = ExceptionHandling::DwarfCFI; + DwarfRegNumForCFI = true; + UsesELFSectionDirectiveForBSS = true; +} Index: lib/Target/Nios2/MCTargetDesc/Nios2MCExpr.h =================================================================== --- /dev/null +++ lib/Target/Nios2/MCTargetDesc/Nios2MCExpr.h @@ -0,0 +1,60 @@ +//===-- Nios2MCExpr.h - Nios2 specific MC expression classes ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_NIOS2_MCTARGETDESC_NIOS2MCEXPR_H +#define LLVM_LIB_TARGET_NIOS2_MCTARGETDESC_NIOS2MCEXPR_H + +#include "llvm/MC/MCAsmLayout.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCValue.h" + +namespace llvm { + +class Nios2MCExpr : public MCTargetExpr { +public: + enum Nios2ExprKind { + CEK_None, + CEK_ABS_HI, + CEK_ABS_LO, + CEK_Special, + }; + +private: + const Nios2ExprKind Kind; + const MCExpr *Expr; + + explicit Nios2MCExpr(Nios2ExprKind Kind, const MCExpr *Expr) + : Kind(Kind), Expr(Expr) {} + +public: + static const Nios2MCExpr *create(Nios2ExprKind Kind, const MCExpr *Expr, + MCContext &Ctx); + static const Nios2MCExpr *create(const MCSymbol *Symbol, + Nios2MCExpr::Nios2ExprKind Kind, + MCContext &Ctx); + + /// Get the kind of this expression. + Nios2ExprKind getKind() const { return Kind; } + + /// Get the child of this expression. + const MCExpr *getSubExpr() const { return Expr; } + + void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override; + bool evaluateAsRelocatableImpl(MCValue &Res, const MCAsmLayout *Layout, + const MCFixup *Fixup) const override; + void visitUsedExpr(MCStreamer &Streamer) const override; + MCFragment *findAssociatedFragment() const override { + return getSubExpr()->findAssociatedFragment(); + } + + void fixELFSymbolsInTLSFixups(MCAssembler &Asm) const override; +}; +} // end namespace llvm + +#endif Index: lib/Target/Nios2/MCTargetDesc/Nios2MCExpr.cpp =================================================================== --- /dev/null +++ lib/Target/Nios2/MCTargetDesc/Nios2MCExpr.cpp @@ -0,0 +1,76 @@ +//===-- Nios2MCExpr.cpp - Nios2 specific MC expression classes ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Nios2.h" + +#include "Nios2MCExpr.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCObjectStreamer.h" +#include "llvm/MC/MCSymbolELF.h" + +using namespace llvm; + +#define DEBUG_TYPE "nios2mcexpr" + +const Nios2MCExpr *Nios2MCExpr::create(Nios2MCExpr::Nios2ExprKind Kind, + const MCExpr *Expr, MCContext &Ctx) { + return new (Ctx) Nios2MCExpr(Kind, Expr); +} + +const Nios2MCExpr *Nios2MCExpr::create(const MCSymbol *Symbol, + Nios2MCExpr::Nios2ExprKind Kind, + MCContext &Ctx) { + const MCSymbolRefExpr *MCSym = + MCSymbolRefExpr::create(Symbol, MCSymbolRefExpr::VK_None, Ctx); + return new (Ctx) Nios2MCExpr(Kind, MCSym); +} + +void Nios2MCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const { + + switch (Kind) { + case CEK_None: + case CEK_Special: + llvm_unreachable("CEK_None and CEK_Special are invalid"); + break; + case CEK_ABS_HI: + OS << "%hiadj"; + break; + case CEK_ABS_LO: + OS << "%lo"; + break; + } + + OS << '('; + Expr->print(OS, MAI, true); + OS << ')'; +} + +bool Nios2MCExpr::evaluateAsRelocatableImpl(MCValue &Res, + const MCAsmLayout *Layout, + const MCFixup *Fixup) const { + return getSubExpr()->evaluateAsRelocatable(Res, Layout, Fixup); +} + +void Nios2MCExpr::visitUsedExpr(MCStreamer &Streamer) const { + Streamer.visitUsedExpr(*getSubExpr()); +} + +void Nios2MCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const { + switch (getKind()) { + case CEK_None: + case CEK_Special: + llvm_unreachable("CEK_None and CEK_Special are invalid"); + break; + case CEK_ABS_HI: + case CEK_ABS_LO: + break; + } +} Index: lib/Target/Nios2/MCTargetDesc/Nios2MCTargetDesc.h =================================================================== --- lib/Target/Nios2/MCTargetDesc/Nios2MCTargetDesc.h +++ lib/Target/Nios2/MCTargetDesc/Nios2MCTargetDesc.h @@ -14,12 +14,27 @@ #ifndef LLVM_LIB_TARGET_NIOS2_MCTARGETDESC_NIOS2MCTARGETDESC_H #define LLVM_LIB_TARGET_NIOS2_MCTARGETDESC_NIOS2MCTARGETDESC_H +#include + namespace llvm { +class MCAsmBackend; +class MCObjectWriter; +class MCRegisterInfo; +class MCTargetOptions; class Target; class Triple; +class StringRef; +class raw_pwrite_stream; Target &getTheNios2Target(); +MCAsmBackend *createNios2AsmBackend(const Target &T, const MCRegisterInfo &MRI, + const Triple &TT, StringRef CPU, + const MCTargetOptions &Options); + +std::unique_ptr +createNios2ELFObjectWriter(raw_pwrite_stream &OS, uint8_t OSABI); + } // namespace llvm // Defines symbolic names for Nios2 registers. This defines a mapping from Index: lib/Target/Nios2/MCTargetDesc/Nios2MCTargetDesc.cpp =================================================================== --- lib/Target/Nios2/MCTargetDesc/Nios2MCTargetDesc.cpp +++ lib/Target/Nios2/MCTargetDesc/Nios2MCTargetDesc.cpp @@ -12,8 +12,13 @@ //===----------------------------------------------------------------------===// #include "Nios2MCTargetDesc.h" +#include "InstPrinter/Nios2InstPrinter.h" +#include "Nios2MCAsmInfo.h" +#include "Nios2TargetStreamer.h" #include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Support/TargetRegistry.h" using namespace llvm; @@ -26,4 +31,89 @@ #define GET_REGINFO_MC_DESC #include "Nios2GenRegisterInfo.inc" -extern "C" void LLVMInitializeNios2TargetMC() {} +static MCInstrInfo *createNios2MCInstrInfo() { + MCInstrInfo *X = new MCInstrInfo(); + InitNios2MCInstrInfo(X); // defined in Nios2GenInstrInfo.inc + return X; +} + +static MCRegisterInfo *createNios2MCRegisterInfo(const Triple &TT) { + MCRegisterInfo *X = new MCRegisterInfo(); + InitNios2MCRegisterInfo(X, Nios2::R15); // defined in Nios2GenRegisterInfo.inc + return X; +} + +static MCSubtargetInfo * +createNios2MCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS) { + std::string ArchFS; + if (CPU.empty() || CPU == "generic") { + if (TT.getArch() == Triple::nios2) { + if (CPU.empty() || CPU == "nios2r2") { + ArchFS = "+nios2r2"; + } else { + if (CPU == "nios2r1") { + ArchFS = "+nios2r1"; + } + } + } + } + + if (!FS.empty()) { + if (!ArchFS.empty()) + ArchFS = ArchFS + "," + FS.str(); + else + ArchFS = FS; + } + return createNios2MCSubtargetInfoImpl(TT, CPU, ArchFS); + // createNios2MCSubtargetInfoImpl defined in Nios2GenSubtargetInfo.inc +} + +static MCAsmInfo *createNios2MCAsmInfo(const MCRegisterInfo &MRI, + const Triple &TT) { + MCAsmInfo *MAI = new Nios2MCAsmInfo(TT); + + unsigned SP = MRI.getDwarfRegNum(Nios2::SP, true); + MCCFIInstruction Inst = MCCFIInstruction::createDefCfa(nullptr, SP, 0); + MAI->addInitialFrameState(Inst); + + return MAI; +} + +static MCInstPrinter *createNios2MCInstPrinter(const Triple &T, + unsigned SyntaxVariant, + const MCAsmInfo &MAI, + const MCInstrInfo &MII, + const MCRegisterInfo &MRI) { + return new Nios2InstPrinter(MAI, MII, MRI); +} + +static MCTargetStreamer *createNios2AsmTargetStreamer(MCStreamer &S, + formatted_raw_ostream &OS, + MCInstPrinter *InstPrint, + bool isVerboseAsm) { + return new Nios2TargetAsmStreamer(S, OS); +} + +extern "C" void LLVMInitializeNios2TargetMC() { + Target *T = &getTheNios2Target(); + + // Register the MC asm info. + RegisterMCAsmInfoFn X(*T, createNios2MCAsmInfo); + + // Register the MC instruction info. + TargetRegistry::RegisterMCInstrInfo(*T, createNios2MCInstrInfo); + + // Register the MC register info. + TargetRegistry::RegisterMCRegInfo(*T, createNios2MCRegisterInfo); + + // Register the asm target streamer. + TargetRegistry::RegisterAsmTargetStreamer(*T, createNios2AsmTargetStreamer); + + // Register the MC subtarget info. + TargetRegistry::RegisterMCSubtargetInfo(*T, createNios2MCSubtargetInfo); + // Register the MCInstPrinter. + TargetRegistry::RegisterMCInstPrinter(*T, createNios2MCInstPrinter); + + // Register the asm backend. + TargetRegistry::RegisterMCAsmBackend(*T, createNios2AsmBackend); +} Index: lib/Target/Nios2/MCTargetDesc/Nios2TargetStreamer.cpp =================================================================== --- /dev/null +++ lib/Target/Nios2/MCTargetDesc/Nios2TargetStreamer.cpp @@ -0,0 +1,22 @@ +//===-- Nios2TargetStreamer.cpp - Nios2 Target Streamer Methods -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides Nios2 specific target streamer methods. +// +//===----------------------------------------------------------------------===// + +#include "Nios2TargetStreamer.h" + +using namespace llvm; + +Nios2TargetStreamer::Nios2TargetStreamer(MCStreamer &S) : MCTargetStreamer(S) {} + +Nios2TargetAsmStreamer::Nios2TargetAsmStreamer(MCStreamer &S, + formatted_raw_ostream &OS) + : Nios2TargetStreamer(S), OS(OS) {} Index: lib/Target/Nios2/Nios2.h =================================================================== --- lib/Target/Nios2/Nios2.h +++ lib/Target/Nios2/Nios2.h @@ -19,7 +19,17 @@ #include "llvm/Target/TargetMachine.h" namespace llvm { +class FunctionPass; +class formatted_raw_ostream; class Nios2TargetMachine; +class AsmPrinter; +class MachineInstr; +class MCInst; + +FunctionPass *createNios2ISelDag(Nios2TargetMachine &TM, + CodeGenOpt::Level OptLevel); +void LowerNios2MachineInstToMCInst(const MachineInstr *MI, MCInst &OutMI, + AsmPrinter &AP); } // namespace llvm #endif Index: lib/Target/Nios2/Nios2.td =================================================================== --- lib/Target/Nios2/Nios2.td +++ lib/Target/Nios2/Nios2.td @@ -13,12 +13,9 @@ include "llvm/Target/Target.td" include "Nios2RegisterInfo.td" -include "Nios2InstrInfo.td" include "Nios2Schedule.td" - -def Nios2InstrInfo : InstrInfo; - -def Nios2 : Target { let InstructionSet = Nios2InstrInfo; } +include "Nios2InstrInfo.td" +include "Nios2CallingConv.td" //===----------------------------------------------------------------------===// // Nios2 Subtarget features @@ -37,3 +34,26 @@ def : Proc<"nios2r1", [FeatureNios2r1]>; def : Proc<"nios2r2", [FeatureNios2r2]>; + +def Nios2InstrInfo : InstrInfo; + +def Nios2AsmParser : AsmParser { + let ShouldEmitMatchRegisterName = 0; +} + +//===----------------------------------------------------------------------===// +// Declare the target which we are implementing +//===----------------------------------------------------------------------===// + +def Nios2AsmWriter : AsmWriter { + string AsmWriterClassName = "InstPrinter"; + int PassSubtarget = 1; + int Variant = 0; +} + +def Nios2 : Target { +// def Nios2InstrInfo : InstrInfo as before. + let InstructionSet = Nios2InstrInfo; + let AssemblyParsers = [Nios2AsmParser]; + let AssemblyWriters = [Nios2AsmWriter]; +} Index: lib/Target/Nios2/Nios2AsmPrinter.cpp =================================================================== --- /dev/null +++ lib/Target/Nios2/Nios2AsmPrinter.cpp @@ -0,0 +1,153 @@ +//===-- Nios2AsmPrinter.cpp - Nios2 LLVM Assembly Printer -----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains a printer that converts from our internal representation +// of machine-dependent LLVM code to GAS-format NIOS2 assembly language. +// +//===----------------------------------------------------------------------===// + +#include "InstPrinter/Nios2InstPrinter.h" +#include "MCTargetDesc/Nios2BaseInfo.h" +#include "Nios2.h" +#include "Nios2TargetMachine.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/Support/TargetRegistry.h" + +using namespace llvm; + +#define DEBUG_TYPE "nios2-asm-printer" + +namespace { + +class Nios2AsmPrinter : public AsmPrinter { + +public: + explicit Nios2AsmPrinter(TargetMachine &TM, + std::unique_ptr Streamer) + : AsmPrinter(TM, std::move(Streamer)) {} + + StringRef getPassName() const override { return "Nios2 Assembly Printer"; } + + //- EmitInstruction() must exists or will have run time error. + void EmitInstruction(const MachineInstr *MI) override; + bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &O) override; + bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum, + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &O) override; + void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O); + void EmitFunctionEntryLabel() override; +}; +} // namespace + +//- EmitInstruction() must exists or will have run time error. +void Nios2AsmPrinter::EmitInstruction(const MachineInstr *MI) { + + // Print out both ordinary instruction and boudle instruction + MachineBasicBlock::const_instr_iterator I = MI->getIterator(); + MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end(); + + do { + + if (I->isPseudo()) { + llvm_unreachable("Pseudo opcode found in EmitInstruction()"); + } + + MCInst TmpInst0; + LowerNios2MachineInstToMCInst(&*I, TmpInst0, *this); + EmitToStreamer(*OutStreamer, TmpInst0); + } while ((++I != E) && I->isInsideBundle()); // Delay slot check +} + +// .type main,@function +//-> .ent main # @main +// main: +void Nios2AsmPrinter::EmitFunctionEntryLabel() { + OutStreamer->EmitLabel(CurrentFnSym); +} + +// Print out an operand for an inline asm expression. +bool Nios2AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, + unsigned AsmVariant, + const char *ExtraCode, raw_ostream &O) { + printOperand(MI, OpNum, O); + return false; +} + +bool Nios2AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, + unsigned OpNum, unsigned AsmVariant, + const char *ExtraCode, + raw_ostream &O) { + if (ExtraCode && ExtraCode[0]) + return true; // Unknown modifier + + const MachineOperand &MO = MI->getOperand(OpNum); + assert(MO.isReg() && "unexpected inline asm memory operand"); + O << "($" << Nios2InstPrinter::getRegisterName(MO.getReg()) << ")"; + + return false; +} + +void Nios2AsmPrinter::printOperand(const MachineInstr *MI, int opNum, + raw_ostream &O) { + const MachineOperand &MO = MI->getOperand(opNum); + bool closeP = false; + + if (MO.getTargetFlags()) + closeP = true; + + switch (MO.getTargetFlags()) { + case Nios2FG::MO_ABS_HI: + O << "%hiadj("; + break; + case Nios2FG::MO_ABS_LO: + O << "%lo("; + break; + } + + switch (MO.getType()) { + case MachineOperand::MO_Register: + O << '$' + << StringRef(Nios2InstPrinter::getRegisterName(MO.getReg())).lower(); + break; + + case MachineOperand::MO_Immediate: + O << MO.getImm(); + break; + + case MachineOperand::MO_MachineBasicBlock: + MO.getMBB()->getSymbol()->print(O, MAI); + return; + + case MachineOperand::MO_GlobalAddress: + getSymbol(MO.getGlobal())->print(O, MAI); + break; + + case MachineOperand::MO_BlockAddress: + O << GetBlockAddressSymbol(MO.getBlockAddress())->getName(); + break; + + case MachineOperand::MO_ExternalSymbol: + O << MO.getSymbolName(); + break; + + default: + llvm_unreachable(""); + } + + if (closeP) + O << ")"; +} + +// Force static initialization. +extern "C" void LLVMInitializeNios2AsmPrinter() { + RegisterAsmPrinter X(getTheNios2Target()); +} Index: lib/Target/Nios2/Nios2CallingConv.td =================================================================== --- /dev/null +++ lib/Target/Nios2/Nios2CallingConv.td @@ -0,0 +1,34 @@ +//===- Nios2CallingConv.td - Calling Conventions for Nios2 -*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// This describes the calling conventions for Nios2 architecture. +//===----------------------------------------------------------------------===// + +/// CCIfSubtarget - Match if the current subtarget has a feature F. +class CCIfSubtarget: + CCIf().", F), A>; + +def CC_Nios2 : CallingConv<[ + // i32 f32 arguments get passed in integer registers if there is space. + CCIfType<[i32, f32], CCAssignToReg<[R4, R5, R6, R7]>>, + + // Alternatively, they are assigned to the stack in 4-byte aligned units. + CCAssignToStack<4, 4> +]>; + +def RetCC_Nios2EABI : CallingConv<[ + // i32 are returned in registers R2, R3 + CCIfType<[i32], CCAssignToReg<[R2, R3]>>, + // In case of floating point (FPH2 instr.) also use the same register set + CCIfType<[f32], CCAssignToReg<[R2, R3]>>, + CCIfByVal>, + // Stack parameter slots for i32 is 32-bit words and 4-byte aligned. + CCIfType<[i32], CCAssignToStack<4, 4>> +]>; + +def CSR : CalleeSavedRegs<(add RA, FP, (sequence "R%u", 16, 23))>; Index: lib/Target/Nios2/Nios2FrameLowering.h =================================================================== --- lib/Target/Nios2/Nios2FrameLowering.h +++ lib/Target/Nios2/Nios2FrameLowering.h @@ -24,11 +24,10 @@ const Nios2Subtarget &STI; public: - explicit Nios2FrameLowering(const Nios2Subtarget &sti, unsigned Alignment) - : TargetFrameLowering(StackGrowsDown, Alignment, 0, Alignment), STI(sti) { - } + explicit Nios2FrameLowering(const Nios2Subtarget &sti) + : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, 4, 0, 4), + STI(sti) {} - static const Nios2FrameLowering *create(const Nios2Subtarget &ST); bool hasFP(const MachineFunction &MF) const override; /// emitProlog/emitEpilog - These methods insert prolog and epilog code into /// the function. Index: lib/Target/Nios2/Nios2FrameLowering.cpp =================================================================== --- lib/Target/Nios2/Nios2FrameLowering.cpp +++ lib/Target/Nios2/Nios2FrameLowering.cpp @@ -25,7 +25,3 @@ void Nios2FrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const {} - -const Nios2FrameLowering *Nios2FrameLowering::create(const Nios2Subtarget &ST) { - return new Nios2FrameLowering(ST, 4); -} Index: lib/Target/Nios2/Nios2ISelDAGToDAG.cpp =================================================================== --- /dev/null +++ lib/Target/Nios2/Nios2ISelDAGToDAG.cpp @@ -0,0 +1,79 @@ +//===-- Nios2ISelDAGToDAG.cpp - A Dag to Dag Inst Selector for Nios2 ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines an instruction selector for the NIOS2 target. +// +//===----------------------------------------------------------------------===// + +#include "Nios2.h" +#include "Nios2TargetMachine.h" +#include "llvm/CodeGen/SelectionDAGISel.h" +#include "llvm/Support/Debug.h" +using namespace llvm; + +#define DEBUG_TYPE "nios2-isel" + +//===----------------------------------------------------------------------===// +// Instruction Selector Implementation +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Nios2DAGToDAGISel - NIOS2 specific code to select NIOS2 machine +// instructions for SelectionDAG operations. +//===----------------------------------------------------------------------===// + +namespace { + +class Nios2DAGToDAGISel : public SelectionDAGISel { + /// Subtarget - Keep a pointer to the Nios2 Subtarget around so that we can + /// make the right decision when generating code for different targets. + const Nios2Subtarget *Subtarget; + +public: + explicit Nios2DAGToDAGISel(Nios2TargetMachine &TM, CodeGenOpt::Level OL) + : SelectionDAGISel(TM, OL) {} + + bool runOnMachineFunction(MachineFunction &MF) override { + Subtarget = &MF.getSubtarget(); + return SelectionDAGISel::runOnMachineFunction(MF); + } + + void Select(SDNode *N) override; + + // Pass Name + StringRef getPassName() const override { + return "NIOS2 DAG->DAG Pattern Instruction Selection"; + } + +#include "Nios2GenDAGISel.inc" +}; +} // namespace + +// Select instructions not customized! Used for +// expanded, promoted and normal instructions +void Nios2DAGToDAGISel::Select(SDNode *Node) { + + // Dump information about the Node being selected + DEBUG(errs() << "Selecting: "; Node->dump(CurDAG); errs() << "\n"); + + // If we have a custom node, we already have selected! + if (Node->isMachineOpcode()) { + DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n"); + Node->setNodeId(-1); + return; + } + + // Select the default instruction + SelectCode(Node); +} + +FunctionPass *llvm::createNios2ISelDag(Nios2TargetMachine &TM, + CodeGenOpt::Level OptLevel) { + return new Nios2DAGToDAGISel(TM, OptLevel); +} Index: lib/Target/Nios2/Nios2ISelLowering.h =================================================================== --- /dev/null +++ lib/Target/Nios2/Nios2ISelLowering.h @@ -0,0 +1,63 @@ +//===-- Nios2ISelLowering.h - Nios2 DAG Lowering Interface ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the interfaces that Nios2 uses to lower LLVM code into a +// selection DAG. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_NIOS2_NIOS2ISELLOWERING_H +#define LLVM_LIB_TARGET_NIOS2_NIOS2ISELLOWERING_H + +#include "Nios2.h" +#include "llvm/Target/TargetLowering.h" + +namespace llvm { +class Nios2Subtarget; + +namespace Nios2ISD { +enum NodeType { + // Start the numbering from where ISD NodeType finishes. + FIRST_NUMBER = ISD::BUILTIN_OP_END, + + // Get the Higher 16 bits from a 32-bit immediate + // No relation with Nios2 Hi register + Hi, + // Get the Lower 16 bits from a 32-bit immediate + // No relation with Nios2 Lo register + Lo, + // Return + Ret +}; +} + +class Nios2TargetLowering : public TargetLowering { + const Nios2Subtarget *Subtarget; + +public: + Nios2TargetLowering(const TargetMachine &TM, const Nios2Subtarget &STI); + + /// getTargetNodeName - This method returns the name of a target specific + // DAG node. + const char *getTargetNodeName(unsigned Opcode) const override; + + SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, + bool IsVarArg, + const SmallVectorImpl &Ins, + const SDLoc &dl, SelectionDAG &DAG, + SmallVectorImpl &InVals) const override; + + SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl &Outs, + const SmallVectorImpl &OutVals, const SDLoc &dl, + SelectionDAG &DAG) const override; +}; +} // end namespace llvm + +#endif // NIOS2_ISELLOWERING_H Index: lib/Target/Nios2/Nios2ISelLowering.cpp =================================================================== --- /dev/null +++ lib/Target/Nios2/Nios2ISelLowering.cpp @@ -0,0 +1,159 @@ +//===-- Nios2ISelLowering.cpp - Nios2 DAG Lowering Implementation ---------===// +// +// 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 interfaces that Nios2 uses to lower LLVM code into a +// selection DAG. +// +//===----------------------------------------------------------------------===// + +#include "Nios2ISelLowering.h" +#include "Nios2MachineFunction.h" +#include "Nios2TargetMachine.h" +#include "llvm/CodeGen/CallingConvLower.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" + +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Calling Convention Implementation +//===----------------------------------------------------------------------===// + +#include "Nios2GenCallingConv.inc" + +SDValue +Nios2TargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, + bool IsVarArg, + const SmallVectorImpl &Outs, + const SmallVectorImpl &OutVals, + const SDLoc &DL, SelectionDAG &DAG) const { + + SmallVector RetOps(1, Chain); + + return DAG.getNode(Nios2ISD::Ret, DL, MVT::Other, RetOps); +} + +// addLiveIn - This helper function adds the specified physical register to the +// MachineFunction as a live in value. It also creates a corresponding +// virtual register for it. +static unsigned addLiveIn(MachineFunction &MF, unsigned PReg, + const TargetRegisterClass *RC) { + unsigned VReg = MF.getRegInfo().createVirtualRegister(RC); + MF.getRegInfo().addLiveIn(PReg, VReg); + return VReg; +} + +//===----------------------------------------------------------------------===// +// Formal Arguments Calling Convention Implementation +//===----------------------------------------------------------------------===// + +// LowerFormalArguments - transform physical registers into virtual registers +// and generate load operations for arguments places on the stack. +SDValue Nios2TargetLowering::LowerFormalArguments( + SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, + const SmallVectorImpl &Ins, const SDLoc &DL, + SelectionDAG &DAG, SmallVectorImpl &InVals) const { + MachineFunction &MF = DAG.getMachineFunction(); + MachineFrameInfo &MFI = MF.getFrameInfo(); + + // Assign locations to all of the incoming arguments. + SmallVector ArgLocs; + CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs, + *DAG.getContext()); + + CCInfo.AnalyzeFormalArguments(Ins, CC_Nios2); + + // Used with vargs to acumulate store chains. + std::vector OutChains; + + for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { + CCValAssign &VA = ArgLocs[i]; + + EVT ValVT = VA.getValVT(); + + // Arguments stored on registers + if (VA.isRegLoc()) { + MVT RegVT = VA.getLocVT(); + unsigned ArgReg = VA.getLocReg(); + const TargetRegisterClass *RC = getRegClassFor(RegVT); + + // Transform the arguments stored on + // physical registers into virtual ones + unsigned Reg = addLiveIn(MF, ArgReg, RC); + SDValue ArgValue = DAG.getCopyFromReg(Chain, DL, Reg, RegVT); + + // If this is an 8 or 16-bit value, it has been passed promoted + // to 32 bits. Insert an assert[sz]ext to capture this, then + // truncate to the right size. + if (VA.getLocInfo() != CCValAssign::Full) { + unsigned Opcode = 0; + if (VA.getLocInfo() == CCValAssign::SExt) + Opcode = ISD::AssertSext; + else if (VA.getLocInfo() == CCValAssign::ZExt) + Opcode = ISD::AssertZext; + if (Opcode) + ArgValue = + DAG.getNode(Opcode, DL, RegVT, ArgValue, DAG.getValueType(ValVT)); + ArgValue = DAG.getNode(ISD::TRUNCATE, DL, ValVT, ArgValue); + } + + // Handle floating point arguments passed in integer registers. + if ((RegVT == MVT::i32 && ValVT == MVT::f32) || + (RegVT == MVT::i64 && ValVT == MVT::f64)) + ArgValue = DAG.getNode(ISD::BITCAST, DL, ValVT, ArgValue); + InVals.push_back(ArgValue); + } else { // VA.isRegLoc() + MVT LocVT = VA.getLocVT(); + + // sanity check + assert(VA.isMemLoc()); + + // The stack pointer offset is relative to the caller stack frame. + int FI = MFI.CreateFixedObject(ValVT.getSizeInBits() / 8, + VA.getLocMemOffset(), true); + + // Create load nodes to retrieve arguments from the stack + SDValue FIN = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout())); + SDValue Load = DAG.getLoad( + LocVT, DL, Chain, FIN, + MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI)); + InVals.push_back(Load); + OutChains.push_back(Load.getValue(1)); + } + } + if (!OutChains.empty()) { + OutChains.push_back(Chain); + Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains); + } + + return Chain; +} + +//===----------------------------------------------------------------------===// +// TargetLowering Implementation +//===----------------------------------------------------------------------===// + +Nios2TargetLowering::Nios2TargetLowering(const TargetMachine &TM, + const Nios2Subtarget &STI) + : TargetLowering(TM), Subtarget(&STI) { + + addRegisterClass(MVT::i32, &Nios2::CPURegsRegClass); + computeRegisterProperties(Subtarget->getRegisterInfo()); +} + +const char *Nios2TargetLowering::getTargetNodeName(unsigned Opcode) const { + switch (Opcode) { + case Nios2ISD::Hi: + return "Nios2ISD::Hi"; + case Nios2ISD::Lo: + return "Nios2ISD::Lo"; + case Nios2ISD::Ret: + return "Nios2ISD::Ret"; + } + return nullptr; +} Index: lib/Target/Nios2/Nios2InstrFormats.td =================================================================== --- lib/Target/Nios2/Nios2InstrFormats.td +++ lib/Target/Nios2/Nios2InstrFormats.td @@ -16,8 +16,8 @@ // Format specifies the encoding used by the instruction. This is part of the // ad-hoc solution used to emit machine instruction encodings by our machine // code emitter. -class Format val> { - bits<3> Value = val; +class Format val> { + bits<6> Value = val; } def Pseudo : Format<0>; @@ -26,92 +26,158 @@ def FrmJ : Format<3>; def FrmOther : Format<4>; // Instruction w/ a custom format -// Generic Nios2 Format -class Nios2Inst pattern, Format f> - : Instruction { +def isNios2r1 : Predicate<"Subtarget->isNios2r1()">; +def isNios2r2 : Predicate<"Subtarget->isNios2r2()">; + +class PredicateControl { + // Predicates related to specific target CPU features + list FeaturePredicates = []; + // Predicates for the instruction group membership in given ISA + list InstrPredicates = []; + + list Predicates = !listconcat(FeaturePredicates, InstrPredicates); +} + +//===----------------------------------------------------------------------===// +// Base classes for 32-bit, 16-bit and pseudo instructions +//===----------------------------------------------------------------------===// + +class Nios2Inst32 pattern, + InstrItinClass itin, Format f>: Instruction, + PredicateControl { field bits<32> Inst; Format Form = f; let Namespace = "Nios2"; - let Size = 4; bits<6> Opcode = 0; // Bottom 6 bits are the 'opcode' field - let Inst{5 - 0} = Opcode; + let Inst{5-0} = Opcode; let OutOperandList = outs; - let InOperandList = ins; + let InOperandList = ins; let AsmString = asmstr; - let Pattern = pattern; + let Pattern = pattern; + let Itinerary = itin; - // // Attributes specific to Nios2 instructions: - // - bits<3> FormBits = Form.Value; // TSFlags layout should be kept in sync with Nios2InstrInfo.h. - let TSFlags{2 - 0} = FormBits; + let TSFlags{5-0} = Form.Value; + let DecoderNamespace = "Nios2"; + field bits<32> SoftFail = 0; +} +class Nios2Pseudo pattern, + InstrItinClass Itin = IIPseudo>: + Nios2Inst32 { + + let isCodeGenOnly = 1; + let isPseudo = 1; +} + +//===----------------------------------------------------------------------===// +// Base classes for R1 and R2 instructions +//===----------------------------------------------------------------------===// + +class Nios2R1Inst32 pattern, + InstrItinClass itin, Format f>: + Nios2Inst32 { let DecoderNamespace = "Nios2"; + let InstrPredicates = [isNios2r1]; } -// Nios2 Instruction Format -class InstSE pattern, Format f> - : Nios2Inst { +class Nios2R2Inst32 pattern, + InstrItinClass itin, Format f>: + Nios2Inst32 { + let DecoderNamespace = "Nios2r2"; + let InstrPredicates = [isNios2r2]; } //===----------------------------------------------------------------------===// // Format I instruction class in Nios2 : <|A|B|immediate|opcode|> //===----------------------------------------------------------------------===// -class FI op, dag outs, dag ins, string asmstr, list pattern> - : InstSE { - bits<5> rA; - bits<5> rB; +class FI op, dag outs, dag ins, string asmstr, list pattern, + InstrItinClass itin>: Nios2R1Inst32 { + + bits<5> rA; + bits<5> rB; bits<16> imm; let Opcode = op; - let Inst{31 - 27} = rA; - let Inst{26 - 22} = rB; - let Inst{21 - 6} = imm; + let Inst{31-27} = rA; + let Inst{26-22} = rB; + let Inst{21-6} = imm; } + //===----------------------------------------------------------------------===// // Format R instruction : <|A|B|C|opx|imm|opcode|> //===----------------------------------------------------------------------===// -class FR opx, dag outs, dag ins, string asmstr, list pattern> - : InstSE { +class FR opx, dag outs, dag ins, string asmstr, list pattern, + InstrItinClass itin>: Nios2R1Inst32 { bits<5> rA; bits<5> rB; bits<5> rC; bits<5> imm = 0; - // opcode is always 0x3a for R instr. - let Opcode = 0x3a; + let Opcode = 0x3a; /* opcode is always 0x3a for R instr. */ - let Inst{31 - 27} = rA; - let Inst{26 - 22} = rB; - let Inst{21 - 17} = rC; - // opx stands for opcode extension - let Inst{16 - 11} = opx; - // optional 5-bit immediate value - let Inst{10 - 6} = imm; + let Inst{31-27} = rA; + let Inst{26-22} = rB; + let Inst{21-17} = rC; + let Inst{16-11} = opx; /* opx stands for opcode extension */ + let Inst{10-6} = imm; /* optional 5-bit immediate value */ } //===----------------------------------------------------------------------===// // Format J instruction class in Nios2 : <|address|opcode|> //===----------------------------------------------------------------------===// -class FJ op, dag outs, dag ins, string asmstr, list pattern> - : InstSE { +class FJ op, dag outs, dag ins, string asmstr, list pattern, + InstrItinClass itin>: + Nios2R1Inst32 { bits<26> addr; - let Opcode = op; + let Inst{31-6} = addr; +} - let Inst{31 - 6} = addr; +//===----------------------------------------------------------------------===// +// Multiclasses for common instructions of both R1 and R2: +//===----------------------------------------------------------------------===// + +// Multiclass for instructions that have R format in R1 and F3X6 format in R2 +// and their opx values differ between R1 and R2 +multiclass CommonInstr_R_F3X6_opx opxR1, bits<6> opxR2, dag outs, + dag ins, string asmstr, list pattern, + InstrItinClass itin> { + def NAME#_R1 : FR; } + +// Multiclass for instructions that have R format in R1 and F3X6 format in R2 +// and their opx values are the same in R1 and R2 +multiclass CommonInstr_R_F3X6 opx, dag outs, dag ins, string asmstr, + list pattern, InstrItinClass itin> : + CommonInstr_R_F3X6_opx; + +// Multiclass for instructions that have I format in R1 and F2I16 format in R2 +// and their op code values differ between R1 and R2 +multiclass CommonInstr_I_F2I16_op opR1, bits<6> opR2, dag outs, dag ins, + string asmstr, list pattern, + InstrItinClass itin> { + def NAME#_R1 : FI; +} + +// Multiclass for instructions that have I format in R1 and F2I16 format in R2 +// and their op code values are the same in R1 and R2 +multiclass CommonInstr_I_F2I16 op, dag outs, dag ins, string asmstr, + list pattern, InstrItinClass itin> : + CommonInstr_I_F2I16_op; Index: lib/Target/Nios2/Nios2InstrInfo.h =================================================================== --- lib/Target/Nios2/Nios2InstrInfo.h +++ lib/Target/Nios2/Nios2InstrInfo.h @@ -14,10 +14,7 @@ #ifndef LLVM_LIB_TARGET_NIOS2_NIOS2INSTRINFO_H #define LLVM_LIB_TARGET_NIOS2_NIOS2INSTRINFO_H -#include "Nios2.h" #include "Nios2RegisterInfo.h" - -#include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/Target/TargetInstrInfo.h" #define GET_INSTRINFO_HEADER @@ -25,22 +22,23 @@ namespace llvm { +class Nios2Subtarget; + class Nios2InstrInfo : public Nios2GenInstrInfo { -protected: - const Nios2Subtarget &Subtarget; const Nios2RegisterInfo RI; + const Nios2Subtarget &Subtarget; + virtual void anchor(); public: - explicit Nios2InstrInfo(const Nios2Subtarget &STI) - : Nios2GenInstrInfo(), Subtarget(STI), RI(STI) {} - - static const Nios2InstrInfo *create(Nios2Subtarget &STI); + explicit Nios2InstrInfo(Nios2Subtarget &ST); /// getRegisterInfo - TargetInstrInfo is a superset of MRegister info. As /// such, whenever a client has an instance of instruction info, it should /// always be able to get register info as well (through this method). /// - const Nios2RegisterInfo &getRegisterInfo() const; + const Nios2RegisterInfo &getRegisterInfo() const { return RI; }; + + bool expandPostRAPseudo(MachineInstr &MI) const override; }; } // namespace llvm Index: lib/Target/Nios2/Nios2InstrInfo.cpp =================================================================== --- lib/Target/Nios2/Nios2InstrInfo.cpp +++ lib/Target/Nios2/Nios2InstrInfo.cpp @@ -13,14 +13,31 @@ #include "Nios2InstrInfo.h" #include "Nios2TargetMachine.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" using namespace llvm; #define GET_INSTRINFO_CTOR_DTOR #include "Nios2GenInstrInfo.inc" -const Nios2InstrInfo *Nios2InstrInfo::create(Nios2Subtarget &STI) { - return new Nios2InstrInfo(STI); -} +// Pin the vtable to this file. +void Nios2InstrInfo::anchor() {} + +Nios2InstrInfo::Nios2InstrInfo(Nios2Subtarget &ST) + : Nios2GenInstrInfo(), RI(ST), Subtarget(ST) {} + +/// Expand Pseudo instructions into real backend instructions +bool Nios2InstrInfo::expandPostRAPseudo(MachineInstr &MI) const { + MachineBasicBlock &MBB = *MI.getParent(); -const Nios2RegisterInfo &Nios2InstrInfo::getRegisterInfo() const { return RI; } + switch (MI.getDesc().getOpcode()) { + default: + return false; + case Nios2::RetRA: + BuildMI(MBB, MI, MI.getDebugLoc(), get(Nios2::RET_R1)).addReg(Nios2::RA); + break; + } + + MBB.erase(MI); + return true; +} Index: lib/Target/Nios2/Nios2InstrInfo.td =================================================================== --- lib/Target/Nios2/Nios2InstrInfo.td +++ lib/Target/Nios2/Nios2InstrInfo.td @@ -17,11 +17,12 @@ include "Nios2InstrFormats.td" + //===----------------------------------------------------------------------===// // Nios2 Operand, Complex Patterns and Transformations Definitions. //===----------------------------------------------------------------------===// -def simm16 : Operand { +def simm16 : Operand { let DecoderMethod= "DecodeSimm16"; } @@ -33,18 +34,45 @@ // Instructions specific format //===----------------------------------------------------------------------===// -// Arithmetic and logical instructions with 2 register operands. -class ArithLogicI op, string instr_asm, SDNode OpNode, - Operand Od, PatLeaf imm_type, RegisterClass RC> : - FI { - let isReMaterializable = 1; +// Arithmetic and logical instructions with 2 registers and 16-bit immediate +// value. +multiclass ArithLogicRegImm16 op, string mnemonic, SDNode opNode, + Operand immOp, PatLeaf immType>: + CommonInstr_I_F2I16; + +multiclass Return opx, dag outs, dag ins, string mnemonic> { + let rB = 0, rC = 0, + isReturn = 1, + isCodeGenOnly = 1, + hasCtrlDep = 1, + hasExtraSrcRegAllocReq = 1 in { + defm NAME# : CommonInstr_R_F3X6; + } } +// Custom return SDNode +def Nios2Ret : SDNode<"Nios2ISD::Ret", SDTNone, + [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; + //===----------------------------------------------------------------------===// -// Nios2 R1 Instructions +// Nios2 Instructions //===----------------------------------------------------------------------===// /// Arithmetic Instructions (ALU Immediate) -def ADDi : ArithLogicI<0x04, "addi", add, simm16, immSExt16, CPURegs>; +defm ADDI : ArithLogicRegImm16<0x04, "addi", add, simm16, immSExt16>; + +// Returns: +defm RET : Return<0x05, (outs), (ins CPURegs:$rA), "ret">; + +//===----------------------------------------------------------------------===// +// Pseudo instructions +//===----------------------------------------------------------------------===// + +// Return RA. +let isReturn=1, isTerminator=1, hasDelaySlot=1, isBarrier=1, hasCtrlDep=1 in +def RetRA : Nios2Pseudo<(outs), (ins), "", [(Nios2Ret)]>; Index: lib/Target/Nios2/Nios2MCInstLower.cpp =================================================================== --- /dev/null +++ lib/Target/Nios2/Nios2MCInstLower.cpp @@ -0,0 +1,117 @@ +//===-- Nios2MCInstLower.cpp - Convert Nios2 MachineInstr to MCInst -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains code to lower Nios2 MachineInstrs to their corresponding +// MCInst records. +// +//===----------------------------------------------------------------------===// + +#include "MCTargetDesc/Nios2BaseInfo.h" +#include "MCTargetDesc/Nios2MCExpr.h" +#include "Nios2.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineOperand.h" + +using namespace llvm; + +static MCOperand LowerSymbolOperand(const MachineOperand &MO, AsmPrinter &AP) { + MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VK_None; + Nios2MCExpr::Nios2ExprKind TargetKind = Nios2MCExpr::CEK_None; + const MCSymbol *Symbol; + + switch (MO.getTargetFlags()) { + default: + llvm_unreachable("Invalid target flag!"); + case Nios2FG::MO_NO_FLAG: + break; + case Nios2FG::MO_ABS_HI: + TargetKind = Nios2MCExpr::CEK_ABS_HI; + break; + case Nios2FG::MO_ABS_LO: + TargetKind = Nios2MCExpr::CEK_ABS_LO; + break; + } + + switch (MO.getType()) { + case MachineOperand::MO_GlobalAddress: + Symbol = AP.getSymbol(MO.getGlobal()); + break; + + case MachineOperand::MO_MachineBasicBlock: + Symbol = MO.getMBB()->getSymbol(); + break; + + case MachineOperand::MO_BlockAddress: + Symbol = AP.GetBlockAddressSymbol(MO.getBlockAddress()); + break; + + case MachineOperand::MO_ExternalSymbol: + Symbol = AP.GetExternalSymbolSymbol(MO.getSymbolName()); + break; + + case MachineOperand::MO_JumpTableIndex: + Symbol = AP.GetJTISymbol(MO.getIndex()); + break; + + case MachineOperand::MO_ConstantPoolIndex: + Symbol = AP.GetCPISymbol(MO.getIndex()); + break; + + default: + llvm_unreachable(""); + } + + const MCExpr *Expr = MCSymbolRefExpr::create(Symbol, Kind, AP.OutContext); + + if (TargetKind != Nios2MCExpr::CEK_None) + Expr = Nios2MCExpr::create(TargetKind, Expr, AP.OutContext); + + return MCOperand::createExpr(Expr); +} + +static MCOperand LowerOperand(const MachineOperand &MO, AsmPrinter &AP) { + + switch (MO.getType()) { + default: + llvm_unreachable("unknown operand type"); + case MachineOperand::MO_Register: + // Ignore all implicit register operands. + if (MO.isImplicit()) + break; + return MCOperand::createReg(MO.getReg()); + case MachineOperand::MO_Immediate: + return MCOperand::createImm(MO.getImm()); + case MachineOperand::MO_MachineBasicBlock: + case MachineOperand::MO_ExternalSymbol: + case MachineOperand::MO_JumpTableIndex: + case MachineOperand::MO_BlockAddress: + case MachineOperand::MO_GlobalAddress: + case MachineOperand::MO_ConstantPoolIndex: + return LowerSymbolOperand(MO, AP); + case MachineOperand::MO_RegisterMask: + break; + } + + return MCOperand(); +} + +void llvm::LowerNios2MachineInstToMCInst(const MachineInstr *MI, MCInst &OutMI, + AsmPrinter &AP) { + + OutMI.setOpcode(MI->getOpcode()); + + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + MCOperand MCOp = LowerOperand(MO, AP); + + if (MCOp.isValid()) + OutMI.addOperand(MCOp); + } +} Index: lib/Target/Nios2/Nios2MachineFunction.h =================================================================== --- /dev/null +++ lib/Target/Nios2/Nios2MachineFunction.h @@ -0,0 +1,62 @@ +//===-- Nios2MachineFunctionInfo.h - Private data used for Nios2 --*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the Nios2 specific subclass of MachineFunctionInfo. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_NIOS2_NIOS2MACHINEFUNCTION_H +#define LLVM_LIB_TARGET_NIOS2_NIOS2MACHINEFUNCTION_H + +#include "llvm/CodeGen/MachineFunction.h" + +namespace llvm { + +/// Nios2FunctionInfo - This class is derived from MachineFunction private +/// Nios2 target-specific information for each MachineFunction. +class Nios2FunctionInfo : public MachineFunctionInfo { + virtual void anchor(); + +private: + unsigned GlobalBaseReg; + + /// VarArgsFrameOffset - Frame offset to start of varargs area. + int VarArgsFrameOffset; + + /// SRetReturnReg - Holds the virtual register into which the sret + /// argument is passed. + unsigned SRetReturnReg; + + /// IsLeafProc - True if the function is a leaf procedure. + bool IsLeafProc; + +public: + Nios2FunctionInfo() + : GlobalBaseReg(0), VarArgsFrameOffset(0), SRetReturnReg(0), + IsLeafProc(false) {} + explicit Nios2FunctionInfo(MachineFunction &MF) + : GlobalBaseReg(0), VarArgsFrameOffset(0), SRetReturnReg(0), + IsLeafProc(false) {} + + unsigned getGlobalBaseReg() const { return GlobalBaseReg; } + void setGlobalBaseReg(unsigned Reg) { GlobalBaseReg = Reg; } + + int getVarArgsFrameOffset() const { return VarArgsFrameOffset; } + void setVarArgsFrameOffset(int Offset) { VarArgsFrameOffset = Offset; } + + unsigned getSRetReturnReg() const { return SRetReturnReg; } + void setSRetReturnReg(unsigned Reg) { SRetReturnReg = Reg; } + + void setLeafProc(bool rhs) { IsLeafProc = rhs; } + bool isLeafProc() const { return IsLeafProc; } +}; + +} // end of namespace llvm + +#endif // NIOS2_MACHINE_FUNCTION_INFO_H Index: lib/Target/Nios2/Nios2MachineFunction.cpp =================================================================== --- /dev/null +++ lib/Target/Nios2/Nios2MachineFunction.cpp @@ -0,0 +1,14 @@ +//===-- Nios2MachineFunctionInfo.cpp - Private data used for Nios2 --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Nios2MachineFunction.h" + +using namespace llvm; + +void Nios2FunctionInfo::anchor() {} Index: lib/Target/Nios2/Nios2RegisterInfo.cpp =================================================================== --- lib/Target/Nios2/Nios2RegisterInfo.cpp +++ lib/Target/Nios2/Nios2RegisterInfo.cpp @@ -32,11 +32,16 @@ const MCPhysReg * Nios2RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { - return nullptr; + return CSR_SaveList; } BitVector Nios2RegisterInfo::getReservedRegs(const MachineFunction &MF) const { - BitVector Reserved(1); + static const uint16_t ReservedCPURegs[] = {Nios2::ZERO, Nios2::AT, Nios2::SP, + Nios2::RA, Nios2::PC, Nios2::GP}; + BitVector Reserved(getNumRegs()); + + for (unsigned I = 0; I < array_lengthof(ReservedCPURegs); ++I) + Reserved.set(ReservedCPURegs[I]); return Reserved; } @@ -46,5 +51,5 @@ RegScavenger *RS) const {} unsigned Nios2RegisterInfo::getFrameRegister(const MachineFunction &MF) const { - return 0; + return Nios2::SP; } Index: lib/Target/Nios2/Nios2Subtarget.h =================================================================== --- lib/Target/Nios2/Nios2Subtarget.h +++ lib/Target/Nios2/Nios2Subtarget.h @@ -15,7 +15,10 @@ #define LLVM_LIB_TARGET_NIOS2_NIOS2SUBTARGET_H #include "Nios2FrameLowering.h" +#include "Nios2ISelLowering.h" #include "Nios2InstrInfo.h" +#include "llvm/CodeGen/SelectionDAGTargetInfo.h" +#include "llvm/CodeGen/TargetFrameLowering.h" #include "llvm/Target/TargetSubtargetInfo.h" #define GET_SUBTARGETINFO_HEADER @@ -51,18 +54,18 @@ // Nios2 architecture version Nios2ArchEnum Nios2ArchVersion; - const Nios2TargetMachine &TM; - Triple TargetTriple; - std::unique_ptr InstrInfo; - std::unique_ptr FrameLowering; + Nios2InstrInfo InstrInfo; + Nios2TargetLowering TLInfo; + SelectionDAGTargetInfo TSInfo; + Nios2FrameLowering FrameLowering; public: /// This constructor initializes the data members to match that /// of the specified triple. Nios2Subtarget(const Triple &TT, const std::string &CPU, - const std::string &FS, const Nios2TargetMachine &_TM); + const std::string &FS, const TargetMachine &TM); /// ParseSubtargetFeatures - Parses features string setting specified /// subtarget options. Definition of function is auto generated by tblgen. @@ -73,14 +76,20 @@ bool hasNios2r2() const { return Nios2ArchVersion >= Nios2r2; } bool isNios2r2() const { return Nios2ArchVersion == Nios2r2; } - Nios2Subtarget &initializeSubtargetDependencies(StringRef CPU, StringRef FS, - const TargetMachine &TM); + Nios2Subtarget &initializeSubtargetDependencies(StringRef CPU, StringRef FS); + const Nios2InstrInfo *getInstrInfo() const override { return &InstrInfo; } const TargetFrameLowering *getFrameLowering() const override { - return FrameLowering.get(); + return &FrameLowering; } const Nios2RegisterInfo *getRegisterInfo() const override { - return &InstrInfo->getRegisterInfo(); + return &InstrInfo.getRegisterInfo(); + } + const Nios2TargetLowering *getTargetLowering() const override { + return &TLInfo; + } + const SelectionDAGTargetInfo *getSelectionDAGInfo() const override { + return &TSInfo; } }; } // namespace llvm Index: lib/Target/Nios2/Nios2Subtarget.cpp =================================================================== --- lib/Target/Nios2/Nios2Subtarget.cpp +++ lib/Target/Nios2/Nios2Subtarget.cpp @@ -12,10 +12,7 @@ //===----------------------------------------------------------------------===// #include "Nios2Subtarget.h" - #include "Nios2.h" -#include "Nios2RegisterInfo.h" -#include "Nios2TargetMachine.h" using namespace llvm; @@ -28,19 +25,17 @@ void Nios2Subtarget::anchor() {} Nios2Subtarget::Nios2Subtarget(const Triple &TT, const std::string &CPU, - const std::string &FS, - const Nios2TargetMachine &_TM) + const std::string &FS, const TargetMachine &TM) : // Nios2GenSubtargetInfo will display features by llc -march=nios2 // -mcpu=help - Nios2GenSubtargetInfo(TT, CPU, FS), TM(_TM), TargetTriple(TT), - InstrInfo(Nios2InstrInfo::create( - initializeSubtargetDependencies(CPU, FS, TM))) {} + Nios2GenSubtargetInfo(TT, CPU, FS), TargetTriple(TT), + InstrInfo(initializeSubtargetDependencies(CPU, FS)), TLInfo(TM, *this), + FrameLowering(*this) {} -Nios2Subtarget & -Nios2Subtarget::initializeSubtargetDependencies(StringRef CPU, StringRef FS, - const TargetMachine &TM) { +Nios2Subtarget &Nios2Subtarget::initializeSubtargetDependencies(StringRef CPU, + StringRef FS) { if (TargetTriple.getArch() == Triple::nios2) { if (CPU != "nios2r2") { CPU = "nios2r1"; Index: lib/Target/Nios2/Nios2TargetMachine.h =================================================================== --- lib/Target/Nios2/Nios2TargetMachine.h +++ lib/Target/Nios2/Nios2TargetMachine.h @@ -20,6 +20,8 @@ namespace llvm { class Nios2TargetMachine : public LLVMTargetMachine { mutable StringMap> SubtargetMap; + std::unique_ptr TLOF; + Nios2Subtarget Subtarget; public: Nios2TargetMachine(const Target &T, const Triple &TT, StringRef CPU, @@ -28,8 +30,13 @@ CodeGenOpt::Level OL, bool JIT); ~Nios2TargetMachine() override; + const Nios2Subtarget *getSubtargetImpl() const { return &Subtarget; } const Nios2Subtarget *getSubtargetImpl(const Function &F) const override; + TargetLoweringObjectFile *getObjFileLowering() const override { + return TLOF.get(); + } + // Pass Pipeline Configuration TargetPassConfig *createPassConfig(PassManagerBase &PM) override; }; Index: lib/Target/Nios2/Nios2TargetMachine.cpp =================================================================== --- lib/Target/Nios2/Nios2TargetMachine.cpp +++ lib/Target/Nios2/Nios2TargetMachine.cpp @@ -13,6 +13,7 @@ #include "Nios2TargetMachine.h" #include "Nios2.h" +#include "Nios2TargetObjectFile.h" #include "llvm/CodeGen/TargetPassConfig.h" #include "llvm/Support/TargetRegistry.h" @@ -36,14 +37,27 @@ return *RM; } +static CodeModel::Model getEffectiveCodeModel(Optional CM, + Reloc::Model RM, bool JIT) { + if (CM) + return *CM; + return CodeModel::Small; +} + Nios2TargetMachine::Nios2TargetMachine(const Target &T, const Triple &TT, StringRef CPU, StringRef FS, const TargetOptions &Options, Optional RM, Optional CM, CodeGenOpt::Level OL, bool JIT) - : LLVMTargetMachine(T, computeDataLayout(), TT, CPU, FS, Options, - getEffectiveRelocModel(RM), *CM, OL) {} + : LLVMTargetMachine( + T, computeDataLayout(), TT, CPU, FS, Options, + getEffectiveRelocModel(RM), + getEffectiveCodeModel(CM, getEffectiveRelocModel(RM), JIT), OL), + TLOF(make_unique()), + Subtarget(TT, CPU, FS, *this) { + initAsmInfo(); +} Nios2TargetMachine::~Nios2TargetMachine() {} @@ -82,6 +96,7 @@ } void addCodeGenPrepare() override; + bool addInstSelector() override; void addIRPasses() override; }; } // namespace @@ -95,3 +110,10 @@ } void Nios2PassConfig::addIRPasses() { TargetPassConfig::addIRPasses(); } + +// Install an instruction selector pass using +// the ISelDag to gen Nios2 code. +bool Nios2PassConfig::addInstSelector() { + addPass(createNios2ISelDag(getNios2TargetMachine(), getOptLevel())); + return false; +} Index: lib/Target/Nios2/Nios2TargetObjectFile.h =================================================================== --- /dev/null +++ lib/Target/Nios2/Nios2TargetObjectFile.h @@ -0,0 +1,28 @@ +//===-- llvm/Target/Nios2TargetObjectFile.h - Nios2 Object Info -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_NIOS2_NIOS2TARGETOBJECTFILE_H +#define LLVM_LIB_TARGET_NIOS2_NIOS2TARGETOBJECTFILE_H + +#include "Nios2TargetMachine.h" +#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" + +namespace llvm { + +class Nios2TargetObjectFile : public TargetLoweringObjectFileELF { + const Nios2TargetMachine *TM; + +public: + Nios2TargetObjectFile() : TargetLoweringObjectFileELF() {} + + void Initialize(MCContext &Ctx, const TargetMachine &TM) override; +}; +} // end namespace llvm + +#endif Index: lib/Target/Nios2/Nios2TargetObjectFile.cpp =================================================================== --- /dev/null +++ lib/Target/Nios2/Nios2TargetObjectFile.cpp @@ -0,0 +1,18 @@ +//===-- Nios2TargetObjectFile.cpp - Nios2 Object Files --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Nios2TargetObjectFile.h" + +using namespace llvm; + +void Nios2TargetObjectFile::Initialize(MCContext &Ctx, + const TargetMachine &TM) { + TargetLoweringObjectFileELF::Initialize(Ctx, TM); + InitializeELF(TM.Options.UseInitArray); +} Index: lib/Target/Nios2/Nios2TargetStreamer.h =================================================================== --- /dev/null +++ lib/Target/Nios2/Nios2TargetStreamer.h @@ -0,0 +1,32 @@ +//===-- Nios2TargetStreamer.h - Nios2 Target Streamer ----------*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_NIOS2_NIOS2TARGETSTREAMER_H +#define LLVM_LIB_TARGET_NIOS2_NIOS2TARGETSTREAMER_H + +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCStreamer.h" + +namespace llvm { + +class Nios2TargetStreamer : public MCTargetStreamer { +public: + Nios2TargetStreamer(MCStreamer &S); +}; + +// This part is for ascii assembly output +class Nios2TargetAsmStreamer : public Nios2TargetStreamer { + formatted_raw_ostream &OS; + +public: + Nios2TargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS); +}; + +} // namespace llvm +#endif Index: test/CodeGen/Nios2/ret_generated.ll =================================================================== --- /dev/null +++ test/CodeGen/Nios2/ret_generated.ll @@ -0,0 +1,9 @@ +; This tests that llc accepts Nios2 target. + +; RUN: llc < %s -march=nios2 2>&1 | FileCheck %s --check-prefix=ARCH + +; ARCH: ret + +define i32 @f(i32 %i) { + ret i32 %i +}