aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Target/Mips/MCTargetDesc
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/Mips/MCTargetDesc')
-rw-r--r--llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp4
-rw-r--r--llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp25
-rw-r--r--llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h2
-rw-r--r--llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h7
-rw-r--r--llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp161
-rw-r--r--llvm/lib/Target/Mips/MCTargetDesc/MipsInstPrinter.cpp3
-rw-r--r--llvm/lib/Target/Mips/MCTargetDesc/MipsInstPrinter.h5
-rw-r--r--llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp17
-rw-r--r--llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.h14
-rw-r--r--llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp100
-rw-r--r--llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h16
-rw-r--r--llvm/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp1
-rw-r--r--llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp5
-rw-r--r--llvm/lib/Target/Mips/MCTargetDesc/MipsWinCOFFObjectWriter.cpp61
-rw-r--r--llvm/lib/Target/Mips/MCTargetDesc/MipsWinCOFFStreamer.cpp33
15 files changed, 312 insertions, 142 deletions
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp
index 3aa78224432d..08cbba952ccc 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp
@@ -9,7 +9,6 @@
#include "MipsABIInfo.h"
#include "Mips.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/CodeGenTypes/LowLevelType.h"
#include "llvm/MC/MCTargetOptions.h"
#include "llvm/Support/CommandLine.h"
@@ -62,7 +61,7 @@ MipsABIInfo MipsABIInfo::computeTargetABI(const Triple &TT, StringRef CPU,
return MipsABIInfo::N32();
if (Options.getABIName().starts_with("n64"))
return MipsABIInfo::N64();
- if (TT.getEnvironment() == llvm::Triple::GNUABIN32)
+ if (TT.isABIN32())
return MipsABIInfo::N32();
assert(Options.getABIName().empty() && "Unknown ABI option for MIPS");
@@ -125,4 +124,3 @@ unsigned MipsABIInfo::GetEhDataReg(unsigned I) const {
return IsN64() ? EhDataReg64[I] : EhDataReg[I];
}
-
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp
index f8172e576ce4..4af6768b13cc 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp
@@ -14,14 +14,11 @@
#include "MCTargetDesc/MipsAsmBackend.h"
#include "MCTargetDesc/MipsABIInfo.h"
#include "MCTargetDesc/MipsFixupKinds.h"
-#include "MCTargetDesc/MipsMCExpr.h"
#include "MCTargetDesc/MipsMCTargetDesc.h"
-#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCDirectives.h"
#include "llvm/MC/MCELFObjectWriter.h"
#include "llvm/MC/MCFixupKindInfo.h"
#include "llvm/MC/MCObjectWriter.h"
@@ -29,7 +26,6 @@
#include "llvm/MC/MCTargetOptions.h"
#include "llvm/MC/MCValue.h"
#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/Format.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
@@ -546,6 +542,7 @@ bool MipsAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,
bool MipsAsmBackend::shouldForceRelocation(const MCAssembler &Asm,
const MCFixup &Fixup,
const MCValue &Target,
+ const uint64_t,
const MCSubtargetInfo *STI) {
if (Fixup.getKind() >= FirstLiteralRelocationKind)
return true;
@@ -597,10 +594,30 @@ bool MipsAsmBackend::isMicroMips(const MCSymbol *Sym) const {
return false;
}
+namespace {
+
+class WindowsMipsAsmBackend : public MipsAsmBackend {
+public:
+ WindowsMipsAsmBackend(const Target &T, const MCRegisterInfo &MRI,
+ const MCSubtargetInfo &STI)
+ : MipsAsmBackend(T, MRI, STI.getTargetTriple(), STI.getCPU(), false) {}
+
+ std::unique_ptr<MCObjectTargetWriter>
+ createObjectTargetWriter() const override {
+ return createMipsWinCOFFObjectWriter();
+ }
+};
+
+} // end anonymous namespace
+
MCAsmBackend *llvm::createMipsAsmBackend(const Target &T,
const MCSubtargetInfo &STI,
const MCRegisterInfo &MRI,
const MCTargetOptions &Options) {
+ const Triple &TheTriple = STI.getTargetTriple();
+ if (TheTriple.isOSWindows() && TheTriple.isOSBinFormatCOFF())
+ return new WindowsMipsAsmBackend(T, MRI, STI);
+
MipsABIInfo ABI = MipsABIInfo::computeTargetABI(STI.getTargetTriple(),
STI.getCPU(), Options);
return new MipsAsmBackend(T, MRI, STI.getTargetTriple(), STI.getCPU(),
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h b/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h
index 799dd569f1ad..3a2c5e824a53 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h
@@ -55,7 +55,7 @@ public:
const MCSubtargetInfo *STI) const override;
bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup,
- const MCValue &Target,
+ const MCValue &Target, const uint64_t Value,
const MCSubtargetInfo *STI) override;
bool isMicroMips(const MCSymbol *Sym) const override;
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h b/llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h
index aa35e7db6bda..b9a2af334123 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h
@@ -92,7 +92,12 @@ namespace MipsII {
MO_CALL_LO16,
/// Helper operand used to generate R_MIPS_JALR
- MO_JALR
+ MO_JALR,
+
+ /// MO_DLLIMPORT - On a symbol operand "FOO", this indicates that the
+ /// reference is actually to the "__imp_FOO" symbol. This is used for
+ /// dllimport linkage on windows.
+ MO_DLLIMPORT = 0x20,
};
enum {
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp
index 4d6a00c14a35..f2d4a6a5bf26 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp
@@ -21,7 +21,6 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
#include <cassert>
#include <cstdint>
#include <iterator>
@@ -40,20 +39,8 @@ struct MipsRelocationEntry {
bool Matched = false; ///< Is this relocation part of a match.
MipsRelocationEntry(const ELFRelocationEntry &R) : R(R) {}
-
- void print(raw_ostream &Out) const {
- R.print(Out);
- Out << ", Matched=" << Matched;
- }
};
-#ifndef NDEBUG
-raw_ostream &operator<<(raw_ostream &OS, const MipsRelocationEntry &RHS) {
- RHS.print(OS);
- return OS;
-}
-#endif
-
class MipsELFObjectWriter : public MCELFObjectTargetWriter {
public:
MipsELFObjectWriter(uint8_t OSABI, bool HasRelocationAddend, bool Is64);
@@ -115,17 +102,11 @@ static InputIt find_best(InputIt First, InputIt Last, UnaryPredicate Predicate,
for (InputIt I = First; I != Last; ++I) {
unsigned Matched = Predicate(*I);
if (Matched != FindBest_NoMatch) {
- LLVM_DEBUG(dbgs() << std::distance(First, I) << " is a match (";
- I->print(dbgs()); dbgs() << ")\n");
- if (Best == Last || BetterThan(*I, *Best)) {
- LLVM_DEBUG(dbgs() << ".. and it beats the last one\n");
+ if (Best == Last || BetterThan(*I, *Best))
Best = I;
- }
}
- if (Matched == FindBest_PerfectMatch) {
- LLVM_DEBUG(dbgs() << ".. and it is unbeatable\n");
+ if (Matched == FindBest_PerfectMatch)
break;
- }
}
return Best;
@@ -147,8 +128,7 @@ static unsigned getMatchingLoType(const ELFRelocationEntry &Reloc) {
if (Type == ELF::R_MIPS16_HI16)
return ELF::R_MIPS16_LO16;
- if (Reloc.OriginalSymbol &&
- Reloc.OriginalSymbol->getBinding() != ELF::STB_LOCAL)
+ if (Reloc.Symbol && Reloc.Symbol->getBinding() != ELF::STB_LOCAL)
return ELF::R_MIPS_NONE;
if (Type == ELF::R_MIPS_GOT16)
@@ -161,54 +141,12 @@ static unsigned getMatchingLoType(const ELFRelocationEntry &Reloc) {
return ELF::R_MIPS_NONE;
}
-/// Determine whether a relocation (X) matches the one given in R.
-///
-/// A relocation matches if:
-/// - It's type matches that of a corresponding low part. This is provided in
-/// MatchingType for efficiency.
-/// - It's based on the same symbol.
-/// - It's offset of greater or equal to that of the one given in R.
-/// It should be noted that this rule assumes the programmer does not use
-/// offsets that exceed the alignment of the symbol. The carry-bit will be
-/// incorrect if this is not true.
-///
-/// A matching relocation is unbeatable if:
-/// - It is not already involved in a match.
-/// - It's offset is exactly that of the one given in R.
-static FindBestPredicateResult isMatchingReloc(const MipsRelocationEntry &X,
- const ELFRelocationEntry &R,
- unsigned MatchingType) {
- if (X.R.Type == MatchingType && X.R.OriginalSymbol == R.OriginalSymbol) {
- if (!X.Matched &&
- X.R.OriginalAddend == R.OriginalAddend)
- return FindBest_PerfectMatch;
- else if (X.R.OriginalAddend >= R.OriginalAddend)
- return FindBest_Match;
- }
- return FindBest_NoMatch;
-}
-
-/// Determine whether Candidate or PreviousBest is the better match.
-/// The return value is true if Candidate is the better match.
-///
-/// A matching relocation is a better match if:
-/// - It has a smaller addend.
-/// - It is not already involved in a match.
-static bool compareMatchingRelocs(const MipsRelocationEntry &Candidate,
- const MipsRelocationEntry &PreviousBest) {
- if (Candidate.R.OriginalAddend != PreviousBest.R.OriginalAddend)
- return Candidate.R.OriginalAddend < PreviousBest.R.OriginalAddend;
- return PreviousBest.Matched && !Candidate.Matched;
-}
-
-#ifndef NDEBUG
-/// Print all the relocations.
-template <class Container>
-static void dumpRelocs(const char *Prefix, const Container &Relocs) {
- for (const auto &R : Relocs)
- dbgs() << Prefix << R << "\n";
+// Determine whether a relocation X is a low-part and matches the high-part R
+// perfectly by symbol and addend.
+static bool isMatchingReloc(unsigned MatchingType, const ELFRelocationEntry &R,
+ const ELFRelocationEntry &X) {
+ return X.Type == MatchingType && X.Symbol == R.Symbol && X.Addend == R.Addend;
}
-#endif
MipsELFObjectWriter::MipsELFObjectWriter(uint8_t OSABI,
bool HasRelocationAddend, bool Is64)
@@ -436,65 +374,52 @@ void MipsELFObjectWriter::sortRelocs(const MCAssembler &Asm,
if (hasRelocationAddend())
return;
- if (Relocs.size() < 2)
- return;
-
// Sort relocations by the address they are applied to.
llvm::sort(Relocs,
[](const ELFRelocationEntry &A, const ELFRelocationEntry &B) {
return A.Offset < B.Offset;
});
+ // Place relocations in a list for reorder convenience. Hi16 contains the
+ // iterators of high-part relocations.
std::list<MipsRelocationEntry> Sorted;
- std::list<ELFRelocationEntry> Remainder;
-
- LLVM_DEBUG(dumpRelocs("R: ", Relocs));
-
- // Separate the movable relocations (AHL relocations using the high bits) from
- // the immobile relocations (everything else). This does not preserve high/low
- // matches that already existed in the input.
- copy_if_else(Relocs.begin(), Relocs.end(), std::back_inserter(Remainder),
- std::back_inserter(Sorted), [](const ELFRelocationEntry &Reloc) {
- return getMatchingLoType(Reloc) != ELF::R_MIPS_NONE;
- });
-
- for (auto &R : Remainder) {
- LLVM_DEBUG(dbgs() << "Matching: " << R << "\n");
+ SmallVector<std::list<MipsRelocationEntry>::iterator, 0> Hi16;
+ for (auto &R : Relocs) {
+ Sorted.push_back(R);
+ if (getMatchingLoType(R) != ELF::R_MIPS_NONE)
+ Hi16.push_back(std::prev(Sorted.end()));
+ }
+ for (auto I : Hi16) {
+ auto &R = I->R;
unsigned MatchingType = getMatchingLoType(R);
- assert(MatchingType != ELF::R_MIPS_NONE &&
- "Wrong list for reloc that doesn't need a match");
-
- // Find the best matching relocation for the current high part.
- // See isMatchingReloc for a description of a matching relocation and
- // compareMatchingRelocs for a description of what 'best' means.
- auto InsertionPoint =
- find_best(Sorted.begin(), Sorted.end(),
- [&R, &MatchingType](const MipsRelocationEntry &X) {
- return isMatchingReloc(X, R, MatchingType);
- },
- compareMatchingRelocs);
-
- // If we matched then insert the high part in front of the match and mark
- // both relocations as being involved in a match. We only mark the high
- // part for cosmetic reasons in the debug output.
+ // If the next relocation is a perfect match, continue;
+ if (std::next(I) != Sorted.end() &&
+ isMatchingReloc(MatchingType, R, std::next(I)->R))
+ continue;
+ // Otherwise, find the best matching low-part relocation with the following
+ // criteria. It must have the same symbol and its addend is no lower than
+ // that of the current high-part.
//
- // If we failed to find a match then the high part is orphaned. This is not
- // permitted since the relocation cannot be evaluated without knowing the
- // carry-in. We can sometimes handle this using a matching low part that is
- // already used in a match but we already cover that case in
- // isMatchingReloc and compareMatchingRelocs. For the remaining cases we
- // should insert the high part at the end of the list. This will cause the
- // linker to fail but the alternative is to cause the linker to bind the
- // high part to a semi-matching low part and silently calculate the wrong
- // value. Unfortunately we have no means to warn the user that we did this
- // so leave it up to the linker to complain about it.
- if (InsertionPoint != Sorted.end())
- InsertionPoint->Matched = true;
- Sorted.insert(InsertionPoint, R)->Matched = true;
- }
+ // (1) %lo with a smaller offset is preferred.
+ // (2) %lo with the same offset that is unmatched is preferred.
+ // (3) later %lo is preferred.
+ auto Best = Sorted.end();
+ for (auto J = Sorted.begin(); J != Sorted.end(); ++J) {
+ auto &R1 = J->R;
+ if (R1.Type == MatchingType && R.Symbol == R1.Symbol &&
+ R.Addend <= R1.Addend &&
+ (Best == Sorted.end() || R1.Addend < Best->R.Addend ||
+ (!Best->Matched && R1.Addend == Best->R.Addend)))
+ Best = J;
+ }
+ if (Best != Sorted.end() && R.Addend == Best->R.Addend)
+ Best->Matched = true;
- LLVM_DEBUG(dumpRelocs("S: ", Sorted));
+ // Move the high-part before the low-part, or if not found, the end of the
+ // list. The unmatched high-part will lead to a linker warning/error.
+ Sorted.splice(Best, Sorted, I);
+ }
assert(Relocs.size() == Sorted.size() && "Some relocs were not consumed");
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsInstPrinter.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsInstPrinter.cpp
index 1518a539782e..dc7e887167d3 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsInstPrinter.cpp
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsInstPrinter.cpp
@@ -12,7 +12,6 @@
#include "MipsInstPrinter.h"
#include "Mips.h"
-#include "MipsMCExpr.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
@@ -72,7 +71,7 @@ const char* Mips::MipsFCCToString(Mips::CondCode CC) {
llvm_unreachable("Impossible condition code!");
}
-void MipsInstPrinter::printRegName(raw_ostream &OS, MCRegister Reg) const {
+void MipsInstPrinter::printRegName(raw_ostream &OS, MCRegister Reg) {
markup(OS, Markup::Register)
<< '$' << StringRef(getRegisterName(Reg)).lower();
}
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsInstPrinter.h b/llvm/lib/Target/Mips/MCTargetDesc/MipsInstPrinter.h
index 0652b237509f..3924cf02e2d6 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsInstPrinter.h
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsInstPrinter.h
@@ -79,12 +79,13 @@ public:
: MCInstPrinter(MAI, MII, MRI) {}
// Autogenerated by tblgen.
- std::pair<const char *, uint64_t> getMnemonic(const MCInst *MI) override;
+ std::pair<const char *, uint64_t>
+ getMnemonic(const MCInst &MI) const override;
void printInstruction(const MCInst *MI, uint64_t Address,
const MCSubtargetInfo &STI, raw_ostream &O);
static const char *getRegisterName(MCRegister Reg);
- void printRegName(raw_ostream &OS, MCRegister Reg) const override;
+ void printRegName(raw_ostream &OS, MCRegister Reg) override;
void printInst(const MCInst *MI, uint64_t Address, StringRef Annot,
const MCSubtargetInfo &STI, raw_ostream &O) override;
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp
index f89c78e75d3e..fa09a14b3e23 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp
@@ -16,10 +16,10 @@
using namespace llvm;
-void MipsMCAsmInfo::anchor() { }
+void MipsELFMCAsmInfo::anchor() {}
-MipsMCAsmInfo::MipsMCAsmInfo(const Triple &TheTriple,
- const MCTargetOptions &Options) {
+MipsELFMCAsmInfo::MipsELFMCAsmInfo(const Triple &TheTriple,
+ const MCTargetOptions &Options) {
IsLittleEndian = TheTriple.isLittleEndian();
MipsABIInfo ABI = MipsABIInfo::computeTargetABI(TheTriple, "", Options);
@@ -51,3 +51,14 @@ MipsMCAsmInfo::MipsMCAsmInfo(const Triple &TheTriple,
DwarfRegNumForCFI = true;
HasMipsExpressions = true;
}
+
+void MipsCOFFMCAsmInfo::anchor() {}
+
+MipsCOFFMCAsmInfo::MipsCOFFMCAsmInfo() {
+ HasSingleParameterDotFile = true;
+ WinEHEncodingType = WinEH::EncodingType::Itanium;
+
+ ExceptionsType = ExceptionHandling::WinEH;
+
+ AllowAtInName = true;
+}
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.h b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.h
index d8bfe58d24a8..3a2895a79f9c 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.h
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.h
@@ -13,17 +13,25 @@
#ifndef LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSMCASMINFO_H
#define LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSMCASMINFO_H
+#include "llvm/MC/MCAsmInfoCOFF.h"
#include "llvm/MC/MCAsmInfoELF.h"
namespace llvm {
class Triple;
-class MipsMCAsmInfo : public MCAsmInfoELF {
+class MipsELFMCAsmInfo : public MCAsmInfoELF {
void anchor() override;
public:
- explicit MipsMCAsmInfo(const Triple &TheTriple,
- const MCTargetOptions &Options);
+ explicit MipsELFMCAsmInfo(const Triple &TheTriple,
+ const MCTargetOptions &Options);
+};
+
+class MipsCOFFMCAsmInfo : public MCAsmInfoGNUCOFF {
+ void anchor() override;
+
+public:
+ explicit MipsCOFFMCAsmInfo();
};
} // namespace llvm
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp
index ca95f67174da..add36d87b9ef 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp
@@ -19,6 +19,7 @@
#include "MipsMCNaCl.h"
#include "MipsTargetStreamer.h"
#include "TargetInfo/MipsTargetInfo.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCELFStreamer.h"
#include "llvm/MC/MCInstrAnalysis.h"
@@ -27,7 +28,6 @@
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCSymbol.h"
-#include "llvm/MC/MachineLocation.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
@@ -45,6 +45,93 @@ using namespace llvm;
#define GET_REGINFO_MC_DESC
#include "MipsGenRegisterInfo.inc"
+void MIPS_MC::initLLVMToCVRegMapping(MCRegisterInfo *MRI) {
+ // Mapping from CodeView to MC register id.
+ static const struct {
+ codeview::RegisterId CVReg;
+ MCPhysReg Reg;
+ } RegMap[] = {
+ {codeview::RegisterId::MIPS_ZERO, Mips::ZERO},
+ {codeview::RegisterId::MIPS_AT, Mips::AT},
+ {codeview::RegisterId::MIPS_V0, Mips::V0},
+ {codeview::RegisterId::MIPS_V1, Mips::V1},
+ {codeview::RegisterId::MIPS_A0, Mips::A0},
+ {codeview::RegisterId::MIPS_A1, Mips::A1},
+ {codeview::RegisterId::MIPS_A2, Mips::A2},
+ {codeview::RegisterId::MIPS_A3, Mips::A3},
+ {codeview::RegisterId::MIPS_T0, Mips::T0},
+ {codeview::RegisterId::MIPS_T1, Mips::T1},
+ {codeview::RegisterId::MIPS_T2, Mips::T2},
+ {codeview::RegisterId::MIPS_T3, Mips::T3},
+ {codeview::RegisterId::MIPS_T4, Mips::T4},
+ {codeview::RegisterId::MIPS_T5, Mips::T5},
+ {codeview::RegisterId::MIPS_T6, Mips::T6},
+ {codeview::RegisterId::MIPS_T7, Mips::T7},
+ {codeview::RegisterId::MIPS_S0, Mips::S0},
+ {codeview::RegisterId::MIPS_S1, Mips::S1},
+ {codeview::RegisterId::MIPS_S2, Mips::S2},
+ {codeview::RegisterId::MIPS_S3, Mips::S3},
+ {codeview::RegisterId::MIPS_S4, Mips::S4},
+ {codeview::RegisterId::MIPS_S5, Mips::S5},
+ {codeview::RegisterId::MIPS_S6, Mips::S6},
+ {codeview::RegisterId::MIPS_S7, Mips::S7},
+ {codeview::RegisterId::MIPS_T8, Mips::T8},
+ {codeview::RegisterId::MIPS_T9, Mips::T9},
+ {codeview::RegisterId::MIPS_K0, Mips::K0},
+ {codeview::RegisterId::MIPS_K1, Mips::K1},
+ {codeview::RegisterId::MIPS_GP, Mips::GP},
+ {codeview::RegisterId::MIPS_SP, Mips::SP},
+ {codeview::RegisterId::MIPS_S8, Mips::FP},
+ {codeview::RegisterId::MIPS_RA, Mips::RA},
+ {codeview::RegisterId::MIPS_LO, Mips::HI0},
+ {codeview::RegisterId::MIPS_HI, Mips::LO0},
+ {codeview::RegisterId::MIPS_Fir, Mips::FCR0},
+ {codeview::RegisterId::MIPS_Psr, Mips::COP012}, // CP0.Status
+ {codeview::RegisterId::MIPS_F0, Mips::F0},
+ {codeview::RegisterId::MIPS_F1, Mips::F1},
+ {codeview::RegisterId::MIPS_F2, Mips::F2},
+ {codeview::RegisterId::MIPS_F3, Mips::F3},
+ {codeview::RegisterId::MIPS_F4, Mips::F4},
+ {codeview::RegisterId::MIPS_F5, Mips::F5},
+ {codeview::RegisterId::MIPS_F6, Mips::F6},
+ {codeview::RegisterId::MIPS_F7, Mips::F7},
+ {codeview::RegisterId::MIPS_F8, Mips::F8},
+ {codeview::RegisterId::MIPS_F9, Mips::F9},
+ {codeview::RegisterId::MIPS_F10, Mips::F10},
+ {codeview::RegisterId::MIPS_F11, Mips::F11},
+ {codeview::RegisterId::MIPS_F12, Mips::F12},
+ {codeview::RegisterId::MIPS_F13, Mips::F13},
+ {codeview::RegisterId::MIPS_F14, Mips::F14},
+ {codeview::RegisterId::MIPS_F15, Mips::F15},
+ {codeview::RegisterId::MIPS_F16, Mips::F16},
+ {codeview::RegisterId::MIPS_F17, Mips::F17},
+ {codeview::RegisterId::MIPS_F18, Mips::F18},
+ {codeview::RegisterId::MIPS_F19, Mips::F19},
+ {codeview::RegisterId::MIPS_F20, Mips::F20},
+ {codeview::RegisterId::MIPS_F21, Mips::F21},
+ {codeview::RegisterId::MIPS_F22, Mips::F22},
+ {codeview::RegisterId::MIPS_F23, Mips::F23},
+ {codeview::RegisterId::MIPS_F24, Mips::F24},
+ {codeview::RegisterId::MIPS_F25, Mips::F25},
+ {codeview::RegisterId::MIPS_F26, Mips::F26},
+ {codeview::RegisterId::MIPS_F27, Mips::F27},
+ {codeview::RegisterId::MIPS_F28, Mips::F28},
+ {codeview::RegisterId::MIPS_F29, Mips::F29},
+ {codeview::RegisterId::MIPS_F30, Mips::F30},
+ {codeview::RegisterId::MIPS_F31, Mips::F31},
+ {codeview::RegisterId::MIPS_Fsr, Mips::FCR31},
+ };
+ for (const auto &I : RegMap)
+ MRI->mapLLVMRegToCVReg(I.Reg, static_cast<int>(I.CVReg));
+}
+
+namespace {
+class MipsWinCOFFTargetStreamer : public MipsTargetStreamer {
+public:
+ MipsWinCOFFTargetStreamer(MCStreamer &S) : MipsTargetStreamer(S) {}
+};
+} // end namespace
+
/// Select the Mips CPU for the given triple and cpu name.
StringRef MIPS_MC::selectMipsCPU(const Triple &TT, StringRef CPU) {
if (CPU.empty() || CPU == "generic") {
@@ -84,7 +171,12 @@ static MCSubtargetInfo *createMipsMCSubtargetInfo(const Triple &TT,
static MCAsmInfo *createMipsMCAsmInfo(const MCRegisterInfo &MRI,
const Triple &TT,
const MCTargetOptions &Options) {
- MCAsmInfo *MAI = new MipsMCAsmInfo(TT, Options);
+ MCAsmInfo *MAI;
+
+ if (TT.isOSWindows())
+ MAI = new MipsCOFFMCAsmInfo();
+ else
+ MAI = new MipsELFMCAsmInfo(TT, Options);
unsigned SP = MRI.getDwarfRegNum(Mips::SP, true);
MCCFIInstruction Inst = MCCFIInstruction::createDefCfaRegister(nullptr, SP);
@@ -127,6 +219,8 @@ static MCTargetStreamer *createMipsNullTargetStreamer(MCStreamer &S) {
static MCTargetStreamer *
createMipsObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) {
+ if (STI.getTargetTriple().isOSBinFormatCOFF())
+ return new MipsWinCOFFTargetStreamer(S);
return new MipsTargetELFStreamer(S, STI);
}
@@ -186,6 +280,8 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeMipsTargetMC() {
TargetRegistry::RegisterNullTargetStreamer(*T,
createMipsNullTargetStreamer);
+ TargetRegistry::RegisterCOFFStreamer(*T, createMipsWinCOFFStreamer);
+
// Register the MC subtarget info.
TargetRegistry::RegisterMCSubtargetInfo(*T, createMipsMCSubtargetInfo);
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h
index d51f3b9abcfd..f3e3e6e8d107 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h
@@ -23,7 +23,9 @@ class MCCodeEmitter;
class MCContext;
class MCInstrInfo;
class MCObjectTargetWriter;
+class MCObjectWriter;
class MCRegisterInfo;
+class MCStreamer;
class MCSubtargetInfo;
class MCTargetOptions;
class StringRef;
@@ -39,10 +41,24 @@ MCAsmBackend *createMipsAsmBackend(const Target &T, const MCSubtargetInfo &STI,
const MCRegisterInfo &MRI,
const MCTargetOptions &Options);
+/// Construct an MIPS Windows COFF machine code streamer which will generate
+/// PE/COFF format object files.
+///
+/// Takes ownership of \p AB and \p CE.
+MCStreamer *createMipsWinCOFFStreamer(MCContext &C,
+ std::unique_ptr<MCAsmBackend> &&AB,
+ std::unique_ptr<MCObjectWriter> &&OW,
+ std::unique_ptr<MCCodeEmitter> &&CE);
+
+/// Construct a Mips ELF object writer.
std::unique_ptr<MCObjectTargetWriter>
createMipsELFObjectWriter(const Triple &TT, bool IsN32);
+/// Construct a Mips Win COFF object writer.
+std::unique_ptr<MCObjectTargetWriter> createMipsWinCOFFObjectWriter();
namespace MIPS_MC {
+void initLLVMToCVRegMapping(MCRegisterInfo *MRI);
+
StringRef selectMipsCPU(const Triple &TT, StringRef CPU);
}
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp
index 86194a9ebb61..8bd2b2ac231b 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp
@@ -16,7 +16,6 @@
//
//===----------------------------------------------------------------------===//
-#include "Mips.h"
#include "MipsELFStreamer.h"
#include "MipsMCNaCl.h"
#include "llvm/MC/MCAsmBackend.h"
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp
index 1650ffc85619..e547e6209440 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp
@@ -19,6 +19,7 @@
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCELFObjectWriter.h"
#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/MCSubtargetInfo.h"
@@ -804,8 +805,8 @@ MipsTargetELFStreamer::MipsTargetELFStreamer(MCStreamer &S,
ELFObjectWriter &W = getStreamer().getWriter();
// It's possible that MCObjectFileInfo isn't fully initialized at this point
- // due to an initialization order problem where LLVMTargetMachine creates the
- // target streamer before TargetLoweringObjectFile calls
+ // due to an initialization order problem where CodeGenTargetMachineImpl
+ // creates the target streamer before TargetLoweringObjectFile calls
// InitializeMCObjectFileInfo. There doesn't seem to be a single place that
// covers all cases so this statement covers most cases and direct object
// emission must call setPic() once MCObjectFileInfo has been initialized. The
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsWinCOFFObjectWriter.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsWinCOFFObjectWriter.cpp
new file mode 100644
index 000000000000..cbe74f87a221
--- /dev/null
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsWinCOFFObjectWriter.cpp
@@ -0,0 +1,61 @@
+//===- MipsWinCOFFObjectWriter.cpp------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===---------------------------------------------------------------------===//
+
+#include "MCTargetDesc/MipsFixupKinds.h"
+#include "MCTargetDesc/MipsMCTargetDesc.h"
+#include "llvm/BinaryFormat/COFF.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCWinCOFFObjectWriter.h"
+
+using namespace llvm;
+
+namespace {
+
+class MipsWinCOFFObjectWriter : public MCWinCOFFObjectTargetWriter {
+public:
+ MipsWinCOFFObjectWriter();
+
+ unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
+ const MCFixup &Fixup, bool IsCrossSection,
+ const MCAsmBackend &MAB) const override;
+};
+
+} // end anonymous namespace
+
+MipsWinCOFFObjectWriter::MipsWinCOFFObjectWriter()
+ : MCWinCOFFObjectTargetWriter(COFF::IMAGE_FILE_MACHINE_R4000) {}
+
+unsigned MipsWinCOFFObjectWriter::getRelocType(MCContext &Ctx,
+ const MCValue &Target,
+ const MCFixup &Fixup,
+ bool IsCrossSection,
+ const MCAsmBackend &MAB) const {
+ unsigned FixupKind = Fixup.getKind();
+
+ switch (FixupKind) {
+ case FK_Data_4:
+ return COFF::IMAGE_REL_MIPS_REFWORD;
+ case FK_SecRel_2:
+ return COFF::IMAGE_REL_MIPS_SECTION;
+ case FK_SecRel_4:
+ return COFF::IMAGE_REL_MIPS_SECREL;
+ case Mips::fixup_Mips_26:
+ return COFF::IMAGE_REL_MIPS_JMPADDR;
+ case Mips::fixup_Mips_HI16:
+ return COFF::IMAGE_REL_MIPS_REFHI;
+ case Mips::fixup_Mips_LO16:
+ return COFF::IMAGE_REL_MIPS_REFLO;
+ default:
+ Ctx.reportError(Fixup.getLoc(), "unsupported relocation type");
+ return COFF::IMAGE_REL_MIPS_REFWORD;
+ }
+}
+
+std::unique_ptr<MCObjectTargetWriter> llvm::createMipsWinCOFFObjectWriter() {
+ return std::make_unique<MipsWinCOFFObjectWriter>();
+}
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsWinCOFFStreamer.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsWinCOFFStreamer.cpp
new file mode 100644
index 000000000000..22bf2e1be203
--- /dev/null
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsWinCOFFStreamer.cpp
@@ -0,0 +1,33 @@
+//===- MipsWinCOFFStreamer.cpp-----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===---------------------------------------------------------------------===//
+
+#include "MipsMCTargetDesc.h"
+#include "llvm/MC/MCAsmBackend.h"
+#include "llvm/MC/MCAssembler.h"
+#include "llvm/MC/MCCodeEmitter.h"
+#include "llvm/MC/MCObjectWriter.h"
+#include "llvm/MC/MCWinCOFFStreamer.h"
+
+using namespace llvm;
+
+namespace {
+class MipsWinCOFFStreamer : public MCWinCOFFStreamer {
+public:
+ MipsWinCOFFStreamer(MCContext &C, std::unique_ptr<MCAsmBackend> AB,
+ std::unique_ptr<MCCodeEmitter> CE,
+ std::unique_ptr<MCObjectWriter> OW)
+ : MCWinCOFFStreamer(C, std::move(AB), std::move(CE), std::move(OW)) {}
+};
+} // namespace
+
+MCStreamer *llvm::createMipsWinCOFFStreamer(
+ MCContext &C, std::unique_ptr<MCAsmBackend> &&AB,
+ std::unique_ptr<MCObjectWriter> &&OW, std::unique_ptr<MCCodeEmitter> &&CE) {
+ return new MipsWinCOFFStreamer(C, std::move(AB), std::move(CE),
+ std::move(OW));
+}