[Nios2] final infrastructure to provide compilation of a return from 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
diff --git a/llvm/lib/Target/Nios2/MCTargetDesc/CMakeLists.txt b/llvm/lib/Target/Nios2/MCTargetDesc/CMakeLists.txt
index 21def50..138832d 100644
--- a/llvm/lib/Target/Nios2/MCTargetDesc/CMakeLists.txt
+++ b/llvm/lib/Target/Nios2/MCTargetDesc/CMakeLists.txt
@@ -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)
+
diff --git a/llvm/lib/Target/Nios2/MCTargetDesc/LLVMBuild.txt b/llvm/lib/Target/Nios2/MCTargetDesc/LLVMBuild.txt
index 4dc6995..3794c83 100644
--- a/llvm/lib/Target/Nios2/MCTargetDesc/LLVMBuild.txt
+++ b/llvm/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
diff --git a/llvm/lib/Target/Nios2/MCTargetDesc/Nios2AsmBackend.cpp b/llvm/lib/Target/Nios2/MCTargetDesc/Nios2AsmBackend.cpp
new file mode 100644
index 0000000..3971630
--- /dev/null
+++ b/llvm/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<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());
+}
diff --git a/llvm/lib/Target/Nios2/MCTargetDesc/Nios2AsmBackend.h b/llvm/lib/Target/Nios2/MCTargetDesc/Nios2AsmBackend.h
new file mode 100644
index 0000000..0aa4204
--- /dev/null
+++ b/llvm/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<MCObjectWriter>
+  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<char> Data,
+                  uint64_t Value, bool IsResolved) const override;
+
+  Optional<MCFixupKind> 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
diff --git a/llvm/lib/Target/Nios2/MCTargetDesc/Nios2BaseInfo.h b/llvm/lib/Target/Nios2/MCTargetDesc/Nios2BaseInfo.h
new file mode 100644
index 0000000..225671e
--- /dev/null
+++ b/llvm/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
diff --git a/llvm/lib/Target/Nios2/MCTargetDesc/Nios2ELFObjectWriter.cpp b/llvm/lib/Target/Nios2/MCTargetDesc/Nios2ELFObjectWriter.cpp
new file mode 100644
index 0000000..04f727a
--- /dev/null
+++ b/llvm/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<MCObjectWriter>
+llvm::createNios2ELFObjectWriter(raw_pwrite_stream &OS, uint8_t OSABI) {
+  auto MOTW = llvm::make_unique<Nios2ELFObjectWriter>(OSABI);
+  return createELFObjectWriter(std::move(MOTW), OS, true);
+}
diff --git a/llvm/lib/Target/Nios2/MCTargetDesc/Nios2FixupKinds.h b/llvm/lib/Target/Nios2/MCTargetDesc/Nios2FixupKinds.h
new file mode 100644
index 0000000..c169a1b
--- /dev/null
+++ b/llvm/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
diff --git a/llvm/lib/Target/Nios2/MCTargetDesc/Nios2MCAsmInfo.cpp b/llvm/lib/Target/Nios2/MCTargetDesc/Nios2MCAsmInfo.cpp
new file mode 100644
index 0000000..e3c66e6
--- /dev/null
+++ b/llvm/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;
+}
diff --git a/llvm/lib/Target/Nios2/MCTargetDesc/Nios2MCAsmInfo.h b/llvm/lib/Target/Nios2/MCTargetDesc/Nios2MCAsmInfo.h
new file mode 100644
index 0000000..0c81276
--- /dev/null
+++ b/llvm/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
diff --git a/llvm/lib/Target/Nios2/MCTargetDesc/Nios2MCExpr.cpp b/llvm/lib/Target/Nios2/MCTargetDesc/Nios2MCExpr.cpp
new file mode 100644
index 0000000..0f12c9e
--- /dev/null
+++ b/llvm/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;
+  }
+}
diff --git a/llvm/lib/Target/Nios2/MCTargetDesc/Nios2MCExpr.h b/llvm/lib/Target/Nios2/MCTargetDesc/Nios2MCExpr.h
new file mode 100644
index 0000000..5b49005
--- /dev/null
+++ b/llvm/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
diff --git a/llvm/lib/Target/Nios2/MCTargetDesc/Nios2MCTargetDesc.cpp b/llvm/lib/Target/Nios2/MCTargetDesc/Nios2MCTargetDesc.cpp
index 0c70dc0..e57b44d 100644
--- a/llvm/lib/Target/Nios2/MCTargetDesc/Nios2MCTargetDesc.cpp
+++ b/llvm/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,72 @@
 #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) {
+  if (CPU.empty() || CPU == "generic")
+    CPU = "nios2r1";
+  return createNios2MCSubtargetInfoImpl(TT, CPU, FS);
+  // 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);
+}
diff --git a/llvm/lib/Target/Nios2/MCTargetDesc/Nios2MCTargetDesc.h b/llvm/lib/Target/Nios2/MCTargetDesc/Nios2MCTargetDesc.h
index e8fe865..d918a06 100644
--- a/llvm/lib/Target/Nios2/MCTargetDesc/Nios2MCTargetDesc.h
+++ b/llvm/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 <memory>
+
 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<MCObjectWriter>
+createNios2ELFObjectWriter(raw_pwrite_stream &OS, uint8_t OSABI);
+
 } // namespace llvm
 
 // Defines symbolic names for Nios2 registers.  This defines a mapping from
diff --git a/llvm/lib/Target/Nios2/MCTargetDesc/Nios2TargetStreamer.cpp b/llvm/lib/Target/Nios2/MCTargetDesc/Nios2TargetStreamer.cpp
new file mode 100644
index 0000000..b7e1bc3
--- /dev/null
+++ b/llvm/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) {}