LLVM 24.0.0git
WebAssemblyAsmPrinter.cpp
Go to the documentation of this file.
1//===-- WebAssemblyAsmPrinter.cpp - WebAssembly LLVM assembly writer ------===//
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/// \file
10/// This file contains a printer that converts from our internal
11/// representation of machine-dependent LLVM code to the WebAssembly assembly
12/// language.
13///
14//===----------------------------------------------------------------------===//
15
22#include "WebAssembly.h"
29#include "llvm/ADT/MapVector.h"
30#include "llvm/ADT/SmallSet.h"
43#include "llvm/IR/Analysis.h"
44#include "llvm/IR/DataLayout.h"
47#include "llvm/IR/Metadata.h"
48#include "llvm/IR/Module.h"
49#include "llvm/IR/PassManager.h"
50#include "llvm/MC/MCContext.h"
52#include "llvm/MC/MCStreamer.h"
53#include "llvm/MC/MCSymbol.h"
57#include "llvm/Support/Debug.h"
59
60using namespace llvm;
61
62#define DEBUG_TYPE "asm-printer"
63
65
66//===----------------------------------------------------------------------===//
67// Helpers.
68//===----------------------------------------------------------------------===//
69
71 const TargetRegisterInfo *TRI = Subtarget->getRegisterInfo();
72 const TargetRegisterClass *TRC = MRI->getRegClass(RegNo);
73 for (MVT T : {MVT::i32, MVT::i64, MVT::f32, MVT::f64, MVT::v16i8, MVT::v8i16,
74 MVT::v4i32, MVT::v2i64, MVT::v4f32, MVT::v2f64, MVT::v8f16})
75 if (TRI->isTypeLegalForClass(*TRC, T))
76 return T;
77 LLVM_DEBUG(errs() << "Unknown type for register number: " << RegNo);
78 llvm_unreachable("Unknown register type");
79 return MVT::Other;
80}
81
83 Register RegNo = MO.getReg();
84 assert(RegNo.isVirtual() &&
85 "Unlowered physical register encountered during assembly printing");
86 assert(!MFI->isVRegStackified(RegNo));
87 unsigned WAReg = MFI->getWAReg(RegNo);
89 return '$' + utostr(WAReg);
90}
91
96
97// Emscripten exception handling helpers
98//
99// This converts invoke names generated by LowerEmscriptenEHSjLj to real names
100// that are expected by JavaScript glue code. The invoke names generated by
101// Emscripten JS glue code are based on their argument and return types; for
102// example, for a function that takes an i32 and returns nothing, it is
103// 'invoke_vi'. But the format of invoke generated by LowerEmscriptenEHSjLj pass
104// contains a mangled string generated from their IR types, for example,
105// "__invoke_void_%struct.mystruct*_int", because final wasm types are not
106// available in the IR pass. So we convert those names to the form that
107// Emscripten JS code expects.
108//
109// Refer to LowerEmscriptenEHSjLj pass for more details.
110
111// Returns true if the given function name is an invoke name generated by
112// LowerEmscriptenEHSjLj pass.
114 if (Name.front() == '"' && Name.back() == '"')
115 Name = Name.substr(1, Name.size() - 2);
116 return Name.starts_with("__invoke_");
117}
118
119// Returns a character that represents the given wasm value type in invoke
120// signatures.
122 switch (VT) {
124 return 'i';
126 return 'j';
128 return 'f';
130 return 'd';
132 return 'V';
134 return 'F';
136 return 'X';
138 return 'E';
139 default:
140 llvm_unreachable("Unhandled wasm::ValType enum");
141 }
142}
143
144// Given the wasm signature, generate the invoke name in the format JS glue code
145// expects.
147 assert(Sig->Returns.size() <= 1);
148 std::string Ret = "invoke_";
149 if (!Sig->Returns.empty())
150 for (auto VT : Sig->Returns)
151 Ret += getInvokeSig(VT);
152 else
153 Ret += 'v';
154 // Invokes' first argument is a pointer to the original function, so skip it
155 for (unsigned I = 1, E = Sig->Params.size(); I < E; I++)
156 Ret += getInvokeSig(Sig->Params[I]);
157 return Ret;
158}
159
160//===----------------------------------------------------------------------===//
161// WebAssemblyAsmPrinter Implementation.
162//===----------------------------------------------------------------------===//
163
165 const Function *F, wasm::WasmSignature *Sig, bool &InvokeDetected) {
166 MCSymbolWasm *WasmSym = nullptr;
167
168 // Prefer the "exception-model" module flag, else the TargetOptions default.
169 ExceptionHandling EM = F->getParent()->getExceptionModel();
171 EM = TM.getExceptionModel();
172 const bool EnableEmEH =
174 if (EnableEmEH && isEmscriptenInvokeName(F->getName())) {
175 assert(Sig);
176 InvokeDetected = true;
177 if (Sig->Returns.size() > 1) {
178 std::string Msg =
179 "Emscripten EH/SjLj does not support multivalue returns: " +
180 std::string(F->getName()) + ": " +
183 }
184 WasmSym = static_cast<MCSymbolWasm *>(
186 } else {
187 WasmSym = static_cast<MCSymbolWasm *>(getSymbol(F));
188 }
189 return WasmSym;
190}
191
193 if (GV->hasAttribute("wasm-import-module") ||
194 GV->hasAttribute("wasm-import-name")) {
195 if (!GV->isDeclaration()) {
196 OutContext.reportError(SMLoc(), "definition of global '" + GV->getName() +
197 "' cannot have import attribute");
198 return;
199 }
201 OutContext.reportError(SMLoc(),
202 "imported global '" + GV->getName() +
203 "' must be in a wasm variable address space");
204 return;
205 }
206 }
208 if (GV->hasAttribute("wasm-export-name")) {
209 auto *Sym = static_cast<MCSymbolWasm *>(getSymbol(GV));
210 StringRef Name = GV->getAttribute("wasm-export-name").getValueAsString();
211 Sym->setExportName(OutContext.allocateString(Name));
212 getTargetStreamer()->emitExportName(Sym, Name);
213 }
215 return;
216 }
217
218 assert(!GV->isThreadLocal());
219 auto *Sym = static_cast<MCSymbolWasm *>(getSymbol(GV));
220 if (!Sym->getType()) {
222 Type *GlobalVT = GV->getValueType();
223 // Function-specific subtargets are not needed here: WebAssembly
224 // coalesces features before isel, so use the TargetMachine's
225 // module-wide subtarget to compute legal value types.
226 auto &WasmTM = static_cast<const WebAssemblyTargetMachine &>(TM);
227 const WebAssemblySubtarget *ST = WasmTM.getSubtargetImpl(
228 WasmTM.getTargetCPU(), WasmTM.getTargetFeatureString(),
229 WasmTM.getTargetABIName(*GV->getParent()));
230 const WebAssemblyTargetLowering &TLI = *ST->getTargetLowering();
232 GV->getDataLayout(), GlobalVT, VTs);
233
234 WebAssembly::wasmSymbolSetType(Sym, GlobalVT, VTs,
235 /*Mutable=*/!GV->isConstant());
236 }
237
238 emitVisibility(Sym, GV->getVisibility(), !GV->isDeclaration());
239 emitSymbolType(Sym);
240 if (GV->isDeclaration()) {
241 if (GV->hasAttribute("wasm-import-module")) {
242 StringRef ImportModule =
243 GV->getAttribute("wasm-import-module").getValueAsString();
244 Sym->setImportModule(OutContext.allocateString(ImportModule));
245 getTargetStreamer()->emitImportModule(Sym, ImportModule);
246 }
247 if (GV->hasAttribute("wasm-import-name")) {
248 StringRef ImportName =
249 GV->getAttribute("wasm-import-name").getValueAsString();
250 Sym->setImportName(OutContext.allocateString(ImportName));
251 getTargetStreamer()->emitImportName(Sym, ImportName);
252 }
253 }
254 if (GV->hasInitializer()) {
255 assert(getSymbolPreferLocal(*GV) == Sym);
256 emitLinkage(GV, Sym);
257 OutStreamer->emitLabel(Sym);
258 if (GV->hasAttribute("wasm-export-name")) {
259 StringRef ExportName =
260 GV->getAttribute("wasm-export-name").getValueAsString();
261 Sym->setExportName(OutContext.allocateString(ExportName));
262 getTargetStreamer()->emitExportName(Sym, ExportName);
263 }
264 // TODO: Actually emit the initializer value. Otherwise the global has the
265 // default value for its type (0, ref.null, etc).
266 OutStreamer->addBlankLine();
267 }
268}
269
271 auto *WasmSym = static_cast<MCSymbolWasm *>(GetExternalSymbolSymbol(Name));
272 // May be called multiple times, so early out.
273 if (WasmSym->getType())
274 return WasmSym;
275
276 const WebAssemblySubtarget &Subtarget = getSubtarget();
277
278 // Except for certain known symbols, all symbols used by CodeGen are
279 // functions. It's OK to hardcode knowledge of specific symbols here; this
280 // method is precisely there for fetching the signatures of known
281 // Clang-provided symbols.
282 if (Name == "__stack_pointer" || Name == "__tls_base" ||
283 Name == "__memory_base" || Name == "__table_base" ||
284 Name == "__tls_size" || Name == "__tls_align") {
285 bool Mutable = Name == "__stack_pointer" || Name == "__tls_base";
286 WasmSym->setType(wasm::WASM_SYMBOL_TYPE_GLOBAL);
287 WasmSym->setGlobalType(wasm::WasmGlobalType{
288 uint8_t(Subtarget.hasAddr64() ? wasm::WASM_TYPE_I64
290 Mutable});
291 return WasmSym;
292 }
293
294 if (Name.starts_with("GCC_except_table")) {
295 WasmSym->setType(wasm::WASM_SYMBOL_TYPE_DATA);
296 return WasmSym;
297 }
298
301 if (Name == "__cpp_exception" || Name == "__c_longjmp") {
302 WasmSym->setType(wasm::WASM_SYMBOL_TYPE_TAG);
303 WasmSym->setExternal(true);
304
305 // Currently both C++ exceptions and C longjmps have a single pointer type
306 // param. For C++ exceptions it is a pointer to an exception object, and for
307 // C longjmps it is pointer to a struct that contains a setjmp buffer and a
308 // longjmp return value. We may consider using multiple value parameters for
309 // longjmps later when multivalue support is ready.
310 wasm::ValType AddrType =
311 Subtarget.hasAddr64() ? wasm::ValType::I64 : wasm::ValType::I32;
312 Params.push_back(AddrType);
313 } else if (Name == "__wasm_get_stack_pointer" ||
314 Name == "__wasm_get_tls_base") {
315 WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
317 } else if (Name == "__wasm_set_stack_pointer" ||
318 Name == "__wasm_set_tls_base") {
319 WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
321 } else { // Function symbols
322 WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
323 WebAssembly::getLibcallSignature(Subtarget, Name, Returns, Params);
324 }
325 auto Signature = OutContext.createWasmSignature();
326 Signature->Returns = std::move(Returns);
327 Signature->Params = std::move(Params);
328 WasmSym->setSignature(Signature);
329
330 return WasmSym;
331}
332
334 std::optional<wasm::WasmSymbolType> WasmTy = Sym->getType();
335 if (!WasmTy)
336 return;
337
338 switch (*WasmTy) {
341 break;
344 break;
347 break;
348 default:
349 break; // We only handle globals, tags and tables here
350 }
351}
352
354 if (signaturesEmitted)
355 return;
356 signaturesEmitted = true;
357
358 // Normally symbols for globals get discovered as the MI gets lowered,
359 // but we need to know about them ahead of time. This will however,
360 // only find symbols that have been used. Unused symbols from globals will
361 // not be found here.
362 MachineModuleInfoWasm &MMIW = MMI->getObjFileInfo<MachineModuleInfoWasm>();
363 for (StringRef Name : MMIW.MachineSymbolsUsed) {
364 auto *WasmSym = static_cast<MCSymbolWasm *>(getOrCreateWasmSymbol(Name));
365 if (WasmSym->isFunction()) {
366 // TODO(wvo): is there any case where this overlaps with the call to
367 // emitFunctionType in the loop below?
369 }
370 }
371
372 for (auto &It : OutContext.getSymbols()) {
373 // Emit .globaltype, .tagtype, or .tabletype declarations for extern
374 // declarations, i.e. those that have only been declared (but not defined)
375 // in the current module
376 auto Sym = static_cast<MCSymbolWasm *>(It.getValue().Symbol);
377 if (Sym && !Sym->isDefined())
378 emitSymbolType(Sym);
379 }
380
381 // We handle `__funcref_call_table` specially here.
382 //
383 // Unlike most table symbols, which are attached to a `GlobalVariable`
384 // this one is a directly created, freestanding MCSymbol, much like
385 // `__indirect_function_table`. However, given that the table is always
386 // identical (single element, default initialized), we declare it
387 // weak in each object, and define it here rather than in the linker.
388 //
389 // TODO: consider moving this definition elsewhere, or doing away with
390 // the table entirely (in favor of `call_ref` exclusively).
391 {
392 StringRef Name = "__funcref_call_table";
393 auto *Sym = static_cast<MCSymbolWasm *>(OutContext.lookupSymbol(Name));
394 if (Sym) {
395 if (!Sym->isFunctionTable())
396 OutContext.reportError(SMLoc(), "symbol is not a wasm funcref table");
397
398 // symbol is declared weak in `getOrCreateFuncrefCallTableSymbol`
399 assert(Sym->isWeak());
400 OutStreamer->emitSymbolAttribute(Sym, MCSA_Weak);
401
402 // Make sure we haven't already emitted it for whatever reason.
403 assert(!Sym->isDefined());
404
405 // Actually define the symbol.
406 // Confusingly enough, `emitLabel` is what "defines" a MCSymbol.
407 // Provides it a fragment, so that it `!isUndefined`
408 OutStreamer->emitLabel(Sym);
409 // No initializer needed. Default ref.null is good
410 OutStreamer->addBlankLine();
411 }
412 }
413
414 DenseSet<MCSymbol *> InvokeSymbols;
415 for (const auto &F : M) {
416 if (F.isIntrinsic())
417 continue;
418
419 // Emit function type info for all functions. This will emit duplicate
420 // information for defined functions (which already have function type
421 // info emitted alongside their definition), but this is necessary in
422 // order to enable the single-pass WebAssemblyAsmTypeCheck to succeed.
424 SmallVector<MVT, 4> Params;
425 computeSignatureVTs(F.getFunctionType(), &F, F, TM, Params, Results);
426 // At this point these MCSymbols may or may not have been created already
427 // and thus also contain a signature, but we need to get the signature
428 // anyway here in case it is an invoke that has not yet been created. We
429 // will discard it later if it turns out not to be necessary.
430 auto Signature = signatureFromMVTs(OutContext, Results, Params);
431 bool InvokeDetected = false;
432 auto *Sym = getMCSymbolForFunction(&F, Signature, InvokeDetected);
433
434 // Multiple functions can be mapped to the same invoke symbol. For
435 // example, two IR functions '__invoke_void_i8*' and '__invoke_void_i32'
436 // are both mapped to '__invoke_vi'. We keep them in a set once we emit an
437 // Emscripten EH symbol so we don't emit the same symbol twice.
438 if (InvokeDetected && !InvokeSymbols.insert(Sym).second)
439 continue;
440
442 if (!Sym->getSignature()) {
443 Sym->setSignature(Signature);
444 }
445
447
448 if (F.hasFnAttribute("wasm-import-module")) {
449 StringRef Name =
450 F.getFnAttribute("wasm-import-module").getValueAsString();
451 Sym->setImportModule(OutContext.allocateString(Name));
453 }
454 if (F.hasFnAttribute("wasm-import-name")) {
455 // If this is a converted Emscripten EH/SjLj symbol, we shouldn't use
456 // the original function name but the converted symbol name.
457 StringRef Name =
458 InvokeDetected
459 ? Sym->getName()
460 : F.getFnAttribute("wasm-import-name").getValueAsString();
461 Sym->setImportName(OutContext.allocateString(Name));
462 getTargetStreamer()->emitImportName(Sym, Name);
463 }
464
465 if (F.hasFnAttribute("wasm-export-name")) {
466 auto *Sym = static_cast<MCSymbolWasm *>(getSymbol(&F));
467 StringRef Name = F.getFnAttribute("wasm-export-name").getValueAsString();
468 Sym->setExportName(OutContext.allocateString(Name));
469 getTargetStreamer()->emitExportName(Sym, Name);
470 }
471 }
472}
473
475 // This is required to emit external declarations (like .functypes) when
476 // no functions are defined in the compilation unit and therefore,
477 // emitDecls() is not called until now.
478 emitDecls(M);
479
480 // When a function's address is taken, a TABLE_INDEX relocation is emitted
481 // against the function symbol at the use site. However the relocation
482 // doesn't explicitly refer to the table. In the future we may want to
483 // define a new kind of reloc against both the function and the table, so
484 // that the linker can see that the function symbol keeps the table alive,
485 // but for now manually mark the table as live.
486 for (const auto &F : M) {
487 if (!F.isIntrinsic() && F.hasAddressTaken()) {
488 MCSymbolWasm *FunctionTable =
490 OutStreamer->emitSymbolAttribute(FunctionTable, MCSA_NoDeadStrip);
491 break;
492 }
493 }
494
495 for (const auto &G : M.globals()) {
496 if (!G.hasInitializer() && G.hasExternalLinkage() &&
497 !WebAssembly::isWasmVarAddressSpace(G.getAddressSpace()) &&
498 G.getValueType()->isSized()) {
499 uint16_t Size = G.getGlobalSize(M.getDataLayout());
500 OutStreamer->emitELFSize(getSymbol(&G),
502 }
503 }
504
505 if (const NamedMDNode *Named = M.getNamedMetadata("wasm.custom_sections")) {
506 for (const Metadata *MD : Named->operands()) {
507 const auto *Tuple = dyn_cast<MDTuple>(MD);
508 if (!Tuple || Tuple->getNumOperands() != 2)
509 continue;
510 const MDString *Name = dyn_cast<MDString>(Tuple->getOperand(0));
511 const MDString *Contents = dyn_cast<MDString>(Tuple->getOperand(1));
512 if (!Name || !Contents)
513 continue;
514
515 OutStreamer->pushSection();
516 std::string SectionName = (".custom_section." + Name->getString()).str();
517 MCSectionWasm *MySection =
519 OutStreamer->switchSection(MySection);
520 OutStreamer->emitBytes(Contents->getString());
521 OutStreamer->popSection();
522 }
523 }
524
528}
529
532 if (const NamedMDNode *Debug = M.getNamedMetadata("llvm.dbg.cu")) {
533 llvm::SmallSet<StringRef, 4> SeenLanguages;
534 for (size_t I = 0, E = Debug->getNumOperands(); I < E; ++I) {
535 const auto *CU = cast<DICompileUnit>(Debug->getOperand(I));
536 StringRef Language =
537 dwarf::LanguageString(CU->getSourceLanguage().getUnversionedName());
538
539 Language.consume_front("DW_LANG_");
540 if (SeenLanguages.insert(Language).second)
541 Languages.emplace_back(Language.str(), "");
542 }
543 }
544
546 if (const NamedMDNode *Ident = M.getNamedMetadata("llvm.ident")) {
548 for (size_t I = 0, E = Ident->getNumOperands(); I < E; ++I) {
549 const auto *S = cast<MDString>(Ident->getOperand(I)->getOperand(0));
550 std::pair<StringRef, StringRef> Field = S->getString().split("version");
551 StringRef Name = Field.first.trim();
552 StringRef Version = Field.second.trim();
553 if (SeenTools.insert(Name).second)
554 Tools.emplace_back(Name.str(), Version.str());
555 }
556 }
557
558 int FieldCount = int(!Languages.empty()) + int(!Tools.empty());
559 if (FieldCount != 0) {
560 MCSectionWasm *Producers = OutContext.getWasmSection(
561 ".custom_section.producers", SectionKind::getMetadata());
562 OutStreamer->pushSection();
563 OutStreamer->switchSection(Producers);
564 OutStreamer->emitULEB128IntValue(FieldCount);
565 for (auto &Producers : {std::make_pair("language", &Languages),
566 std::make_pair("processed-by", &Tools)}) {
567 if (Producers.second->empty())
568 continue;
569 OutStreamer->emitULEB128IntValue(strlen(Producers.first));
570 OutStreamer->emitBytes(Producers.first);
571 OutStreamer->emitULEB128IntValue(Producers.second->size());
572 for (auto &Producer : *Producers.second) {
573 OutStreamer->emitULEB128IntValue(Producer.first.size());
574 OutStreamer->emitBytes(Producer.first);
575 OutStreamer->emitULEB128IntValue(Producer.second.size());
576 OutStreamer->emitBytes(Producer.second);
577 }
578 }
579 OutStreamer->popSection();
580 }
581}
582
584 struct FeatureEntry {
585 uint8_t Prefix;
586 std::string Name;
587 };
588
589 // Read target features and linkage policies from module metadata
590 SmallVector<FeatureEntry, 4> EmittedFeatures;
591 auto EmitFeature = [&](std::string Feature) {
592 std::string MDKey = (StringRef("wasm-feature-") + Feature).str();
593 Metadata *Policy = M.getModuleFlag(MDKey);
594 if (Policy == nullptr)
595 return;
596
597 FeatureEntry Entry;
598 Entry.Prefix = 0;
599 Entry.Name = Feature;
600
601 if (auto *MD = cast<ConstantAsMetadata>(Policy))
602 if (auto *I = cast<ConstantInt>(MD->getValue()))
603 Entry.Prefix = I->getZExtValue();
604
605 // Silently ignore invalid metadata
606 if (Entry.Prefix != wasm::WASM_FEATURE_PREFIX_USED &&
608 return;
609
610 EmittedFeatures.push_back(Entry);
611 };
612
613 // If we never compiled a single function, Subtarget is null.
614 if (!Subtarget) {
615 Subtarget = static_cast<WebAssemblyTargetMachine &>(TM).getSubtargetImpl(
616 TM.getTargetCPU(), TM.getTargetFeatureString(), TM.getTargetABIName(M));
617 }
618 for (const SubtargetFeatureKV &KV : Subtarget->getAllProcessorFeatures()) {
619 EmitFeature(KV.key());
620 }
621 // This pseudo-feature tells the linker whether shared memory would be safe
622 EmitFeature("shared-mem");
623
624 // This is an "architecture", not a "feature", but we emit it as such for
625 // the benefit of tools like Binaryen and consistency with other producers.
626 if (Subtarget->hasAddr64()) {
627 // Can't use EmitFeature since "wasm-feature-memory64" is not a module
628 // flag.
629 EmittedFeatures.push_back({wasm::WASM_FEATURE_PREFIX_USED, "memory64"});
630 }
631
632 if (EmittedFeatures.size() == 0)
633 return;
634
635 // Emit features and linkage policies into the "target_features" section
636 MCSectionWasm *FeaturesSection = OutContext.getWasmSection(
637 ".custom_section.target_features", SectionKind::getMetadata());
638 OutStreamer->pushSection();
639 OutStreamer->switchSection(FeaturesSection);
640
641 OutStreamer->emitULEB128IntValue(EmittedFeatures.size());
642 for (auto &F : EmittedFeatures) {
643 OutStreamer->emitIntValue(F.Prefix, 1);
644 OutStreamer->emitULEB128IntValue(F.Name.size());
645 OutStreamer->emitBytes(F.Name);
646 }
647
648 OutStreamer->popSection();
649}
650
652 auto V = M.getNamedGlobal("llvm.global.annotations");
653 if (!V)
654 return;
655
656 // Group all the custom attributes by name.
658 const ConstantArray *CA = cast<ConstantArray>(V->getOperand(0));
659 for (Value *Op : CA->operands()) {
660 auto *CS = cast<ConstantStruct>(Op);
661 // The first field is a pointer to the annotated variable.
662 Value *AnnotatedVar = CS->getOperand(0)->stripPointerCasts();
663 // Only annotated functions are supported for now.
664 if (!isa<Function>(AnnotatedVar))
665 continue;
666 auto *F = cast<Function>(AnnotatedVar);
667
668 // The second field is a pointer to a global annotation string.
669 auto *GV = cast<GlobalVariable>(CS->getOperand(1)->stripPointerCasts());
670 StringRef AnnotationString;
671 getConstantStringInfo(GV, AnnotationString);
672 auto *Sym = static_cast<MCSymbolWasm *>(getSymbol(F));
673 CustomSections[AnnotationString].push_back(Sym);
674 }
675
676 // Emit a custom section for each unique attribute.
677 for (const auto &[Name, Symbols] : CustomSections) {
678 MCSectionWasm *CustomSection = OutContext.getWasmSection(
679 ".custom_section.llvm.func_attr.annotate." + Name, SectionKind::getMetadata());
680 OutStreamer->pushSection();
681 OutStreamer->switchSection(CustomSection);
682
683 for (auto &Sym : Symbols) {
684 OutStreamer->emitValue(
686 4);
687 }
688 OutStreamer->popSection();
689 }
690}
691
693 emitDecls(*MMI->getModule());
694 assert(MF->getConstantPool()->getConstants().empty() &&
695 "WebAssembly disables constant pools");
696}
697
699 // Nothing to do; jump tables are incorporated into the instruction stream.
700}
701
703 const Function &F = MF->getFunction();
704 SmallVector<MVT, 1> ResultVTs;
705 SmallVector<MVT, 4> ParamVTs;
706 computeSignatureVTs(F.getFunctionType(), &F, F, TM, ParamVTs, ResultVTs);
707
708 auto Signature = signatureFromMVTs(OutContext, ResultVTs, ParamVTs);
709 auto *WasmSym = static_cast<MCSymbolWasm *>(CurrentFnSym);
710 WasmSym->setSignature(Signature);
711 WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
712
714
715 // Emit the function index.
716 if (MDNode *Idx = F.getMetadata("wasm.index")) {
717 assert(Idx->getNumOperands() == 1);
718
720 cast<ConstantAsMetadata>(Idx->getOperand(0))->getValue()));
721 }
722
724 valTypesFromMVTs(MFI->getLocals(), Locals);
725 getTargetStreamer()->emitLocal(Locals);
726
728}
729
731 LLVM_DEBUG(dbgs() << "EmitInstruction: " << *MI << '\n');
732 WebAssembly_MC::verifyInstructionPredicates(MI->getOpcode(),
733 Subtarget->getFeatureBits());
734
735 switch (MI->getOpcode()) {
736 case WebAssembly::ARGUMENT_i32:
737 case WebAssembly::ARGUMENT_i32_S:
738 case WebAssembly::ARGUMENT_i64:
739 case WebAssembly::ARGUMENT_i64_S:
740 case WebAssembly::ARGUMENT_f32:
741 case WebAssembly::ARGUMENT_f32_S:
742 case WebAssembly::ARGUMENT_f64:
743 case WebAssembly::ARGUMENT_f64_S:
744 case WebAssembly::ARGUMENT_v16i8:
745 case WebAssembly::ARGUMENT_v16i8_S:
746 case WebAssembly::ARGUMENT_v8i16:
747 case WebAssembly::ARGUMENT_v8i16_S:
748 case WebAssembly::ARGUMENT_v4i32:
749 case WebAssembly::ARGUMENT_v4i32_S:
750 case WebAssembly::ARGUMENT_v2i64:
751 case WebAssembly::ARGUMENT_v2i64_S:
752 case WebAssembly::ARGUMENT_v4f32:
753 case WebAssembly::ARGUMENT_v4f32_S:
754 case WebAssembly::ARGUMENT_v2f64:
755 case WebAssembly::ARGUMENT_v2f64_S:
756 case WebAssembly::ARGUMENT_v8f16:
757 case WebAssembly::ARGUMENT_v8f16_S:
758 case WebAssembly::ARGUMENT_externref:
759 case WebAssembly::ARGUMENT_externref_S:
760 case WebAssembly::ARGUMENT_funcref:
761 case WebAssembly::ARGUMENT_funcref_S:
762 case WebAssembly::ARGUMENT_exnref:
763 case WebAssembly::ARGUMENT_exnref_S:
764 // These represent values which are live into the function entry, so there's
765 // no instruction to emit.
766 break;
767 case WebAssembly::FALLTHROUGH_RETURN: {
768 // These instructions represent the implicit return at the end of a
769 // function body.
770 if (isVerbose()) {
771 OutStreamer->AddComment("fallthrough-return");
772 OutStreamer->addBlankLine();
773 }
774 break;
775 }
776 case WebAssembly::COMPILER_FENCE:
777 // This is a compiler barrier that prevents instruction reordering during
778 // backend compilation, and should not be emitted.
779 break;
780 case WebAssembly::CATCH:
781 case WebAssembly::CATCH_S:
782 case WebAssembly::CATCH_REF:
783 case WebAssembly::CATCH_REF_S:
784 case WebAssembly::CATCH_ALL:
785 case WebAssembly::CATCH_ALL_S:
786 case WebAssembly::CATCH_ALL_REF:
787 case WebAssembly::CATCH_ALL_REF_S:
788 // These are pseudo instructions to represent catch clauses in try_table
789 // instruction to simulate block return values.
790 break;
791 default: {
792 WebAssemblyMCInstLower MCInstLowering(OutContext, *this);
793 MCInst TmpInst;
794 MCInstLowering.lower(MI, TmpInst);
795 EmitToStreamer(*OutStreamer, TmpInst);
796 break;
797 }
798 }
799}
800
802 unsigned OpNo,
803 const char *ExtraCode,
804 raw_ostream &OS) {
805 // First try the generic code, which knows about modifiers like 'c' and 'n'.
806 if (!AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS))
807 return false;
808
809 if (!ExtraCode) {
810 const MachineOperand &MO = MI->getOperand(OpNo);
811 switch (MO.getType()) {
813 OS << MO.getImm();
814 return false;
816 // FIXME: only opcode that still contains registers, as required by
817 // MachineInstr::getDebugVariable().
818 assert(MI->getOpcode() == WebAssembly::INLINEASM);
819 OS << regToString(MO);
820 return false;
822 PrintSymbolOperand(MO, OS);
823 return false;
826 printOffset(MO.getOffset(), OS);
827 return false;
829 MO.getMBB()->getSymbol()->print(OS, MAI);
830 return false;
831 default:
832 break;
833 }
834 }
835
836 return true;
837}
838
840 unsigned OpNo,
841 const char *ExtraCode,
842 raw_ostream &OS) {
843 // The current approach to inline asm is that "r" constraints are expressed
844 // as local indices, rather than values on the operand stack. This simplifies
845 // using "r" as it eliminates the need to push and pop the values in a
846 // particular order, however it also makes it impossible to have an "m"
847 // constraint. So we don't support it.
848
849 return AsmPrinter::PrintAsmMemoryOperand(MI, OpNo, ExtraCode, OS);
850}
851
853
854INITIALIZE_PASS(WebAssemblyAsmPrinter, "webassembly-asm-printer",
855 "WebAssembly Assembly Printer", false, false)
856
857// Force static initialization.
859LLVMInitializeWebAssemblyAsmPrinter() {
862}
863
872
884
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Function Alias Analysis Results
static const Function * getParent(const Value *V)
#define X(NUM, ENUM, NAME)
Definition ELF.h:857
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_ABI
Definition Compiler.h:215
#define LLVM_EXTERNAL_VISIBILITY
Definition Compiler.h:132
IRTranslator LLVM IR MI
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
#define G(x, y, z)
Definition MD5.cpp:55
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
Register const TargetRegisterInfo * TRI
This file implements a map that provides insertion order iteration.
This file contains the declarations for metadata subclasses.
#define T
OptimizedStructLayoutField Field
ModuleAnalysisManager MAM
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
const char * Msg
This file defines the SmallSet class.
This file contains some functions that are useful when dealing with strings.
#define LLVM_DEBUG(...)
Definition Debug.h:119
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static std::string getEmscriptenInvokeSymbolName(wasm::WasmSignature *Sig)
static bool isEmscriptenInvokeName(StringRef Name)
static char getInvokeSig(wasm::ValType VT)
cl::opt< bool > WasmKeepRegisters
This file contains the declaration of the WebAssemblyMCAsmInfo class.
This file declares the class to lower WebAssembly MachineInstrs to their corresponding MCInst records...
This file provides WebAssembly-specific target descriptions.
This file declares WebAssembly-specific per-machine-function information.
This file contains the WebAssembly implementation of the WebAssemblyRegisterInfo class.
This file provides signature information for runtime libcalls.
This file registers the WebAssembly target.
This file declares the WebAssembly-specific subclass of TargetMachine.
This file declares WebAssembly-specific target streamer classes.
This file contains the declaration of the WebAssembly-specific type parsing utility functions.
This file contains the declaration of the WebAssembly-specific utility functions.
This file contains the entry points for global functions defined in the LLVM WebAssembly back-end.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
This class is intended to be used as a driving class for all asm writers.
Definition AsmPrinter.h:91
MCSymbol * getSymbol(const GlobalValue *GV) const
void EmitToStreamer(MCStreamer &S, const MCInst &Inst)
virtual void emitGlobalVariable(const GlobalVariable *GV)
Emit the specified global variable to the .s file.
TargetMachine & TM
Target machine description.
Definition AsmPrinter.h:94
virtual void PrintSymbolOperand(const MachineOperand &MO, raw_ostream &OS)
Print the MachineOperand as a symbol.
MachineFunction * MF
The current machine function.
Definition AsmPrinter.h:109
virtual const MCExpr * lowerConstant(const Constant *CV, const Constant *BaseCV=nullptr, uint64_t Offset=0)
Lower the specified LLVM Constant to an MCExpr.
virtual void emitFunctionBodyStart()
Targets can override this to emit stuff before the first basic block in the function.
Definition AsmPrinter.h:627
bool doInitialization(Module &M) override
Set up the AsmPrinter when we are working on a new module.
virtual void emitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const
This emits linkage information about GVSym based on GV, if this is supported by the target.
void printOffset(int64_t Offset, raw_ostream &OS) const
This is just convenient handler for printing offsets.
MCSymbol * getSymbolPreferLocal(const GlobalValue &GV) const
Similar to getSymbol() but preferred for references.
MCSymbol * CurrentFnSym
The symbol for the current function.
Definition AsmPrinter.h:128
MachineModuleInfo * MMI
This is a pointer to the current MachineModuleInfo.
Definition AsmPrinter.h:112
MCContext & OutContext
This is the context for the output file that we are streaming.
Definition AsmPrinter.h:101
bool doFinalization(Module &M) override
Shut down the asmprinter.
void emitVisibility(MCSymbol *Sym, unsigned Visibility, bool IsDefinition=true) const
This emits visibility information about symbol, if this is supported by the target.
bool runOnMachineFunction(MachineFunction &MF) override
Emit the specified function out to the OutStreamer.
Definition AsmPrinter.h:453
std::unique_ptr< MCStreamer > OutStreamer
This is the MCStreamer object for the file we are generating.
Definition AsmPrinter.h:106
const MCAsmInfo & MAI
Target Asm Printer information.
Definition AsmPrinter.h:97
virtual bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &OS)
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant as...
bool isVerbose() const
Return true if assembly output should contain comments.
Definition AsmPrinter.h:310
MCSymbol * GetExternalSymbolSymbol(const Twine &Sym) const
Return the MCSymbol for the specified ExternalSymbol.
@ Debug
Emit .debug_frame.
Definition AsmPrinter.h:169
virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &OS)
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant.
LLVM_ABI StringRef getValueAsString() const
Return the attribute's value as a string.
ConstantArray - Constant Array Declarations.
Definition Constants.h:590
Implements a dense probed hash-table based set.
Definition DenseSet.h:281
bool isThreadLocal() const
If the value is "Thread Local", its value isn't shared by the threads.
VisibilityTypes getVisibility() const
LLVM_ABI bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
Definition Globals.cpp:408
unsigned getAddressSpace() const
Module * getParent()
Get the module that this global value is contained inside of...
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this global belongs to.
Definition Globals.cpp:205
Type * getValueType() const
bool hasAttribute(Attribute::AttrKind Kind) const
Return true if the attribute exists.
bool hasInitializer() const
Definitions have initializers, declarations don't.
Attribute getAttribute(Attribute::AttrKind Kind) const
Return the attribute object.
bool isConstant() const
If the value is a global constant, its value is immutable throughout the runtime execution of the pro...
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition MCExpr.cpp:212
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
This represents a section on wasm.
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:213
void setSignature(wasm::WasmSignature *Sig)
std::optional< wasm::WasmSymbolType > getType() const
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition MCSymbol.h:42
LLVM_ABI void print(raw_ostream &OS, const MCAsmInfo *MAI) const
print - Print the value to the stream OS.
Definition MCSymbol.cpp:59
Target specific streamer interface.
Definition MCStreamer.h:95
Metadata node.
Definition Metadata.h:1081
A single uniqued string.
Definition Metadata.h:733
LLVM_ABI StringRef getString() const
Definition Metadata.cpp:615
Machine Value Type.
LLVM_ABI MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
Function & getFunction()
Return the LLVM function that this machine code represents.
Representation of each machine instruction.
MachineModuleInfoWasm - This is a MachineModuleInfoImpl implementation for Wasm targets.
SetVector< StringRef > MachineSymbolsUsed
MachineOperand class - Representation of each machine instruction operand.
int64_t getImm() const
MachineBasicBlock * getMBB() const
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
const char * getSymbolName() const
Register getReg() const
getReg - Returns the register number.
@ MO_Immediate
Immediate operand.
@ MO_GlobalAddress
Address of a global value.
@ MO_MachineBasicBlock
MachineBasicBlock reference.
@ MO_Register
Register operand.
@ MO_ExternalSymbol
Name of external global symbol.
int64_t getOffset() const
Return the offset from the symbol in this operand.
This class implements a map that also provides access to all stored values in a deterministic order.
Definition MapVector.h:38
Root of the metadata hierarchy.
Definition Metadata.h:64
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:68
LLVMContext & getContext() const
Get the global data context.
Definition Module.h:332
A tuple of MDNodes.
Definition Metadata.h:1767
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
Wrapper class representing virtual and physical registers.
Definition Register.h:20
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Definition Register.h:79
Represents a location in source code.
Definition SMLoc.h:22
static SectionKind getMetadata()
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
Definition SmallSet.h:134
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
Definition SmallSet.h:184
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
op_range operands()
Definition User.h:267
LLVM Value Representation.
Definition Value.h:75
LLVM_ABI const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
Definition Value.cpp:712
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:319
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
void emitJumpTableInfo() override
Print assembly representations of the jump tables used by the current function to the current output ...
void emitGlobalVariable(const GlobalVariable *GV) override
Emit the specified global variable to the .s file.
bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &OS) override
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant as...
const WebAssemblySubtarget & getSubtarget() const
WebAssemblyTargetStreamer * getTargetStreamer()
void emitInstruction(const MachineInstr *MI) override
Targets should implement this to emit instructions.
std::string regToString(const MachineOperand &MO)
void emitSymbolType(const MCSymbolWasm *Sym)
MCSymbol * getOrCreateWasmSymbol(StringRef Name)
void emitConstantPool() override
Print to the current output stream assembly representations of the constants in the constant pool MCP...
MVT getRegType(unsigned RegNo) const
void emitFunctionBodyStart() override
Targets can override this to emit stuff before the first basic block in the function.
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &OS) override
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant.
void emitEndOfAsmFile(Module &M) override
This virtual method can be overridden by targets that want to emit something at the end of their file...
MCSymbolWasm * getMCSymbolForFunction(const Function *F, wasm::WasmSignature *Sig, bool &InvokeDetected)
This class is used to lower an MachineInstr into an MCInst.
void lower(const MachineInstr *MI, MCInst &OutMI) const
WebAssembly-specific streamer interface, to implement support WebAssembly-specific assembly directive...
virtual void emitFunctionType(const MCSymbolWasm *Sym)=0
.functype
virtual void emitLocal(ArrayRef< wasm::ValType > Types)=0
.local
virtual void emitTagType(const MCSymbolWasm *Sym)=0
.tagtype
virtual void emitExportName(const MCSymbolWasm *Sym, StringRef ExportName)=0
.export_name
virtual void emitGlobalType(const MCSymbolWasm *Sym)=0
.globaltype
virtual void emitImportModule(const MCSymbolWasm *Sym, StringRef ImportModule)=0
.import_module
virtual void emitTableType(const MCSymbolWasm *Sym)=0
.tabletype
virtual void emitImportName(const MCSymbolWasm *Sym, StringRef ImportName)=0
.import_name
virtual void emitIndIdx(const MCExpr *Value)=0
.indidx
std::pair< iterator, bool > insert(const ValueT &V)
Definition DenseSet.h:209
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
LLVM_ABI StringRef LanguageString(unsigned Language)
Definition Dwarf.cpp:413
Pass manager infrastructure for declaring and invalidating analyses.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
MCSymbolWasm * getOrCreateFunctionTableSymbol(MCContext &Ctx, const WebAssemblySubtarget *Subtarget)
Returns the __indirect_function_table, for use in call_indirect and in function bitcasts.
static const unsigned UnusedReg
void wasmSymbolSetType(MCSymbolWasm *Sym, const Type *GlobalVT, ArrayRef< MVT > VTs, bool Mutable)
Sets a Wasm Symbol Type.
cl::opt< bool > WasmEnableEmSjLj
std::string signatureToString(const wasm::WasmSignature *Sig)
void getLibcallSignature(const WebAssemblySubtarget &Subtarget, RTLIB::Libcall LC, SmallVectorImpl< wasm::ValType > &Rets, SmallVectorImpl< wasm::ValType > &Params)
bool isWasmVarAddressSpace(unsigned AS)
@ WASM_TYPE_I64
Definition Wasm.h:57
@ WASM_TYPE_I32
Definition Wasm.h:56
@ WASM_FEATURE_PREFIX_USED
Definition Wasm.h:189
@ WASM_FEATURE_PREFIX_DISALLOWED
Definition Wasm.h:190
@ WASM_SYMBOL_TYPE_GLOBAL
Definition Wasm.h:231
@ WASM_SYMBOL_TYPE_DATA
Definition Wasm.h:230
@ WASM_SYMBOL_TYPE_TAG
Definition Wasm.h:233
@ WASM_SYMBOL_TYPE_TABLE
Definition Wasm.h:234
@ WASM_SYMBOL_TYPE_FUNCTION
Definition Wasm.h:229
This is an optimization pass for GlobalISel generic memory operations.
void computeSignatureVTs(const FunctionType *Ty, const Function *TargetFunc, const Function &ContextFunc, const TargetMachine &TM, SmallVectorImpl< MVT > &Params, SmallVectorImpl< MVT > &Results)
OuterAnalysisManagerProxy< ModuleAnalysisManager, MachineFunction > ModuleAnalysisManagerMachineFunctionProxy
Provide the ModuleAnalysisManager to Function proxy.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
LLVM_ABI bool getConstantStringInfo(const Value *V, StringRef &Str, bool TrimAtNul=true)
This function computes the length of a null-terminated C string pointed to by V.
std::string utostr(uint64_t X, bool isNeg=false)
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
LLVM_ABI void setupModuleAsmPrinter(Module &M, ModuleAnalysisManager &MAM, AsmPrinter &AsmPrinter)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
Target & getTheWebAssemblyTarget32()
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
Target & getTheWebAssemblyTarget64()
DWARFExpression::Operation Op
void valTypesFromMVTs(ArrayRef< MVT > In, SmallVectorImpl< wasm::ValType > &Out)
ExceptionHandling
Definition CodeGen.h:54
@ Emscripten
Emscripten JavaScript-based exception handling.
Definition CodeGen.h:62
@ Default
Not specified; resolve to the target's default model.
Definition CodeGen.h:55
LLVM_ABI void setupMachineFunctionAsmPrinter(MachineFunctionAnalysisManager &MFAM, MachineFunction &MF, AsmPrinter &AsmPrinter)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
wasm::WasmSignature * signatureFromMVTs(MCContext &Ctx, const SmallVectorImpl< MVT > &Results, const SmallVectorImpl< MVT > &Params)
void computeLegalValueVTs(const WebAssemblyTargetLowering &TLI, LLVMContext &Ctx, const DataLayout &DL, Type *Ty, SmallVectorImpl< MVT > &ValueVTs)
@ MCSA_Weak
.weak
@ MCSA_NoDeadStrip
.no_dead_strip (MachO)
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Definition MIRParser.h:39
MCRegisterClass TargetRegisterClass
Definition FastISel.h:58
RegisterAsmPrinter - Helper template for registering a target specific assembly printer,...
Used to provide key value pairs for feature and CPU bit flags.
SmallVector< ValType, 1 > Returns
Definition Wasm.h:524
SmallVector< ValType, 4 > Params
Definition Wasm.h:525