blob: ad59f2f405879e90cb8470c116b47243f1af3427 [file] [log] [blame]
Dan Gohman3469ee12016-01-12 20:30:51 +00001//==-- WebAssemblyTargetStreamer.cpp - WebAssembly Target Streamer Methods --=//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9///
10/// \file
11/// \brief This file defines WebAssembly-specific target streamer classes.
12/// These are for implementing support for target-specific assembly directives.
13///
14//===----------------------------------------------------------------------===//
15
16#include "WebAssemblyTargetStreamer.h"
17#include "InstPrinter/WebAssemblyInstPrinter.h"
18#include "WebAssemblyMCTargetDesc.h"
Dan Gohman3469ee12016-01-12 20:30:51 +000019#include "llvm/MC/MCContext.h"
20#include "llvm/MC/MCSectionELF.h"
Dan Gohman18eafb62017-02-22 01:23:18 +000021#include "llvm/MC/MCSectionWasm.h"
Dan Gohman3469ee12016-01-12 20:30:51 +000022#include "llvm/MC/MCSubtargetInfo.h"
23#include "llvm/MC/MCSymbolELF.h"
Dan Gohman18eafb62017-02-22 01:23:18 +000024#include "llvm/MC/MCSymbolWasm.h"
Dan Gohmand934cb82017-02-24 23:18:00 +000025#include "llvm/Support/Casting.h"
Dan Gohman3469ee12016-01-12 20:30:51 +000026#include "llvm/Support/ErrorHandling.h"
27#include "llvm/Support/FormattedStream.h"
28using namespace llvm;
29
30WebAssemblyTargetStreamer::WebAssemblyTargetStreamer(MCStreamer &S)
31 : MCTargetStreamer(S) {}
32
Derek Schuffb8795392017-03-16 20:49:48 +000033void WebAssemblyTargetStreamer::emitValueType(wasm::ValType Type) {
34 Streamer.EmitSLEB128IntValue(int32_t(Type));
35}
36
Dan Gohman3469ee12016-01-12 20:30:51 +000037WebAssemblyTargetAsmStreamer::WebAssemblyTargetAsmStreamer(
38 MCStreamer &S, formatted_raw_ostream &OS)
39 : WebAssemblyTargetStreamer(S), OS(OS) {}
40
41WebAssemblyTargetELFStreamer::WebAssemblyTargetELFStreamer(MCStreamer &S)
42 : WebAssemblyTargetStreamer(S) {}
43
Dan Gohman18eafb62017-02-22 01:23:18 +000044WebAssemblyTargetWasmStreamer::WebAssemblyTargetWasmStreamer(MCStreamer &S)
45 : WebAssemblyTargetStreamer(S) {}
46
Dan Gohman3469ee12016-01-12 20:30:51 +000047static void PrintTypes(formatted_raw_ostream &OS, ArrayRef<MVT> Types) {
48 bool First = true;
49 for (MVT Type : Types) {
50 if (First)
51 First = false;
52 else
53 OS << ", ";
54 OS << WebAssembly::TypeToString(Type);
55 }
56 OS << '\n';
57}
58
Dan Gohmand934cb82017-02-24 23:18:00 +000059void WebAssemblyTargetAsmStreamer::emitParam(MCSymbol *Symbol,
60 ArrayRef<MVT> Types) {
61 if (!Types.empty()) {
62 OS << "\t.param \t";
63
64 // FIXME: Currently this applies to the "current" function; it may
65 // be cleaner to specify an explicit symbol as part of the directive.
66
67 PrintTypes(OS, Types);
68 }
Dan Gohman3469ee12016-01-12 20:30:51 +000069}
70
Dan Gohmand934cb82017-02-24 23:18:00 +000071void WebAssemblyTargetAsmStreamer::emitResult(MCSymbol *Symbol,
72 ArrayRef<MVT> Types) {
73 if (!Types.empty()) {
74 OS << "\t.result \t";
75
76 // FIXME: Currently this applies to the "current" function; it may
77 // be cleaner to specify an explicit symbol as part of the directive.
78
79 PrintTypes(OS, Types);
80 }
Dan Gohman3469ee12016-01-12 20:30:51 +000081}
82
83void WebAssemblyTargetAsmStreamer::emitLocal(ArrayRef<MVT> Types) {
Dan Gohman3acb1872016-10-24 23:27:49 +000084 if (!Types.empty()) {
85 OS << "\t.local \t";
86 PrintTypes(OS, Types);
87 }
Dan Gohman3469ee12016-01-12 20:30:51 +000088}
89
Dan Gohman970d02c2017-03-30 23:58:19 +000090void WebAssemblyTargetAsmStreamer::emitGlobal(
91 ArrayRef<wasm::Global> Globals) {
92 if (!Globals.empty()) {
Dan Gohman82607f52017-02-24 23:46:05 +000093 OS << "\t.globalvar \t";
Dan Gohman970d02c2017-03-30 23:58:19 +000094
95 bool First = true;
96 for (const wasm::Global &G : Globals) {
97 if (First)
98 First = false;
99 else
100 OS << ", ";
101 OS << WebAssembly::TypeToString(G.Type);
102 if (!G.InitialModule.empty())
103 OS << '=' << G.InitialModule << ':' << G.InitialName;
104 else
105 OS << '=' << G.InitialValue;
106 }
107 OS << '\n';
Dan Gohman82607f52017-02-24 23:46:05 +0000108 }
109}
110
Dan Gohman970d02c2017-03-30 23:58:19 +0000111void WebAssemblyTargetAsmStreamer::emitStackPointer(uint32_t Index) {
112 OS << "\t.stack_pointer\t" << Index << '\n';
113}
114
Dan Gohman3469ee12016-01-12 20:30:51 +0000115void WebAssemblyTargetAsmStreamer::emitEndFunc() { OS << "\t.endfunc\n"; }
116
Derek Schuff5859a9ed2016-06-03 18:34:36 +0000117void WebAssemblyTargetAsmStreamer::emitIndirectFunctionType(
Dan Gohman2726b882016-10-06 22:29:32 +0000118 StringRef name, SmallVectorImpl<MVT> &Params, SmallVectorImpl<MVT> &Results) {
Derek Schuff5859a9ed2016-06-03 18:34:36 +0000119 OS << "\t.functype\t" << name;
Dan Gohman2726b882016-10-06 22:29:32 +0000120 if (Results.empty())
Derek Schuffc64d7652016-08-01 22:25:02 +0000121 OS << ", void";
Dan Gohman2726b882016-10-06 22:29:32 +0000122 else {
123 assert(Results.size() == 1);
124 OS << ", " << WebAssembly::TypeToString(Results.front());
Derek Schuff5859a9ed2016-06-03 18:34:36 +0000125 }
Dan Gohman2726b882016-10-06 22:29:32 +0000126 for (auto Ty : Params)
127 OS << ", " << WebAssembly::TypeToString(Ty);
128 OS << '\n';
Derek Schuff5859a9ed2016-06-03 18:34:36 +0000129}
130
Derek Schuff7747d703e2016-12-01 00:11:15 +0000131void WebAssemblyTargetAsmStreamer::emitGlobalImport(StringRef name) {
132 OS << "\t.import_global\t" << name << '\n';
133}
134
Derek Schuffc64d7652016-08-01 22:25:02 +0000135void WebAssemblyTargetAsmStreamer::emitIndIdx(const MCExpr *Value) {
136 OS << "\t.indidx \t" << *Value << '\n';
137}
138
Dan Gohmand934cb82017-02-24 23:18:00 +0000139void WebAssemblyTargetELFStreamer::emitParam(MCSymbol *Symbol,
140 ArrayRef<MVT> Types) {
Dan Gohman3acb1872016-10-24 23:27:49 +0000141 // Nothing to emit; params are declared as part of the function signature.
Dan Gohman3469ee12016-01-12 20:30:51 +0000142}
143
Dan Gohmand934cb82017-02-24 23:18:00 +0000144void WebAssemblyTargetELFStreamer::emitResult(MCSymbol *Symbol,
145 ArrayRef<MVT> Types) {
Dan Gohman3acb1872016-10-24 23:27:49 +0000146 // Nothing to emit; results are declared as part of the function signature.
Dan Gohman3469ee12016-01-12 20:30:51 +0000147}
148
149void WebAssemblyTargetELFStreamer::emitLocal(ArrayRef<MVT> Types) {
Dan Gohman3acb1872016-10-24 23:27:49 +0000150 Streamer.EmitULEB128IntValue(Types.size());
151 for (MVT Type : Types)
Derek Schuffb8795392017-03-16 20:49:48 +0000152 emitValueType(WebAssembly::toValType(Type));
Dan Gohman3469ee12016-01-12 20:30:51 +0000153}
154
Dan Gohman970d02c2017-03-30 23:58:19 +0000155void WebAssemblyTargetELFStreamer::emitGlobal(
156 ArrayRef<wasm::Global> Globals) {
Dan Gohman82607f52017-02-24 23:46:05 +0000157 llvm_unreachable(".globalvar encoding not yet implemented");
158}
159
Dan Gohman970d02c2017-03-30 23:58:19 +0000160void WebAssemblyTargetELFStreamer::emitStackPointer(
161 uint32_t Index) {
162 llvm_unreachable(".stack_pointer encoding not yet implemented");
163}
164
Dan Gohman3469ee12016-01-12 20:30:51 +0000165void WebAssemblyTargetELFStreamer::emitEndFunc() {
Dan Gohman3acb1872016-10-24 23:27:49 +0000166 Streamer.EmitIntValue(WebAssembly::End, 1);
Dan Gohman3469ee12016-01-12 20:30:51 +0000167}
Derek Schuffc64d7652016-08-01 22:25:02 +0000168
169void WebAssemblyTargetELFStreamer::emitIndIdx(const MCExpr *Value) {
Dan Gohman3acb1872016-10-24 23:27:49 +0000170 llvm_unreachable(".indidx encoding not yet implemented");
171}
172
173void WebAssemblyTargetELFStreamer::emitIndirectFunctionType(
174 StringRef name, SmallVectorImpl<MVT> &Params, SmallVectorImpl<MVT> &Results) {
175 // Nothing to emit here. TODO: Re-design how linking works and re-evaluate
176 // whether it's necessary for .o files to declare indirect function types.
Derek Schuffc64d7652016-08-01 22:25:02 +0000177}
Derek Schuff7747d703e2016-12-01 00:11:15 +0000178
179void WebAssemblyTargetELFStreamer::emitGlobalImport(StringRef name) {
Dan Gohman18eafb62017-02-22 01:23:18 +0000180}
181
Dan Gohmand934cb82017-02-24 23:18:00 +0000182void WebAssemblyTargetWasmStreamer::emitParam(MCSymbol *Symbol,
183 ArrayRef<MVT> Types) {
Derek Schuffe2688c42017-03-14 20:23:22 +0000184 SmallVector<wasm::ValType, 4> Params;
Dan Gohmand934cb82017-02-24 23:18:00 +0000185 for (MVT Ty : Types)
Derek Schuffe2688c42017-03-14 20:23:22 +0000186 Params.push_back(WebAssembly::toValType(Ty));
Dan Gohmand934cb82017-02-24 23:18:00 +0000187
188 cast<MCSymbolWasm>(Symbol)->setParams(std::move(Params));
189}
190
191void WebAssemblyTargetWasmStreamer::emitResult(MCSymbol *Symbol,
192 ArrayRef<MVT> Types) {
Derek Schuffe2688c42017-03-14 20:23:22 +0000193 SmallVector<wasm::ValType, 4> Returns;
Dan Gohmand934cb82017-02-24 23:18:00 +0000194 for (MVT Ty : Types)
Derek Schuffe2688c42017-03-14 20:23:22 +0000195 Returns.push_back(WebAssembly::toValType(Ty));
Dan Gohmand934cb82017-02-24 23:18:00 +0000196
197 cast<MCSymbolWasm>(Symbol)->setReturns(std::move(Returns));
Dan Gohman18eafb62017-02-22 01:23:18 +0000198}
199
200void WebAssemblyTargetWasmStreamer::emitLocal(ArrayRef<MVT> Types) {
Dan Gohmand934cb82017-02-24 23:18:00 +0000201 SmallVector<std::pair<MVT, uint32_t>, 4> Grouped;
202 for (MVT Type : Types) {
203 if (Grouped.empty() || Grouped.back().first != Type)
204 Grouped.push_back(std::make_pair(Type, 1));
205 else
206 ++Grouped.back().second;
207 }
208
209 Streamer.EmitULEB128IntValue(Grouped.size());
210 for (auto Pair : Grouped) {
211 Streamer.EmitULEB128IntValue(Pair.second);
Derek Schuffb8795392017-03-16 20:49:48 +0000212 emitValueType(WebAssembly::toValType(Pair.first));
Dan Gohmand934cb82017-02-24 23:18:00 +0000213 }
Dan Gohman18eafb62017-02-22 01:23:18 +0000214}
215
Dan Gohman970d02c2017-03-30 23:58:19 +0000216void WebAssemblyTargetWasmStreamer::emitGlobal(
217 ArrayRef<wasm::Global> Globals) {
Dan Gohman82607f52017-02-24 23:46:05 +0000218 // Encode the globals use by the funciton into the special .global_variables
219 // section. This will later be decoded and turned into contents for the
220 // Globals Section.
221 Streamer.PushSection();
222 Streamer.SwitchSection(Streamer.getContext()
223 .getWasmSection(".global_variables", 0, 0));
Dan Gohman970d02c2017-03-30 23:58:19 +0000224 for (const wasm::Global &G : Globals) {
225 Streamer.EmitIntValue(int32_t(G.Type), 1);
226 Streamer.EmitIntValue(G.Mutable, 1);
227 if (G.InitialModule.empty()) {
228 Streamer.EmitIntValue(0, 1); // indicate that we have an int value
229 Streamer.EmitSLEB128IntValue(0);
230 } else {
231 Streamer.EmitIntValue(1, 1); // indicate that we have a module import
232 Streamer.EmitBytes(G.InitialModule);
233 Streamer.EmitIntValue(0, 1); // nul-terminate
234 Streamer.EmitBytes(G.InitialName);
235 Streamer.EmitIntValue(0, 1); // nul-terminate
236 }
237 }
238 Streamer.PopSection();
239}
240
241void WebAssemblyTargetWasmStreamer::emitStackPointer(uint32_t Index) {
242 Streamer.PushSection();
243 Streamer.SwitchSection(Streamer.getContext()
244 .getWasmSection(".stack_pointer", 0, 0));
245 Streamer.EmitIntValue(Index, 4);
Dan Gohman82607f52017-02-24 23:46:05 +0000246 Streamer.PopSection();
247}
248
Dan Gohman18eafb62017-02-22 01:23:18 +0000249void WebAssemblyTargetWasmStreamer::emitEndFunc() {
Dan Gohmand934cb82017-02-24 23:18:00 +0000250 llvm_unreachable(".end_func is not needed for direct wasm output");
Dan Gohman18eafb62017-02-22 01:23:18 +0000251}
252
253void WebAssemblyTargetWasmStreamer::emitIndIdx(const MCExpr *Value) {
254 llvm_unreachable(".indidx encoding not yet implemented");
255}
256
257void WebAssemblyTargetWasmStreamer::emitIndirectFunctionType(
258 StringRef name, SmallVectorImpl<MVT> &Params, SmallVectorImpl<MVT> &Results) {
259 // Nothing to emit here. TODO: Re-design how linking works and re-evaluate
260 // whether it's necessary for .o files to declare indirect function types.
261}
262
263void WebAssemblyTargetWasmStreamer::emitGlobalImport(StringRef name) {
264}