145 lines · cpp
1//===- MCAsmBackend.cpp - Target MC Assembly Backend ----------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/MC/MCAsmBackend.h"10#include "llvm/MC/MCAssembler.h"11#include "llvm/MC/MCContext.h"12#include "llvm/MC/MCDXContainerWriter.h"13#include "llvm/MC/MCELFObjectWriter.h"14#include "llvm/MC/MCGOFFObjectWriter.h"15#include "llvm/MC/MCMachObjectWriter.h"16#include "llvm/MC/MCObjectWriter.h"17#include "llvm/MC/MCSPIRVObjectWriter.h"18#include "llvm/MC/MCWasmObjectWriter.h"19#include "llvm/MC/MCWinCOFFObjectWriter.h"20#include "llvm/MC/MCXCOFFObjectWriter.h"21#include <cassert>22#include <cstddef>23#include <cstdint>24 25using namespace llvm;26 27MCAsmBackend::~MCAsmBackend() = default;28 29MCContext &MCAsmBackend::getContext() const { return Asm->getContext(); }30 31std::unique_ptr<MCObjectWriter>32MCAsmBackend::createObjectWriter(raw_pwrite_stream &OS) const {33 auto TW = createObjectTargetWriter();34 bool IsLE = Endian == llvm::endianness::little;35 switch (TW->getFormat()) {36 case Triple::MachO:37 return std::make_unique<MachObjectWriter>(38 cast<MCMachObjectTargetWriter>(std::move(TW)), OS, IsLE);39 case Triple::COFF:40 return createWinCOFFObjectWriter(41 cast<MCWinCOFFObjectTargetWriter>(std::move(TW)), OS);42 case Triple::ELF:43 return std::make_unique<ELFObjectWriter>(44 cast<MCELFObjectTargetWriter>(std::move(TW)), OS, IsLE);45 case Triple::SPIRV:46 return createSPIRVObjectWriter(47 cast<MCSPIRVObjectTargetWriter>(std::move(TW)), OS);48 case Triple::Wasm:49 return createWasmObjectWriter(cast<MCWasmObjectTargetWriter>(std::move(TW)),50 OS);51 case Triple::GOFF:52 return createGOFFObjectWriter(cast<MCGOFFObjectTargetWriter>(std::move(TW)),53 OS);54 case Triple::XCOFF:55 return createXCOFFObjectWriter(56 cast<MCXCOFFObjectTargetWriter>(std::move(TW)), OS);57 case Triple::DXContainer:58 return std::make_unique<DXContainerObjectWriter>(59 cast<MCDXContainerTargetWriter>(std::move(TW)), OS);60 default:61 llvm_unreachable("unexpected object format");62 }63}64 65std::unique_ptr<MCObjectWriter>66MCAsmBackend::createDwoObjectWriter(raw_pwrite_stream &OS,67 raw_pwrite_stream &DwoOS) const {68 auto TW = createObjectTargetWriter();69 switch (TW->getFormat()) {70 case Triple::COFF:71 return createWinCOFFDwoObjectWriter(72 cast<MCWinCOFFObjectTargetWriter>(std::move(TW)), OS, DwoOS);73 case Triple::ELF:74 return std::make_unique<ELFObjectWriter>(75 cast<MCELFObjectTargetWriter>(std::move(TW)), OS, DwoOS,76 Endian == llvm::endianness::little);77 case Triple::Wasm:78 return createWasmDwoObjectWriter(79 cast<MCWasmObjectTargetWriter>(std::move(TW)), OS, DwoOS);80 default:81 report_fatal_error("dwo only supported with COFF, ELF, and Wasm");82 }83}84 85std::optional<MCFixupKind> MCAsmBackend::getFixupKind(StringRef Name) const {86 return std::nullopt;87}88 89MCFixupKindInfo MCAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {90 // clang-format off91 static const MCFixupKindInfo Builtins[] = {92 {"FK_NONE", 0, 0, 0},93 {"FK_Data_1", 0, 8, 0},94 {"FK_Data_2", 0, 16, 0},95 {"FK_Data_4", 0, 32, 0},96 {"FK_Data_8", 0, 64, 0},97 {"FK_Data_leb128", 0, 0, 0},98 {"FK_SecRel_1", 0, 8, 0},99 {"FK_SecRel_2", 0, 16, 0},100 {"FK_SecRel_4", 0, 32, 0},101 {"FK_SecRel_8", 0, 64, 0},102 };103 // clang-format on104 105 assert(size_t(Kind - FK_NONE) < std::size(Builtins) && "Unknown fixup kind");106 return Builtins[Kind - FK_NONE];107}108 109bool MCAsmBackend::fixupNeedsRelaxationAdvanced(const MCFragment &,110 const MCFixup &Fixup,111 const MCValue &, uint64_t Value,112 bool Resolved) const {113 if (!Resolved)114 return true;115 return fixupNeedsRelaxation(Fixup, Value);116}117 118void MCAsmBackend::maybeAddReloc(const MCFragment &F, const MCFixup &Fixup,119 const MCValue &Target, uint64_t &Value,120 bool IsResolved) {121 if (!IsResolved)122 Asm->getWriter().recordRelocation(F, Fixup, Target, Value);123}124 125bool MCAsmBackend::isDarwinCanonicalPersonality(const MCSymbol *Sym) const {126 assert(getContext().isMachO());127 // Consider a NULL personality (ie., no personality encoding) to be canonical128 // because it's always at 0.129 if (!Sym)130 return true;131 132 StringRef name = Sym->getName();133 // XXX: We intentionally leave out "___gcc_personality_v0" because, despite134 // being system-defined like these two, it is not very commonly-used.135 // Reserving an empty slot for it seems silly.136 return name == "___gxx_personality_v0" || name == "___objc_personality_v0";137}138 139const MCSubtargetInfo *MCAsmBackend::getSubtargetInfo(const MCFragment &F) {140 const MCSubtargetInfo *STI = nullptr;141 STI = F.getSubtargetInfo();142 assert(!F.hasInstructions() || STI != nullptr);143 return STI;144}145