LLVM 19.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
21#include "WebAssembly.h"
28#include "llvm/ADT/MapVector.h"
29#include "llvm/ADT/SmallSet.h"
38#include "llvm/IR/DataLayout.h"
41#include "llvm/IR/Metadata.h"
42#include "llvm/MC/MCContext.h"
44#include "llvm/MC/MCStreamer.h"
45#include "llvm/MC/MCSymbol.h"
48#include "llvm/Support/Debug.h"
50
51using namespace llvm;
52
53#define DEBUG_TYPE "asm-printer"
54
56
57//===----------------------------------------------------------------------===//
58// Helpers.
59//===----------------------------------------------------------------------===//
60
62 const TargetRegisterInfo *TRI = Subtarget->getRegisterInfo();
63 const TargetRegisterClass *TRC = MRI->getRegClass(RegNo);
64 for (MVT T : {MVT::i32, MVT::i64, MVT::f32, MVT::f64, MVT::v16i8, MVT::v8i16,
65 MVT::v4i32, MVT::v2i64, MVT::v4f32, MVT::v2f64})
66 if (TRI->isTypeLegalForClass(*TRC, T))
67 return T;
68 LLVM_DEBUG(errs() << "Unknown type for register number: " << RegNo);
69 llvm_unreachable("Unknown register type");
70 return MVT::Other;
71}
72
74 Register RegNo = MO.getReg();
75 assert(RegNo.isVirtual() &&
76 "Unlowered physical register encountered during assembly printing");
77 assert(!MFI->isVRegStackified(RegNo));
78 unsigned WAReg = MFI->getWAReg(RegNo);
80 return '$' + utostr(WAReg);
81}
82
84 MCTargetStreamer *TS = OutStreamer->getTargetStreamer();
85 return static_cast<WebAssemblyTargetStreamer *>(TS);
86}
87
88// Emscripten exception handling helpers
89//
90// This converts invoke names generated by LowerEmscriptenEHSjLj to real names
91// that are expected by JavaScript glue code. The invoke names generated by
92// Emscripten JS glue code are based on their argument and return types; for
93// example, for a function that takes an i32 and returns nothing, it is
94// 'invoke_vi'. But the format of invoke generated by LowerEmscriptenEHSjLj pass
95// contains a mangled string generated from their IR types, for example,
96// "__invoke_void_%struct.mystruct*_int", because final wasm types are not
97// available in the IR pass. So we convert those names to the form that
98// Emscripten JS code expects.
99//
100// Refer to LowerEmscriptenEHSjLj pass for more details.
101
102// Returns true if the given function name is an invoke name generated by
103// LowerEmscriptenEHSjLj pass.
105 if (Name.front() == '"' && Name.back() == '"')
106 Name = Name.substr(1, Name.size() - 2);
107 return Name.starts_with("__invoke_");
108}
109
110// Returns a character that represents the given wasm value type in invoke
111// signatures.
113 switch (VT) {
115 return 'i';
117 return 'j';
119 return 'f';
121 return 'd';
123 return 'V';
125 return 'F';
127 return 'X';
128 default:
129 llvm_unreachable("Unhandled wasm::ValType enum");
130 }
131}
132
133// Given the wasm signature, generate the invoke name in the format JS glue code
134// expects.
136 assert(Sig->Returns.size() <= 1);
137 std::string Ret = "invoke_";
138 if (!Sig->Returns.empty())
139 for (auto VT : Sig->Returns)
140 Ret += getInvokeSig(VT);
141 else
142 Ret += 'v';
143 // Invokes' first argument is a pointer to the original function, so skip it
144 for (unsigned I = 1, E = Sig->Params.size(); I < E; I++)
145 Ret += getInvokeSig(Sig->Params[I]);
146 return Ret;
147}
148
149//===----------------------------------------------------------------------===//
150// WebAssemblyAsmPrinter Implementation.
151//===----------------------------------------------------------------------===//
152
154 const Function *F, bool EnableEmEH, wasm::WasmSignature *Sig,
155 bool &InvokeDetected) {
156 MCSymbolWasm *WasmSym = nullptr;
157 if (EnableEmEH && isEmscriptenInvokeName(F->getName())) {
158 assert(Sig);
159 InvokeDetected = true;
160 if (Sig->Returns.size() > 1) {
161 std::string Msg =
162 "Emscripten EH/SjLj does not support multivalue returns: " +
163 std::string(F->getName()) + ": " +
166 }
167 WasmSym = cast<MCSymbolWasm>(
169 } else {
170 WasmSym = cast<MCSymbolWasm>(getSymbol(F));
171 }
172 return WasmSym;
173}
174
178 return;
179 }
180
181 assert(!GV->isThreadLocal());
182
183 MCSymbolWasm *Sym = cast<MCSymbolWasm>(getSymbol(GV));
184
185 if (!Sym->getType()) {
187 Type *GlobalVT = GV->getValueType();
188 if (Subtarget) {
189 // Subtarget is only set when a function is defined, because
190 // each function can declare a different subtarget. For example,
191 // on ARM a compilation unit might have a function on ARM and
192 // another on Thumb. Therefore only if Subtarget is non-null we
193 // can actually calculate the legal VTs.
194 const WebAssemblyTargetLowering &TLI = *Subtarget->getTargetLowering();
196 GV->getParent()->getDataLayout(), GlobalVT, VTs);
197 }
198 WebAssembly::wasmSymbolSetType(Sym, GlobalVT, VTs);
199 }
200
203 if (GV->hasInitializer()) {
205 emitLinkage(GV, Sym);
206 OutStreamer->emitLabel(Sym);
207 // TODO: Actually emit the initializer value. Otherwise the global has the
208 // default value for its type (0, ref.null, etc).
209 OutStreamer->addBlankLine();
210 }
211}
212
214 auto *WasmSym = cast<MCSymbolWasm>(GetExternalSymbolSymbol(Name));
215
216 // May be called multiple times, so early out.
217 if (WasmSym->getType())
218 return WasmSym;
219
220 const WebAssemblySubtarget &Subtarget = getSubtarget();
221
222 // Except for certain known symbols, all symbols used by CodeGen are
223 // functions. It's OK to hardcode knowledge of specific symbols here; this
224 // method is precisely there for fetching the signatures of known
225 // Clang-provided symbols.
226 if (Name == "__stack_pointer" || Name == "__tls_base" ||
227 Name == "__memory_base" || Name == "__table_base" ||
228 Name == "__tls_size" || Name == "__tls_align") {
229 bool Mutable =
230 Name == "__stack_pointer" || Name == "__tls_base";
231 WasmSym->setType(wasm::WASM_SYMBOL_TYPE_GLOBAL);
232 WasmSym->setGlobalType(wasm::WasmGlobalType{
233 uint8_t(Subtarget.hasAddr64() ? wasm::WASM_TYPE_I64
235 Mutable});
236 return WasmSym;
237 }
238
239 if (Name.starts_with("GCC_except_table")) {
240 WasmSym->setType(wasm::WASM_SYMBOL_TYPE_DATA);
241 return WasmSym;
242 }
243
246 if (Name == "__cpp_exception" || Name == "__c_longjmp") {
247 WasmSym->setType(wasm::WASM_SYMBOL_TYPE_TAG);
248 // In static linking we define tag symbols in WasmException::endModule().
249 // But we may have multiple objects to be linked together, each of which
250 // defines the tag symbols. To resolve them, we declare them as weak. In
251 // dynamic linking we make tag symbols undefined in the backend, define it
252 // in JS, and feed them to each importing module.
254 WasmSym->setWeak(true);
255 WasmSym->setExternal(true);
256
257 // Currently both C++ exceptions and C longjmps have a single pointer type
258 // param. For C++ exceptions it is a pointer to an exception object, and for
259 // C longjmps it is pointer to a struct that contains a setjmp buffer and a
260 // longjmp return value. We may consider using multiple value parameters for
261 // longjmps later when multivalue support is ready.
262 wasm::ValType AddrType =
264 Params.push_back(AddrType);
265 } else { // Function symbols
266 WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
267 getLibcallSignature(Subtarget, Name, Returns, Params);
268 }
269 auto Signature = std::make_unique<wasm::WasmSignature>(std::move(Returns),
270 std::move(Params));
271 WasmSym->setSignature(Signature.get());
272 addSignature(std::move(Signature));
273
274 return WasmSym;
275}
276
278 std::optional<wasm::WasmSymbolType> WasmTy = Sym->getType();
279 if (!WasmTy)
280 return;
281
282 switch (*WasmTy) {
285 break;
288 break;
291 break;
292 default:
293 break; // We only handle globals, tags and tables here
294 }
295}
296
298 if (signaturesEmitted)
299 return;
300 signaturesEmitted = true;
301
302 // Normally symbols for globals get discovered as the MI gets lowered,
303 // but we need to know about them ahead of time. This will however,
304 // only find symbols that have been used. Unused symbols from globals will
305 // not be found here.
307 for (StringRef Name : MMIW.MachineSymbolsUsed) {
308 auto *WasmSym = cast<MCSymbolWasm>(getOrCreateWasmSymbol(Name));
309 if (WasmSym->isFunction()) {
310 // TODO(wvo): is there any case where this overlaps with the call to
311 // emitFunctionType in the loop below?
313 }
314 }
315
316 for (auto &It : OutContext.getSymbols()) {
317 // Emit .globaltype, .tagtype, or .tabletype declarations for extern
318 // declarations, i.e. those that have only been declared (but not defined)
319 // in the current module
320 auto Sym = cast<MCSymbolWasm>(It.getValue());
321 if (!Sym->isDefined())
323 }
324
325 DenseSet<MCSymbol *> InvokeSymbols;
326 for (const auto &F : M) {
327 if (F.isIntrinsic())
328 continue;
329
330 // Emit function type info for all functions. This will emit duplicate
331 // information for defined functions (which already have function type
332 // info emitted alongside their definition), but this is necessary in
333 // order to enable the single-pass WebAssemblyAsmTypeCheck to succeed.
335 SmallVector<MVT, 4> Params;
336 computeSignatureVTs(F.getFunctionType(), &F, F, TM, Params, Results);
337 // At this point these MCSymbols may or may not have been created already
338 // and thus also contain a signature, but we need to get the signature
339 // anyway here in case it is an invoke that has not yet been created. We
340 // will discard it later if it turns out not to be necessary.
341 auto Signature = signatureFromMVTs(Results, Params);
342 bool InvokeDetected = false;
345 Signature.get(), InvokeDetected);
346
347 // Multiple functions can be mapped to the same invoke symbol. For
348 // example, two IR functions '__invoke_void_i8*' and '__invoke_void_i32'
349 // are both mapped to '__invoke_vi'. We keep them in a set once we emit an
350 // Emscripten EH symbol so we don't emit the same symbol twice.
351 if (InvokeDetected && !InvokeSymbols.insert(Sym).second)
352 continue;
353
355 if (!Sym->getSignature()) {
356 Sym->setSignature(Signature.get());
357 addSignature(std::move(Signature));
358 } else {
359 // This symbol has already been created and had a signature. Discard it.
360 Signature.reset();
361 }
362
364
365 if (F.hasFnAttribute("wasm-import-module")) {
367 F.getFnAttribute("wasm-import-module").getValueAsString();
368 Sym->setImportModule(storeName(Name));
370 }
371 if (F.hasFnAttribute("wasm-import-name")) {
372 // If this is a converted Emscripten EH/SjLj symbol, we shouldn't use
373 // the original function name but the converted symbol name.
375 InvokeDetected
376 ? Sym->getName()
377 : F.getFnAttribute("wasm-import-name").getValueAsString();
378 Sym->setImportName(storeName(Name));
380 }
381
382 if (F.hasFnAttribute("wasm-export-name")) {
383 auto *Sym = cast<MCSymbolWasm>(getSymbol(&F));
384 StringRef Name = F.getFnAttribute("wasm-export-name").getValueAsString();
385 Sym->setExportName(storeName(Name));
387 }
388 }
389}
390
392 // This is required to emit external declarations (like .functypes) when
393 // no functions are defined in the compilation unit and therefore,
394 // emitDecls() is not called until now.
395 emitDecls(M);
396
397 // When a function's address is taken, a TABLE_INDEX relocation is emitted
398 // against the function symbol at the use site. However the relocation
399 // doesn't explicitly refer to the table. In the future we may want to
400 // define a new kind of reloc against both the function and the table, so
401 // that the linker can see that the function symbol keeps the table alive,
402 // but for now manually mark the table as live.
403 for (const auto &F : M) {
404 if (!F.isIntrinsic() && F.hasAddressTaken()) {
405 MCSymbolWasm *FunctionTable =
407 OutStreamer->emitSymbolAttribute(FunctionTable, MCSA_NoDeadStrip);
408 break;
409 }
410 }
411
412 for (const auto &G : M.globals()) {
413 if (!G.hasInitializer() && G.hasExternalLinkage() &&
414 !WebAssembly::isWasmVarAddressSpace(G.getAddressSpace()) &&
415 G.getValueType()->isSized()) {
416 uint16_t Size = M.getDataLayout().getTypeAllocSize(G.getValueType());
417 OutStreamer->emitELFSize(getSymbol(&G),
419 }
420 }
421
422 if (const NamedMDNode *Named = M.getNamedMetadata("wasm.custom_sections")) {
423 for (const Metadata *MD : Named->operands()) {
424 const auto *Tuple = dyn_cast<MDTuple>(MD);
425 if (!Tuple || Tuple->getNumOperands() != 2)
426 continue;
427 const MDString *Name = dyn_cast<MDString>(Tuple->getOperand(0));
428 const MDString *Contents = dyn_cast<MDString>(Tuple->getOperand(1));
429 if (!Name || !Contents)
430 continue;
431
432 OutStreamer->pushSection();
433 std::string SectionName = (".custom_section." + Name->getString()).str();
434 MCSectionWasm *MySection =
436 OutStreamer->switchSection(MySection);
437 OutStreamer->emitBytes(Contents->getString());
438 OutStreamer->popSection();
439 }
440 }
441
445}
446
449 if (const NamedMDNode *Debug = M.getNamedMetadata("llvm.dbg.cu")) {
450 llvm::SmallSet<StringRef, 4> SeenLanguages;
451 for (size_t I = 0, E = Debug->getNumOperands(); I < E; ++I) {
452 const auto *CU = cast<DICompileUnit>(Debug->getOperand(I));
453 StringRef Language = dwarf::LanguageString(CU->getSourceLanguage());
454 Language.consume_front("DW_LANG_");
455 if (SeenLanguages.insert(Language).second)
456 Languages.emplace_back(Language.str(), "");
457 }
458 }
459
461 if (const NamedMDNode *Ident = M.getNamedMetadata("llvm.ident")) {
463 for (size_t I = 0, E = Ident->getNumOperands(); I < E; ++I) {
464 const auto *S = cast<MDString>(Ident->getOperand(I)->getOperand(0));
465 std::pair<StringRef, StringRef> Field = S->getString().split("version");
466 StringRef Name = Field.first.trim();
467 StringRef Version = Field.second.trim();
468 if (SeenTools.insert(Name).second)
469 Tools.emplace_back(Name.str(), Version.str());
470 }
471 }
472
473 int FieldCount = int(!Languages.empty()) + int(!Tools.empty());
474 if (FieldCount != 0) {
476 ".custom_section.producers", SectionKind::getMetadata());
477 OutStreamer->pushSection();
478 OutStreamer->switchSection(Producers);
479 OutStreamer->emitULEB128IntValue(FieldCount);
480 for (auto &Producers : {std::make_pair("language", &Languages),
481 std::make_pair("processed-by", &Tools)}) {
482 if (Producers.second->empty())
483 continue;
484 OutStreamer->emitULEB128IntValue(strlen(Producers.first));
485 OutStreamer->emitBytes(Producers.first);
486 OutStreamer->emitULEB128IntValue(Producers.second->size());
487 for (auto &Producer : *Producers.second) {
488 OutStreamer->emitULEB128IntValue(Producer.first.size());
489 OutStreamer->emitBytes(Producer.first);
490 OutStreamer->emitULEB128IntValue(Producer.second.size());
491 OutStreamer->emitBytes(Producer.second);
492 }
493 }
494 OutStreamer->popSection();
495 }
496}
497
499 struct FeatureEntry {
500 uint8_t Prefix;
501 std::string Name;
502 };
503
504 // Read target features and linkage policies from module metadata
505 SmallVector<FeatureEntry, 4> EmittedFeatures;
506 auto EmitFeature = [&](std::string Feature) {
507 std::string MDKey = (StringRef("wasm-feature-") + Feature).str();
508 Metadata *Policy = M.getModuleFlag(MDKey);
509 if (Policy == nullptr)
510 return;
511
512 FeatureEntry Entry;
513 Entry.Prefix = 0;
514 Entry.Name = Feature;
515
516 if (auto *MD = cast<ConstantAsMetadata>(Policy))
517 if (auto *I = cast<ConstantInt>(MD->getValue()))
518 Entry.Prefix = I->getZExtValue();
519
520 // Silently ignore invalid metadata
521 if (Entry.Prefix != wasm::WASM_FEATURE_PREFIX_USED &&
522 Entry.Prefix != wasm::WASM_FEATURE_PREFIX_REQUIRED &&
524 return;
525
526 EmittedFeatures.push_back(Entry);
527 };
528
529 for (const SubtargetFeatureKV &KV : WebAssemblyFeatureKV) {
530 EmitFeature(KV.Key);
531 }
532 // This pseudo-feature tells the linker whether shared memory would be safe
533 EmitFeature("shared-mem");
534
535 // This is an "architecture", not a "feature", but we emit it as such for
536 // the benefit of tools like Binaryen and consistency with other producers.
537 // FIXME: Subtarget is null here, so can't Subtarget->hasAddr64() ?
538 if (M.getDataLayout().getPointerSize() == 8) {
539 // Can't use EmitFeature since "wasm-feature-memory64" is not a module
540 // flag.
541 EmittedFeatures.push_back({wasm::WASM_FEATURE_PREFIX_USED, "memory64"});
542 }
543
544 if (EmittedFeatures.size() == 0)
545 return;
546
547 // Emit features and linkage policies into the "target_features" section
548 MCSectionWasm *FeaturesSection = OutContext.getWasmSection(
549 ".custom_section.target_features", SectionKind::getMetadata());
550 OutStreamer->pushSection();
551 OutStreamer->switchSection(FeaturesSection);
552
553 OutStreamer->emitULEB128IntValue(EmittedFeatures.size());
554 for (auto &F : EmittedFeatures) {
555 OutStreamer->emitIntValue(F.Prefix, 1);
556 OutStreamer->emitULEB128IntValue(F.Name.size());
557 OutStreamer->emitBytes(F.Name);
558 }
559
560 OutStreamer->popSection();
561}
562
564 auto V = M.getNamedGlobal("llvm.global.annotations");
565 if (!V)
566 return;
567
568 // Group all the custom attributes by name.
570 const ConstantArray *CA = cast<ConstantArray>(V->getOperand(0));
571 for (Value *Op : CA->operands()) {
572 auto *CS = cast<ConstantStruct>(Op);
573 // The first field is a pointer to the annotated variable.
574 Value *AnnotatedVar = CS->getOperand(0)->stripPointerCasts();
575 // Only annotated functions are supported for now.
576 if (!isa<Function>(AnnotatedVar))
577 continue;
578 auto *F = cast<Function>(AnnotatedVar);
579
580 // The second field is a pointer to a global annotation string.
581 auto *GV = cast<GlobalVariable>(CS->getOperand(1)->stripPointerCasts());
582 StringRef AnnotationString;
583 getConstantStringInfo(GV, AnnotationString);
584 auto *Sym = cast<MCSymbolWasm>(getSymbol(F));
585 CustomSections[AnnotationString].push_back(Sym);
586 }
587
588 // Emit a custom section for each unique attribute.
589 for (const auto &[Name, Symbols] : CustomSections) {
590 MCSectionWasm *CustomSection = OutContext.getWasmSection(
591 ".custom_section.llvm.func_attr.annotate." + Name, SectionKind::getMetadata());
592 OutStreamer->pushSection();
593 OutStreamer->switchSection(CustomSection);
594
595 for (auto &Sym : Symbols) {
596 OutStreamer->emitValue(
598 OutContext),
599 4);
600 }
601 OutStreamer->popSection();
602 }
603}
604
607 assert(MF->getConstantPool()->getConstants().empty() &&
608 "WebAssembly disables constant pools");
609}
610
612 // Nothing to do; jump tables are incorporated into the instruction stream.
613}
614
616 const Function &F = MF->getFunction();
617 SmallVector<MVT, 1> ResultVTs;
618 SmallVector<MVT, 4> ParamVTs;
619 computeSignatureVTs(F.getFunctionType(), &F, F, TM, ParamVTs, ResultVTs);
620
621 auto Signature = signatureFromMVTs(ResultVTs, ParamVTs);
622 auto *WasmSym = cast<MCSymbolWasm>(CurrentFnSym);
623 WasmSym->setSignature(Signature.get());
624 addSignature(std::move(Signature));
625 WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
626
628
629 // Emit the function index.
630 if (MDNode *Idx = F.getMetadata("wasm.index")) {
631 assert(Idx->getNumOperands() == 1);
632
634 cast<ConstantAsMetadata>(Idx->getOperand(0))->getValue()));
635 }
636
638 valTypesFromMVTs(MFI->getLocals(), Locals);
639 getTargetStreamer()->emitLocal(Locals);
640
642}
643
645 LLVM_DEBUG(dbgs() << "EmitInstruction: " << *MI << '\n');
646 WebAssembly_MC::verifyInstructionPredicates(MI->getOpcode(),
647 Subtarget->getFeatureBits());
648
649 switch (MI->getOpcode()) {
650 case WebAssembly::ARGUMENT_i32:
651 case WebAssembly::ARGUMENT_i32_S:
652 case WebAssembly::ARGUMENT_i64:
653 case WebAssembly::ARGUMENT_i64_S:
654 case WebAssembly::ARGUMENT_f32:
655 case WebAssembly::ARGUMENT_f32_S:
656 case WebAssembly::ARGUMENT_f64:
657 case WebAssembly::ARGUMENT_f64_S:
658 case WebAssembly::ARGUMENT_v16i8:
659 case WebAssembly::ARGUMENT_v16i8_S:
660 case WebAssembly::ARGUMENT_v8i16:
661 case WebAssembly::ARGUMENT_v8i16_S:
662 case WebAssembly::ARGUMENT_v4i32:
663 case WebAssembly::ARGUMENT_v4i32_S:
664 case WebAssembly::ARGUMENT_v2i64:
665 case WebAssembly::ARGUMENT_v2i64_S:
666 case WebAssembly::ARGUMENT_v4f32:
667 case WebAssembly::ARGUMENT_v4f32_S:
668 case WebAssembly::ARGUMENT_v2f64:
669 case WebAssembly::ARGUMENT_v2f64_S:
670 // These represent values which are live into the function entry, so there's
671 // no instruction to emit.
672 break;
673 case WebAssembly::FALLTHROUGH_RETURN: {
674 // These instructions represent the implicit return at the end of a
675 // function body.
676 if (isVerbose()) {
677 OutStreamer->AddComment("fallthrough-return");
678 OutStreamer->addBlankLine();
679 }
680 break;
681 }
682 case WebAssembly::COMPILER_FENCE:
683 // This is a compiler barrier that prevents instruction reordering during
684 // backend compilation, and should not be emitted.
685 break;
686 default: {
687 WebAssemblyMCInstLower MCInstLowering(OutContext, *this);
688 MCInst TmpInst;
689 MCInstLowering.lower(MI, TmpInst);
690 EmitToStreamer(*OutStreamer, TmpInst);
691 break;
692 }
693 }
694}
695
697 unsigned OpNo,
698 const char *ExtraCode,
699 raw_ostream &OS) {
700 // First try the generic code, which knows about modifiers like 'c' and 'n'.
701 if (!AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS))
702 return false;
703
704 if (!ExtraCode) {
705 const MachineOperand &MO = MI->getOperand(OpNo);
706 switch (MO.getType()) {
708 OS << MO.getImm();
709 return false;
711 // FIXME: only opcode that still contains registers, as required by
712 // MachineInstr::getDebugVariable().
713 assert(MI->getOpcode() == WebAssembly::INLINEASM);
714 OS << regToString(MO);
715 return false;
718 return false;
721 printOffset(MO.getOffset(), OS);
722 return false;
724 MO.getMBB()->getSymbol()->print(OS, MAI);
725 return false;
726 default:
727 break;
728 }
729 }
730
731 return true;
732}
733
735 unsigned OpNo,
736 const char *ExtraCode,
737 raw_ostream &OS) {
738 // The current approach to inline asm is that "r" constraints are expressed
739 // as local indices, rather than values on the operand stack. This simplifies
740 // using "r" as it eliminates the need to push and pop the values in a
741 // particular order, however it also makes it impossible to have an "m"
742 // constraint. So we don't support it.
743
744 return AsmPrinter::PrintAsmMemoryOperand(MI, OpNo, ExtraCode, OS);
745}
746
747// Force static initialization.
751}
Function Alias Analysis Results
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_EXTERNAL_VISIBILITY
Definition: Compiler.h:135
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
#define LLVM_DEBUG(X)
Definition: Debug.h:101
std::string Name
uint64_t Size
Symbol * Sym
Definition: ELF_riscv.cpp:479
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
IRTranslator LLVM IR MI
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
#define G(x, y, z)
Definition: MD5.cpp:56
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
unsigned const TargetRegisterInfo * TRI
This file implements a map that provides insertion order iteration.
This file contains the declarations for metadata subclasses.
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
raw_pwrite_stream & OS
This file defines the SmallSet class.
This file contains some functions that are useful when dealing with strings.
static std::string getEmscriptenInvokeSymbolName(wasm::WasmSignature *Sig)
static bool isEmscriptenInvokeName(StringRef Name)
static char getInvokeSig(wasm::ValType VT)
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeWebAssemblyAsmPrinter()
cl::opt< bool > WasmKeepRegisters
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.
MCSymbol * getSymbol(const GlobalValue *GV) const
Definition: AsmPrinter.cpp:698
void EmitToStreamer(MCStreamer &S, const MCInst &Inst)
Definition: AsmPrinter.cpp:418
virtual void emitGlobalVariable(const GlobalVariable *GV)
Emit the specified global variable to the .s file.
Definition: AsmPrinter.cpp:720
TargetMachine & TM
Target machine description.
Definition: AsmPrinter.h:87
virtual void PrintSymbolOperand(const MachineOperand &MO, raw_ostream &OS)
Print the MachineOperand as a symbol.
const MCAsmInfo * MAI
Target Asm Printer information.
Definition: AsmPrinter.h:90
MachineFunction * MF
The current machine function.
Definition: AsmPrinter.h:102
virtual void emitFunctionBodyStart()
Targets can override this to emit stuff before the first basic block in the function.
Definition: AsmPrinter.h:551
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.
Definition: AsmPrinter.cpp:653
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.
Definition: AsmPrinter.cpp:702
MCSymbol * CurrentFnSym
The symbol for the current function.
Definition: AsmPrinter.h:121
MachineModuleInfo * MMI
This is a pointer to the current MachineModuleInfo.
Definition: AsmPrinter.h:105
MCContext & OutContext
This is the context for the output file that we are streaming.
Definition: AsmPrinter.h:94
MCSymbol * GetExternalSymbolSymbol(Twine Sym) const
Return the MCSymbol for the specified ExternalSymbol.
bool isPositionIndependent() const
Definition: AsmPrinter.cpp:389
void emitVisibility(MCSymbol *Sym, unsigned Visibility, bool IsDefinition=true) const
This emits visibility information about symbol, if this is supported by the target.
std::unique_ptr< MCStreamer > OutStreamer
This is the MCStreamer object for the file we are generating.
Definition: AsmPrinter.h:99
virtual const MCExpr * lowerConstant(const Constant *CV)
Lower the specified LLVM Constant to an MCExpr.
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:265
@ Debug
Emit .debug_frame.
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.
ConstantArray - Constant Array Declarations.
Definition: Constants.h:422
This class represents an Operation in the Expression.
Implements a dense probed hash-table based set.
Definition: DenseSet.h:271
bool isThreadLocal() const
If the value is "Thread Local", its value isn't shared by the threads.
Definition: GlobalValue.h:263
VisibilityTypes getVisibility() const
Definition: GlobalValue.h:248
bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
Definition: Globals.cpp:274
unsigned getAddressSpace() const
Definition: GlobalValue.h:205
Module * getParent()
Get the module that this global value is contained inside of...
Definition: GlobalValue.h:655
Type * getValueType() const
Definition: GlobalValue.h:296
bool hasInitializer() const
Definitions have initializers, declarations don't.
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition: MCExpr.cpp:194
MCSectionWasm * getWasmSection(const Twine &Section, SectionKind K, unsigned Flags=0)
Definition: MCContext.h:646
const SymbolTable & getSymbols() const
getSymbols - Get a reference for the symbol table for clients that want to, for example,...
Definition: MCContext.h:527
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:184
This represents a section on wasm.
Definition: MCSectionWasm.h:26
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
Definition: MCExpr.h:395
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:40
void print(raw_ostream &OS, const MCAsmInfo *MAI) const
print - Print the value to the stream OS.
Definition: MCSymbol.cpp:58
Target specific streamer interface.
Definition: MCStreamer.h:93
Metadata node.
Definition: Metadata.h:1067
A single uniqued string.
Definition: Metadata.h:720
StringRef getString() const
Definition: Metadata.cpp:607
Machine Value Type.
MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
const std::vector< MachineConstantPoolEntry > & getConstants() const
Function & getFunction()
Return the LLVM function that this machine code represents.
MachineConstantPool * getConstantPool()
getConstantPool - Return the constant pool object for the current function.
Representation of each machine instruction.
Definition: MachineInstr.h:69
MachineModuleInfoWasm - This is a MachineModuleInfoImpl implementation for Wasm targets.
SetVector< StringRef > MachineSymbolsUsed
const Module * getModule() const
Ty & getObjFileInfo()
Keep track of various per-module pieces of information for backends that would like to do so.
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.
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
This class implements a map that also provides access to all stored values in a deterministic order.
Definition: MapVector.h:36
Root of the metadata hierarchy.
Definition: Metadata.h:62
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
LLVMContext & getContext() const
Get the global data context.
Definition: Module.h:283
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
Definition: Module.h:275
A tuple of MDNodes.
Definition: Metadata.h:1729
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Definition: Register.h:91
static SectionKind getMetadata()
Definition: SectionKind.h:188
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
Definition: SmallSet.h:135
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:179
bool empty() const
Definition: SmallVector.h:94
size_t size() const
Definition: SmallVector.h:91
reference emplace_back(ArgTypes &&... Args)
Definition: SmallVector.h:950
void push_back(const T &Elt)
Definition: SmallVector.h:426
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1209
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
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:81
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
op_range operands()
Definition: User.h:242
LLVM Value Representation.
Definition: Value.h:74
const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
Definition: Value.cpp:693
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.
MCSymbolWasm * getMCSymbolForFunction(const Function *F, bool EnableEmEH, wasm::WasmSignature *Sig, bool &InvokeDetected)
void addSignature(std::unique_ptr< wasm::WasmSignature > &&Sig)
void emitEndOfAsmFile(Module &M) override
This virtual method can be overridden by targets that want to emit something at the end of their file...
unsigned getWAReg(unsigned VReg) const
const std::vector< MVT > & getLocals() const
This class is used to lower an MachineInstr into an MCInst.
void lower(const MachineInstr *MI, MCInst &OutMI) const
const WebAssemblyTargetLowering * getTargetLowering() const override
const WebAssemblyRegisterInfo * getRegisterInfo() const override
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:206
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
StringRef LanguageString(unsigned Language)
Definition: Dwarf.cpp:361
#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
cl::opt< bool > WasmEnableEmEH
cl::opt< bool > WasmEnableEmSjLj
std::string signatureToString(const wasm::WasmSignature *Sig)
void wasmSymbolSetType(MCSymbolWasm *Sym, const Type *GlobalVT, const ArrayRef< MVT > &VTs)
Sets a Wasm Symbol Type.
bool isWasmVarAddressSpace(unsigned AS)
@ WASM_FEATURE_PREFIX_USED
Definition: Wasm.h:168
@ WASM_FEATURE_PREFIX_REQUIRED
Definition: Wasm.h:169
@ WASM_FEATURE_PREFIX_DISALLOWED
Definition: Wasm.h:170
@ WASM_SYMBOL_TYPE_GLOBAL
Definition: Wasm.h:210
@ WASM_SYMBOL_TYPE_DATA
Definition: Wasm.h:209
@ WASM_SYMBOL_TYPE_TAG
Definition: Wasm.h:212
@ WASM_SYMBOL_TYPE_TABLE
Definition: Wasm.h:213
@ WASM_SYMBOL_TYPE_FUNCTION
Definition: Wasm.h:208
@ WASM_TYPE_I64
Definition: Wasm.h:55
@ WASM_TYPE_I32
Definition: Wasm.h:54
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
void computeSignatureVTs(const FunctionType *Ty, const Function *TargetFunc, const Function &ContextFunc, const TargetMachine &TM, SmallVectorImpl< MVT > &Params, SmallVectorImpl< MVT > &Results)
const SubtargetFeatureKV WebAssemblyFeatureKV[WebAssembly::NumSubtargetFeatures]
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.
void valTypesFromMVTs(const ArrayRef< MVT > &In, SmallVectorImpl< wasm::ValType > &Out)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
Target & getTheWebAssemblyTarget32()
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:156
std::unique_ptr< wasm::WasmSignature > signatureFromMVTs(const SmallVectorImpl< MVT > &Results, const SmallVectorImpl< MVT > &Params)
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
Target & getTheWebAssemblyTarget64()
void getLibcallSignature(const WebAssemblySubtarget &Subtarget, RTLIB::Libcall LC, SmallVectorImpl< wasm::ValType > &Rets, SmallVectorImpl< wasm::ValType > &Params)
void computeLegalValueVTs(const WebAssemblyTargetLowering &TLI, LLVMContext &Ctx, const DataLayout &DL, Type *Ty, SmallVectorImpl< MVT > &ValueVTs)
@ MCSA_NoDeadStrip
.no_dead_strip (MachO)
Definition: MCDirectives.h:39
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:485
SmallVector< ValType, 4 > Params
Definition: Wasm.h:486