1 | //===- DarwinAsmParser.cpp - Darwin (Mach-O) Assembly Parser --------------===// |
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/ADT/SmallVector.h" |
10 | #include "llvm/ADT/StringRef.h" |
11 | #include "llvm/ADT/StringSwitch.h" |
12 | #include "llvm/ADT/Twine.h" |
13 | #include "llvm/BinaryFormat/MachO.h" |
14 | #include "llvm/MC/MCContext.h" |
15 | #include "llvm/MC/MCDirectives.h" |
16 | #include "llvm/MC/MCParser/MCAsmLexer.h" |
17 | #include "llvm/MC/MCParser/MCAsmParser.h" |
18 | #include "llvm/MC/MCParser/MCAsmParserExtension.h" |
19 | #include "llvm/MC/MCSectionMachO.h" |
20 | #include "llvm/MC/MCStreamer.h" |
21 | #include "llvm/MC/MCSymbol.h" |
22 | #include "llvm/MC/SectionKind.h" |
23 | #include "llvm/Support/Error.h" |
24 | #include "llvm/Support/FileSystem.h" |
25 | #include "llvm/Support/MemoryBuffer.h" |
26 | #include "llvm/Support/SMLoc.h" |
27 | #include "llvm/Support/SourceMgr.h" |
28 | #include "llvm/Support/raw_ostream.h" |
29 | #include "llvm/TargetParser/Triple.h" |
30 | #include <cstddef> |
31 | #include <cstdint> |
32 | #include <string> |
33 | #include <system_error> |
34 | #include <utility> |
35 | |
36 | using namespace llvm; |
37 | |
38 | namespace { |
39 | |
40 | /// Implementation of directive handling which is shared across all |
41 | /// Darwin targets. |
42 | class DarwinAsmParser : public MCAsmParserExtension { |
43 | template<bool (DarwinAsmParser::*HandlerMethod)(StringRef, SMLoc)> |
44 | void addDirectiveHandler(StringRef Directive) { |
45 | MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair( |
46 | this, HandleDirective<DarwinAsmParser, HandlerMethod>); |
47 | getParser().addDirectiveHandler(Directive, Handler); |
48 | } |
49 | |
50 | bool parseSectionSwitch(StringRef Segment, StringRef Section, |
51 | unsigned TAA = 0, unsigned ImplicitAlign = 0, |
52 | unsigned StubSize = 0); |
53 | |
54 | SMLoc LastVersionDirective; |
55 | |
56 | public: |
57 | DarwinAsmParser() = default; |
58 | |
59 | void Initialize(MCAsmParser &Parser) override { |
60 | // Call the base implementation. |
61 | this->MCAsmParserExtension::Initialize(Parser); |
62 | |
63 | addDirectiveHandler<&DarwinAsmParser::parseDirectiveAltEntry>(Directive: ".alt_entry" ); |
64 | addDirectiveHandler<&DarwinAsmParser::parseDirectiveDesc>(Directive: ".desc" ); |
65 | addDirectiveHandler<&DarwinAsmParser::parseDirectiveIndirectSymbol>( |
66 | Directive: ".indirect_symbol" ); |
67 | addDirectiveHandler<&DarwinAsmParser::parseDirectiveLsym>(Directive: ".lsym" ); |
68 | addDirectiveHandler<&DarwinAsmParser::parseDirectiveSubsectionsViaSymbols>( |
69 | Directive: ".subsections_via_symbols" ); |
70 | addDirectiveHandler<&DarwinAsmParser::parseDirectiveDumpOrLoad>(Directive: ".dump" ); |
71 | addDirectiveHandler<&DarwinAsmParser::parseDirectiveDumpOrLoad>(Directive: ".load" ); |
72 | addDirectiveHandler<&DarwinAsmParser::parseDirectiveSection>(Directive: ".section" ); |
73 | addDirectiveHandler<&DarwinAsmParser::parseDirectivePushSection>( |
74 | Directive: ".pushsection" ); |
75 | addDirectiveHandler<&DarwinAsmParser::parseDirectivePopSection>( |
76 | Directive: ".popsection" ); |
77 | addDirectiveHandler<&DarwinAsmParser::parseDirectivePrevious>(Directive: ".previous" ); |
78 | addDirectiveHandler<&DarwinAsmParser::parseDirectiveSecureLogUnique>( |
79 | Directive: ".secure_log_unique" ); |
80 | addDirectiveHandler<&DarwinAsmParser::parseDirectiveSecureLogReset>( |
81 | Directive: ".secure_log_reset" ); |
82 | addDirectiveHandler<&DarwinAsmParser::parseDirectiveTBSS>(Directive: ".tbss" ); |
83 | addDirectiveHandler<&DarwinAsmParser::parseDirectiveZerofill>(Directive: ".zerofill" ); |
84 | |
85 | addDirectiveHandler<&DarwinAsmParser::parseDirectiveDataRegion>( |
86 | Directive: ".data_region" ); |
87 | addDirectiveHandler<&DarwinAsmParser::parseDirectiveDataRegionEnd>( |
88 | Directive: ".end_data_region" ); |
89 | |
90 | // Special section directives. |
91 | addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveBss>(Directive: ".bss" ); |
92 | addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveConst>(Directive: ".const" ); |
93 | addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveConstData>( |
94 | Directive: ".const_data" ); |
95 | addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveConstructor>( |
96 | Directive: ".constructor" ); |
97 | addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveCString>( |
98 | Directive: ".cstring" ); |
99 | addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveData>(Directive: ".data" ); |
100 | addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveDestructor>( |
101 | Directive: ".destructor" ); |
102 | addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveDyld>(Directive: ".dyld" ); |
103 | addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveFVMLibInit0>( |
104 | Directive: ".fvmlib_init0" ); |
105 | addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveFVMLibInit1>( |
106 | Directive: ".fvmlib_init1" ); |
107 | addDirectiveHandler< |
108 | &DarwinAsmParser::parseSectionDirectiveLazySymbolPointers>( |
109 | Directive: ".lazy_symbol_pointer" ); |
110 | addDirectiveHandler<&DarwinAsmParser::parseDirectiveLinkerOption>( |
111 | Directive: ".linker_option" ); |
112 | addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveLiteral16>( |
113 | Directive: ".literal16" ); |
114 | addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveLiteral4>( |
115 | Directive: ".literal4" ); |
116 | addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveLiteral8>( |
117 | Directive: ".literal8" ); |
118 | addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveModInitFunc>( |
119 | Directive: ".mod_init_func" ); |
120 | addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveModTermFunc>( |
121 | Directive: ".mod_term_func" ); |
122 | addDirectiveHandler< |
123 | &DarwinAsmParser::parseSectionDirectiveNonLazySymbolPointers>( |
124 | Directive: ".non_lazy_symbol_pointer" ); |
125 | addDirectiveHandler< |
126 | &DarwinAsmParser::parseSectionDirectiveThreadLocalVariablePointers>( |
127 | Directive: ".thread_local_variable_pointer" ); |
128 | addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCCatClsMeth>( |
129 | Directive: ".objc_cat_cls_meth" ); |
130 | addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCCatInstMeth>( |
131 | Directive: ".objc_cat_inst_meth" ); |
132 | addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCCategory>( |
133 | Directive: ".objc_category" ); |
134 | addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClass>( |
135 | Directive: ".objc_class" ); |
136 | addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClassNames>( |
137 | Directive: ".objc_class_names" ); |
138 | addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClassVars>( |
139 | Directive: ".objc_class_vars" ); |
140 | addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClsMeth>( |
141 | Directive: ".objc_cls_meth" ); |
142 | addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClsRefs>( |
143 | Directive: ".objc_cls_refs" ); |
144 | addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCInstMeth>( |
145 | Directive: ".objc_inst_meth" ); |
146 | addDirectiveHandler< |
147 | &DarwinAsmParser::parseSectionDirectiveObjCInstanceVars>( |
148 | Directive: ".objc_instance_vars" ); |
149 | addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCMessageRefs>( |
150 | Directive: ".objc_message_refs" ); |
151 | addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCMetaClass>( |
152 | Directive: ".objc_meta_class" ); |
153 | addDirectiveHandler< |
154 | &DarwinAsmParser::parseSectionDirectiveObjCMethVarNames>( |
155 | Directive: ".objc_meth_var_names" ); |
156 | addDirectiveHandler< |
157 | &DarwinAsmParser::parseSectionDirectiveObjCMethVarTypes>( |
158 | Directive: ".objc_meth_var_types" ); |
159 | addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCModuleInfo>( |
160 | Directive: ".objc_module_info" ); |
161 | addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCProtocol>( |
162 | Directive: ".objc_protocol" ); |
163 | addDirectiveHandler< |
164 | &DarwinAsmParser::parseSectionDirectiveObjCSelectorStrs>( |
165 | Directive: ".objc_selector_strs" ); |
166 | addDirectiveHandler< |
167 | &DarwinAsmParser::parseSectionDirectiveObjCStringObject>( |
168 | Directive: ".objc_string_object" ); |
169 | addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCSymbols>( |
170 | Directive: ".objc_symbols" ); |
171 | addDirectiveHandler<&DarwinAsmParser::parseSectionDirectivePICSymbolStub>( |
172 | Directive: ".picsymbol_stub" ); |
173 | addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveStaticConst>( |
174 | Directive: ".static_const" ); |
175 | addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveStaticData>( |
176 | Directive: ".static_data" ); |
177 | addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveSymbolStub>( |
178 | Directive: ".symbol_stub" ); |
179 | addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveTData>(Directive: ".tdata" ); |
180 | addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveText>(Directive: ".text" ); |
181 | addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveThreadInitFunc>( |
182 | Directive: ".thread_init_func" ); |
183 | addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveTLV>(Directive: ".tlv" ); |
184 | |
185 | addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveIdent>(Directive: ".ident" ); |
186 | addDirectiveHandler<&DarwinAsmParser::parseWatchOSVersionMin>( |
187 | Directive: ".watchos_version_min" ); |
188 | addDirectiveHandler<&DarwinAsmParser::parseTvOSVersionMin>( |
189 | Directive: ".tvos_version_min" ); |
190 | addDirectiveHandler<&DarwinAsmParser::parseIOSVersionMin>( |
191 | Directive: ".ios_version_min" ); |
192 | addDirectiveHandler<&DarwinAsmParser::parseMacOSXVersionMin>( |
193 | Directive: ".macosx_version_min" ); |
194 | addDirectiveHandler<&DarwinAsmParser::parseBuildVersion>(Directive: ".build_version" ); |
195 | addDirectiveHandler<&DarwinAsmParser::parseDirectiveCGProfile>( |
196 | Directive: ".cg_profile" ); |
197 | |
198 | LastVersionDirective = SMLoc(); |
199 | } |
200 | |
201 | bool parseDirectiveAltEntry(StringRef, SMLoc); |
202 | bool parseDirectiveDesc(StringRef, SMLoc); |
203 | bool parseDirectiveIndirectSymbol(StringRef, SMLoc); |
204 | bool parseDirectiveDumpOrLoad(StringRef, SMLoc); |
205 | bool parseDirectiveLsym(StringRef, SMLoc); |
206 | bool parseDirectiveLinkerOption(StringRef, SMLoc); |
207 | bool parseDirectiveSection(StringRef, SMLoc); |
208 | bool parseDirectivePushSection(StringRef, SMLoc); |
209 | bool parseDirectivePopSection(StringRef, SMLoc); |
210 | bool parseDirectivePrevious(StringRef, SMLoc); |
211 | bool parseDirectiveSecureLogReset(StringRef, SMLoc); |
212 | bool parseDirectiveSecureLogUnique(StringRef, SMLoc); |
213 | bool parseDirectiveSubsectionsViaSymbols(StringRef, SMLoc); |
214 | bool parseDirectiveTBSS(StringRef, SMLoc); |
215 | bool parseDirectiveZerofill(StringRef, SMLoc); |
216 | bool parseDirectiveDataRegion(StringRef, SMLoc); |
217 | bool parseDirectiveDataRegionEnd(StringRef, SMLoc); |
218 | |
219 | // Named Section Directive |
220 | bool parseSectionDirectiveBss(StringRef, SMLoc) { |
221 | return parseSectionSwitch(Segment: "__DATA" , Section: "__bss" ); |
222 | } |
223 | |
224 | bool parseSectionDirectiveConst(StringRef, SMLoc) { |
225 | return parseSectionSwitch(Segment: "__TEXT" , Section: "__const" ); |
226 | } |
227 | |
228 | bool parseSectionDirectiveStaticConst(StringRef, SMLoc) { |
229 | return parseSectionSwitch(Segment: "__TEXT" , Section: "__static_const" ); |
230 | } |
231 | |
232 | bool parseSectionDirectiveCString(StringRef, SMLoc) { |
233 | return parseSectionSwitch(Segment: "__TEXT" ,Section: "__cstring" , |
234 | TAA: MachO::S_CSTRING_LITERALS); |
235 | } |
236 | |
237 | bool parseSectionDirectiveLiteral4(StringRef, SMLoc) { |
238 | return parseSectionSwitch(Segment: "__TEXT" , Section: "__literal4" , |
239 | TAA: MachO::S_4BYTE_LITERALS, ImplicitAlign: 4); |
240 | } |
241 | |
242 | bool parseSectionDirectiveLiteral8(StringRef, SMLoc) { |
243 | return parseSectionSwitch(Segment: "__TEXT" , Section: "__literal8" , |
244 | TAA: MachO::S_8BYTE_LITERALS, ImplicitAlign: 8); |
245 | } |
246 | |
247 | bool parseSectionDirectiveLiteral16(StringRef, SMLoc) { |
248 | return parseSectionSwitch(Segment: "__TEXT" ,Section: "__literal16" , |
249 | TAA: MachO::S_16BYTE_LITERALS, ImplicitAlign: 16); |
250 | } |
251 | |
252 | bool parseSectionDirectiveConstructor(StringRef, SMLoc) { |
253 | return parseSectionSwitch(Segment: "__TEXT" ,Section: "__constructor" ); |
254 | } |
255 | |
256 | bool parseSectionDirectiveDestructor(StringRef, SMLoc) { |
257 | return parseSectionSwitch(Segment: "__TEXT" ,Section: "__destructor" ); |
258 | } |
259 | |
260 | bool parseSectionDirectiveFVMLibInit0(StringRef, SMLoc) { |
261 | return parseSectionSwitch(Segment: "__TEXT" ,Section: "__fvmlib_init0" ); |
262 | } |
263 | |
264 | bool parseSectionDirectiveFVMLibInit1(StringRef, SMLoc) { |
265 | return parseSectionSwitch(Segment: "__TEXT" ,Section: "__fvmlib_init1" ); |
266 | } |
267 | |
268 | bool parseSectionDirectiveSymbolStub(StringRef, SMLoc) { |
269 | return parseSectionSwitch(Segment: "__TEXT" ,Section: "__symbol_stub" , |
270 | TAA: MachO::S_SYMBOL_STUBS | |
271 | MachO::S_ATTR_PURE_INSTRUCTIONS, |
272 | // FIXME: Different on PPC and ARM. |
273 | ImplicitAlign: 0, StubSize: 16); |
274 | } |
275 | |
276 | bool parseSectionDirectivePICSymbolStub(StringRef, SMLoc) { |
277 | return parseSectionSwitch(Segment: "__TEXT" ,Section: "__picsymbol_stub" , |
278 | TAA: MachO::S_SYMBOL_STUBS | |
279 | MachO::S_ATTR_PURE_INSTRUCTIONS, ImplicitAlign: 0, StubSize: 26); |
280 | } |
281 | |
282 | bool parseSectionDirectiveData(StringRef, SMLoc) { |
283 | return parseSectionSwitch(Segment: "__DATA" , Section: "__data" ); |
284 | } |
285 | |
286 | bool parseSectionDirectiveStaticData(StringRef, SMLoc) { |
287 | return parseSectionSwitch(Segment: "__DATA" , Section: "__static_data" ); |
288 | } |
289 | |
290 | bool parseSectionDirectiveNonLazySymbolPointers(StringRef, SMLoc) { |
291 | return parseSectionSwitch(Segment: "__DATA" , Section: "__nl_symbol_ptr" , |
292 | TAA: MachO::S_NON_LAZY_SYMBOL_POINTERS, ImplicitAlign: 4); |
293 | } |
294 | |
295 | bool parseSectionDirectiveLazySymbolPointers(StringRef, SMLoc) { |
296 | return parseSectionSwitch(Segment: "__DATA" , Section: "__la_symbol_ptr" , |
297 | TAA: MachO::S_LAZY_SYMBOL_POINTERS, ImplicitAlign: 4); |
298 | } |
299 | |
300 | bool parseSectionDirectiveThreadLocalVariablePointers(StringRef, SMLoc) { |
301 | return parseSectionSwitch(Segment: "__DATA" , Section: "__thread_ptr" , |
302 | TAA: MachO::S_THREAD_LOCAL_VARIABLE_POINTERS, ImplicitAlign: 4); |
303 | } |
304 | |
305 | bool parseSectionDirectiveDyld(StringRef, SMLoc) { |
306 | return parseSectionSwitch(Segment: "__DATA" , Section: "__dyld" ); |
307 | } |
308 | |
309 | bool parseSectionDirectiveModInitFunc(StringRef, SMLoc) { |
310 | return parseSectionSwitch(Segment: "__DATA" , Section: "__mod_init_func" , |
311 | TAA: MachO::S_MOD_INIT_FUNC_POINTERS, ImplicitAlign: 4); |
312 | } |
313 | |
314 | bool parseSectionDirectiveModTermFunc(StringRef, SMLoc) { |
315 | return parseSectionSwitch(Segment: "__DATA" , Section: "__mod_term_func" , |
316 | TAA: MachO::S_MOD_TERM_FUNC_POINTERS, ImplicitAlign: 4); |
317 | } |
318 | |
319 | bool parseSectionDirectiveConstData(StringRef, SMLoc) { |
320 | return parseSectionSwitch(Segment: "__DATA" , Section: "__const" ); |
321 | } |
322 | |
323 | bool parseSectionDirectiveObjCClass(StringRef, SMLoc) { |
324 | return parseSectionSwitch(Segment: "__OBJC" , Section: "__class" , |
325 | TAA: MachO::S_ATTR_NO_DEAD_STRIP); |
326 | } |
327 | |
328 | bool parseSectionDirectiveObjCMetaClass(StringRef, SMLoc) { |
329 | return parseSectionSwitch(Segment: "__OBJC" , Section: "__meta_class" , |
330 | TAA: MachO::S_ATTR_NO_DEAD_STRIP); |
331 | } |
332 | |
333 | bool parseSectionDirectiveObjCCatClsMeth(StringRef, SMLoc) { |
334 | return parseSectionSwitch(Segment: "__OBJC" , Section: "__cat_cls_meth" , |
335 | TAA: MachO::S_ATTR_NO_DEAD_STRIP); |
336 | } |
337 | |
338 | bool parseSectionDirectiveObjCCatInstMeth(StringRef, SMLoc) { |
339 | return parseSectionSwitch(Segment: "__OBJC" , Section: "__cat_inst_meth" , |
340 | TAA: MachO::S_ATTR_NO_DEAD_STRIP); |
341 | } |
342 | |
343 | bool parseSectionDirectiveObjCProtocol(StringRef, SMLoc) { |
344 | return parseSectionSwitch(Segment: "__OBJC" , Section: "__protocol" , |
345 | TAA: MachO::S_ATTR_NO_DEAD_STRIP); |
346 | } |
347 | |
348 | bool parseSectionDirectiveObjCStringObject(StringRef, SMLoc) { |
349 | return parseSectionSwitch(Segment: "__OBJC" , Section: "__string_object" , |
350 | TAA: MachO::S_ATTR_NO_DEAD_STRIP); |
351 | } |
352 | |
353 | bool parseSectionDirectiveObjCClsMeth(StringRef, SMLoc) { |
354 | return parseSectionSwitch(Segment: "__OBJC" , Section: "__cls_meth" , |
355 | TAA: MachO::S_ATTR_NO_DEAD_STRIP); |
356 | } |
357 | |
358 | bool parseSectionDirectiveObjCInstMeth(StringRef, SMLoc) { |
359 | return parseSectionSwitch(Segment: "__OBJC" , Section: "__inst_meth" , |
360 | TAA: MachO::S_ATTR_NO_DEAD_STRIP); |
361 | } |
362 | |
363 | bool parseSectionDirectiveObjCClsRefs(StringRef, SMLoc) { |
364 | return parseSectionSwitch(Segment: "__OBJC" , Section: "__cls_refs" , |
365 | TAA: MachO::S_ATTR_NO_DEAD_STRIP | |
366 | MachO::S_LITERAL_POINTERS, ImplicitAlign: 4); |
367 | } |
368 | |
369 | bool parseSectionDirectiveObjCMessageRefs(StringRef, SMLoc) { |
370 | return parseSectionSwitch(Segment: "__OBJC" , Section: "__message_refs" , |
371 | TAA: MachO::S_ATTR_NO_DEAD_STRIP | |
372 | MachO::S_LITERAL_POINTERS, ImplicitAlign: 4); |
373 | } |
374 | |
375 | bool parseSectionDirectiveObjCSymbols(StringRef, SMLoc) { |
376 | return parseSectionSwitch(Segment: "__OBJC" , Section: "__symbols" , |
377 | TAA: MachO::S_ATTR_NO_DEAD_STRIP); |
378 | } |
379 | |
380 | bool parseSectionDirectiveObjCCategory(StringRef, SMLoc) { |
381 | return parseSectionSwitch(Segment: "__OBJC" , Section: "__category" , |
382 | TAA: MachO::S_ATTR_NO_DEAD_STRIP); |
383 | } |
384 | |
385 | bool parseSectionDirectiveObjCClassVars(StringRef, SMLoc) { |
386 | return parseSectionSwitch(Segment: "__OBJC" , Section: "__class_vars" , |
387 | TAA: MachO::S_ATTR_NO_DEAD_STRIP); |
388 | } |
389 | |
390 | bool parseSectionDirectiveObjCInstanceVars(StringRef, SMLoc) { |
391 | return parseSectionSwitch(Segment: "__OBJC" , Section: "__instance_vars" , |
392 | TAA: MachO::S_ATTR_NO_DEAD_STRIP); |
393 | } |
394 | |
395 | bool parseSectionDirectiveObjCModuleInfo(StringRef, SMLoc) { |
396 | return parseSectionSwitch(Segment: "__OBJC" , Section: "__module_info" , |
397 | TAA: MachO::S_ATTR_NO_DEAD_STRIP); |
398 | } |
399 | |
400 | bool parseSectionDirectiveObjCClassNames(StringRef, SMLoc) { |
401 | return parseSectionSwitch(Segment: "__TEXT" , Section: "__cstring" , |
402 | TAA: MachO::S_CSTRING_LITERALS); |
403 | } |
404 | |
405 | bool parseSectionDirectiveObjCMethVarTypes(StringRef, SMLoc) { |
406 | return parseSectionSwitch(Segment: "__TEXT" , Section: "__cstring" , |
407 | TAA: MachO::S_CSTRING_LITERALS); |
408 | } |
409 | |
410 | bool parseSectionDirectiveObjCMethVarNames(StringRef, SMLoc) { |
411 | return parseSectionSwitch(Segment: "__TEXT" , Section: "__cstring" , |
412 | TAA: MachO::S_CSTRING_LITERALS); |
413 | } |
414 | |
415 | bool parseSectionDirectiveObjCSelectorStrs(StringRef, SMLoc) { |
416 | return parseSectionSwitch(Segment: "__OBJC" , Section: "__selector_strs" , |
417 | TAA: MachO::S_CSTRING_LITERALS); |
418 | } |
419 | |
420 | bool parseSectionDirectiveTData(StringRef, SMLoc) { |
421 | return parseSectionSwitch(Segment: "__DATA" , Section: "__thread_data" , |
422 | TAA: MachO::S_THREAD_LOCAL_REGULAR); |
423 | } |
424 | |
425 | bool parseSectionDirectiveText(StringRef, SMLoc) { |
426 | return parseSectionSwitch(Segment: "__TEXT" , Section: "__text" , |
427 | TAA: MachO::S_ATTR_PURE_INSTRUCTIONS); |
428 | } |
429 | |
430 | bool parseSectionDirectiveTLV(StringRef, SMLoc) { |
431 | return parseSectionSwitch(Segment: "__DATA" , Section: "__thread_vars" , |
432 | TAA: MachO::S_THREAD_LOCAL_VARIABLES); |
433 | } |
434 | |
435 | bool parseSectionDirectiveIdent(StringRef, SMLoc) { |
436 | // Darwin silently ignores the .ident directive. |
437 | getParser().eatToEndOfStatement(); |
438 | return false; |
439 | } |
440 | |
441 | bool parseSectionDirectiveThreadInitFunc(StringRef, SMLoc) { |
442 | return parseSectionSwitch(Segment: "__DATA" , Section: "__thread_init" , |
443 | TAA: MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS); |
444 | } |
445 | |
446 | bool parseWatchOSVersionMin(StringRef Directive, SMLoc Loc) { |
447 | return parseVersionMin(Directive, Loc, Type: MCVM_WatchOSVersionMin); |
448 | } |
449 | bool parseTvOSVersionMin(StringRef Directive, SMLoc Loc) { |
450 | return parseVersionMin(Directive, Loc, Type: MCVM_TvOSVersionMin); |
451 | } |
452 | bool parseIOSVersionMin(StringRef Directive, SMLoc Loc) { |
453 | return parseVersionMin(Directive, Loc, Type: MCVM_IOSVersionMin); |
454 | } |
455 | bool parseMacOSXVersionMin(StringRef Directive, SMLoc Loc) { |
456 | return parseVersionMin(Directive, Loc, Type: MCVM_OSXVersionMin); |
457 | } |
458 | |
459 | bool parseBuildVersion(StringRef Directive, SMLoc Loc); |
460 | bool parseVersionMin(StringRef Directive, SMLoc Loc, MCVersionMinType Type); |
461 | bool parseMajorMinorVersionComponent(unsigned *Major, unsigned *Minor, |
462 | const char *VersionName); |
463 | bool parseOptionalTrailingVersionComponent(unsigned *Component, |
464 | const char *ComponentName); |
465 | bool parseVersion(unsigned *Major, unsigned *Minor, unsigned *Update); |
466 | bool parseSDKVersion(VersionTuple &SDKVersion); |
467 | void checkVersion(StringRef Directive, StringRef Arg, SMLoc Loc, |
468 | Triple::OSType ExpectedOS); |
469 | bool parseDirectiveCGProfile(StringRef Directive, SMLoc Loc); |
470 | }; |
471 | |
472 | } // end anonymous namespace |
473 | |
474 | bool DarwinAsmParser::parseSectionSwitch(StringRef Segment, StringRef Section, |
475 | unsigned TAA, unsigned Alignment, |
476 | unsigned StubSize) { |
477 | if (getLexer().isNot(K: AsmToken::EndOfStatement)) |
478 | return TokError(Msg: "unexpected token in section switching directive" ); |
479 | Lex(); |
480 | |
481 | // FIXME: Arch specific. |
482 | bool isText = TAA & MachO::S_ATTR_PURE_INSTRUCTIONS; |
483 | getStreamer().switchSection(Section: getContext().getMachOSection( |
484 | Segment, Section, TypeAndAttributes: TAA, Reserved2: StubSize, |
485 | K: isText ? SectionKind::getText() : SectionKind::getData())); |
486 | |
487 | // Set the implicit alignment, if any. |
488 | // |
489 | // FIXME: This isn't really what 'as' does; I think it just uses the implicit |
490 | // alignment on the section (e.g., if one manually inserts bytes into the |
491 | // section, then just issuing the section switch directive will not realign |
492 | // the section. However, this is arguably more reasonable behavior, and there |
493 | // is no good reason for someone to intentionally emit incorrectly sized |
494 | // values into the implicitly aligned sections. |
495 | if (Alignment) |
496 | getStreamer().emitValueToAlignment(Alignment: Align(Alignment)); |
497 | |
498 | return false; |
499 | } |
500 | |
501 | /// parseDirectiveAltEntry |
502 | /// ::= .alt_entry identifier |
503 | bool DarwinAsmParser::parseDirectiveAltEntry(StringRef, SMLoc) { |
504 | StringRef Name; |
505 | if (getParser().parseIdentifier(Res&: Name)) |
506 | return TokError(Msg: "expected identifier in directive" ); |
507 | |
508 | // Look up symbol. |
509 | MCSymbol *Sym = getContext().getOrCreateSymbol(Name); |
510 | |
511 | if (Sym->isDefined()) |
512 | return TokError(Msg: ".alt_entry must preceed symbol definition" ); |
513 | |
514 | if (!getStreamer().emitSymbolAttribute(Symbol: Sym, Attribute: MCSA_AltEntry)) |
515 | return TokError(Msg: "unable to emit symbol attribute" ); |
516 | |
517 | Lex(); |
518 | return false; |
519 | } |
520 | |
521 | /// parseDirectiveDesc |
522 | /// ::= .desc identifier , expression |
523 | bool DarwinAsmParser::parseDirectiveDesc(StringRef, SMLoc) { |
524 | StringRef Name; |
525 | if (getParser().parseIdentifier(Res&: Name)) |
526 | return TokError(Msg: "expected identifier in directive" ); |
527 | |
528 | // Handle the identifier as the key symbol. |
529 | MCSymbol *Sym = getContext().getOrCreateSymbol(Name); |
530 | |
531 | if (getLexer().isNot(K: AsmToken::Comma)) |
532 | return TokError(Msg: "unexpected token in '.desc' directive" ); |
533 | Lex(); |
534 | |
535 | int64_t DescValue; |
536 | if (getParser().parseAbsoluteExpression(Res&: DescValue)) |
537 | return true; |
538 | |
539 | if (getLexer().isNot(K: AsmToken::EndOfStatement)) |
540 | return TokError(Msg: "unexpected token in '.desc' directive" ); |
541 | |
542 | Lex(); |
543 | |
544 | // Set the n_desc field of this Symbol to this DescValue |
545 | getStreamer().emitSymbolDesc(Symbol: Sym, DescValue); |
546 | |
547 | return false; |
548 | } |
549 | |
550 | /// parseDirectiveIndirectSymbol |
551 | /// ::= .indirect_symbol identifier |
552 | bool DarwinAsmParser::parseDirectiveIndirectSymbol(StringRef, SMLoc Loc) { |
553 | const MCSectionMachO *Current = static_cast<const MCSectionMachO *>( |
554 | getStreamer().getCurrentSectionOnly()); |
555 | MachO::SectionType SectionType = Current->getType(); |
556 | if (SectionType != MachO::S_NON_LAZY_SYMBOL_POINTERS && |
557 | SectionType != MachO::S_LAZY_SYMBOL_POINTERS && |
558 | SectionType != MachO::S_THREAD_LOCAL_VARIABLE_POINTERS && |
559 | SectionType != MachO::S_SYMBOL_STUBS) |
560 | return Error(L: Loc, Msg: "indirect symbol not in a symbol pointer or stub " |
561 | "section" ); |
562 | |
563 | StringRef Name; |
564 | if (getParser().parseIdentifier(Res&: Name)) |
565 | return TokError(Msg: "expected identifier in .indirect_symbol directive" ); |
566 | |
567 | MCSymbol *Sym = getContext().getOrCreateSymbol(Name); |
568 | |
569 | // Assembler local symbols don't make any sense here. Complain loudly. |
570 | if (Sym->isTemporary()) |
571 | return TokError(Msg: "non-local symbol required in directive" ); |
572 | |
573 | if (!getStreamer().emitSymbolAttribute(Symbol: Sym, Attribute: MCSA_IndirectSymbol)) |
574 | return TokError(Msg: "unable to emit indirect symbol attribute for: " + Name); |
575 | |
576 | if (getLexer().isNot(K: AsmToken::EndOfStatement)) |
577 | return TokError(Msg: "unexpected token in '.indirect_symbol' directive" ); |
578 | |
579 | Lex(); |
580 | |
581 | return false; |
582 | } |
583 | |
584 | /// parseDirectiveDumpOrLoad |
585 | /// ::= ( .dump | .load ) "filename" |
586 | bool DarwinAsmParser::parseDirectiveDumpOrLoad(StringRef Directive, |
587 | SMLoc IDLoc) { |
588 | bool IsDump = Directive == ".dump" ; |
589 | if (getLexer().isNot(K: AsmToken::String)) |
590 | return TokError(Msg: "expected string in '.dump' or '.load' directive" ); |
591 | |
592 | Lex(); |
593 | |
594 | if (getLexer().isNot(K: AsmToken::EndOfStatement)) |
595 | return TokError(Msg: "unexpected token in '.dump' or '.load' directive" ); |
596 | |
597 | Lex(); |
598 | |
599 | // FIXME: If/when .dump and .load are implemented they will be done in the |
600 | // the assembly parser and not have any need for an MCStreamer API. |
601 | if (IsDump) |
602 | return Warning(L: IDLoc, Msg: "ignoring directive .dump for now" ); |
603 | else |
604 | return Warning(L: IDLoc, Msg: "ignoring directive .load for now" ); |
605 | } |
606 | |
607 | /// ParseDirectiveLinkerOption |
608 | /// ::= .linker_option "string" ( , "string" )* |
609 | bool DarwinAsmParser::parseDirectiveLinkerOption(StringRef IDVal, SMLoc) { |
610 | SmallVector<std::string, 4> Args; |
611 | while (true) { |
612 | if (getLexer().isNot(K: AsmToken::String)) |
613 | return TokError(Msg: "expected string in '" + Twine(IDVal) + "' directive" ); |
614 | |
615 | std::string Data; |
616 | if (getParser().parseEscapedString(Data)) |
617 | return true; |
618 | |
619 | Args.push_back(Elt: Data); |
620 | |
621 | if (getLexer().is(K: AsmToken::EndOfStatement)) |
622 | break; |
623 | |
624 | if (getLexer().isNot(K: AsmToken::Comma)) |
625 | return TokError(Msg: "unexpected token in '" + Twine(IDVal) + "' directive" ); |
626 | Lex(); |
627 | } |
628 | |
629 | getStreamer().emitLinkerOptions(Kind: Args); |
630 | return false; |
631 | } |
632 | |
633 | /// parseDirectiveLsym |
634 | /// ::= .lsym identifier , expression |
635 | bool DarwinAsmParser::parseDirectiveLsym(StringRef, SMLoc) { |
636 | StringRef Name; |
637 | if (getParser().parseIdentifier(Res&: Name)) |
638 | return TokError(Msg: "expected identifier in directive" ); |
639 | |
640 | // Handle the identifier as the key symbol. |
641 | MCSymbol *Sym = getContext().getOrCreateSymbol(Name); |
642 | |
643 | if (getLexer().isNot(K: AsmToken::Comma)) |
644 | return TokError(Msg: "unexpected token in '.lsym' directive" ); |
645 | Lex(); |
646 | |
647 | const MCExpr *Value; |
648 | if (getParser().parseExpression(Res&: Value)) |
649 | return true; |
650 | |
651 | if (getLexer().isNot(K: AsmToken::EndOfStatement)) |
652 | return TokError(Msg: "unexpected token in '.lsym' directive" ); |
653 | |
654 | Lex(); |
655 | |
656 | // We don't currently support this directive. |
657 | // |
658 | // FIXME: Diagnostic location! |
659 | (void) Sym; |
660 | return TokError(Msg: "directive '.lsym' is unsupported" ); |
661 | } |
662 | |
663 | /// parseDirectiveSection: |
664 | /// ::= .section identifier (',' identifier)* |
665 | bool DarwinAsmParser::parseDirectiveSection(StringRef, SMLoc) { |
666 | SMLoc Loc = getLexer().getLoc(); |
667 | |
668 | StringRef SectionName; |
669 | if (getParser().parseIdentifier(Res&: SectionName)) |
670 | return Error(L: Loc, Msg: "expected identifier after '.section' directive" ); |
671 | |
672 | // Verify there is a following comma. |
673 | if (!getLexer().is(K: AsmToken::Comma)) |
674 | return TokError(Msg: "unexpected token in '.section' directive" ); |
675 | |
676 | std::string SectionSpec = std::string(SectionName); |
677 | SectionSpec += "," ; |
678 | |
679 | // Add all the tokens until the end of the line, ParseSectionSpecifier will |
680 | // handle this. |
681 | StringRef EOL = getLexer().LexUntilEndOfStatement(); |
682 | SectionSpec.append(first: EOL.begin(), last: EOL.end()); |
683 | |
684 | Lex(); |
685 | if (getLexer().isNot(K: AsmToken::EndOfStatement)) |
686 | return TokError(Msg: "unexpected token in '.section' directive" ); |
687 | Lex(); |
688 | |
689 | StringRef Segment, Section; |
690 | unsigned StubSize; |
691 | unsigned TAA; |
692 | bool TAAParsed; |
693 | if (class Error E = MCSectionMachO::ParseSectionSpecifier( |
694 | Spec: SectionSpec, Segment, Section, TAA, TAAParsed, StubSize)) |
695 | return Error(L: Loc, Msg: toString(E: std::move(E))); |
696 | |
697 | // Issue a warning if the target is not powerpc and Section is a *coal* section. |
698 | Triple TT = getParser().getContext().getTargetTriple(); |
699 | Triple::ArchType ArchTy = TT.getArch(); |
700 | |
701 | if (ArchTy != Triple::ppc && ArchTy != Triple::ppc64) { |
702 | StringRef NonCoalSection = StringSwitch<StringRef>(Section) |
703 | .Case(S: "__textcoal_nt" , Value: "__text" ) |
704 | .Case(S: "__const_coal" , Value: "__const" ) |
705 | .Case(S: "__datacoal_nt" , Value: "__data" ) |
706 | .Default(Value: Section); |
707 | |
708 | if (Section != NonCoalSection) { |
709 | StringRef SectionVal(Loc.getPointer()); |
710 | size_t B = SectionVal.find(C: ',') + 1, E = SectionVal.find(C: ',', From: B); |
711 | SMLoc BLoc = SMLoc::getFromPointer(Ptr: SectionVal.data() + B); |
712 | SMLoc ELoc = SMLoc::getFromPointer(Ptr: SectionVal.data() + E); |
713 | getParser().Warning(L: Loc, Msg: "section \"" + Section + "\" is deprecated" , |
714 | Range: SMRange(BLoc, ELoc)); |
715 | getParser().Note(L: Loc, Msg: "change section name to \"" + NonCoalSection + |
716 | "\"" , Range: SMRange(BLoc, ELoc)); |
717 | } |
718 | } |
719 | |
720 | // FIXME: Arch specific. |
721 | bool isText = Segment == "__TEXT" ; // FIXME: Hack. |
722 | getStreamer().switchSection(Section: getContext().getMachOSection( |
723 | Segment, Section, TypeAndAttributes: TAA, Reserved2: StubSize, |
724 | K: isText ? SectionKind::getText() : SectionKind::getData())); |
725 | return false; |
726 | } |
727 | |
728 | /// ParseDirectivePushSection: |
729 | /// ::= .pushsection identifier (',' identifier)* |
730 | bool DarwinAsmParser::parseDirectivePushSection(StringRef S, SMLoc Loc) { |
731 | getStreamer().pushSection(); |
732 | |
733 | if (parseDirectiveSection(S, Loc)) { |
734 | getStreamer().popSection(); |
735 | return true; |
736 | } |
737 | |
738 | return false; |
739 | } |
740 | |
741 | /// ParseDirectivePopSection: |
742 | /// ::= .popsection |
743 | bool DarwinAsmParser::parseDirectivePopSection(StringRef, SMLoc) { |
744 | if (!getStreamer().popSection()) |
745 | return TokError(Msg: ".popsection without corresponding .pushsection" ); |
746 | return false; |
747 | } |
748 | |
749 | /// ParseDirectivePrevious: |
750 | /// ::= .previous |
751 | bool DarwinAsmParser::parseDirectivePrevious(StringRef DirName, SMLoc) { |
752 | MCSectionSubPair PreviousSection = getStreamer().getPreviousSection(); |
753 | if (!PreviousSection.first) |
754 | return TokError(Msg: ".previous without corresponding .section" ); |
755 | getStreamer().switchSection(Section: PreviousSection.first, Subsec: PreviousSection.second); |
756 | return false; |
757 | } |
758 | |
759 | /// ParseDirectiveSecureLogUnique |
760 | /// ::= .secure_log_unique ... message ... |
761 | bool DarwinAsmParser::parseDirectiveSecureLogUnique(StringRef, SMLoc IDLoc) { |
762 | StringRef LogMessage = getParser().parseStringToEndOfStatement(); |
763 | if (getLexer().isNot(K: AsmToken::EndOfStatement)) |
764 | return TokError(Msg: "unexpected token in '.secure_log_unique' directive" ); |
765 | |
766 | if (getContext().getSecureLogUsed()) |
767 | return Error(L: IDLoc, Msg: ".secure_log_unique specified multiple times" ); |
768 | |
769 | // Get the secure log path. |
770 | StringRef SecureLogFile = getContext().getSecureLogFile(); |
771 | if (SecureLogFile.empty()) |
772 | return Error(L: IDLoc, Msg: ".secure_log_unique used but AS_SECURE_LOG_FILE " |
773 | "environment variable unset." ); |
774 | |
775 | // Open the secure log file if we haven't already. |
776 | raw_fd_ostream *OS = getContext().getSecureLog(); |
777 | if (!OS) { |
778 | std::error_code EC; |
779 | auto NewOS = std::make_unique<raw_fd_ostream>( |
780 | args&: SecureLogFile, args&: EC, args: sys::fs::OF_Append | sys::fs::OF_TextWithCRLF); |
781 | if (EC) |
782 | return Error(L: IDLoc, Msg: Twine("can't open secure log file: " ) + |
783 | SecureLogFile + " (" + EC.message() + ")" ); |
784 | OS = NewOS.get(); |
785 | getContext().setSecureLog(std::move(NewOS)); |
786 | } |
787 | |
788 | // Write the message. |
789 | unsigned CurBuf = getSourceManager().FindBufferContainingLoc(Loc: IDLoc); |
790 | *OS << getSourceManager().getBufferInfo(i: CurBuf).Buffer->getBufferIdentifier() |
791 | << ":" << getSourceManager().FindLineNumber(Loc: IDLoc, BufferID: CurBuf) << ":" |
792 | << LogMessage + "\n" ; |
793 | |
794 | getContext().setSecureLogUsed(true); |
795 | |
796 | return false; |
797 | } |
798 | |
799 | /// ParseDirectiveSecureLogReset |
800 | /// ::= .secure_log_reset |
801 | bool DarwinAsmParser::parseDirectiveSecureLogReset(StringRef, SMLoc IDLoc) { |
802 | if (getLexer().isNot(K: AsmToken::EndOfStatement)) |
803 | return TokError(Msg: "unexpected token in '.secure_log_reset' directive" ); |
804 | |
805 | Lex(); |
806 | |
807 | getContext().setSecureLogUsed(false); |
808 | |
809 | return false; |
810 | } |
811 | |
812 | /// parseDirectiveSubsectionsViaSymbols |
813 | /// ::= .subsections_via_symbols |
814 | bool DarwinAsmParser::parseDirectiveSubsectionsViaSymbols(StringRef, SMLoc) { |
815 | if (getLexer().isNot(K: AsmToken::EndOfStatement)) |
816 | return TokError(Msg: "unexpected token in '.subsections_via_symbols' directive" ); |
817 | |
818 | Lex(); |
819 | |
820 | getStreamer().emitAssemblerFlag(Flag: MCAF_SubsectionsViaSymbols); |
821 | |
822 | return false; |
823 | } |
824 | |
825 | /// ParseDirectiveTBSS |
826 | /// ::= .tbss identifier, size, align |
827 | bool DarwinAsmParser::parseDirectiveTBSS(StringRef, SMLoc) { |
828 | SMLoc IDLoc = getLexer().getLoc(); |
829 | StringRef Name; |
830 | if (getParser().parseIdentifier(Res&: Name)) |
831 | return TokError(Msg: "expected identifier in directive" ); |
832 | |
833 | // Handle the identifier as the key symbol. |
834 | MCSymbol *Sym = getContext().getOrCreateSymbol(Name); |
835 | |
836 | if (getLexer().isNot(K: AsmToken::Comma)) |
837 | return TokError(Msg: "unexpected token in directive" ); |
838 | Lex(); |
839 | |
840 | int64_t Size; |
841 | SMLoc SizeLoc = getLexer().getLoc(); |
842 | if (getParser().parseAbsoluteExpression(Res&: Size)) |
843 | return true; |
844 | |
845 | int64_t Pow2Alignment = 0; |
846 | SMLoc Pow2AlignmentLoc; |
847 | if (getLexer().is(K: AsmToken::Comma)) { |
848 | Lex(); |
849 | Pow2AlignmentLoc = getLexer().getLoc(); |
850 | if (getParser().parseAbsoluteExpression(Res&: Pow2Alignment)) |
851 | return true; |
852 | } |
853 | |
854 | if (getLexer().isNot(K: AsmToken::EndOfStatement)) |
855 | return TokError(Msg: "unexpected token in '.tbss' directive" ); |
856 | |
857 | Lex(); |
858 | |
859 | if (Size < 0) |
860 | return Error(L: SizeLoc, Msg: "invalid '.tbss' directive size, can't be less than" |
861 | "zero" ); |
862 | |
863 | // FIXME: Diagnose overflow. |
864 | if (Pow2Alignment < 0) |
865 | return Error(L: Pow2AlignmentLoc, Msg: "invalid '.tbss' alignment, can't be less" |
866 | "than zero" ); |
867 | |
868 | if (!Sym->isUndefined()) |
869 | return Error(L: IDLoc, Msg: "invalid symbol redefinition" ); |
870 | |
871 | getStreamer().emitTBSSSymbol( |
872 | Section: getContext().getMachOSection(Segment: "__DATA" , Section: "__thread_bss" , |
873 | TypeAndAttributes: MachO::S_THREAD_LOCAL_ZEROFILL, Reserved2: 0, |
874 | K: SectionKind::getThreadBSS()), |
875 | Symbol: Sym, Size, ByteAlignment: Align(1ULL << Pow2Alignment)); |
876 | |
877 | return false; |
878 | } |
879 | |
880 | /// ParseDirectiveZerofill |
881 | /// ::= .zerofill segname , sectname [, identifier , size_expression [ |
882 | /// , align_expression ]] |
883 | bool DarwinAsmParser::parseDirectiveZerofill(StringRef, SMLoc) { |
884 | StringRef Segment; |
885 | if (getParser().parseIdentifier(Res&: Segment)) |
886 | return TokError(Msg: "expected segment name after '.zerofill' directive" ); |
887 | |
888 | if (getLexer().isNot(K: AsmToken::Comma)) |
889 | return TokError(Msg: "unexpected token in directive" ); |
890 | Lex(); |
891 | |
892 | StringRef Section; |
893 | SMLoc SectionLoc = getLexer().getLoc(); |
894 | if (getParser().parseIdentifier(Res&: Section)) |
895 | return TokError(Msg: "expected section name after comma in '.zerofill' " |
896 | "directive" ); |
897 | |
898 | // If this is the end of the line all that was wanted was to create the |
899 | // the section but with no symbol. |
900 | if (getLexer().is(K: AsmToken::EndOfStatement)) { |
901 | // Create the zerofill section but no symbol |
902 | getStreamer().emitZerofill( |
903 | Section: getContext().getMachOSection(Segment, Section, TypeAndAttributes: MachO::S_ZEROFILL, Reserved2: 0, |
904 | K: SectionKind::getBSS()), |
905 | /*Symbol=*/nullptr, /*Size=*/0, ByteAlignment: Align(1), Loc: SectionLoc); |
906 | return false; |
907 | } |
908 | |
909 | if (getLexer().isNot(K: AsmToken::Comma)) |
910 | return TokError(Msg: "unexpected token in directive" ); |
911 | Lex(); |
912 | |
913 | SMLoc IDLoc = getLexer().getLoc(); |
914 | StringRef IDStr; |
915 | if (getParser().parseIdentifier(Res&: IDStr)) |
916 | return TokError(Msg: "expected identifier in directive" ); |
917 | |
918 | // handle the identifier as the key symbol. |
919 | MCSymbol *Sym = getContext().getOrCreateSymbol(Name: IDStr); |
920 | |
921 | if (getLexer().isNot(K: AsmToken::Comma)) |
922 | return TokError(Msg: "unexpected token in directive" ); |
923 | Lex(); |
924 | |
925 | int64_t Size; |
926 | SMLoc SizeLoc = getLexer().getLoc(); |
927 | if (getParser().parseAbsoluteExpression(Res&: Size)) |
928 | return true; |
929 | |
930 | int64_t Pow2Alignment = 0; |
931 | SMLoc Pow2AlignmentLoc; |
932 | if (getLexer().is(K: AsmToken::Comma)) { |
933 | Lex(); |
934 | Pow2AlignmentLoc = getLexer().getLoc(); |
935 | if (getParser().parseAbsoluteExpression(Res&: Pow2Alignment)) |
936 | return true; |
937 | } |
938 | |
939 | if (getLexer().isNot(K: AsmToken::EndOfStatement)) |
940 | return TokError(Msg: "unexpected token in '.zerofill' directive" ); |
941 | |
942 | Lex(); |
943 | |
944 | if (Size < 0) |
945 | return Error(L: SizeLoc, Msg: "invalid '.zerofill' directive size, can't be less " |
946 | "than zero" ); |
947 | |
948 | // NOTE: The alignment in the directive is a power of 2 value, the assembler |
949 | // may internally end up wanting an alignment in bytes. |
950 | // FIXME: Diagnose overflow. |
951 | if (Pow2Alignment < 0) |
952 | return Error(L: Pow2AlignmentLoc, Msg: "invalid '.zerofill' directive alignment, " |
953 | "can't be less than zero" ); |
954 | |
955 | if (!Sym->isUndefined()) |
956 | return Error(L: IDLoc, Msg: "invalid symbol redefinition" ); |
957 | |
958 | // Create the zerofill Symbol with Size and Pow2Alignment |
959 | // |
960 | // FIXME: Arch specific. |
961 | getStreamer().emitZerofill( |
962 | Section: getContext().getMachOSection(Segment, Section, TypeAndAttributes: MachO::S_ZEROFILL, Reserved2: 0, |
963 | K: SectionKind::getBSS()), |
964 | Symbol: Sym, Size, ByteAlignment: Align(1ULL << Pow2Alignment), Loc: SectionLoc); |
965 | |
966 | return false; |
967 | } |
968 | |
969 | /// ParseDirectiveDataRegion |
970 | /// ::= .data_region [ ( jt8 | jt16 | jt32 ) ] |
971 | bool DarwinAsmParser::parseDirectiveDataRegion(StringRef, SMLoc) { |
972 | if (getLexer().is(K: AsmToken::EndOfStatement)) { |
973 | Lex(); |
974 | getStreamer().emitDataRegion(Kind: MCDR_DataRegion); |
975 | return false; |
976 | } |
977 | StringRef RegionType; |
978 | SMLoc Loc = getParser().getTok().getLoc(); |
979 | if (getParser().parseIdentifier(Res&: RegionType)) |
980 | return TokError(Msg: "expected region type after '.data_region' directive" ); |
981 | int Kind = StringSwitch<int>(RegionType) |
982 | .Case(S: "jt8" , Value: MCDR_DataRegionJT8) |
983 | .Case(S: "jt16" , Value: MCDR_DataRegionJT16) |
984 | .Case(S: "jt32" , Value: MCDR_DataRegionJT32) |
985 | .Default(Value: -1); |
986 | if (Kind == -1) |
987 | return Error(L: Loc, Msg: "unknown region type in '.data_region' directive" ); |
988 | Lex(); |
989 | |
990 | getStreamer().emitDataRegion(Kind: (MCDataRegionType)Kind); |
991 | return false; |
992 | } |
993 | |
994 | /// ParseDirectiveDataRegionEnd |
995 | /// ::= .end_data_region |
996 | bool DarwinAsmParser::parseDirectiveDataRegionEnd(StringRef, SMLoc) { |
997 | if (getLexer().isNot(K: AsmToken::EndOfStatement)) |
998 | return TokError(Msg: "unexpected token in '.end_data_region' directive" ); |
999 | |
1000 | Lex(); |
1001 | getStreamer().emitDataRegion(Kind: MCDR_DataRegionEnd); |
1002 | return false; |
1003 | } |
1004 | |
1005 | static bool isSDKVersionToken(const AsmToken &Tok) { |
1006 | return Tok.is(K: AsmToken::Identifier) && Tok.getIdentifier() == "sdk_version" ; |
1007 | } |
1008 | |
1009 | /// parseMajorMinorVersionComponent ::= major, minor |
1010 | bool DarwinAsmParser::parseMajorMinorVersionComponent(unsigned *Major, |
1011 | unsigned *Minor, |
1012 | const char *VersionName) { |
1013 | // Get the major version number. |
1014 | if (getLexer().isNot(K: AsmToken::Integer)) |
1015 | return TokError(Msg: Twine("invalid " ) + VersionName + |
1016 | " major version number, integer expected" ); |
1017 | int64_t MajorVal = getLexer().getTok().getIntVal(); |
1018 | if (MajorVal > 65535 || MajorVal <= 0) |
1019 | return TokError(Msg: Twine("invalid " ) + VersionName + " major version number" ); |
1020 | *Major = (unsigned)MajorVal; |
1021 | Lex(); |
1022 | if (getLexer().isNot(K: AsmToken::Comma)) |
1023 | return TokError(Msg: Twine(VersionName) + |
1024 | " minor version number required, comma expected" ); |
1025 | Lex(); |
1026 | // Get the minor version number. |
1027 | if (getLexer().isNot(K: AsmToken::Integer)) |
1028 | return TokError(Msg: Twine("invalid " ) + VersionName + |
1029 | " minor version number, integer expected" ); |
1030 | int64_t MinorVal = getLexer().getTok().getIntVal(); |
1031 | if (MinorVal > 255 || MinorVal < 0) |
1032 | return TokError(Msg: Twine("invalid " ) + VersionName + " minor version number" ); |
1033 | *Minor = MinorVal; |
1034 | Lex(); |
1035 | return false; |
1036 | } |
1037 | |
1038 | /// parseOptionalTrailingVersionComponent ::= , version_number |
1039 | bool DarwinAsmParser::parseOptionalTrailingVersionComponent( |
1040 | unsigned *Component, const char *ComponentName) { |
1041 | assert(getLexer().is(AsmToken::Comma) && "comma expected" ); |
1042 | Lex(); |
1043 | if (getLexer().isNot(K: AsmToken::Integer)) |
1044 | return TokError(Msg: Twine("invalid " ) + ComponentName + |
1045 | " version number, integer expected" ); |
1046 | int64_t Val = getLexer().getTok().getIntVal(); |
1047 | if (Val > 255 || Val < 0) |
1048 | return TokError(Msg: Twine("invalid " ) + ComponentName + " version number" ); |
1049 | *Component = Val; |
1050 | Lex(); |
1051 | return false; |
1052 | } |
1053 | |
1054 | /// parseVersion ::= parseMajorMinorVersionComponent |
1055 | /// parseOptionalTrailingVersionComponent |
1056 | bool DarwinAsmParser::parseVersion(unsigned *Major, unsigned *Minor, |
1057 | unsigned *Update) { |
1058 | if (parseMajorMinorVersionComponent(Major, Minor, VersionName: "OS" )) |
1059 | return true; |
1060 | |
1061 | // Get the update level, if specified |
1062 | *Update = 0; |
1063 | if (getLexer().is(K: AsmToken::EndOfStatement) || |
1064 | isSDKVersionToken(Tok: getLexer().getTok())) |
1065 | return false; |
1066 | if (getLexer().isNot(K: AsmToken::Comma)) |
1067 | return TokError(Msg: "invalid OS update specifier, comma expected" ); |
1068 | if (parseOptionalTrailingVersionComponent(Component: Update, ComponentName: "OS update" )) |
1069 | return true; |
1070 | return false; |
1071 | } |
1072 | |
1073 | bool DarwinAsmParser::parseSDKVersion(VersionTuple &SDKVersion) { |
1074 | assert(isSDKVersionToken(getLexer().getTok()) && "expected sdk_version" ); |
1075 | Lex(); |
1076 | unsigned Major, Minor; |
1077 | if (parseMajorMinorVersionComponent(Major: &Major, Minor: &Minor, VersionName: "SDK" )) |
1078 | return true; |
1079 | SDKVersion = VersionTuple(Major, Minor); |
1080 | |
1081 | // Get the subminor version, if specified. |
1082 | if (getLexer().is(K: AsmToken::Comma)) { |
1083 | unsigned Subminor; |
1084 | if (parseOptionalTrailingVersionComponent(Component: &Subminor, ComponentName: "SDK subminor" )) |
1085 | return true; |
1086 | SDKVersion = VersionTuple(Major, Minor, Subminor); |
1087 | } |
1088 | return false; |
1089 | } |
1090 | |
1091 | void DarwinAsmParser::checkVersion(StringRef Directive, StringRef Arg, |
1092 | SMLoc Loc, Triple::OSType ExpectedOS) { |
1093 | const Triple &Target = getContext().getTargetTriple(); |
1094 | if (Target.getOS() != ExpectedOS) |
1095 | Warning(L: Loc, Msg: Twine(Directive) + |
1096 | (Arg.empty() ? Twine() : Twine(' ') + Arg) + |
1097 | " used while targeting " + Target.getOSName()); |
1098 | |
1099 | if (LastVersionDirective.isValid()) { |
1100 | Warning(L: Loc, Msg: "overriding previous version directive" ); |
1101 | Note(L: LastVersionDirective, Msg: "previous definition is here" ); |
1102 | } |
1103 | LastVersionDirective = Loc; |
1104 | } |
1105 | |
1106 | static Triple::OSType getOSTypeFromMCVM(MCVersionMinType Type) { |
1107 | switch (Type) { |
1108 | case MCVM_WatchOSVersionMin: return Triple::WatchOS; |
1109 | case MCVM_TvOSVersionMin: return Triple::TvOS; |
1110 | case MCVM_IOSVersionMin: return Triple::IOS; |
1111 | case MCVM_OSXVersionMin: return Triple::MacOSX; |
1112 | } |
1113 | llvm_unreachable("Invalid mc version min type" ); |
1114 | } |
1115 | |
1116 | /// parseVersionMin |
1117 | /// ::= .ios_version_min parseVersion parseSDKVersion |
1118 | /// | .macosx_version_min parseVersion parseSDKVersion |
1119 | /// | .tvos_version_min parseVersion parseSDKVersion |
1120 | /// | .watchos_version_min parseVersion parseSDKVersion |
1121 | bool DarwinAsmParser::parseVersionMin(StringRef Directive, SMLoc Loc, |
1122 | MCVersionMinType Type) { |
1123 | unsigned Major; |
1124 | unsigned Minor; |
1125 | unsigned Update; |
1126 | if (parseVersion(Major: &Major, Minor: &Minor, Update: &Update)) |
1127 | return true; |
1128 | |
1129 | VersionTuple SDKVersion; |
1130 | if (isSDKVersionToken(Tok: getLexer().getTok()) && parseSDKVersion(SDKVersion)) |
1131 | return true; |
1132 | |
1133 | if (parseEOL()) |
1134 | return addErrorSuffix(Suffix: Twine(" in '" ) + Directive + "' directive" ); |
1135 | |
1136 | Triple::OSType ExpectedOS = getOSTypeFromMCVM(Type); |
1137 | checkVersion(Directive, Arg: StringRef(), Loc, ExpectedOS); |
1138 | getStreamer().emitVersionMin(Type, Major, Minor, Update, SDKVersion); |
1139 | return false; |
1140 | } |
1141 | |
1142 | static Triple::OSType getOSTypeFromPlatform(MachO::PlatformType Type) { |
1143 | switch (Type) { |
1144 | case MachO::PLATFORM_UNKNOWN: /* silence warning */ |
1145 | break; |
1146 | case MachO::PLATFORM_MACOS: return Triple::MacOSX; |
1147 | case MachO::PLATFORM_IOS: return Triple::IOS; |
1148 | case MachO::PLATFORM_TVOS: return Triple::TvOS; |
1149 | case MachO::PLATFORM_WATCHOS: return Triple::WatchOS; |
1150 | case MachO::PLATFORM_XROS: return Triple::XROS; |
1151 | case MachO::PLATFORM_BRIDGEOS: /* silence warning */ break; |
1152 | case MachO::PLATFORM_DRIVERKIT: |
1153 | return Triple::DriverKit; |
1154 | case MachO::PLATFORM_MACCATALYST: return Triple::IOS; |
1155 | case MachO::PLATFORM_IOSSIMULATOR: /* silence warning */ break; |
1156 | case MachO::PLATFORM_TVOSSIMULATOR: /* silence warning */ break; |
1157 | case MachO::PLATFORM_WATCHOSSIMULATOR: /* silence warning */ break; |
1158 | case MachO::PLATFORM_XROS_SIMULATOR: /* silence warning */ break; |
1159 | } |
1160 | llvm_unreachable("Invalid mach-o platform type" ); |
1161 | } |
1162 | |
1163 | /// parseBuildVersion |
1164 | /// ::= .build_version (macos|ios|tvos|watchos), parseVersion parseSDKVersion |
1165 | bool DarwinAsmParser::parseBuildVersion(StringRef Directive, SMLoc Loc) { |
1166 | StringRef PlatformName; |
1167 | SMLoc PlatformLoc = getTok().getLoc(); |
1168 | if (getParser().parseIdentifier(Res&: PlatformName)) |
1169 | return TokError(Msg: "platform name expected" ); |
1170 | |
1171 | unsigned Platform = StringSwitch<unsigned>(PlatformName) |
1172 | #define PLATFORM(platform, id, name, build_name, target, tapi_target, \ |
1173 | marketing) \ |
1174 | .Case(#build_name, MachO::PLATFORM_##platform) |
1175 | #include "llvm/BinaryFormat/MachO.def" |
1176 | .Default(Value: MachO::PLATFORM_UNKNOWN); |
1177 | |
1178 | if (Platform == MachO::PLATFORM_UNKNOWN) |
1179 | return Error(L: PlatformLoc, Msg: "unknown platform name" ); |
1180 | |
1181 | if (getLexer().isNot(K: AsmToken::Comma)) |
1182 | return TokError(Msg: "version number required, comma expected" ); |
1183 | Lex(); |
1184 | |
1185 | unsigned Major; |
1186 | unsigned Minor; |
1187 | unsigned Update; |
1188 | if (parseVersion(Major: &Major, Minor: &Minor, Update: &Update)) |
1189 | return true; |
1190 | |
1191 | VersionTuple SDKVersion; |
1192 | if (isSDKVersionToken(Tok: getLexer().getTok()) && parseSDKVersion(SDKVersion)) |
1193 | return true; |
1194 | |
1195 | if (parseEOL()) |
1196 | return addErrorSuffix(Suffix: " in '.build_version' directive" ); |
1197 | |
1198 | Triple::OSType ExpectedOS |
1199 | = getOSTypeFromPlatform(Type: (MachO::PlatformType)Platform); |
1200 | checkVersion(Directive, Arg: PlatformName, Loc, ExpectedOS); |
1201 | getStreamer().emitBuildVersion(Platform, Major, Minor, Update, SDKVersion); |
1202 | return false; |
1203 | } |
1204 | |
1205 | /// parseDirectiveCGProfile |
1206 | /// ::= .cg_profile from, to, count |
1207 | bool DarwinAsmParser::parseDirectiveCGProfile(StringRef S, SMLoc Loc) { |
1208 | return MCAsmParserExtension::ParseDirectiveCGProfile(S, Loc); |
1209 | } |
1210 | |
1211 | namespace llvm { |
1212 | |
1213 | MCAsmParserExtension *createDarwinAsmParser() { |
1214 | return new DarwinAsmParser; |
1215 | } |
1216 | |
1217 | } // end llvm namespace |
1218 | |