10b57cec5SDimitry Andric //==-- WebAssemblyTargetStreamer.cpp - WebAssembly Target Streamer Methods --=//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric ///
90b57cec5SDimitry Andric /// \file
100b57cec5SDimitry Andric /// This file defines WebAssembly-specific target streamer classes.
110b57cec5SDimitry Andric /// These are for implementing support for target-specific assembly directives.
120b57cec5SDimitry Andric ///
130b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric #include "MCTargetDesc/WebAssemblyTargetStreamer.h"
160b57cec5SDimitry Andric #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
1706c3fb27SDimitry Andric #include "MCTargetDesc/WebAssemblyMCTypeUtilities.h"
180b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
190b57cec5SDimitry Andric #include "llvm/MC/MCSectionWasm.h"
200b57cec5SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
210b57cec5SDimitry Andric #include "llvm/MC/MCSymbolWasm.h"
220b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
230b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
240b57cec5SDimitry Andric #include "llvm/Support/FormattedStream.h"
250b57cec5SDimitry Andric using namespace llvm;
260b57cec5SDimitry Andric 
WebAssemblyTargetStreamer(MCStreamer & S)270b57cec5SDimitry Andric WebAssemblyTargetStreamer::WebAssemblyTargetStreamer(MCStreamer &S)
280b57cec5SDimitry Andric     : MCTargetStreamer(S) {}
290b57cec5SDimitry Andric 
emitValueType(wasm::ValType Type)300b57cec5SDimitry Andric void WebAssemblyTargetStreamer::emitValueType(wasm::ValType Type) {
315ffd83dbSDimitry Andric   Streamer.emitIntValue(uint8_t(Type), 1);
320b57cec5SDimitry Andric }
330b57cec5SDimitry Andric 
WebAssemblyTargetAsmStreamer(MCStreamer & S,formatted_raw_ostream & OS)340b57cec5SDimitry Andric WebAssemblyTargetAsmStreamer::WebAssemblyTargetAsmStreamer(
350b57cec5SDimitry Andric     MCStreamer &S, formatted_raw_ostream &OS)
360b57cec5SDimitry Andric     : WebAssemblyTargetStreamer(S), OS(OS) {}
370b57cec5SDimitry Andric 
WebAssemblyTargetWasmStreamer(MCStreamer & S)380b57cec5SDimitry Andric WebAssemblyTargetWasmStreamer::WebAssemblyTargetWasmStreamer(MCStreamer &S)
390b57cec5SDimitry Andric     : WebAssemblyTargetStreamer(S) {}
400b57cec5SDimitry Andric 
printTypes(formatted_raw_ostream & OS,ArrayRef<wasm::ValType> Types)410b57cec5SDimitry Andric static void printTypes(formatted_raw_ostream &OS,
420b57cec5SDimitry Andric                        ArrayRef<wasm::ValType> Types) {
430b57cec5SDimitry Andric   bool First = true;
440b57cec5SDimitry Andric   for (auto Type : Types) {
450b57cec5SDimitry Andric     if (First)
460b57cec5SDimitry Andric       First = false;
470b57cec5SDimitry Andric     else
480b57cec5SDimitry Andric       OS << ", ";
490b57cec5SDimitry Andric     OS << WebAssembly::typeToString(Type);
500b57cec5SDimitry Andric   }
510b57cec5SDimitry Andric   OS << '\n';
520b57cec5SDimitry Andric }
530b57cec5SDimitry Andric 
emitLocal(ArrayRef<wasm::ValType> Types)540b57cec5SDimitry Andric void WebAssemblyTargetAsmStreamer::emitLocal(ArrayRef<wasm::ValType> Types) {
550b57cec5SDimitry Andric   if (!Types.empty()) {
560b57cec5SDimitry Andric     OS << "\t.local  \t";
570b57cec5SDimitry Andric     printTypes(OS, Types);
580b57cec5SDimitry Andric   }
590b57cec5SDimitry Andric }
600b57cec5SDimitry Andric 
emitFunctionType(const MCSymbolWasm * Sym)610b57cec5SDimitry Andric void WebAssemblyTargetAsmStreamer::emitFunctionType(const MCSymbolWasm *Sym) {
620b57cec5SDimitry Andric   assert(Sym->isFunction());
630b57cec5SDimitry Andric   OS << "\t.functype\t" << Sym->getName() << " ";
648bcb0991SDimitry Andric   OS << WebAssembly::signatureToString(Sym->getSignature());
650b57cec5SDimitry Andric   OS << "\n";
660b57cec5SDimitry Andric }
670b57cec5SDimitry Andric 
emitGlobalType(const MCSymbolWasm * Sym)680b57cec5SDimitry Andric void WebAssemblyTargetAsmStreamer::emitGlobalType(const MCSymbolWasm *Sym) {
690b57cec5SDimitry Andric   assert(Sym->isGlobal());
700b57cec5SDimitry Andric   OS << "\t.globaltype\t" << Sym->getName() << ", "
710b57cec5SDimitry Andric      << WebAssembly::typeToString(
72e8d8bef9SDimitry Andric             static_cast<wasm::ValType>(Sym->getGlobalType().Type));
73e8d8bef9SDimitry Andric   if (!Sym->getGlobalType().Mutable)
74e8d8bef9SDimitry Andric     OS << ", immutable";
75e8d8bef9SDimitry Andric   OS << '\n';
76e8d8bef9SDimitry Andric }
77e8d8bef9SDimitry Andric 
emitTableType(const MCSymbolWasm * Sym)78e8d8bef9SDimitry Andric void WebAssemblyTargetAsmStreamer::emitTableType(const MCSymbolWasm *Sym) {
79e8d8bef9SDimitry Andric   assert(Sym->isTable());
80fe6060f1SDimitry Andric   const wasm::WasmTableType &Type = Sym->getTableType();
81e8d8bef9SDimitry Andric   OS << "\t.tabletype\t" << Sym->getName() << ", "
82fe6060f1SDimitry Andric      << WebAssembly::typeToString(static_cast<wasm::ValType>(Type.ElemType));
83fe6060f1SDimitry Andric   bool HasMaximum = Type.Limits.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX;
84fe6060f1SDimitry Andric   if (Type.Limits.Minimum != 0 || HasMaximum) {
85fe6060f1SDimitry Andric     OS << ", " << Type.Limits.Minimum;
86fe6060f1SDimitry Andric     if (HasMaximum)
87fe6060f1SDimitry Andric       OS << ", " << Type.Limits.Maximum;
88fe6060f1SDimitry Andric   }
89e8d8bef9SDimitry Andric   OS << '\n';
900b57cec5SDimitry Andric }
910b57cec5SDimitry Andric 
emitTagType(const MCSymbolWasm * Sym)92fe6060f1SDimitry Andric void WebAssemblyTargetAsmStreamer::emitTagType(const MCSymbolWasm *Sym) {
93fe6060f1SDimitry Andric   assert(Sym->isTag());
94fe6060f1SDimitry Andric   OS << "\t.tagtype\t" << Sym->getName() << " ";
958bcb0991SDimitry Andric   OS << WebAssembly::typeListToString(Sym->getSignature()->Params);
960b57cec5SDimitry Andric   OS << "\n";
970b57cec5SDimitry Andric }
980b57cec5SDimitry Andric 
emitImportModule(const MCSymbolWasm * Sym,StringRef ImportModule)990b57cec5SDimitry Andric void WebAssemblyTargetAsmStreamer::emitImportModule(const MCSymbolWasm *Sym,
1000b57cec5SDimitry Andric                                                     StringRef ImportModule) {
1010b57cec5SDimitry Andric   OS << "\t.import_module\t" << Sym->getName() << ", "
1020b57cec5SDimitry Andric                              << ImportModule << '\n';
1030b57cec5SDimitry Andric }
1040b57cec5SDimitry Andric 
emitImportName(const MCSymbolWasm * Sym,StringRef ImportName)1050b57cec5SDimitry Andric void WebAssemblyTargetAsmStreamer::emitImportName(const MCSymbolWasm *Sym,
1060b57cec5SDimitry Andric                                                   StringRef ImportName) {
1070b57cec5SDimitry Andric   OS << "\t.import_name\t" << Sym->getName() << ", "
1080b57cec5SDimitry Andric                            << ImportName << '\n';
1090b57cec5SDimitry Andric }
1100b57cec5SDimitry Andric 
emitExportName(const MCSymbolWasm * Sym,StringRef ExportName)111480093f4SDimitry Andric void WebAssemblyTargetAsmStreamer::emitExportName(const MCSymbolWasm *Sym,
112480093f4SDimitry Andric                                                   StringRef ExportName) {
113480093f4SDimitry Andric   OS << "\t.export_name\t" << Sym->getName() << ", "
114480093f4SDimitry Andric                            << ExportName << '\n';
115480093f4SDimitry Andric }
116480093f4SDimitry Andric 
emitIndIdx(const MCExpr * Value)1170b57cec5SDimitry Andric void WebAssemblyTargetAsmStreamer::emitIndIdx(const MCExpr *Value) {
1180b57cec5SDimitry Andric   OS << "\t.indidx  \t" << *Value << '\n';
1190b57cec5SDimitry Andric }
1200b57cec5SDimitry Andric 
emitLocal(ArrayRef<wasm::ValType> Types)1210b57cec5SDimitry Andric void WebAssemblyTargetWasmStreamer::emitLocal(ArrayRef<wasm::ValType> Types) {
1220b57cec5SDimitry Andric   SmallVector<std::pair<wasm::ValType, uint32_t>, 4> Grouped;
1230b57cec5SDimitry Andric   for (auto Type : Types) {
1240b57cec5SDimitry Andric     if (Grouped.empty() || Grouped.back().first != Type)
1250b57cec5SDimitry Andric       Grouped.push_back(std::make_pair(Type, 1));
1260b57cec5SDimitry Andric     else
1270b57cec5SDimitry Andric       ++Grouped.back().second;
1280b57cec5SDimitry Andric   }
1290b57cec5SDimitry Andric 
1305ffd83dbSDimitry Andric   Streamer.emitULEB128IntValue(Grouped.size());
1310b57cec5SDimitry Andric   for (auto Pair : Grouped) {
1325ffd83dbSDimitry Andric     Streamer.emitULEB128IntValue(Pair.second);
1330b57cec5SDimitry Andric     emitValueType(Pair.first);
1340b57cec5SDimitry Andric   }
1350b57cec5SDimitry Andric }
1360b57cec5SDimitry Andric 
emitIndIdx(const MCExpr * Value)1370b57cec5SDimitry Andric void WebAssemblyTargetWasmStreamer::emitIndIdx(const MCExpr *Value) {
1380b57cec5SDimitry Andric   llvm_unreachable(".indidx encoding not yet implemented");
1390b57cec5SDimitry Andric }
140