1//===- MC/MCAsmInfoXCOFF.cpp - XCOFF asm properties ------------ *- C++ -*-===//
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-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "llvm/MC/MCAsmInfoXCOFF.h"
10#include "MCCLOptions.h"
11#include "llvm/ADT/StringExtras.h"
12#include "llvm/MC/MCAsmInfo.h"
13#include "llvm/MC/MCSectionXCOFF.h"
14#include "llvm/Support/Format.h"
15#include "llvm/Support/raw_ostream.h"
16
17using namespace llvm;
18
19MCAsmInfoXCOFF::MCAsmInfoXCOFF(const MCTargetOptions &Options)
20 : MCAsmInfo(Options) {
21 IsAIX = true;
22 IsLittleEndian = false;
23
24 InternalSymbolPrefix = "L..";
25 SupportsQuotedNames = false;
26 if (MCCLOptions::Global.use_leb128_directives == BoolOrDefault::Default)
27 HasLEB128Directives = false;
28 ZeroDirective = "\t.space\t";
29 AsciiDirective = nullptr; // not supported
30 AscizDirective = nullptr; // not supported
31 CharacterLiteralSyntax = ACLS_SingleQuotePrefix;
32
33 // Use .vbyte for data definition to avoid directives that apply an implicit
34 // alignment.
35 Data16bitsDirective = "\t.vbyte\t2, ";
36 Data32bitsDirective = "\t.vbyte\t4, ";
37
38 COMMDirectiveAlignmentIsInBytes = false;
39 LCOMMDirectiveAlignmentType = LCOMM::Log2Alignment;
40 HasDotTypeDotSizeDirective = false;
41 ParseInlineAsmUsingAsmParser = true;
42
43 ExceptionsType = ExceptionHandling::AIX;
44}
45
46bool MCAsmInfoXCOFF::useCodeAlign(const MCSection &Sec) const {
47 return static_cast<const MCSectionXCOFF &>(Sec).getKind().isText();
48}
49
50MCSectionXCOFF::~MCSectionXCOFF() = default;
51
52void MCSectionXCOFF::printCsectDirective(raw_ostream &OS) const {
53 OS << "\t.csect " << QualName->getName() << "," << Log2(A: getAlign()) << '\n';
54}
55
56void MCAsmInfoXCOFF::printSwitchToSection(const MCSection &Section, uint32_t,
57 const Triple &T,
58 raw_ostream &OS) const {
59 auto &Sec = static_cast<const MCSectionXCOFF &>(Section);
60 if (Sec.getKind().isText()) {
61 if (Sec.getMappingClass() != XCOFF::XMC_PR)
62 report_fatal_error(reason: "Unhandled storage-mapping class for .text csect");
63
64 Sec.printCsectDirective(OS);
65 return;
66 }
67
68 if (Sec.getKind().isReadOnly()) {
69 if (Sec.getMappingClass() != XCOFF::XMC_RO &&
70 Sec.getMappingClass() != XCOFF::XMC_TD)
71 report_fatal_error(reason: "Unhandled storage-mapping class for .rodata csect.");
72 Sec.printCsectDirective(OS);
73 return;
74 }
75
76 if (Sec.getKind().isReadOnlyWithRel()) {
77 if (Sec.getMappingClass() != XCOFF::XMC_RW &&
78 Sec.getMappingClass() != XCOFF::XMC_RO &&
79 Sec.getMappingClass() != XCOFF::XMC_TD)
80 report_fatal_error(
81 reason: "Unexepected storage-mapping class for ReadOnlyWithRel kind");
82 Sec.printCsectDirective(OS);
83 return;
84 }
85
86 // Initialized TLS data.
87 if (Sec.getKind().isThreadData()) {
88 // We only expect XMC_TL here for initialized TLS data.
89 if (Sec.getMappingClass() != XCOFF::XMC_TL)
90 report_fatal_error(reason: "Unhandled storage-mapping class for .tdata csect.");
91 Sec.printCsectDirective(OS);
92 return;
93 }
94
95 if (Sec.getKind().isData()) {
96 switch (Sec.getMappingClass()) {
97 case XCOFF::XMC_RW:
98 case XCOFF::XMC_DS:
99 case XCOFF::XMC_TD:
100 Sec.printCsectDirective(OS);
101 break;
102 case XCOFF::XMC_TC:
103 case XCOFF::XMC_TE:
104 break;
105 case XCOFF::XMC_TC0:
106 OS << "\t.toc\n";
107 break;
108 default:
109 report_fatal_error(reason: "Unhandled storage-mapping class for .data csect.");
110 }
111 return;
112 }
113
114 if (Sec.isCsect() && Sec.getMappingClass() == XCOFF::XMC_TD) {
115 // Common csect type (uninitialized storage) does not have to print
116 // csect directive for section switching unless it is local.
117 if (Sec.getKind().isCommon() && !Sec.getKind().isBSSLocal())
118 return;
119
120 assert(Sec.getKind().isBSS() && "Unexpected section kind for toc-data");
121 Sec.printCsectDirective(OS);
122 return;
123 }
124 // Common csect type (uninitialized storage) does not have to print csect
125 // directive for section switching.
126 if (Sec.isCsect() && Sec.getCSectType() == XCOFF::XTY_CM) {
127 assert((Sec.getMappingClass() == XCOFF::XMC_RW ||
128 Sec.getMappingClass() == XCOFF::XMC_BS ||
129 Sec.getMappingClass() == XCOFF::XMC_UL) &&
130 "Generated a storage-mapping class for a common/bss/tbss csect we "
131 "don't "
132 "understand how to switch to.");
133 // Common symbols and local zero-initialized symbols for TLS and Non-TLS are
134 // eligible for .bss/.tbss csect, getKind().isThreadBSS() is used to
135 // cover TLS common and zero-initialized local symbols since linkage type
136 // (in the GlobalVariable) is not accessible in this class.
137 assert((Sec.getKind().isBSSLocal() || Sec.getKind().isCommon() ||
138 Sec.getKind().isThreadBSS()) &&
139 "wrong symbol type for .bss/.tbss csect");
140 // Don't have to print a directive for switching to section for commons
141 // and zero-initialized TLS data. The '.comm' and '.lcomm' directives of the
142 // variable will create the needed csect.
143 return;
144 }
145
146 // Zero-initialized TLS data with weak or external linkage are not eligible to
147 // be put into common csect.
148 if (Sec.getKind().isThreadBSS()) {
149 Sec.printCsectDirective(OS);
150 return;
151 }
152
153 // XCOFF debug sections.
154 if (Sec.getKind().isMetadata() && Sec.isDwarfSect()) {
155 OS << "\n\t.dwsect " << format(Fmt: "0x%" PRIx32, Vals: *Sec.getDwarfSubtypeFlags())
156 << '\n';
157 OS << Sec.getName() << ':' << '\n';
158 return;
159 }
160
161 report_fatal_error(reason: "Printing for this SectionKind is unimplemented.");
162}
163