diff options
author | Dan Gohman <dan433584@gmail.com> | 2017-03-30 23:58:19 +0000 |
---|---|---|
committer | Dan Gohman <dan433584@gmail.com> | 2017-03-30 23:58:19 +0000 |
commit | 970d02c42dc122a4a550599aa9153965a521660b (patch) | |
tree | 585011ec096221540d87c3527856b4e5e25a2c43 /llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp | |
parent | 1074cb5420f6cec1d2ea039d0f343719de7d84aa (diff) | |
download | bcm5719-llvm-970d02c42dc122a4a550599aa9153965a521660b.tar.gz bcm5719-llvm-970d02c42dc122a4a550599aa9153965a521660b.zip |
[WebAssembly] Initial linking metadata support
Add support for the new relocations and linking metadata section support in
https://github.com/WebAssembly/tool-conventions/blob/master/Linking.md. In
particular, this allows LLVM to indicate which variable is the stack pointer,
so that it can be linked with other objects.
This also adds support for emitting type relocations for call_indirect
instructions.
Right now, this is mainly tested by using wabt and hexdump to examine the
output on selected testcases. We'll add more tests as the design stablizes
and more of the pieces are in place.
llvm-svn: 299141
Diffstat (limited to 'llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp')
-rw-r--r-- | llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp | 60 |
1 files changed, 52 insertions, 8 deletions
diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp index f3b6b100d65..ad59f2f4058 100644 --- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp +++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp @@ -25,7 +25,6 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormattedStream.h" -#include "llvm/Support/Wasm.h" using namespace llvm; WebAssemblyTargetStreamer::WebAssemblyTargetStreamer(MCStreamer &S) @@ -88,13 +87,31 @@ void WebAssemblyTargetAsmStreamer::emitLocal(ArrayRef<MVT> Types) { } } -void WebAssemblyTargetAsmStreamer::emitGlobal(ArrayRef<MVT> Types) { - if (!Types.empty()) { +void WebAssemblyTargetAsmStreamer::emitGlobal( + ArrayRef<wasm::Global> Globals) { + if (!Globals.empty()) { OS << "\t.globalvar \t"; - PrintTypes(OS, Types); + + bool First = true; + for (const wasm::Global &G : Globals) { + if (First) + First = false; + else + OS << ", "; + OS << WebAssembly::TypeToString(G.Type); + if (!G.InitialModule.empty()) + OS << '=' << G.InitialModule << ':' << G.InitialName; + else + OS << '=' << G.InitialValue; + } + OS << '\n'; } } +void WebAssemblyTargetAsmStreamer::emitStackPointer(uint32_t Index) { + OS << "\t.stack_pointer\t" << Index << '\n'; +} + void WebAssemblyTargetAsmStreamer::emitEndFunc() { OS << "\t.endfunc\n"; } void WebAssemblyTargetAsmStreamer::emitIndirectFunctionType( @@ -135,10 +152,16 @@ void WebAssemblyTargetELFStreamer::emitLocal(ArrayRef<MVT> Types) { emitValueType(WebAssembly::toValType(Type)); } -void WebAssemblyTargetELFStreamer::emitGlobal(ArrayRef<MVT> Types) { +void WebAssemblyTargetELFStreamer::emitGlobal( + ArrayRef<wasm::Global> Globals) { llvm_unreachable(".globalvar encoding not yet implemented"); } +void WebAssemblyTargetELFStreamer::emitStackPointer( + uint32_t Index) { + llvm_unreachable(".stack_pointer encoding not yet implemented"); +} + void WebAssemblyTargetELFStreamer::emitEndFunc() { Streamer.EmitIntValue(WebAssembly::End, 1); } @@ -190,15 +213,36 @@ void WebAssemblyTargetWasmStreamer::emitLocal(ArrayRef<MVT> Types) { } } -void WebAssemblyTargetWasmStreamer::emitGlobal(ArrayRef<MVT> Types) { +void WebAssemblyTargetWasmStreamer::emitGlobal( + ArrayRef<wasm::Global> Globals) { // Encode the globals use by the funciton into the special .global_variables // section. This will later be decoded and turned into contents for the // Globals Section. Streamer.PushSection(); Streamer.SwitchSection(Streamer.getContext() .getWasmSection(".global_variables", 0, 0)); - for (MVT Ty : Types) - Streamer.EmitIntValue(int64_t(WebAssembly::toValType(Ty)), 1); + for (const wasm::Global &G : Globals) { + Streamer.EmitIntValue(int32_t(G.Type), 1); + Streamer.EmitIntValue(G.Mutable, 1); + if (G.InitialModule.empty()) { + Streamer.EmitIntValue(0, 1); // indicate that we have an int value + Streamer.EmitSLEB128IntValue(0); + } else { + Streamer.EmitIntValue(1, 1); // indicate that we have a module import + Streamer.EmitBytes(G.InitialModule); + Streamer.EmitIntValue(0, 1); // nul-terminate + Streamer.EmitBytes(G.InitialName); + Streamer.EmitIntValue(0, 1); // nul-terminate + } + } + Streamer.PopSection(); +} + +void WebAssemblyTargetWasmStreamer::emitStackPointer(uint32_t Index) { + Streamer.PushSection(); + Streamer.SwitchSection(Streamer.getContext() + .getWasmSection(".stack_pointer", 0, 0)); + Streamer.EmitIntValue(Index, 4); Streamer.PopSection(); } |