1444ed5c5SDimitry Andric //==-- WebAssemblyTargetStreamer.cpp - WebAssembly Target Streamer Methods --=//
2444ed5c5SDimitry Andric //
3444ed5c5SDimitry Andric //                     The LLVM Compiler Infrastructure
4444ed5c5SDimitry Andric //
5444ed5c5SDimitry Andric // This file is distributed under the University of Illinois Open Source
6444ed5c5SDimitry Andric // License. See LICENSE.TXT for details.
7444ed5c5SDimitry Andric //
8444ed5c5SDimitry Andric //===----------------------------------------------------------------------===//
9444ed5c5SDimitry Andric ///
10444ed5c5SDimitry Andric /// \file
114ba319b5SDimitry Andric /// This file defines WebAssembly-specific target streamer classes.
12444ed5c5SDimitry Andric /// These are for implementing support for target-specific assembly directives.
13444ed5c5SDimitry Andric ///
14444ed5c5SDimitry Andric //===----------------------------------------------------------------------===//
15444ed5c5SDimitry Andric 
16444ed5c5SDimitry Andric #include "WebAssemblyTargetStreamer.h"
17444ed5c5SDimitry Andric #include "InstPrinter/WebAssemblyInstPrinter.h"
18444ed5c5SDimitry Andric #include "WebAssemblyMCTargetDesc.h"
19444ed5c5SDimitry Andric #include "llvm/MC/MCContext.h"
207a7e6055SDimitry Andric #include "llvm/MC/MCSectionWasm.h"
21444ed5c5SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
227a7e6055SDimitry Andric #include "llvm/MC/MCSymbolWasm.h"
237a7e6055SDimitry Andric #include "llvm/Support/Casting.h"
24444ed5c5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
25444ed5c5SDimitry Andric #include "llvm/Support/FormattedStream.h"
26444ed5c5SDimitry Andric using namespace llvm;
27444ed5c5SDimitry Andric 
WebAssemblyTargetStreamer(MCStreamer & S)28444ed5c5SDimitry Andric WebAssemblyTargetStreamer::WebAssemblyTargetStreamer(MCStreamer &S)
29444ed5c5SDimitry Andric     : MCTargetStreamer(S) {}
30444ed5c5SDimitry Andric 
emitValueType(wasm::ValType Type)317a7e6055SDimitry Andric void WebAssemblyTargetStreamer::emitValueType(wasm::ValType Type) {
324ba319b5SDimitry Andric   Streamer.EmitIntValue(uint8_t(Type), 1);
337a7e6055SDimitry Andric }
347a7e6055SDimitry Andric 
WebAssemblyTargetAsmStreamer(MCStreamer & S,formatted_raw_ostream & OS)35444ed5c5SDimitry Andric WebAssemblyTargetAsmStreamer::WebAssemblyTargetAsmStreamer(
36444ed5c5SDimitry Andric     MCStreamer &S, formatted_raw_ostream &OS)
37444ed5c5SDimitry Andric     : WebAssemblyTargetStreamer(S), OS(OS) {}
38444ed5c5SDimitry Andric 
WebAssemblyTargetWasmStreamer(MCStreamer & S)397a7e6055SDimitry Andric WebAssemblyTargetWasmStreamer::WebAssemblyTargetWasmStreamer(MCStreamer &S)
407a7e6055SDimitry Andric     : WebAssemblyTargetStreamer(S) {}
417a7e6055SDimitry Andric 
printTypes(formatted_raw_ostream & OS,ArrayRef<wasm::ValType> Types)42*b5893f02SDimitry Andric static void printTypes(formatted_raw_ostream &OS,
43*b5893f02SDimitry Andric                        ArrayRef<wasm::ValType> Types) {
44444ed5c5SDimitry Andric   bool First = true;
45*b5893f02SDimitry Andric   for (auto Type : Types) {
46444ed5c5SDimitry Andric     if (First)
47444ed5c5SDimitry Andric       First = false;
48444ed5c5SDimitry Andric     else
49444ed5c5SDimitry Andric       OS << ", ";
50*b5893f02SDimitry Andric     OS << WebAssembly::typeToString(Type);
51444ed5c5SDimitry Andric   }
52444ed5c5SDimitry Andric   OS << '\n';
53444ed5c5SDimitry Andric }
54444ed5c5SDimitry Andric 
emitLocal(ArrayRef<wasm::ValType> Types)55*b5893f02SDimitry Andric void WebAssemblyTargetAsmStreamer::emitLocal(ArrayRef<wasm::ValType> Types) {
56d88c1a5aSDimitry Andric   if (!Types.empty()) {
57444ed5c5SDimitry Andric     OS << "\t.local  \t";
58*b5893f02SDimitry Andric     printTypes(OS, Types);
59444ed5c5SDimitry Andric   }
60d88c1a5aSDimitry Andric }
61444ed5c5SDimitry Andric 
emitEndFunc()62444ed5c5SDimitry Andric void WebAssemblyTargetAsmStreamer::emitEndFunc() { OS << "\t.endfunc\n"; }
63444ed5c5SDimitry Andric 
emitSignature(const wasm::WasmSignature * Sig)64*b5893f02SDimitry Andric void WebAssemblyTargetAsmStreamer::emitSignature(
65*b5893f02SDimitry Andric     const wasm::WasmSignature *Sig) {
66*b5893f02SDimitry Andric   OS << "(";
67*b5893f02SDimitry Andric   emitParamList(Sig);
68*b5893f02SDimitry Andric   OS << ") -> (";
69*b5893f02SDimitry Andric   emitReturnList(Sig);
70*b5893f02SDimitry Andric   OS << ")";
713ca95b02SDimitry Andric }
723ca95b02SDimitry Andric 
emitParamList(const wasm::WasmSignature * Sig)73*b5893f02SDimitry Andric void WebAssemblyTargetAsmStreamer::emitParamList(
74*b5893f02SDimitry Andric     const wasm::WasmSignature *Sig) {
75*b5893f02SDimitry Andric   auto &Params = Sig->Params;
76*b5893f02SDimitry Andric   for (auto &Ty : Params) {
77*b5893f02SDimitry Andric     if (&Ty != &Params[0])
78*b5893f02SDimitry Andric       OS << ", ";
79*b5893f02SDimitry Andric     OS << WebAssembly::typeToString(Ty);
80*b5893f02SDimitry Andric   }
81d88c1a5aSDimitry Andric }
82444ed5c5SDimitry Andric 
emitReturnList(const wasm::WasmSignature * Sig)83*b5893f02SDimitry Andric void WebAssemblyTargetAsmStreamer::emitReturnList(
84*b5893f02SDimitry Andric     const wasm::WasmSignature *Sig) {
85*b5893f02SDimitry Andric   auto &Returns = Sig->Returns;
86*b5893f02SDimitry Andric   for (auto &Ty : Returns) {
87*b5893f02SDimitry Andric     if (&Ty != &Returns[0])
88*b5893f02SDimitry Andric       OS << ", ";
89*b5893f02SDimitry Andric     OS << WebAssembly::typeToString(Ty);
90*b5893f02SDimitry Andric   }
91*b5893f02SDimitry Andric }
92*b5893f02SDimitry Andric 
emitFunctionType(const MCSymbolWasm * Sym)93*b5893f02SDimitry Andric void WebAssemblyTargetAsmStreamer::emitFunctionType(const MCSymbolWasm *Sym) {
94*b5893f02SDimitry Andric   assert(Sym->isFunction());
95*b5893f02SDimitry Andric   OS << "\t.functype\t" << Sym->getName() << " ";
96*b5893f02SDimitry Andric   emitSignature(Sym->getSignature());
97*b5893f02SDimitry Andric   OS << "\n";
98*b5893f02SDimitry Andric }
99*b5893f02SDimitry Andric 
emitGlobalType(const MCSymbolWasm * Sym)100*b5893f02SDimitry Andric void WebAssemblyTargetAsmStreamer::emitGlobalType(const MCSymbolWasm *Sym) {
101*b5893f02SDimitry Andric   assert(Sym->isGlobal());
102*b5893f02SDimitry Andric   OS << "\t.globaltype\t" << Sym->getName() << ", "
103*b5893f02SDimitry Andric      << WebAssembly::typeToString(
104*b5893f02SDimitry Andric             static_cast<wasm::ValType>(Sym->getGlobalType().Type))
105*b5893f02SDimitry Andric      << '\n';
106*b5893f02SDimitry Andric }
107*b5893f02SDimitry Andric 
emitEventType(const MCSymbolWasm * Sym)108*b5893f02SDimitry Andric void WebAssemblyTargetAsmStreamer::emitEventType(const MCSymbolWasm *Sym) {
109*b5893f02SDimitry Andric   assert(Sym->isEvent());
110*b5893f02SDimitry Andric   OS << "\t.eventtype\t" << Sym->getName() << " ";
111*b5893f02SDimitry Andric   emitParamList(Sym->getSignature());
112*b5893f02SDimitry Andric   OS << "\n";
113*b5893f02SDimitry Andric }
114*b5893f02SDimitry Andric 
emitImportModule(const MCSymbolWasm * Sym,StringRef ImportModule)115*b5893f02SDimitry Andric void WebAssemblyTargetAsmStreamer::emitImportModule(const MCSymbolWasm *Sym,
116*b5893f02SDimitry Andric                                                     StringRef ImportModule) {
117*b5893f02SDimitry Andric   OS << "\t.import_module\t" << Sym->getName() << ", "
118*b5893f02SDimitry Andric                              << ImportModule << '\n';
119*b5893f02SDimitry Andric }
120*b5893f02SDimitry Andric 
emitImportName(const MCSymbolWasm * Sym,StringRef ImportName)121*b5893f02SDimitry Andric void WebAssemblyTargetAsmStreamer::emitImportName(const MCSymbolWasm *Sym,
122*b5893f02SDimitry Andric                                                   StringRef ImportName) {
123*b5893f02SDimitry Andric   OS << "\t.import_name\t" << Sym->getName() << ", "
124*b5893f02SDimitry Andric                            << ImportName << '\n';
1254ba319b5SDimitry Andric }
1264ba319b5SDimitry Andric 
emitIndIdx(const MCExpr * Value)127d88c1a5aSDimitry Andric void WebAssemblyTargetAsmStreamer::emitIndIdx(const MCExpr *Value) {
128d88c1a5aSDimitry Andric   OS << "\t.indidx  \t" << *Value << '\n';
129444ed5c5SDimitry Andric }
130444ed5c5SDimitry Andric 
emitLocal(ArrayRef<wasm::ValType> Types)131*b5893f02SDimitry Andric void WebAssemblyTargetWasmStreamer::emitLocal(ArrayRef<wasm::ValType> Types) {
132*b5893f02SDimitry Andric   SmallVector<std::pair<wasm::ValType, uint32_t>, 4> Grouped;
133*b5893f02SDimitry Andric   for (auto Type : Types) {
1347a7e6055SDimitry Andric     if (Grouped.empty() || Grouped.back().first != Type)
1357a7e6055SDimitry Andric       Grouped.push_back(std::make_pair(Type, 1));
1367a7e6055SDimitry Andric     else
1377a7e6055SDimitry Andric       ++Grouped.back().second;
1387a7e6055SDimitry Andric   }
1397a7e6055SDimitry Andric 
1407a7e6055SDimitry Andric   Streamer.EmitULEB128IntValue(Grouped.size());
1417a7e6055SDimitry Andric   for (auto Pair : Grouped) {
1427a7e6055SDimitry Andric     Streamer.EmitULEB128IntValue(Pair.second);
143*b5893f02SDimitry Andric     emitValueType(Pair.first);
1447a7e6055SDimitry Andric   }
1457a7e6055SDimitry Andric }
1467a7e6055SDimitry Andric 
emitEndFunc()1477a7e6055SDimitry Andric void WebAssemblyTargetWasmStreamer::emitEndFunc() {
1487a7e6055SDimitry Andric   llvm_unreachable(".end_func is not needed for direct wasm output");
1497a7e6055SDimitry Andric }
1507a7e6055SDimitry Andric 
emitIndIdx(const MCExpr * Value)1517a7e6055SDimitry Andric void WebAssemblyTargetWasmStreamer::emitIndIdx(const MCExpr *Value) {
1527a7e6055SDimitry Andric   llvm_unreachable(".indidx encoding not yet implemented");
1537a7e6055SDimitry Andric }
154