151 lines · cpp
1//===- lib/MC/MCXCOFFStreamer.cpp - XCOFF Object Output -------------------===//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// This file assembles .s files and emits XCOFF .o object files.10//11//===----------------------------------------------------------------------===//12 13#include "llvm/MC/MCXCOFFStreamer.h"14#include "llvm/BinaryFormat/XCOFF.h"15#include "llvm/MC/MCAsmBackend.h"16#include "llvm/MC/MCAssembler.h"17#include "llvm/MC/MCCodeEmitter.h"18#include "llvm/MC/MCDirectives.h"19#include "llvm/MC/MCObjectWriter.h"20#include "llvm/MC/MCSectionXCOFF.h"21#include "llvm/MC/MCSymbolXCOFF.h"22#include "llvm/MC/MCXCOFFObjectWriter.h"23#include "llvm/MC/TargetRegistry.h"24 25using namespace llvm;26 27MCXCOFFStreamer::MCXCOFFStreamer(MCContext &Context,28 std::unique_ptr<MCAsmBackend> MAB,29 std::unique_ptr<MCObjectWriter> OW,30 std::unique_ptr<MCCodeEmitter> Emitter)31 : MCObjectStreamer(Context, std::move(MAB), std::move(OW),32 std::move(Emitter)) {}33 34XCOFFObjectWriter &MCXCOFFStreamer::getWriter() {35 return static_cast<XCOFFObjectWriter &>(getAssembler().getWriter());36}37 38void MCXCOFFStreamer::changeSection(MCSection *Section, uint32_t Subsection) {39 MCObjectStreamer::changeSection(Section, Subsection);40 auto *Sec = static_cast<const MCSectionXCOFF *>(Section);41 // We might miss calculating the symbols difference as absolute value before42 // adding fixups when symbol_A without the fragment set is the csect itself43 // and symbol_B is in it.44 // TODO: Currently we only set the fragment for XMC_PR csects and DWARF45 // sections because we don't have other cases that hit this problem yet.46 // if (IsDwarfSec || CsectProp->MappingClass == XCOFF::XMC_PR)47 // QualName->setFragment(F);48 if (Sec->isDwarfSect() || Sec->getMappingClass() == XCOFF::XMC_PR)49 Sec->getQualNameSymbol()->setFragment(CurFrag);50}51 52bool MCXCOFFStreamer::emitSymbolAttribute(MCSymbol *Sym,53 MCSymbolAttr Attribute) {54 auto *Symbol = static_cast<MCSymbolXCOFF *>(Sym);55 getAssembler().registerSymbol(*Symbol);56 57 switch (Attribute) {58 // XCOFF doesn't support the cold feature.59 case MCSA_Cold:60 return false;61 62 case MCSA_Global:63 case MCSA_Extern:64 Symbol->setStorageClass(XCOFF::C_EXT);65 Symbol->setExternal(true);66 break;67 case MCSA_LGlobal:68 Symbol->setStorageClass(XCOFF::C_HIDEXT);69 Symbol->setExternal(true);70 break;71 case llvm::MCSA_Weak:72 Symbol->setStorageClass(XCOFF::C_WEAKEXT);73 Symbol->setExternal(true);74 break;75 case llvm::MCSA_Hidden:76 Symbol->setVisibilityType(XCOFF::SYM_V_HIDDEN);77 break;78 case llvm::MCSA_Protected:79 Symbol->setVisibilityType(XCOFF::SYM_V_PROTECTED);80 break;81 case llvm::MCSA_Exported:82 Symbol->setVisibilityType(XCOFF::SYM_V_EXPORTED);83 break;84 default:85 report_fatal_error("Not implemented yet.");86 }87 return true;88}89 90void MCXCOFFStreamer::emitXCOFFSymbolLinkageWithVisibility(91 MCSymbol *Symbol, MCSymbolAttr Linkage, MCSymbolAttr Visibility) {92 93 emitSymbolAttribute(Symbol, Linkage);94 95 // When the caller passes `MCSA_Invalid` for the visibility, do not emit one.96 if (Visibility == MCSA_Invalid)97 return;98 99 emitSymbolAttribute(Symbol, Visibility);100}101 102void MCXCOFFStreamer::emitXCOFFRefDirective(const MCSymbol *Symbol) {103 // Add a Fixup here to later record a relocation of type R_REF to prevent the104 // ref symbol from being garbage collected (by the binder).105 addFixup(MCSymbolRefExpr::create(Symbol, getContext()),106 XCOFF::RelocationType::R_REF);107}108 109void MCXCOFFStreamer::emitXCOFFRenameDirective(const MCSymbol *Name,110 StringRef Rename) {111 auto *Symbol = static_cast<const MCSymbolXCOFF *>(Name);112 if (!Symbol->hasRename())113 report_fatal_error("Only explicit .rename is supported for XCOFF.");114}115 116void MCXCOFFStreamer::emitXCOFFExceptDirective(const MCSymbol *Symbol,117 const MCSymbol *Trap,118 unsigned Lang, unsigned Reason,119 unsigned FunctionSize,120 bool hasDebug) {121 getWriter().addExceptionEntry(Symbol, Trap, Lang, Reason, FunctionSize,122 hasDebug);123}124 125void MCXCOFFStreamer::emitXCOFFCInfoSym(StringRef Name, StringRef Metadata) {126 getWriter().addCInfoSymEntry(Name, Metadata);127}128 129void MCXCOFFStreamer::emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,130 Align ByteAlignment) {131 auto &Sym = static_cast<MCSymbolXCOFF &>(*Symbol);132 getAssembler().registerSymbol(*Symbol);133 Sym.setExternal(Sym.getStorageClass() != XCOFF::C_HIDEXT);134 Symbol->setCommon(Size, ByteAlignment);135 136 // Default csect align is 4, but common symbols have explicit alignment values137 // and we should honor it.138 Sym.getRepresentedCsect()->setAlignment(ByteAlignment);139 140 // Emit the alignment and storage for the variable to the section.141 emitValueToAlignment(ByteAlignment);142 emitZeros(Size);143}144 145void MCXCOFFStreamer::emitXCOFFLocalCommonSymbol(MCSymbol *LabelSym,146 uint64_t Size,147 MCSymbol *CsectSym,148 Align Alignment) {149 emitCommonSymbol(CsectSym, Size, Alignment);150}151