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