118eafb6cSDan Gohman //===-- WebAssemblyWasmObjectWriter.cpp - WebAssembly Wasm Writer ---------===//
218eafb6cSDan Gohman //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
618eafb6cSDan Gohman //
718eafb6cSDan Gohman //===----------------------------------------------------------------------===//
818eafb6cSDan Gohman ///
918eafb6cSDan Gohman /// \file
105f8f34e4SAdrian Prantl /// This file handles Wasm-specific object emission, converting LLVM's
1118eafb6cSDan Gohman /// internal fixups into the appropriate relocations.
1218eafb6cSDan Gohman ///
1318eafb6cSDan Gohman //===----------------------------------------------------------------------===//
1418eafb6cSDan Gohman 
15d934cb88SDan Gohman #include "MCTargetDesc/WebAssemblyFixupKinds.h"
166bda14b3SChandler Carruth #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
17264b5d9eSZachary Turner #include "llvm/BinaryFormat/Wasm.h"
18ae03c1e7SSam Clegg #include "llvm/MC/MCAsmBackend.h"
1918eafb6cSDan Gohman #include "llvm/MC/MCFixup.h"
20ae03c1e7SSam Clegg #include "llvm/MC/MCFixupKindInfo.h"
21669300dbSDerek Schuff #include "llvm/MC/MCObjectWriter.h"
226a31a0d6SSam Clegg #include "llvm/MC/MCSectionWasm.h"
23d934cb88SDan Gohman #include "llvm/MC/MCSymbolWasm.h"
24ae03c1e7SSam Clegg #include "llvm/MC/MCValue.h"
256a31a0d6SSam Clegg #include "llvm/MC/MCWasmObjectWriter.h"
26d934cb88SDan Gohman #include "llvm/Support/Casting.h"
2718eafb6cSDan Gohman #include "llvm/Support/ErrorHandling.h"
28ae03c1e7SSam Clegg 
2918eafb6cSDan Gohman using namespace llvm;
3018eafb6cSDan Gohman 
3118eafb6cSDan Gohman namespace {
3218eafb6cSDan Gohman class WebAssemblyWasmObjectWriter final : public MCWasmObjectTargetWriter {
3318eafb6cSDan Gohman public:
3418eafb6cSDan Gohman   explicit WebAssemblyWasmObjectWriter(bool Is64Bit);
3518eafb6cSDan Gohman 
3618eafb6cSDan Gohman private:
37ae03c1e7SSam Clegg   unsigned getRelocType(const MCValue &Target,
38ae03c1e7SSam Clegg                         const MCFixup &Fixup) const override;
3918eafb6cSDan Gohman };
4018eafb6cSDan Gohman } // end anonymous namespace
4118eafb6cSDan Gohman 
4218eafb6cSDan Gohman WebAssemblyWasmObjectWriter::WebAssemblyWasmObjectWriter(bool Is64Bit)
4318eafb6cSDan Gohman     : MCWasmObjectTargetWriter(Is64Bit) {}
4418eafb6cSDan Gohman 
45*8fffa1dfSSam Clegg static bool isFunctionSignatureRef(const MCSymbolRefExpr *Ref) {
46*8fffa1dfSSam Clegg   return Ref->getKind() == MCSymbolRefExpr::VK_WebAssembly_TYPEINDEX;
47acd7d2b0SSam Clegg }
48acd7d2b0SSam Clegg 
4918c56a07SHeejin Ahn static const MCSection *getFixupSection(const MCExpr *Expr) {
506a31a0d6SSam Clegg   if (auto SyExp = dyn_cast<MCSymbolRefExpr>(Expr)) {
516a31a0d6SSam Clegg     if (SyExp->getSymbol().isInSection())
526a31a0d6SSam Clegg       return &SyExp->getSymbol().getSection();
536a31a0d6SSam Clegg     return nullptr;
546a31a0d6SSam Clegg   }
556a31a0d6SSam Clegg 
566a31a0d6SSam Clegg   if (auto BinOp = dyn_cast<MCBinaryExpr>(Expr)) {
5718c56a07SHeejin Ahn     auto SectionLHS = getFixupSection(BinOp->getLHS());
5818c56a07SHeejin Ahn     auto SectionRHS = getFixupSection(BinOp->getRHS());
596a31a0d6SSam Clegg     return SectionLHS == SectionRHS ? nullptr : SectionLHS;
606a31a0d6SSam Clegg   }
616a31a0d6SSam Clegg 
626a31a0d6SSam Clegg   if (auto UnOp = dyn_cast<MCUnaryExpr>(Expr))
6318c56a07SHeejin Ahn     return getFixupSection(UnOp->getSubExpr());
646a31a0d6SSam Clegg 
656a31a0d6SSam Clegg   return nullptr;
666a31a0d6SSam Clegg }
676a31a0d6SSam Clegg 
68f208f631SHeejin Ahn unsigned WebAssemblyWasmObjectWriter::getRelocType(const MCValue &Target,
69ae03c1e7SSam Clegg                                                    const MCFixup &Fixup) const {
70*8fffa1dfSSam Clegg   const MCSymbolRefExpr *RefA = Target.getSymA();
71*8fffa1dfSSam Clegg   assert(RefA);
72*8fffa1dfSSam Clegg   auto& SymA = cast<MCSymbolWasm>(RefA->getSymbol());
73d934cb88SDan Gohman 
74d934cb88SDan Gohman   switch (unsigned(Fixup.getKind())) {
75d934cb88SDan Gohman   case WebAssembly::fixup_code_sleb128_i32:
76*8fffa1dfSSam Clegg     if (SymA.isFunction())
77d1152a26SSam Clegg       return wasm::R_WASM_TABLE_INDEX_SLEB;
78d1152a26SSam Clegg     return wasm::R_WASM_MEMORY_ADDR_SLEB;
79d934cb88SDan Gohman   case WebAssembly::fixup_code_sleb128_i64:
80d934cb88SDan Gohman     llvm_unreachable("fixup_sleb128_i64 not implemented yet");
81d934cb88SDan Gohman   case WebAssembly::fixup_code_uleb128_i32:
82*8fffa1dfSSam Clegg     if (SymA.isFunction()) {
83*8fffa1dfSSam Clegg       if (isFunctionSignatureRef(RefA))
84d1152a26SSam Clegg         return wasm::R_WASM_TYPE_INDEX_LEB;
85*8fffa1dfSSam Clegg       else
86d1152a26SSam Clegg         return wasm::R_WASM_FUNCTION_INDEX_LEB;
87*8fffa1dfSSam Clegg     }
88*8fffa1dfSSam Clegg     if (SymA.isGlobal())
89*8fffa1dfSSam Clegg       return wasm::R_WASM_GLOBAL_INDEX_LEB;
90*8fffa1dfSSam Clegg     if (SymA.isEvent())
91d1152a26SSam Clegg       return wasm::R_WASM_EVENT_INDEX_LEB;
92d1152a26SSam Clegg     return wasm::R_WASM_MEMORY_ADDR_LEB;
93d934cb88SDan Gohman   case FK_Data_4:
94*8fffa1dfSSam Clegg     if (SymA.isFunction())
95d1152a26SSam Clegg       return wasm::R_WASM_TABLE_INDEX_I32;
966a31a0d6SSam Clegg     if (auto Section = static_cast<const MCSectionWasm *>(
9718c56a07SHeejin Ahn             getFixupSection(Fixup.getValue()))) {
986a31a0d6SSam Clegg       if (Section->getKind().isText())
99d1152a26SSam Clegg         return wasm::R_WASM_FUNCTION_OFFSET_I32;
1006a31a0d6SSam Clegg       else if (!Section->isWasmData())
101d1152a26SSam Clegg         return wasm::R_WASM_SECTION_OFFSET_I32;
1026a31a0d6SSam Clegg     }
103d1152a26SSam Clegg     return wasm::R_WASM_MEMORY_ADDR_I32;
104d934cb88SDan Gohman   case FK_Data_8:
105d934cb88SDan Gohman     llvm_unreachable("FK_Data_8 not implemented yet");
106d934cb88SDan Gohman   default:
107d934cb88SDan Gohman     llvm_unreachable("unimplemented fixup kind");
108d934cb88SDan Gohman   }
10918eafb6cSDan Gohman }
11018eafb6cSDan Gohman 
111dcd7d6c3SPeter Collingbourne std::unique_ptr<MCObjectTargetWriter>
112dcd7d6c3SPeter Collingbourne llvm::createWebAssemblyWasmObjectWriter(bool Is64Bit) {
113dcd7d6c3SPeter Collingbourne   return llvm::make_unique<WebAssemblyWasmObjectWriter>(Is64Bit);
11418eafb6cSDan Gohman }
115