xref: /freebsd-src/contrib/llvm-project/llvm/lib/MC/MCAsmBackend.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- MCAsmBackend.cpp - Target MC Assembly Backend ----------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "llvm/MC/MCAsmBackend.h"
10*0fca6ea1SDimitry Andric #include "llvm/MC/MCAssembler.h"
1181ad6265SDimitry Andric #include "llvm/MC/MCDXContainerWriter.h"
120b57cec5SDimitry Andric #include "llvm/MC/MCELFObjectWriter.h"
130b57cec5SDimitry Andric #include "llvm/MC/MCFixupKindInfo.h"
145f757f3fSDimitry Andric #include "llvm/MC/MCGOFFObjectWriter.h"
150b57cec5SDimitry Andric #include "llvm/MC/MCMachObjectWriter.h"
160b57cec5SDimitry Andric #include "llvm/MC/MCObjectWriter.h"
1781ad6265SDimitry Andric #include "llvm/MC/MCSPIRVObjectWriter.h"
180b57cec5SDimitry Andric #include "llvm/MC/MCWasmObjectWriter.h"
190b57cec5SDimitry Andric #include "llvm/MC/MCWinCOFFObjectWriter.h"
200b57cec5SDimitry Andric #include "llvm/MC/MCXCOFFObjectWriter.h"
210b57cec5SDimitry Andric #include <cassert>
220b57cec5SDimitry Andric #include <cstddef>
230b57cec5SDimitry Andric #include <cstdint>
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric using namespace llvm;
260b57cec5SDimitry Andric 
275f757f3fSDimitry Andric MCAsmBackend::MCAsmBackend(llvm::endianness Endian, unsigned RelaxFixupKind)
2806c3fb27SDimitry Andric     : Endian(Endian), RelaxFixupKind(RelaxFixupKind) {}
290b57cec5SDimitry Andric 
300b57cec5SDimitry Andric MCAsmBackend::~MCAsmBackend() = default;
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric std::unique_ptr<MCObjectWriter>
330b57cec5SDimitry Andric MCAsmBackend::createObjectWriter(raw_pwrite_stream &OS) const {
340b57cec5SDimitry Andric   auto TW = createObjectTargetWriter();
35*0fca6ea1SDimitry Andric   bool IsLE = Endian == llvm::endianness::little;
360b57cec5SDimitry Andric   switch (TW->getFormat()) {
370b57cec5SDimitry Andric   case Triple::MachO:
380b57cec5SDimitry Andric     return createMachObjectWriter(cast<MCMachObjectTargetWriter>(std::move(TW)),
39*0fca6ea1SDimitry Andric                                   OS, IsLE);
400b57cec5SDimitry Andric   case Triple::COFF:
410b57cec5SDimitry Andric     return createWinCOFFObjectWriter(
420b57cec5SDimitry Andric         cast<MCWinCOFFObjectTargetWriter>(std::move(TW)), OS);
43*0fca6ea1SDimitry Andric   case Triple::ELF:
44*0fca6ea1SDimitry Andric     return std::make_unique<ELFObjectWriter>(
45*0fca6ea1SDimitry Andric         cast<MCELFObjectTargetWriter>(std::move(TW)), OS, IsLE);
4681ad6265SDimitry Andric   case Triple::SPIRV:
4781ad6265SDimitry Andric     return createSPIRVObjectWriter(
4881ad6265SDimitry Andric         cast<MCSPIRVObjectTargetWriter>(std::move(TW)), OS);
490b57cec5SDimitry Andric   case Triple::Wasm:
500b57cec5SDimitry Andric     return createWasmObjectWriter(cast<MCWasmObjectTargetWriter>(std::move(TW)),
510b57cec5SDimitry Andric                                   OS);
525f757f3fSDimitry Andric   case Triple::GOFF:
535f757f3fSDimitry Andric     return createGOFFObjectWriter(cast<MCGOFFObjectTargetWriter>(std::move(TW)),
545f757f3fSDimitry Andric                                   OS);
550b57cec5SDimitry Andric   case Triple::XCOFF:
560b57cec5SDimitry Andric     return createXCOFFObjectWriter(
570b57cec5SDimitry Andric         cast<MCXCOFFObjectTargetWriter>(std::move(TW)), OS);
5881ad6265SDimitry Andric   case Triple::DXContainer:
5981ad6265SDimitry Andric     return createDXContainerObjectWriter(
6081ad6265SDimitry Andric         cast<MCDXContainerTargetWriter>(std::move(TW)), OS);
610b57cec5SDimitry Andric   default:
620b57cec5SDimitry Andric     llvm_unreachable("unexpected object format");
630b57cec5SDimitry Andric   }
640b57cec5SDimitry Andric }
650b57cec5SDimitry Andric 
660b57cec5SDimitry Andric std::unique_ptr<MCObjectWriter>
670b57cec5SDimitry Andric MCAsmBackend::createDwoObjectWriter(raw_pwrite_stream &OS,
680b57cec5SDimitry Andric                                     raw_pwrite_stream &DwoOS) const {
690b57cec5SDimitry Andric   auto TW = createObjectTargetWriter();
70e8d8bef9SDimitry Andric   switch (TW->getFormat()) {
7106c3fb27SDimitry Andric   case Triple::COFF:
7206c3fb27SDimitry Andric     return createWinCOFFDwoObjectWriter(
7306c3fb27SDimitry Andric         cast<MCWinCOFFObjectTargetWriter>(std::move(TW)), OS, DwoOS);
74e8d8bef9SDimitry Andric   case Triple::ELF:
75*0fca6ea1SDimitry Andric     return std::make_unique<ELFObjectWriter>(
76e8d8bef9SDimitry Andric         cast<MCELFObjectTargetWriter>(std::move(TW)), OS, DwoOS,
775f757f3fSDimitry Andric         Endian == llvm::endianness::little);
78e8d8bef9SDimitry Andric   case Triple::Wasm:
79e8d8bef9SDimitry Andric     return createWasmDwoObjectWriter(
80e8d8bef9SDimitry Andric         cast<MCWasmObjectTargetWriter>(std::move(TW)), OS, DwoOS);
81e8d8bef9SDimitry Andric   default:
8206c3fb27SDimitry Andric     report_fatal_error("dwo only supported with COFF, ELF, and Wasm");
83e8d8bef9SDimitry Andric   }
840b57cec5SDimitry Andric }
850b57cec5SDimitry Andric 
86bdd1243dSDimitry Andric std::optional<MCFixupKind> MCAsmBackend::getFixupKind(StringRef Name) const {
87bdd1243dSDimitry Andric   return std::nullopt;
880b57cec5SDimitry Andric }
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric const MCFixupKindInfo &MCAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
910b57cec5SDimitry Andric   static const MCFixupKindInfo Builtins[] = {
920b57cec5SDimitry Andric       {"FK_NONE", 0, 0, 0},
930b57cec5SDimitry Andric       {"FK_Data_1", 0, 8, 0},
940b57cec5SDimitry Andric       {"FK_Data_2", 0, 16, 0},
950b57cec5SDimitry Andric       {"FK_Data_4", 0, 32, 0},
960b57cec5SDimitry Andric       {"FK_Data_8", 0, 64, 0},
975f757f3fSDimitry Andric       {"FK_Data_leb128", 0, 0, 0},
980b57cec5SDimitry Andric       {"FK_PCRel_1", 0, 8, MCFixupKindInfo::FKF_IsPCRel},
990b57cec5SDimitry Andric       {"FK_PCRel_2", 0, 16, MCFixupKindInfo::FKF_IsPCRel},
1000b57cec5SDimitry Andric       {"FK_PCRel_4", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
1010b57cec5SDimitry Andric       {"FK_PCRel_8", 0, 64, MCFixupKindInfo::FKF_IsPCRel},
1020b57cec5SDimitry Andric       {"FK_GPRel_1", 0, 8, 0},
1030b57cec5SDimitry Andric       {"FK_GPRel_2", 0, 16, 0},
1040b57cec5SDimitry Andric       {"FK_GPRel_4", 0, 32, 0},
1050b57cec5SDimitry Andric       {"FK_GPRel_8", 0, 64, 0},
1060b57cec5SDimitry Andric       {"FK_DTPRel_4", 0, 32, 0},
1070b57cec5SDimitry Andric       {"FK_DTPRel_8", 0, 64, 0},
1080b57cec5SDimitry Andric       {"FK_TPRel_4", 0, 32, 0},
1090b57cec5SDimitry Andric       {"FK_TPRel_8", 0, 64, 0},
1100b57cec5SDimitry Andric       {"FK_SecRel_1", 0, 8, 0},
1110b57cec5SDimitry Andric       {"FK_SecRel_2", 0, 16, 0},
1120b57cec5SDimitry Andric       {"FK_SecRel_4", 0, 32, 0},
1130b57cec5SDimitry Andric       {"FK_SecRel_8", 0, 64, 0},
114fe6060f1SDimitry Andric   };
1150b57cec5SDimitry Andric 
116bdd1243dSDimitry Andric   assert((size_t)Kind <= std::size(Builtins) && "Unknown fixup kind");
1170b57cec5SDimitry Andric   return Builtins[Kind];
1180b57cec5SDimitry Andric }
1190b57cec5SDimitry Andric 
120*0fca6ea1SDimitry Andric bool MCAsmBackend::fixupNeedsRelaxationAdvanced(const MCAssembler &Asm,
121*0fca6ea1SDimitry Andric                                                 const MCFixup &Fixup,
122*0fca6ea1SDimitry Andric                                                 bool Resolved, uint64_t Value,
123*0fca6ea1SDimitry Andric                                                 const MCRelaxableFragment *DF,
1240b57cec5SDimitry Andric                                                 const bool WasForced) const {
1250b57cec5SDimitry Andric   if (!Resolved)
1260b57cec5SDimitry Andric     return true;
127*0fca6ea1SDimitry Andric   return fixupNeedsRelaxation(Fixup, Value);
1280b57cec5SDimitry Andric }
12906c3fb27SDimitry Andric 
13006c3fb27SDimitry Andric bool MCAsmBackend::isDarwinCanonicalPersonality(const MCSymbol *Sym) const {
13106c3fb27SDimitry Andric   // Consider a NULL personality (ie., no personality encoding) to be canonical
13206c3fb27SDimitry Andric   // because it's always at 0.
13306c3fb27SDimitry Andric   if (!Sym)
13406c3fb27SDimitry Andric     return true;
13506c3fb27SDimitry Andric 
13606c3fb27SDimitry Andric   if (!Sym->isMachO())
13706c3fb27SDimitry Andric     llvm_unreachable("Expected MachO symbols only");
13806c3fb27SDimitry Andric 
13906c3fb27SDimitry Andric   StringRef name = Sym->getName();
14006c3fb27SDimitry Andric   // XXX: We intentionally leave out "___gcc_personality_v0" because, despite
14106c3fb27SDimitry Andric   // being system-defined like these two, it is not very commonly-used.
14206c3fb27SDimitry Andric   // Reserving an empty slot for it seems silly.
14306c3fb27SDimitry Andric   return name == "___gxx_personality_v0" || name == "___objc_personality_v0";
14406c3fb27SDimitry Andric }
145