LLVM 22.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"
39#include "llvm/IR/DataLayout.h"
42#include "llvm/IR/Metadata.h"
43#include "llvm/IR/Module.h"
44#include "llvm/MC/MCContext.h"
46#include "llvm/MC/MCStreamer.h"
47#include "llvm/MC/MCSymbol.h"
51#include "llvm/Support/Debug.h"
53
54using namespace llvm;
55
56#define DEBUG_TYPE "asm-printer"
57
59
60//===----------------------------------------------------------------------===//
61// Helpers.
62//===----------------------------------------------------------------------===//
63
65 const TargetRegisterInfo *TRI = Subtarget->getRegisterInfo();
66 const TargetRegisterClass *TRC = MRI->getRegClass(RegNo);
67 for (MVT T : {MVT::i32, MVT::i64, MVT::f32, MVT::f64, MVT::v16i8, MVT::v8i16,
68 MVT::v4i32, MVT::v2i64, MVT::v4f32, MVT::v2f64, MVT::v8f16})
69 if (TRI->isTypeLegalForClass(*TRC, T))
70 return T;
71 LLVM_DEBUG(errs() << "Unknown type for register number: " << RegNo);
72 llvm_unreachable("Unknown register type");
73 return MVT::Other;
74}
75
77 Register RegNo = MO.getReg();
78 assert(RegNo.isVirtual() &&
79 "Unlowered physical register encountered during assembly printing");
80 assert(!MFI->isVRegStackified(RegNo));
81 unsigned WAReg = MFI->getWAReg(RegNo);
83 return '$' + utostr(WAReg);
84}
85
90
91// Emscripten exception handling helpers
92//
93// This converts invoke names generated by LowerEmscriptenEHSjLj to real names
94// that are expected by JavaScript glue code. The invoke names generated by
95// Emscripten JS glue code are based on their argument and return types; for
96// example, for a function that takes an i32 and returns nothing, it is
97// 'invoke_vi'. But the format of invoke generated by LowerEmscriptenEHSjLj pass
98// contains a mangled string generated from their IR types, for example,
99// "__invoke_void_%struct.mystruct*_int", because final wasm types are not
100// available in the IR pass. So we convert those names to the form that
101// Emscripten JS code expects.
102//
103// Refer to LowerEmscriptenEHSjLj pass for more details.
104
105// Returns true if the given function name is an invoke name generated by
106// LowerEmscriptenEHSjLj pass.
108 if (Name.front() == '"' && Name.back() == '"')
109 Name = Name.substr(1, Name.size() - 2);
110 return Name.starts_with("__invoke_");
111}
112
113// Returns a character that represents the given wasm value type in invoke
114// signatures.
116 switch (VT) {
118 return 'i';
120 return 'j';
122 return 'f';
124 return 'd';
126 return 'V';
128 return 'F';
130 return 'X';
132 return 'E';
133 default:
134 llvm_unreachable("Unhandled wasm::ValType enum");
135 }
136}
137
138// Given the wasm signature, generate the invoke name in the format JS glue code
139// expects.
141 assert(Sig->Returns.size() <= 1);
142 std::string Ret = "invoke_";
143 if (!Sig->Returns.empty())
144 for (auto VT : Sig->Returns)
145 Ret += getInvokeSig(VT);
146 else
147 Ret += 'v';
148 // Invokes' first argument is a pointer to the original function, so skip it
149 for (unsigned I = 1, E = Sig->Params.size(); I < E; I++)
150 Ret += getInvokeSig(Sig->Params[I]);
151 return Ret;
152}
153
154//===----------------------------------------------------------------------===//
155// WebAssemblyAsmPrinter Implementation.
156//===----------------------------------------------------------------------===//
157
159 const Function *F, wasm::WasmSignature *Sig, bool &InvokeDetected) {
160 MCSymbolWasm *WasmSym = nullptr;
161
162 const bool EnableEmEH =
164 if (EnableEmEH && isEmscriptenInvokeName(F->getName())) {
165 assert(Sig);
166 InvokeDetected = true;
167 if (Sig->Returns.size() > 1) {
168 std::string Msg =
169 "Emscripten EH/SjLj does not support multivalue returns: " +
170 std::string(F->getName()) + ": " +
173 }
174 WasmSym = static_cast<MCSymbolWasm *>(
176 } else {
177 WasmSym = static_cast<MCSymbolWasm *>(getSymbol(F));
178 }
179 return WasmSym;
180}
181
185 return;
186 }
187
188 assert(!GV->isThreadLocal());
189 auto *Sym = static_cast<MCSymbolWasm *>(getSymbol(GV));
190 if (!Sym->getType()) {
192 Type *GlobalVT = GV->getValueType();
193 if (Subtarget) {
194 // Subtarget is only set when a function is defined, because
195 // each function can declare a different subtarget. For example,
196 // on ARM a compilation unit might have a function on ARM and
197 // another on Thumb. Therefore only if Subtarget is non-null we
198 // can actually calculate the legal VTs.
199 const WebAssemblyTargetLowering &TLI = *Subtarget->getTargetLowering();
201 GV->getDataLayout(), GlobalVT, VTs);
202 }
203 WebAssembly::wasmSymbolSetType(Sym, GlobalVT, VTs);
204 }
205
206 emitVisibility(Sym, GV->getVisibility(), !GV->isDeclaration());
207 emitSymbolType(Sym);
208 if (GV->hasInitializer()) {
209 assert(getSymbolPreferLocal(*GV) == Sym);
210 emitLinkage(GV, Sym);
211 OutStreamer->emitLabel(Sym);
212 // TODO: Actually emit the initializer value. Otherwise the global has the
213 // default value for its type (0, ref.null, etc).
214 OutStreamer->addBlankLine();
215 }
216}
217
219 auto *WasmSym = static_cast<MCSymbolWasm *>(GetExternalSymbolSymbol(Name));
220 // May be called multiple times, so early out.
221 if (WasmSym->getType())
222 return WasmSym;
223
224 const WebAssemblySubtarget &Subtarget = getSubtarget();
225
226 // Except for certain known symbols, all symbols used by CodeGen are
227 // functions. It's OK to hardcode knowledge of specific symbols here; this
228 // method is precisely there for fetching the signatures of known
229 // Clang-provided symbols.
230 if (Name == "__stack_pointer" || Name == "__tls_base" ||
231 Name == "__memory_base" || Name == "__table_base" ||
232 Name == "__tls_size" || Name == "__tls_align") {
233 bool Mutable =
234 Name == "__stack_pointer" || Name == "__tls_base";
235 WasmSym->setType(wasm::WASM_SYMBOL_TYPE_GLOBAL);
236 WasmSym->setGlobalType(wasm::WasmGlobalType{
237 uint8_t(Subtarget.hasAddr64() ? wasm::WASM_TYPE_I64
239 Mutable});
240 return WasmSym;
241 }
242
243 if (Name.starts_with("GCC_except_table")) {
244 WasmSym->setType(wasm::WASM_SYMBOL_TYPE_DATA);
245 return WasmSym;
246 }
247
250 if (Name == "__cpp_exception" || Name == "__c_longjmp") {
251 WasmSym->setType(wasm::WASM_SYMBOL_TYPE_TAG);
252 WasmSym->setExternal(true);
253
254 // Currently both C++ exceptions and C longjmps have a single pointer type
255 // param. For C++ exceptions it is a pointer to an exception object, and for
256 // C longjmps it is pointer to a struct that contains a setjmp buffer and a
257 // longjmp return value. We may consider using multiple value parameters for
258 // longjmps later when multivalue support is ready.
259 wasm::ValType AddrType =
260 Subtarget.hasAddr64() ? wasm::ValType::I64 : wasm::ValType::I32;
261 Params.push_back(AddrType);
262 } else { // Function symbols
263 WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
264 WebAssembly::getLibcallSignature(Subtarget, Name, Returns, Params);
265 }
266 auto Signature = OutContext.createWasmSignature();
267 Signature->Returns = std::move(Returns);
268 Signature->Params = std::move(Params);
269 WasmSym->setSignature(Signature);
270
271 return WasmSym;
272}
273
275 std::optional<wasm::WasmSymbolType> WasmTy = Sym->getType();
276 if (!WasmTy)
277 return;
278
279 switch (*WasmTy) {
282 break;
285 break;
288 break;
289 default:
290 break; // We only handle globals, tags and tables here
291 }
292}
293
295 if (signaturesEmitted)
296 return;
297 signaturesEmitted = true;
298
299 // Normally symbols for globals get discovered as the MI gets lowered,
300 // but we need to know about them ahead of time. This will however,
301 // only find symbols that have been used. Unused symbols from globals will
302 // not be found here.
303 MachineModuleInfoWasm &MMIW = MMI->getObjFileInfo<MachineModuleInfoWasm>();
304 for (StringRef Name : MMIW.MachineSymbolsUsed) {
305 auto *WasmSym = static_cast<MCSymbolWasm *>(getOrCreateWasmSymbol(Name));
306 if (WasmSym->isFunction()) {
307 // TODO(wvo): is there any case where this overlaps with the call to
308 // emitFunctionType in the loop below?
310 }
311 }
312
313 for (auto &It : OutContext.getSymbols()) {
314 // Emit .globaltype, .tagtype, or .tabletype declarations for extern
315 // declarations, i.e. those that have only been declared (but not defined)
316 // in the current module
317 auto Sym = static_cast<MCSymbolWasm *>(It.getValue().Symbol);
318 if (Sym && !Sym->isDefined())
319 emitSymbolType(Sym);
320 }
321
322 DenseSet<MCSymbol *> InvokeSymbols;
323 for (const auto &F : M) {
324 if (F.isIntrinsic())
325 continue;
326
327 // Emit function type info for all functions. This will emit duplicate
328 // information for defined functions (which already have function type
329 // info emitted alongside their definition), but this is necessary in
330 // order to enable the single-pass WebAssemblyAsmTypeCheck to succeed.
332 SmallVector<MVT, 4> Params;
333 computeSignatureVTs(F.getFunctionType(), &F, F, TM, Params, Results);
334 // At this point these MCSymbols may or may not have been created already
335 // and thus also contain a signature, but we need to get the signature
336 // anyway here in case it is an invoke that has not yet been created. We
337 // will discard it later if it turns out not to be necessary.
338 auto Signature = signatureFromMVTs(OutContext, Results, Params);
339 bool InvokeDetected = false;
340 auto *Sym = getMCSymbolForFunction(&F, Signature, InvokeDetected);
341
342 // Multiple functions can be mapped to the same invoke symbol. For
343 // example, two IR functions '__invoke_void_i8*' and '__invoke_void_i32'
344 // are both mapped to '__invoke_vi'. We keep them in a set once we emit an
345 // Emscripten EH symbol so we don't emit the same symbol twice.
346 if (InvokeDetected && !InvokeSymbols.insert(Sym).second)
347 continue;
348
350 if (!Sym->getSignature()) {
351 Sym->setSignature(Signature);
352 }
353
355
356 if (F.hasFnAttribute("wasm-import-module")) {
357 StringRef Name =
358 F.getFnAttribute("wasm-import-module").getValueAsString();
359 Sym->setImportModule(OutContext.allocateString(Name));
361 }
362 if (F.hasFnAttribute("wasm-import-name")) {
363 // If this is a converted Emscripten EH/SjLj symbol, we shouldn't use
364 // the original function name but the converted symbol name.
365 StringRef Name =
366 InvokeDetected
367 ? Sym->getName()
368 : F.getFnAttribute("wasm-import-name").getValueAsString();
369 Sym->setImportName(OutContext.allocateString(Name));
370 getTargetStreamer()->emitImportName(Sym, Name);
371 }
372
373 if (F.hasFnAttribute("wasm-export-name")) {
374 auto *Sym = static_cast<MCSymbolWasm *>(getSymbol(&F));
375 StringRef Name = F.getFnAttribute("wasm-export-name").getValueAsString();
376 Sym->setExportName(OutContext.allocateString(Name));
377 getTargetStreamer()->emitExportName(Sym, Name);
378 }
379 }
380}
381
383 // This is required to emit external declarations (like .functypes) when
384 // no functions are defined in the compilation unit and therefore,
385 // emitDecls() is not called until now.
386 emitDecls(M);
387
388 // When a function's address is taken, a TABLE_INDEX relocation is emitted
389 // against the function symbol at the use site. However the relocation
390 // doesn't explicitly refer to the table. In the future we may want to
391 // define a new kind of reloc against both the function and the table, so
392 // that the linker can see that the function symbol keeps the table alive,
393 // but for now manually mark the table as live.
394 for (const auto &F : M) {
395 if (!F.isIntrinsic() && F.hasAddressTaken()) {
396 MCSymbolWasm *FunctionTable =
398 OutStreamer->emitSymbolAttribute(FunctionTable, MCSA_NoDeadStrip);
399 break;
400 }
401 }
402
403 for (const auto &G : M.globals()) {
404 if (!G.hasInitializer() && G.hasExternalLinkage() &&
405 !WebAssembly::isWasmVarAddressSpace(G.getAddressSpace()) &&
406 G.getValueType()->isSized()) {
407 uint16_t Size = M.getDataLayout().getTypeAllocSize(G.getValueType());
408 OutStreamer->emitELFSize(getSymbol(&G),
410 }
411 }
412
413 if (const NamedMDNode *Named = M.getNamedMetadata("wasm.custom_sections")) {
414 for (const Metadata *MD : Named->operands()) {
415 const auto *Tuple = dyn_cast<MDTuple>(MD);
416 if (!Tuple || Tuple->getNumOperands() != 2)
417 continue;
418 const MDString *Name = dyn_cast<MDString>(Tuple->getOperand(0));
419 const MDString *Contents = dyn_cast<MDString>(Tuple->getOperand(1));
420 if (!Name || !Contents)
421 continue;
422
423 OutStreamer->pushSection();
424 std::string SectionName = (".custom_section." + Name->getString()).str();
425 MCSectionWasm *MySection =
427 OutStreamer->switchSection(MySection);
428 OutStreamer->emitBytes(Contents->getString());
429 OutStreamer->popSection();
430 }
431 }
432
436}
437
440 if (const NamedMDNode *Debug = M.getNamedMetadata("llvm.dbg.cu")) {
441 llvm::SmallSet<StringRef, 4> SeenLanguages;
442 for (size_t I = 0, E = Debug->getNumOperands(); I < E; ++I) {
443 const auto *CU = cast<DICompileUnit>(Debug->getOperand(I));
444 StringRef Language = dwarf::LanguageString(CU->getSourceLanguage());
445 Language.consume_front("DW_LANG_");
446 if (SeenLanguages.insert(Language).second)
447 Languages.emplace_back(Language.str(), "");
448 }
449 }
450
452 if (const NamedMDNode *Ident = M.getNamedMetadata("llvm.ident")) {
454 for (size_t I = 0, E = Ident->getNumOperands(); I < E; ++I) {
455 const auto *S = cast<MDString>(Ident->getOperand(I)->getOperand(0));
456 std::pair<StringRef, StringRef> Field = S->getString().split("version");
457 StringRef Name = Field.first.trim();
458 StringRef Version = Field.second.trim();
459 if (SeenTools.insert(Name).second)
460 Tools.emplace_back(Name.str(), Version.str());
461 }
462 }
463
464 int FieldCount = int(!Languages.empty()) + int(!Tools.empty());
465 if (FieldCount != 0) {
466 MCSectionWasm *Producers = OutContext.getWasmSection(
467 ".custom_section.producers", SectionKind::getMetadata());
468 OutStreamer->pushSection();
469 OutStreamer->switchSection(Producers);
470 OutStreamer->emitULEB128IntValue(FieldCount);
471 for (auto &Producers : {std::make_pair("language", &Languages),
472 std::make_pair("processed-by", &Tools)}) {
473 if (Producers.second->empty())
474 continue;
475 OutStreamer->emitULEB128IntValue(strlen(Producers.first));
476 OutStreamer->emitBytes(Producers.first);
477 OutStreamer->emitULEB128IntValue(Producers.second->size());
478 for (auto &Producer : *Producers.second) {
479 OutStreamer->emitULEB128IntValue(Producer.first.size());
480 OutStreamer->emitBytes(Producer.first);
481 OutStreamer->emitULEB128IntValue(Producer.second.size());
482 OutStreamer->emitBytes(Producer.second);
483 }
484 }
485 OutStreamer->popSection();
486 }
487}
488
490 struct FeatureEntry {
491 uint8_t Prefix;
492 std::string Name;
493 };
494
495 // Read target features and linkage policies from module metadata
496 SmallVector<FeatureEntry, 4> EmittedFeatures;
497 auto EmitFeature = [&](std::string Feature) {
498 std::string MDKey = (StringRef("wasm-feature-") + Feature).str();
499 Metadata *Policy = M.getModuleFlag(MDKey);
500 if (Policy == nullptr)
501 return;
502
503 FeatureEntry Entry;
504 Entry.Prefix = 0;
505 Entry.Name = Feature;
506
507 if (auto *MD = cast<ConstantAsMetadata>(Policy))
508 if (auto *I = cast<ConstantInt>(MD->getValue()))
509 Entry.Prefix = I->getZExtValue();
510
511 // Silently ignore invalid metadata
512 if (Entry.Prefix != wasm::WASM_FEATURE_PREFIX_USED &&
514 return;
515
516 EmittedFeatures.push_back(Entry);
517 };
518
519 for (const SubtargetFeatureKV &KV : WebAssemblyFeatureKV) {
520 EmitFeature(KV.Key);
521 }
522 // This pseudo-feature tells the linker whether shared memory would be safe
523 EmitFeature("shared-mem");
524
525 // This is an "architecture", not a "feature", but we emit it as such for
526 // the benefit of tools like Binaryen and consistency with other producers.
527 // FIXME: Subtarget is null here, so can't Subtarget->hasAddr64() ?
528 if (M.getDataLayout().getPointerSize() == 8) {
529 // Can't use EmitFeature since "wasm-feature-memory64" is not a module
530 // flag.
531 EmittedFeatures.push_back({wasm::WASM_FEATURE_PREFIX_USED, "memory64"});
532 }
533
534 if (EmittedFeatures.size() == 0)
535 return;
536
537 // Emit features and linkage policies into the "target_features" section
538 MCSectionWasm *FeaturesSection = OutContext.getWasmSection(
539 ".custom_section.target_features", SectionKind::getMetadata());
540 OutStreamer->pushSection();
541 OutStreamer->switchSection(FeaturesSection);
542
543 OutStreamer->emitULEB128IntValue(EmittedFeatures.size());
544 for (auto &F : EmittedFeatures) {
545 OutStreamer->emitIntValue(F.Prefix, 1);
546 OutStreamer->emitULEB128IntValue(F.Name.size());
547 OutStreamer->emitBytes(F.Name);
548 }
549
550 OutStreamer->popSection();
551}
552
554 auto V = M.getNamedGlobal("llvm.global.annotations");
555 if (!V)
556 return;
557
558 // Group all the custom attributes by name.
560 const ConstantArray *CA = cast<ConstantArray>(V->getOperand(0));
561 for (Value *Op : CA->operands()) {
562 auto *CS = cast<ConstantStruct>(Op);
563 // The first field is a pointer to the annotated variable.
564 Value *AnnotatedVar = CS->getOperand(0)->stripPointerCasts();
565 // Only annotated functions are supported for now.
566 if (!isa<Function>(AnnotatedVar))
567 continue;
568 auto *F = cast<Function>(AnnotatedVar);
569
570 // The second field is a pointer to a global annotation string.
571 auto *GV = cast<GlobalVariable>(CS->getOperand(1)->stripPointerCasts());
572 StringRef AnnotationString;
573 getConstantStringInfo(GV, AnnotationString);
574 auto *Sym = static_cast<MCSymbolWasm *>(getSymbol(F));
575 CustomSections[AnnotationString].push_back(Sym);
576 }
577
578 // Emit a custom section for each unique attribute.
579 for (const auto &[Name, Symbols] : CustomSections) {
580 MCSectionWasm *CustomSection = OutContext.getWasmSection(
581 ".custom_section.llvm.func_attr.annotate." + Name, SectionKind::getMetadata());
582 OutStreamer->pushSection();
583 OutStreamer->switchSection(CustomSection);
584
585 for (auto &Sym : Symbols) {
586 OutStreamer->emitValue(
588 4);
589 }
590 OutStreamer->popSection();
591 }
592}
593
595 emitDecls(*MMI->getModule());
596 assert(MF->getConstantPool()->getConstants().empty() &&
597 "WebAssembly disables constant pools");
598}
599
601 // Nothing to do; jump tables are incorporated into the instruction stream.
602}
603
605 const Function &F = MF->getFunction();
606 SmallVector<MVT, 1> ResultVTs;
607 SmallVector<MVT, 4> ParamVTs;
608 computeSignatureVTs(F.getFunctionType(), &F, F, TM, ParamVTs, ResultVTs);
609
610 auto Signature = signatureFromMVTs(OutContext, ResultVTs, ParamVTs);
611 auto *WasmSym = static_cast<MCSymbolWasm *>(CurrentFnSym);
612 WasmSym->setSignature(Signature);
613 WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
614
616
617 // Emit the function index.
618 if (MDNode *Idx = F.getMetadata("wasm.index")) {
619 assert(Idx->getNumOperands() == 1);
620
622 cast<ConstantAsMetadata>(Idx->getOperand(0))->getValue()));
623 }
624
626 valTypesFromMVTs(MFI->getLocals(), Locals);
627 getTargetStreamer()->emitLocal(Locals);
628
630}
631
633 LLVM_DEBUG(dbgs() << "EmitInstruction: " << *MI << '\n');
634 WebAssembly_MC::verifyInstructionPredicates(MI->getOpcode(),
635 Subtarget->getFeatureBits());
636
637 switch (MI->getOpcode()) {
638 case WebAssembly::ARGUMENT_i32:
639 case WebAssembly::ARGUMENT_i32_S:
640 case WebAssembly::ARGUMENT_i64:
641 case WebAssembly::ARGUMENT_i64_S:
642 case WebAssembly::ARGUMENT_f32:
643 case WebAssembly::ARGUMENT_f32_S:
644 case WebAssembly::ARGUMENT_f64:
645 case WebAssembly::ARGUMENT_f64_S:
646 case WebAssembly::ARGUMENT_v16i8:
647 case WebAssembly::ARGUMENT_v16i8_S:
648 case WebAssembly::ARGUMENT_v8i16:
649 case WebAssembly::ARGUMENT_v8i16_S:
650 case WebAssembly::ARGUMENT_v4i32:
651 case WebAssembly::ARGUMENT_v4i32_S:
652 case WebAssembly::ARGUMENT_v2i64:
653 case WebAssembly::ARGUMENT_v2i64_S:
654 case WebAssembly::ARGUMENT_v4f32:
655 case WebAssembly::ARGUMENT_v4f32_S:
656 case WebAssembly::ARGUMENT_v2f64:
657 case WebAssembly::ARGUMENT_v2f64_S:
658 case WebAssembly::ARGUMENT_v8f16:
659 case WebAssembly::ARGUMENT_v8f16_S:
660 // These represent values which are live into the function entry, so there's
661 // no instruction to emit.
662 break;
663 case WebAssembly::FALLTHROUGH_RETURN: {
664 // These instructions represent the implicit return at the end of a
665 // function body.
666 if (isVerbose()) {
667 OutStreamer->AddComment("fallthrough-return");
668 OutStreamer->addBlankLine();
669 }
670 break;
671 }
672 case WebAssembly::COMPILER_FENCE:
673 // This is a compiler barrier that prevents instruction reordering during
674 // backend compilation, and should not be emitted.
675 break;
676 case WebAssembly::CATCH:
677 case WebAssembly::CATCH_S:
678 case WebAssembly::CATCH_REF:
679 case WebAssembly::CATCH_REF_S:
680 case WebAssembly::CATCH_ALL:
681 case WebAssembly::CATCH_ALL_S:
682 case WebAssembly::CATCH_ALL_REF:
683 case WebAssembly::CATCH_ALL_REF_S:
684 // These are pseudo instructions to represent catch clauses in try_table
685 // instruction to simulate block return values.
686 break;
687 default: {
688 WebAssemblyMCInstLower MCInstLowering(OutContext, *this);
689 MCInst TmpInst;
690 MCInstLowering.lower(MI, TmpInst);
691 EmitToStreamer(*OutStreamer, TmpInst);
692 break;
693 }
694 }
695}
696
698 unsigned OpNo,
699 const char *ExtraCode,
700 raw_ostream &OS) {
701 // First try the generic code, which knows about modifiers like 'c' and 'n'.
702 if (!AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS))
703 return false;
704
705 if (!ExtraCode) {
706 const MachineOperand &MO = MI->getOperand(OpNo);
707 switch (MO.getType()) {
709 OS << MO.getImm();
710 return false;
712 // FIXME: only opcode that still contains registers, as required by
713 // MachineInstr::getDebugVariable().
714 assert(MI->getOpcode() == WebAssembly::INLINEASM);
715 OS << regToString(MO);
716 return false;
718 PrintSymbolOperand(MO, OS);
719 return false;
722 printOffset(MO.getOffset(), OS);
723 return false;
725 MO.getMBB()->getSymbol()->print(OS, MAI);
726 return false;
727 default:
728 break;
729 }
730 }
731
732 return true;
733}
734
736 unsigned OpNo,
737 const char *ExtraCode,
738 raw_ostream &OS) {
739 // The current approach to inline asm is that "r" constraints are expressed
740 // as local indices, rather than values on the operand stack. This simplifies
741 // using "r" as it eliminates the need to push and pop the values in a
742 // particular order, however it also makes it impossible to have an "m"
743 // constraint. So we don't support it.
744
745 return AsmPrinter::PrintAsmMemoryOperand(MI, OpNo, ExtraCode, OS);
746}
747
749
750INITIALIZE_PASS(WebAssemblyAsmPrinter, "webassembly-asm-printer",
751 "WebAssembly Assmebly Printer", false, false)
752
753// Force static initialization.
755LLVMInitializeWebAssemblyAsmPrinter() {
758}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Function Alias Analysis Results
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_ABI
Definition Compiler.h:213
#define LLVM_EXTERNAL_VISIBILITY
Definition Compiler.h:132
IRTranslator LLVM IR MI
Module.h This file contains the declarations for the Module class.
#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 ...
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
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
This file defines the SmallSet class.
This file contains some functions that are useful when dealing with strings.
#define LLVM_DEBUG(...)
Definition Debug.h:114
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
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.
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:93
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:96
MachineFunction * MF
The current machine function.
Definition AsmPrinter.h:108
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:613
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:127
MachineModuleInfo * MMI
This is a pointer to the current MachineModuleInfo.
Definition AsmPrinter.h:111
MCContext & OutContext
This is the context for the output file that we are streaming.
Definition AsmPrinter.h:100
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:105
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:307
MCSymbol * GetExternalSymbolSymbol(const Twine &Sym) const
Return the MCSymbol for the specified ExternalSymbol.
@ Debug
Emit .debug_frame.
Definition AsmPrinter.h:168
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:433
Implements a dense probed hash-table based set.
Definition DenseSet.h:269
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:328
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:132
Type * getValueType() const
bool hasInitializer() const
Definitions have initializers, declarations don't.
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:214
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:93
Metadata node.
Definition Metadata.h:1077
A single uniqued string.
Definition Metadata.h:720
LLVM_ABI StringRef getString() const
Definition Metadata.cpp:617
Machine Value Type.
LLVM_ABI MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
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:36
Root of the metadata hierarchy.
Definition Metadata.h:63
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
LLVMContext & getContext() const
Get the global data context.
Definition Module.h:285
A tuple of MDNodes.
Definition Metadata.h:1753
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:74
static SectionKind getMetadata()
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
Definition SmallSet.h:133
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:181
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.
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
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:45
op_range operands()
Definition User.h:292
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:701
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:194
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:412
#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.
void wasmSymbolSetType(MCSymbolWasm *Sym, const Type *GlobalVT, ArrayRef< MVT > VTs)
Sets a Wasm Symbol Type.
static const unsigned UnusedReg
cl::opt< bool > WasmEnableEmEH
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:180
@ WASM_FEATURE_PREFIX_DISALLOWED
Definition Wasm.h:181
@ WASM_SYMBOL_TYPE_GLOBAL
Definition Wasm.h:222
@ WASM_SYMBOL_TYPE_DATA
Definition Wasm.h:221
@ WASM_SYMBOL_TYPE_TAG
Definition Wasm.h:224
@ WASM_SYMBOL_TYPE_TABLE
Definition Wasm.h:225
@ WASM_SYMBOL_TYPE_FUNCTION
Definition Wasm.h:220
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)
const SubtargetFeatureKV WebAssemblyFeatureKV[WebAssembly::NumSubtargetFeatures]
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:649
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)
FunctionAddr VTableAddr uintptr_t uintptr_t Version
Definition InstrProf.h:302
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:207
Target & getTheWebAssemblyTarget32()
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:167
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:548
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)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:565
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_NoDeadStrip
.no_dead_strip (MachO)
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:507
SmallVector< ValType, 4 > Params
Definition Wasm.h:508