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
87 MCTargetStreamer *TS = OutStreamer->getTargetStreamer();
88 return static_cast<WebAssemblyTargetStreamer *>(TS);
89}
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
208 if (GV->hasInitializer()) {
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{
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 // In static linking we define tag symbols in WasmException::endModule().
253 // But we may have multiple objects to be linked together, each of which
254 // defines the tag symbols. To resolve them, we declare them as weak. In
255 // dynamic linking we make tag symbols undefined in the backend, define it
256 // in JS, and feed them to each importing module.
258 WasmSym->setWeak(true);
259 WasmSym->setExternal(true);
260
261 // Currently both C++ exceptions and C longjmps have a single pointer type
262 // param. For C++ exceptions it is a pointer to an exception object, and for
263 // C longjmps it is pointer to a struct that contains a setjmp buffer and a
264 // longjmp return value. We may consider using multiple value parameters for
265 // longjmps later when multivalue support is ready.
266 wasm::ValType AddrType =
268 Params.push_back(AddrType);
269 } else { // Function symbols
270 WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
271 WebAssembly::getLibcallSignature(Subtarget, Name, Returns, Params);
272 }
273 auto Signature = OutContext.createWasmSignature();
274 Signature->Returns = std::move(Returns);
275 Signature->Params = std::move(Params);
276 WasmSym->setSignature(Signature);
277
278 return WasmSym;
279}
280
282 std::optional<wasm::WasmSymbolType> WasmTy = Sym->getType();
283 if (!WasmTy)
284 return;
285
286 switch (*WasmTy) {
289 break;
292 break;
295 break;
296 default:
297 break; // We only handle globals, tags and tables here
298 }
299}
300
302 if (signaturesEmitted)
303 return;
304 signaturesEmitted = true;
305
306 // Normally symbols for globals get discovered as the MI gets lowered,
307 // but we need to know about them ahead of time. This will however,
308 // only find symbols that have been used. Unused symbols from globals will
309 // not be found here.
311 for (StringRef Name : MMIW.MachineSymbolsUsed) {
312 auto *WasmSym = static_cast<MCSymbolWasm *>(getOrCreateWasmSymbol(Name));
313 if (WasmSym->isFunction()) {
314 // TODO(wvo): is there any case where this overlaps with the call to
315 // emitFunctionType in the loop below?
317 }
318 }
319
320 for (auto &It : OutContext.getSymbols()) {
321 // Emit .globaltype, .tagtype, or .tabletype declarations for extern
322 // declarations, i.e. those that have only been declared (but not defined)
323 // in the current module
324 auto Sym = static_cast<MCSymbolWasm *>(It.getValue().Symbol);
325 if (Sym && !Sym->isDefined())
327 }
328
329 DenseSet<MCSymbol *> InvokeSymbols;
330 for (const auto &F : M) {
331 if (F.isIntrinsic())
332 continue;
333
334 // Emit function type info for all functions. This will emit duplicate
335 // information for defined functions (which already have function type
336 // info emitted alongside their definition), but this is necessary in
337 // order to enable the single-pass WebAssemblyAsmTypeCheck to succeed.
339 SmallVector<MVT, 4> Params;
340 computeSignatureVTs(F.getFunctionType(), &F, F, TM, Params, Results);
341 // At this point these MCSymbols may or may not have been created already
342 // and thus also contain a signature, but we need to get the signature
343 // anyway here in case it is an invoke that has not yet been created. We
344 // will discard it later if it turns out not to be necessary.
345 auto Signature = signatureFromMVTs(OutContext, Results, Params);
346 bool InvokeDetected = false;
347 auto *Sym = getMCSymbolForFunction(&F, Signature, InvokeDetected);
348
349 // Multiple functions can be mapped to the same invoke symbol. For
350 // example, two IR functions '__invoke_void_i8*' and '__invoke_void_i32'
351 // are both mapped to '__invoke_vi'. We keep them in a set once we emit an
352 // Emscripten EH symbol so we don't emit the same symbol twice.
353 if (InvokeDetected && !InvokeSymbols.insert(Sym).second)
354 continue;
355
357 if (!Sym->getSignature()) {
358 Sym->setSignature(Signature);
359 }
360
362
363 if (F.hasFnAttribute("wasm-import-module")) {
365 F.getFnAttribute("wasm-import-module").getValueAsString();
366 Sym->setImportModule(OutContext.allocateString(Name));
368 }
369 if (F.hasFnAttribute("wasm-import-name")) {
370 // If this is a converted Emscripten EH/SjLj symbol, we shouldn't use
371 // the original function name but the converted symbol name.
373 InvokeDetected
374 ? Sym->getName()
375 : F.getFnAttribute("wasm-import-name").getValueAsString();
376 Sym->setImportName(OutContext.allocateString(Name));
378 }
379
380 if (F.hasFnAttribute("wasm-export-name")) {
381 auto *Sym = static_cast<MCSymbolWasm *>(getSymbol(&F));
382 StringRef Name = F.getFnAttribute("wasm-export-name").getValueAsString();
383 Sym->setExportName(OutContext.allocateString(Name));
385 }
386 }
387}
388
390 // This is required to emit external declarations (like .functypes) when
391 // no functions are defined in the compilation unit and therefore,
392 // emitDecls() is not called until now.
393 emitDecls(M);
394
395 // When a function's address is taken, a TABLE_INDEX relocation is emitted
396 // against the function symbol at the use site. However the relocation
397 // doesn't explicitly refer to the table. In the future we may want to
398 // define a new kind of reloc against both the function and the table, so
399 // that the linker can see that the function symbol keeps the table alive,
400 // but for now manually mark the table as live.
401 for (const auto &F : M) {
402 if (!F.isIntrinsic() && F.hasAddressTaken()) {
403 MCSymbolWasm *FunctionTable =
405 OutStreamer->emitSymbolAttribute(FunctionTable, MCSA_NoDeadStrip);
406 break;
407 }
408 }
409
410 for (const auto &G : M.globals()) {
411 if (!G.hasInitializer() && G.hasExternalLinkage() &&
412 !WebAssembly::isWasmVarAddressSpace(G.getAddressSpace()) &&
413 G.getValueType()->isSized()) {
414 uint16_t Size = M.getDataLayout().getTypeAllocSize(G.getValueType());
415 OutStreamer->emitELFSize(getSymbol(&G),
417 }
418 }
419
420 if (const NamedMDNode *Named = M.getNamedMetadata("wasm.custom_sections")) {
421 for (const Metadata *MD : Named->operands()) {
422 const auto *Tuple = dyn_cast<MDTuple>(MD);
423 if (!Tuple || Tuple->getNumOperands() != 2)
424 continue;
425 const MDString *Name = dyn_cast<MDString>(Tuple->getOperand(0));
426 const MDString *Contents = dyn_cast<MDString>(Tuple->getOperand(1));
427 if (!Name || !Contents)
428 continue;
429
430 OutStreamer->pushSection();
431 std::string SectionName = (".custom_section." + Name->getString()).str();
432 MCSectionWasm *MySection =
434 OutStreamer->switchSection(MySection);
435 OutStreamer->emitBytes(Contents->getString());
436 OutStreamer->popSection();
437 }
438 }
439
443}
444
447 if (const NamedMDNode *Debug = M.getNamedMetadata("llvm.dbg.cu")) {
448 llvm::SmallSet<StringRef, 4> SeenLanguages;
449 for (size_t I = 0, E = Debug->getNumOperands(); I < E; ++I) {
450 const auto *CU = cast<DICompileUnit>(Debug->getOperand(I));
451 StringRef Language = dwarf::LanguageString(CU->getSourceLanguage());
452 Language.consume_front("DW_LANG_");
453 if (SeenLanguages.insert(Language).second)
454 Languages.emplace_back(Language.str(), "");
455 }
456 }
457
459 if (const NamedMDNode *Ident = M.getNamedMetadata("llvm.ident")) {
461 for (size_t I = 0, E = Ident->getNumOperands(); I < E; ++I) {
462 const auto *S = cast<MDString>(Ident->getOperand(I)->getOperand(0));
463 std::pair<StringRef, StringRef> Field = S->getString().split("version");
464 StringRef Name = Field.first.trim();
465 StringRef Version = Field.second.trim();
466 if (SeenTools.insert(Name).second)
467 Tools.emplace_back(Name.str(), Version.str());
468 }
469 }
470
471 int FieldCount = int(!Languages.empty()) + int(!Tools.empty());
472 if (FieldCount != 0) {
474 ".custom_section.producers", SectionKind::getMetadata());
475 OutStreamer->pushSection();
476 OutStreamer->switchSection(Producers);
477 OutStreamer->emitULEB128IntValue(FieldCount);
478 for (auto &Producers : {std::make_pair("language", &Languages),
479 std::make_pair("processed-by", &Tools)}) {
480 if (Producers.second->empty())
481 continue;
482 OutStreamer->emitULEB128IntValue(strlen(Producers.first));
483 OutStreamer->emitBytes(Producers.first);
484 OutStreamer->emitULEB128IntValue(Producers.second->size());
485 for (auto &Producer : *Producers.second) {
486 OutStreamer->emitULEB128IntValue(Producer.first.size());
487 OutStreamer->emitBytes(Producer.first);
488 OutStreamer->emitULEB128IntValue(Producer.second.size());
489 OutStreamer->emitBytes(Producer.second);
490 }
491 }
492 OutStreamer->popSection();
493 }
494}
495
497 struct FeatureEntry {
498 uint8_t Prefix;
499 std::string Name;
500 };
501
502 // Read target features and linkage policies from module metadata
503 SmallVector<FeatureEntry, 4> EmittedFeatures;
504 auto EmitFeature = [&](std::string Feature) {
505 std::string MDKey = (StringRef("wasm-feature-") + Feature).str();
506 Metadata *Policy = M.getModuleFlag(MDKey);
507 if (Policy == nullptr)
508 return;
509
510 FeatureEntry Entry;
511 Entry.Prefix = 0;
512 Entry.Name = Feature;
513
514 if (auto *MD = cast<ConstantAsMetadata>(Policy))
515 if (auto *I = cast<ConstantInt>(MD->getValue()))
516 Entry.Prefix = I->getZExtValue();
517
518 // Silently ignore invalid metadata
519 if (Entry.Prefix != wasm::WASM_FEATURE_PREFIX_USED &&
521 return;
522
523 EmittedFeatures.push_back(Entry);
524 };
525
526 for (const SubtargetFeatureKV &KV : WebAssemblyFeatureKV) {
527 EmitFeature(KV.Key);
528 }
529 // This pseudo-feature tells the linker whether shared memory would be safe
530 EmitFeature("shared-mem");
531
532 // This is an "architecture", not a "feature", but we emit it as such for
533 // the benefit of tools like Binaryen and consistency with other producers.
534 // FIXME: Subtarget is null here, so can't Subtarget->hasAddr64() ?
535 if (M.getDataLayout().getPointerSize() == 8) {
536 // Can't use EmitFeature since "wasm-feature-memory64" is not a module
537 // flag.
538 EmittedFeatures.push_back({wasm::WASM_FEATURE_PREFIX_USED, "memory64"});
539 }
540
541 if (EmittedFeatures.size() == 0)
542 return;
543
544 // Emit features and linkage policies into the "target_features" section
545 MCSectionWasm *FeaturesSection = OutContext.getWasmSection(
546 ".custom_section.target_features", SectionKind::getMetadata());
547 OutStreamer->pushSection();
548 OutStreamer->switchSection(FeaturesSection);
549
550 OutStreamer->emitULEB128IntValue(EmittedFeatures.size());
551 for (auto &F : EmittedFeatures) {
552 OutStreamer->emitIntValue(F.Prefix, 1);
553 OutStreamer->emitULEB128IntValue(F.Name.size());
554 OutStreamer->emitBytes(F.Name);
555 }
556
557 OutStreamer->popSection();
558}
559
561 auto V = M.getNamedGlobal("llvm.global.annotations");
562 if (!V)
563 return;
564
565 // Group all the custom attributes by name.
567 const ConstantArray *CA = cast<ConstantArray>(V->getOperand(0));
568 for (Value *Op : CA->operands()) {
569 auto *CS = cast<ConstantStruct>(Op);
570 // The first field is a pointer to the annotated variable.
571 Value *AnnotatedVar = CS->getOperand(0)->stripPointerCasts();
572 // Only annotated functions are supported for now.
573 if (!isa<Function>(AnnotatedVar))
574 continue;
575 auto *F = cast<Function>(AnnotatedVar);
576
577 // The second field is a pointer to a global annotation string.
578 auto *GV = cast<GlobalVariable>(CS->getOperand(1)->stripPointerCasts());
579 StringRef AnnotationString;
580 getConstantStringInfo(GV, AnnotationString);
581 auto *Sym = static_cast<MCSymbolWasm *>(getSymbol(F));
582 CustomSections[AnnotationString].push_back(Sym);
583 }
584
585 // Emit a custom section for each unique attribute.
586 for (const auto &[Name, Symbols] : CustomSections) {
587 MCSectionWasm *CustomSection = OutContext.getWasmSection(
588 ".custom_section.llvm.func_attr.annotate." + Name, SectionKind::getMetadata());
589 OutStreamer->pushSection();
590 OutStreamer->switchSection(CustomSection);
591
592 for (auto &Sym : Symbols) {
593 OutStreamer->emitValue(
595 4);
596 }
597 OutStreamer->popSection();
598 }
599}
600
603 assert(MF->getConstantPool()->getConstants().empty() &&
604 "WebAssembly disables constant pools");
605}
606
608 // Nothing to do; jump tables are incorporated into the instruction stream.
609}
610
612 const Function &F = MF->getFunction();
613 SmallVector<MVT, 1> ResultVTs;
614 SmallVector<MVT, 4> ParamVTs;
615 computeSignatureVTs(F.getFunctionType(), &F, F, TM, ParamVTs, ResultVTs);
616
617 auto Signature = signatureFromMVTs(OutContext, ResultVTs, ParamVTs);
618 auto *WasmSym = static_cast<MCSymbolWasm *>(CurrentFnSym);
619 WasmSym->setSignature(Signature);
620 WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
621
623
624 // Emit the function index.
625 if (MDNode *Idx = F.getMetadata("wasm.index")) {
626 assert(Idx->getNumOperands() == 1);
627
629 cast<ConstantAsMetadata>(Idx->getOperand(0))->getValue()));
630 }
631
633 valTypesFromMVTs(MFI->getLocals(), Locals);
634 getTargetStreamer()->emitLocal(Locals);
635
637}
638
640 LLVM_DEBUG(dbgs() << "EmitInstruction: " << *MI << '\n');
641 WebAssembly_MC::verifyInstructionPredicates(MI->getOpcode(),
642 Subtarget->getFeatureBits());
643
644 switch (MI->getOpcode()) {
645 case WebAssembly::ARGUMENT_i32:
646 case WebAssembly::ARGUMENT_i32_S:
647 case WebAssembly::ARGUMENT_i64:
648 case WebAssembly::ARGUMENT_i64_S:
649 case WebAssembly::ARGUMENT_f32:
650 case WebAssembly::ARGUMENT_f32_S:
651 case WebAssembly::ARGUMENT_f64:
652 case WebAssembly::ARGUMENT_f64_S:
653 case WebAssembly::ARGUMENT_v16i8:
654 case WebAssembly::ARGUMENT_v16i8_S:
655 case WebAssembly::ARGUMENT_v8i16:
656 case WebAssembly::ARGUMENT_v8i16_S:
657 case WebAssembly::ARGUMENT_v4i32:
658 case WebAssembly::ARGUMENT_v4i32_S:
659 case WebAssembly::ARGUMENT_v2i64:
660 case WebAssembly::ARGUMENT_v2i64_S:
661 case WebAssembly::ARGUMENT_v4f32:
662 case WebAssembly::ARGUMENT_v4f32_S:
663 case WebAssembly::ARGUMENT_v2f64:
664 case WebAssembly::ARGUMENT_v2f64_S:
665 case WebAssembly::ARGUMENT_v8f16:
666 case WebAssembly::ARGUMENT_v8f16_S:
667 // These represent values which are live into the function entry, so there's
668 // no instruction to emit.
669 break;
670 case WebAssembly::FALLTHROUGH_RETURN: {
671 // These instructions represent the implicit return at the end of a
672 // function body.
673 if (isVerbose()) {
674 OutStreamer->AddComment("fallthrough-return");
675 OutStreamer->addBlankLine();
676 }
677 break;
678 }
679 case WebAssembly::COMPILER_FENCE:
680 // This is a compiler barrier that prevents instruction reordering during
681 // backend compilation, and should not be emitted.
682 break;
683 case WebAssembly::CATCH:
684 case WebAssembly::CATCH_S:
685 case WebAssembly::CATCH_REF:
686 case WebAssembly::CATCH_REF_S:
687 case WebAssembly::CATCH_ALL:
688 case WebAssembly::CATCH_ALL_S:
689 case WebAssembly::CATCH_ALL_REF:
690 case WebAssembly::CATCH_ALL_REF_S:
691 // These are pseudo instructions to represent catch clauses in try_table
692 // instruction to simulate block return values.
693 break;
694 default: {
695 WebAssemblyMCInstLower MCInstLowering(OutContext, *this);
696 MCInst TmpInst;
697 MCInstLowering.lower(MI, TmpInst);
698 EmitToStreamer(*OutStreamer, TmpInst);
699 break;
700 }
701 }
702}
703
705 unsigned OpNo,
706 const char *ExtraCode,
707 raw_ostream &OS) {
708 // First try the generic code, which knows about modifiers like 'c' and 'n'.
709 if (!AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS))
710 return false;
711
712 if (!ExtraCode) {
713 const MachineOperand &MO = MI->getOperand(OpNo);
714 switch (MO.getType()) {
716 OS << MO.getImm();
717 return false;
719 // FIXME: only opcode that still contains registers, as required by
720 // MachineInstr::getDebugVariable().
721 assert(MI->getOpcode() == WebAssembly::INLINEASM);
722 OS << regToString(MO);
723 return false;
726 return false;
729 printOffset(MO.getOffset(), OS);
730 return false;
732 MO.getMBB()->getSymbol()->print(OS, MAI);
733 return false;
734 default:
735 break;
736 }
737 }
738
739 return true;
740}
741
743 unsigned OpNo,
744 const char *ExtraCode,
745 raw_ostream &OS) {
746 // The current approach to inline asm is that "r" constraints are expressed
747 // as local indices, rather than values on the operand stack. This simplifies
748 // using "r" as it eliminates the need to push and pop the values in a
749 // particular order, however it also makes it impossible to have an "m"
750 // constraint. So we don't support it.
751
752 return AsmPrinter::PrintAsmMemoryOperand(MI, OpNo, ExtraCode, OS);
753}
754
756
757INITIALIZE_PASS(WebAssemblyAsmPrinter, "webassembly-asm-printer",
758 "WebAssembly Assmebly Printer", false, false)
759
760// Force static initialization.
762LLVMInitializeWebAssemblyAsmPrinter() {
765}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Function Alias Analysis Results
#define LLVM_ABI
Definition: Compiler.h:213
#define LLVM_EXTERNAL_VISIBILITY
Definition: Compiler.h:132
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
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
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.
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:56
raw_pwrite_stream & OS
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 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
Definition: AsmPrinter.cpp:706
void EmitToStreamer(MCStreamer &S, const MCInst &Inst)
Definition: AsmPrinter.cpp:433
virtual void emitGlobalVariable(const GlobalVariable *GV)
Emit the specified global variable to the .s file.
Definition: AsmPrinter.cpp:728
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.
Definition: AsmPrinter.cpp:661
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:710
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
bool isPositionIndependent() const
Definition: AsmPrinter.cpp:404
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.
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
This class represents an Operation in the Expression.
Implements a dense probed hash-table based set.
Definition: DenseSet.h:263
bool isThreadLocal() const
If the value is "Thread Local", its value isn't shared by the threads.
Definition: GlobalValue.h:265
VisibilityTypes getVisibility() const
Definition: GlobalValue.h:250
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:316
unsigned getAddressSpace() const
Definition: GlobalValue.h:207
Module * getParent()
Get the module that this global value is contained inside of...
Definition: GlobalValue.h:663
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this global belongs to.
Definition: Globals.cpp:132
Type * getValueType() const
Definition: GlobalValue.h:298
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
MCSectionWasm * getWasmSection(const Twine &Section, SectionKind K, unsigned Flags=0)
Definition: MCContext.h:637
LLVM_ABI wasm::WasmSignature * createWasmSignature()
Allocates and returns a new WasmSignature instance (with empty parameter and return type lists).
Definition: MCContext.cpp:473
StringRef allocateString(StringRef s)
Allocates a copy of the given string on the allocator managed by this context and returns the result.
Definition: MCContext.h:835
const SymbolTable & getSymbols() const
getSymbols - Get a reference for the symbol table for clients that want to, for example,...
Definition: MCContext.h:514
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:188
This represents a section on wasm.
Definition: MCSectionWasm.h:26
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition: MCExpr.h:214
void setSignature(wasm::WasmSignature *Sig)
Definition: MCSymbolWasm.h:133
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.
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:72
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: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()
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: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:182
bool empty() const
Definition: SmallVector.h:82
size_t size() const
Definition: SmallVector.h:79
reference emplace_back(ArgTypes &&... Args)
Definition: SmallVector.h:938
void push_back(const T &Elt)
Definition: SmallVector.h:414
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1197
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)
const std::vector< MVT > & getLocals() const
unsigned getWAReg(Register VReg) 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: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.
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
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_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
@ WASM_FEATURE_PREFIX_USED
Definition: Wasm.h:180
@ WASM_FEATURE_PREFIX_DISALLOWED
Definition: Wasm.h:181
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]
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.
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
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
Target & getTheWebAssemblyTarget64()
void valTypesFromMVTs(ArrayRef< MVT > In, SmallVectorImpl< wasm::ValType > &Out)
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)
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:507
SmallVector< ValType, 4 > Params
Definition: Wasm.h:508