blob: 99a393e8ef959c6fca97a1ea661563470b01639e [file] [log] [blame]
Sam Cleggf61910d2018-01-12 22:18:22 +00001//===- InputChunks.cpp ----------------------------------------------------===//
Sam Cleggc94d3932017-11-17 18:14:09 +00002//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Sam Cleggc94d3932017-11-17 18:14:09 +00006//
7//===----------------------------------------------------------------------===//
8
Sam Clegg5fa274b2018-01-10 01:13:34 +00009#include "InputChunks.h"
Sam Cleggd96d9352018-01-10 19:22:42 +000010#include "Config.h"
Sam Cleggc94d3932017-11-17 18:14:09 +000011#include "OutputSegment.h"
Rui Ueyamabf450d92018-02-20 04:26:26 +000012#include "WriterUtils.h"
Sam Cleggd96d9352018-01-10 19:22:42 +000013#include "lld/Common/ErrorHandler.h"
Sam Cleggc94d3932017-11-17 18:14:09 +000014#include "lld/Common/LLVM.h"
Sam Cleggd96d9352018-01-10 19:22:42 +000015#include "llvm/Support/LEB128.h"
Sam Cleggc94d3932017-11-17 18:14:09 +000016
17#define DEBUG_TYPE "lld"
18
19using namespace llvm;
Sam Cleggd96d9352018-01-10 19:22:42 +000020using namespace llvm::wasm;
Rui Ueyamae351c3a2018-02-16 20:38:15 +000021using namespace llvm::support::endian;
Sam Cleggc94d3932017-11-17 18:14:09 +000022
Fangrui Song33c59ab2019-10-10 05:25:39 +000023namespace lld {
24StringRef relocTypeToString(uint8_t relocType) {
Rui Ueyama136d27a2019-07-11 05:40:30 +000025 switch (relocType) {
Heejin Ahn4821ebf2018-08-29 21:03:16 +000026#define WASM_RELOC(NAME, REL) \
27 case REL: \
28 return #NAME;
Sam Cleggc1be8232018-03-11 01:35:02 +000029#include "llvm/BinaryFormat/WasmRelocs.def"
30#undef WASM_RELOC
31 }
32 llvm_unreachable("unknown reloc type");
33}
34
Fangrui Song33c59ab2019-10-10 05:25:39 +000035std::string toString(const wasm::InputChunk *c) {
Rui Ueyama136d27a2019-07-11 05:40:30 +000036 return (toString(c->file) + ":(" + c->getName() + ")").str();
Rui Ueyama81bee042018-02-19 22:29:48 +000037}
38
Fangrui Song33c59ab2019-10-10 05:25:39 +000039namespace wasm {
Nicholas Wilsonc4d9aa12018-03-14 15:45:11 +000040StringRef InputChunk::getComdatName() const {
Rui Ueyama136d27a2019-07-11 05:40:30 +000041 uint32_t index = getComdat();
42 if (index == UINT32_MAX)
Nicholas Wilsonc4d9aa12018-03-14 15:45:11 +000043 return StringRef();
Rui Ueyama136d27a2019-07-11 05:40:30 +000044 return file->getWasmObj()->linkingData().Comdats[index];
Nicholas Wilsonc4d9aa12018-03-14 15:45:11 +000045}
46
Sam Cleggc1953142018-05-05 00:18:43 +000047void InputChunk::verifyRelocTargets() const {
Rui Ueyama136d27a2019-07-11 05:40:30 +000048 for (const WasmRelocation &rel : relocations) {
49 uint32_t existingValue;
50 unsigned bytesRead = 0;
51 uint32_t offset = rel.Offset - getInputSectionOffset();
52 const uint8_t *loc = data().data() + offset;
53 switch (rel.Type) {
Sam Clegg79e33172019-02-04 17:49:33 +000054 case R_WASM_TYPE_INDEX_LEB:
55 case R_WASM_FUNCTION_INDEX_LEB:
56 case R_WASM_GLOBAL_INDEX_LEB:
57 case R_WASM_EVENT_INDEX_LEB:
58 case R_WASM_MEMORY_ADDR_LEB:
Rui Ueyama136d27a2019-07-11 05:40:30 +000059 existingValue = decodeULEB128(loc, &bytesRead);
Sam Cleggc1953142018-05-05 00:18:43 +000060 break;
Sam Clegg79e33172019-02-04 17:49:33 +000061 case R_WASM_TABLE_INDEX_SLEB:
Sam Clegg2a7cac92019-04-04 17:43:50 +000062 case R_WASM_TABLE_INDEX_REL_SLEB:
Sam Clegg79e33172019-02-04 17:49:33 +000063 case R_WASM_MEMORY_ADDR_SLEB:
Sam Clegg2a7cac92019-04-04 17:43:50 +000064 case R_WASM_MEMORY_ADDR_REL_SLEB:
Rui Ueyama136d27a2019-07-11 05:40:30 +000065 existingValue = static_cast<uint32_t>(decodeSLEB128(loc, &bytesRead));
Sam Cleggc1953142018-05-05 00:18:43 +000066 break;
Sam Clegg79e33172019-02-04 17:49:33 +000067 case R_WASM_TABLE_INDEX_I32:
68 case R_WASM_MEMORY_ADDR_I32:
69 case R_WASM_FUNCTION_OFFSET_I32:
70 case R_WASM_SECTION_OFFSET_I32:
Rui Ueyama136d27a2019-07-11 05:40:30 +000071 existingValue = static_cast<uint32_t>(read32le(loc));
Sam Cleggc1953142018-05-05 00:18:43 +000072 break;
73 default:
74 llvm_unreachable("unknown relocation type");
75 }
76
Rui Ueyama136d27a2019-07-11 05:40:30 +000077 if (bytesRead && bytesRead != 5)
Sam Cleggc1953142018-05-05 00:18:43 +000078 warn("expected LEB at relocation site be 5-byte padded");
Sam Clegg492f7522019-03-26 19:46:15 +000079
Rui Ueyama136d27a2019-07-11 05:40:30 +000080 if (rel.Type != R_WASM_GLOBAL_INDEX_LEB) {
81 uint32_t expectedValue = file->calcExpectedValue(rel);
82 if (expectedValue != existingValue)
83 warn("unexpected existing value for " + relocTypeToString(rel.Type) +
84 ": existing=" + Twine(existingValue) +
85 " expected=" + Twine(expectedValue));
Sam Clegg492f7522019-03-26 19:46:15 +000086 }
Sam Cleggc1953142018-05-05 00:18:43 +000087 }
88}
89
Rui Ueyamabf450d92018-02-20 04:26:26 +000090// Copy this input chunk to an mmap'ed output file and apply relocations.
Rui Ueyama136d27a2019-07-11 05:40:30 +000091void InputChunk::writeTo(uint8_t *buf) const {
Rui Ueyamabf450d92018-02-20 04:26:26 +000092 // Copy contents
Rui Ueyama136d27a2019-07-11 05:40:30 +000093 memcpy(buf + outputOffset, data().data(), data().size());
Rui Ueyamac06d94a2018-02-19 22:39:52 +000094
Rui Ueyamabf450d92018-02-20 04:26:26 +000095 // Apply relocations
Rui Ueyama136d27a2019-07-11 05:40:30 +000096 if (relocations.empty())
Rui Ueyamabf450d92018-02-20 04:26:26 +000097 return;
Rui Ueyamac06d94a2018-02-19 22:39:52 +000098
Sam Cleggc1953142018-05-05 00:18:43 +000099#ifndef NDEBUG
100 verifyRelocTargets();
101#endif
102
Sam Cleggcf2b8722019-08-20 18:39:24 +0000103 LLVM_DEBUG(dbgs() << "applying relocations: " << toString(this)
Rui Ueyama136d27a2019-07-11 05:40:30 +0000104 << " count=" << relocations.size() << "\n");
105 int32_t off = outputOffset - getInputSectionOffset();
Rui Ueyamabf450d92018-02-20 04:26:26 +0000106
Rui Ueyama136d27a2019-07-11 05:40:30 +0000107 for (const WasmRelocation &rel : relocations) {
108 uint8_t *loc = buf + rel.Offset + off;
109 uint32_t value = file->calcNewValue(rel);
110 LLVM_DEBUG(dbgs() << "apply reloc: type=" << relocTypeToString(rel.Type));
111 if (rel.Type != R_WASM_TYPE_INDEX_LEB)
112 LLVM_DEBUG(dbgs() << " sym=" << file->getSymbols()[rel.Index]->getName());
113 LLVM_DEBUG(dbgs() << " addend=" << rel.Addend << " index=" << rel.Index
114 << " value=" << value << " offset=" << rel.Offset
Nicola Zaghene7245b42018-05-15 13:36:20 +0000115 << "\n");
Rui Ueyamabf450d92018-02-20 04:26:26 +0000116
Rui Ueyama136d27a2019-07-11 05:40:30 +0000117 switch (rel.Type) {
Sam Clegg79e33172019-02-04 17:49:33 +0000118 case R_WASM_TYPE_INDEX_LEB:
119 case R_WASM_FUNCTION_INDEX_LEB:
120 case R_WASM_GLOBAL_INDEX_LEB:
121 case R_WASM_EVENT_INDEX_LEB:
122 case R_WASM_MEMORY_ADDR_LEB:
Rui Ueyama136d27a2019-07-11 05:40:30 +0000123 encodeULEB128(value, loc, 5);
Rui Ueyamabf450d92018-02-20 04:26:26 +0000124 break;
Sam Clegg79e33172019-02-04 17:49:33 +0000125 case R_WASM_TABLE_INDEX_SLEB:
Sam Clegg2a7cac92019-04-04 17:43:50 +0000126 case R_WASM_TABLE_INDEX_REL_SLEB:
Sam Clegg79e33172019-02-04 17:49:33 +0000127 case R_WASM_MEMORY_ADDR_SLEB:
Sam Clegg2a7cac92019-04-04 17:43:50 +0000128 case R_WASM_MEMORY_ADDR_REL_SLEB:
Rui Ueyama136d27a2019-07-11 05:40:30 +0000129 encodeSLEB128(static_cast<int32_t>(value), loc, 5);
Rui Ueyamabf450d92018-02-20 04:26:26 +0000130 break;
Sam Clegg79e33172019-02-04 17:49:33 +0000131 case R_WASM_TABLE_INDEX_I32:
132 case R_WASM_MEMORY_ADDR_I32:
133 case R_WASM_FUNCTION_OFFSET_I32:
134 case R_WASM_SECTION_OFFSET_I32:
Rui Ueyama136d27a2019-07-11 05:40:30 +0000135 write32le(loc, value);
Rui Ueyamabf450d92018-02-20 04:26:26 +0000136 break;
137 default:
138 llvm_unreachable("unknown relocation type");
Sam Cleggd96d9352018-01-10 19:22:42 +0000139 }
Sam Cleggd96d9352018-01-10 19:22:42 +0000140 }
141}
142
Rui Ueyamabf450d92018-02-20 04:26:26 +0000143// Copy relocation entries to a given output stream.
144// This function is used only when a user passes "-r". For a regular link,
145// we consume relocations instead of copying them to an output file.
Rui Ueyama136d27a2019-07-11 05:40:30 +0000146void InputChunk::writeRelocations(raw_ostream &os) const {
147 if (relocations.empty())
Sam Clegg50686852018-01-12 18:35:13 +0000148 return;
Rui Ueyamabf450d92018-02-20 04:26:26 +0000149
Rui Ueyama136d27a2019-07-11 05:40:30 +0000150 int32_t off = outputOffset - getInputSectionOffset();
151 LLVM_DEBUG(dbgs() << "writeRelocations: " << file->getName()
152 << " offset=" << Twine(off) << "\n");
Sam Cleggd96d9352018-01-10 19:22:42 +0000153
Rui Ueyama136d27a2019-07-11 05:40:30 +0000154 for (const WasmRelocation &rel : relocations) {
155 writeUleb128(os, rel.Type, "reloc type");
156 writeUleb128(os, rel.Offset + off, "reloc offset");
157 writeUleb128(os, file->calcNewIndex(rel), "reloc index");
Sam Cleggd96d9352018-01-10 19:22:42 +0000158
Rui Ueyama136d27a2019-07-11 05:40:30 +0000159 if (relocTypeHasAddend(rel.Type))
160 writeSleb128(os, file->calcNewAddend(rel), "reloc addend");
Sam Cleggd96d9352018-01-10 19:22:42 +0000161 }
162}
Sam Clegg50686852018-01-12 18:35:13 +0000163
Rui Ueyama136d27a2019-07-11 05:40:30 +0000164void InputFunction::setFunctionIndex(uint32_t index) {
Nicola Zaghene7245b42018-05-15 13:36:20 +0000165 LLVM_DEBUG(dbgs() << "InputFunction::setFunctionIndex: " << getName()
Rui Ueyama136d27a2019-07-11 05:40:30 +0000166 << " -> " << index << "\n");
Sam Clegge3f3ccf2018-03-12 19:56:23 +0000167 assert(!hasFunctionIndex());
Rui Ueyama136d27a2019-07-11 05:40:30 +0000168 functionIndex = index;
Eric Christopher9ea500b2018-01-13 00:44:45 +0000169}
Sam Clegg67abf532018-01-24 21:45:25 +0000170
Rui Ueyama136d27a2019-07-11 05:40:30 +0000171void InputFunction::setTableIndex(uint32_t index) {
Nicola Zaghene7245b42018-05-15 13:36:20 +0000172 LLVM_DEBUG(dbgs() << "InputFunction::setTableIndex: " << getName() << " -> "
Rui Ueyama136d27a2019-07-11 05:40:30 +0000173 << index << "\n");
Sam Clegg67abf532018-01-24 21:45:25 +0000174 assert(!hasTableIndex());
Rui Ueyama136d27a2019-07-11 05:40:30 +0000175 tableIndex = index;
Sam Clegg67abf532018-01-24 21:45:25 +0000176}
Sam Cleggfb983cd2018-05-18 23:28:05 +0000177
178// Write a relocation value without padding and return the number of bytes
179// witten.
Rui Ueyama136d27a2019-07-11 05:40:30 +0000180static unsigned writeCompressedReloc(uint8_t *buf, const WasmRelocation &rel,
181 uint32_t value) {
182 switch (rel.Type) {
Sam Clegg79e33172019-02-04 17:49:33 +0000183 case R_WASM_TYPE_INDEX_LEB:
184 case R_WASM_FUNCTION_INDEX_LEB:
185 case R_WASM_GLOBAL_INDEX_LEB:
186 case R_WASM_EVENT_INDEX_LEB:
187 case R_WASM_MEMORY_ADDR_LEB:
Rui Ueyama136d27a2019-07-11 05:40:30 +0000188 return encodeULEB128(value, buf);
Sam Clegg79e33172019-02-04 17:49:33 +0000189 case R_WASM_TABLE_INDEX_SLEB:
190 case R_WASM_MEMORY_ADDR_SLEB:
Rui Ueyama136d27a2019-07-11 05:40:30 +0000191 return encodeSLEB128(static_cast<int32_t>(value), buf);
Sam Cleggfb983cd2018-05-18 23:28:05 +0000192 default:
Sam Cleggf3770302018-05-22 20:52:20 +0000193 llvm_unreachable("unexpected relocation type");
Sam Cleggfb983cd2018-05-18 23:28:05 +0000194 }
195}
196
Rui Ueyama136d27a2019-07-11 05:40:30 +0000197static unsigned getRelocWidthPadded(const WasmRelocation &rel) {
198 switch (rel.Type) {
Sam Clegg79e33172019-02-04 17:49:33 +0000199 case R_WASM_TYPE_INDEX_LEB:
200 case R_WASM_FUNCTION_INDEX_LEB:
201 case R_WASM_GLOBAL_INDEX_LEB:
202 case R_WASM_EVENT_INDEX_LEB:
203 case R_WASM_MEMORY_ADDR_LEB:
204 case R_WASM_TABLE_INDEX_SLEB:
205 case R_WASM_MEMORY_ADDR_SLEB:
Sam Cleggfb983cd2018-05-18 23:28:05 +0000206 return 5;
Sam Cleggfb983cd2018-05-18 23:28:05 +0000207 default:
Sam Cleggf3770302018-05-22 20:52:20 +0000208 llvm_unreachable("unexpected relocation type");
Sam Cleggfb983cd2018-05-18 23:28:05 +0000209 }
210}
211
Rui Ueyama136d27a2019-07-11 05:40:30 +0000212static unsigned getRelocWidth(const WasmRelocation &rel, uint32_t value) {
213 uint8_t buf[5];
214 return writeCompressedReloc(buf, rel, value);
Sam Cleggfb983cd2018-05-18 23:28:05 +0000215}
216
217// Relocations of type LEB and SLEB in the code section are padded to 5 bytes
218// so that a fast linker can blindly overwrite them without needing to worry
219// about the number of bytes needed to encode the values.
220// However, for optimal output the code section can be compressed to remove
221// the padding then outputting non-relocatable files.
222// In this case we need to perform a size calculation based on the value at each
223// relocation. At best we end up saving 4 bytes for each relocation entry.
224//
225// This function only computes the final output size. It must be called
226// before getSize() is used to calculate of layout of the code section.
227void InputFunction::calculateSize() {
Rui Ueyama136d27a2019-07-11 05:40:30 +0000228 if (!file || !config->compressRelocations)
Sam Cleggfb983cd2018-05-18 23:28:05 +0000229 return;
230
Nicola Zaghen5c4fb452018-05-23 14:03:01 +0000231 LLVM_DEBUG(dbgs() << "calculateSize: " << getName() << "\n");
Sam Cleggfb983cd2018-05-18 23:28:05 +0000232
Rui Ueyama136d27a2019-07-11 05:40:30 +0000233 const uint8_t *secStart = file->codeSection->Content.data();
234 const uint8_t *funcStart = secStart + getInputSectionOffset();
235 uint32_t functionSizeLength;
236 decodeULEB128(funcStart, &functionSizeLength);
Sam Cleggfb983cd2018-05-18 23:28:05 +0000237
Rui Ueyama136d27a2019-07-11 05:40:30 +0000238 uint32_t start = getInputSectionOffset();
239 uint32_t end = start + function->Size;
Sam Cleggfb983cd2018-05-18 23:28:05 +0000240
Rui Ueyama136d27a2019-07-11 05:40:30 +0000241 uint32_t lastRelocEnd = start + functionSizeLength;
242 for (const WasmRelocation &rel : relocations) {
243 LLVM_DEBUG(dbgs() << " region: " << (rel.Offset - lastRelocEnd) << "\n");
244 compressedFuncSize += rel.Offset - lastRelocEnd;
245 compressedFuncSize += getRelocWidth(rel, file->calcNewValue(rel));
246 lastRelocEnd = rel.Offset + getRelocWidthPadded(rel);
Sam Cleggfb983cd2018-05-18 23:28:05 +0000247 }
Rui Ueyama136d27a2019-07-11 05:40:30 +0000248 LLVM_DEBUG(dbgs() << " final region: " << (end - lastRelocEnd) << "\n");
249 compressedFuncSize += end - lastRelocEnd;
Sam Cleggfb983cd2018-05-18 23:28:05 +0000250
251 // Now we know how long the resulting function is we can add the encoding
252 // of its length
Rui Ueyama136d27a2019-07-11 05:40:30 +0000253 uint8_t buf[5];
254 compressedSize = compressedFuncSize + encodeULEB128(compressedFuncSize, buf);
Sam Cleggfb983cd2018-05-18 23:28:05 +0000255
Rui Ueyama136d27a2019-07-11 05:40:30 +0000256 LLVM_DEBUG(dbgs() << " calculateSize orig: " << function->Size << "\n");
257 LLVM_DEBUG(dbgs() << " calculateSize new: " << compressedSize << "\n");
Sam Cleggfb983cd2018-05-18 23:28:05 +0000258}
259
260// Override the default writeTo method so that we can (optionally) write the
261// compressed version of the function.
Rui Ueyama136d27a2019-07-11 05:40:30 +0000262void InputFunction::writeTo(uint8_t *buf) const {
263 if (!file || !config->compressRelocations)
264 return InputChunk::writeTo(buf);
Sam Cleggfb983cd2018-05-18 23:28:05 +0000265
Rui Ueyama136d27a2019-07-11 05:40:30 +0000266 buf += outputOffset;
267 uint8_t *orig = buf;
268 (void)orig;
Sam Cleggfb983cd2018-05-18 23:28:05 +0000269
Rui Ueyama136d27a2019-07-11 05:40:30 +0000270 const uint8_t *secStart = file->codeSection->Content.data();
271 const uint8_t *funcStart = secStart + getInputSectionOffset();
272 const uint8_t *end = funcStart + function->Size;
273 uint32_t count;
274 decodeULEB128(funcStart, &count);
275 funcStart += count;
Sam Cleggfb983cd2018-05-18 23:28:05 +0000276
Nicola Zaghen5c4fb452018-05-23 14:03:01 +0000277 LLVM_DEBUG(dbgs() << "write func: " << getName() << "\n");
Rui Ueyama136d27a2019-07-11 05:40:30 +0000278 buf += encodeULEB128(compressedFuncSize, buf);
279 const uint8_t *lastRelocEnd = funcStart;
280 for (const WasmRelocation &rel : relocations) {
281 unsigned chunkSize = (secStart + rel.Offset) - lastRelocEnd;
282 LLVM_DEBUG(dbgs() << " write chunk: " << chunkSize << "\n");
283 memcpy(buf, lastRelocEnd, chunkSize);
284 buf += chunkSize;
285 buf += writeCompressedReloc(buf, rel, file->calcNewValue(rel));
286 lastRelocEnd = secStart + rel.Offset + getRelocWidthPadded(rel);
Sam Cleggfb983cd2018-05-18 23:28:05 +0000287 }
288
Rui Ueyama136d27a2019-07-11 05:40:30 +0000289 unsigned chunkSize = end - lastRelocEnd;
290 LLVM_DEBUG(dbgs() << " write final chunk: " << chunkSize << "\n");
291 memcpy(buf, lastRelocEnd, chunkSize);
292 LLVM_DEBUG(dbgs() << " total: " << (buf + chunkSize - orig) << "\n");
Sam Cleggfb983cd2018-05-18 23:28:05 +0000293}
Sam Clegg09137be2019-04-04 18:40:51 +0000294
295// Generate code to apply relocations to the data section at runtime.
296// This is only called when generating shared libaries (PIC) where address are
297// not known at static link time.
Rui Ueyama136d27a2019-07-11 05:40:30 +0000298void InputSegment::generateRelocationCode(raw_ostream &os) const {
Sam Cleggb685ddf2019-04-25 17:11:54 +0000299 LLVM_DEBUG(dbgs() << "generating runtime relocations: " << getName()
Rui Ueyama136d27a2019-07-11 05:40:30 +0000300 << " count=" << relocations.size() << "\n");
Sam Cleggb685ddf2019-04-25 17:11:54 +0000301
302 // TODO(sbc): Encode the relocations in the data section and write a loop
303 // here to apply them.
Rui Ueyama136d27a2019-07-11 05:40:30 +0000304 uint32_t segmentVA = outputSeg->startVA + outputSegmentOffset;
305 for (const WasmRelocation &rel : relocations) {
306 uint32_t offset = rel.Offset - getInputSectionOffset();
307 uint32_t outputOffset = segmentVA + offset;
Sam Cleggb685ddf2019-04-25 17:11:54 +0000308
Rui Ueyama136d27a2019-07-11 05:40:30 +0000309 LLVM_DEBUG(dbgs() << "gen reloc: type=" << relocTypeToString(rel.Type)
310 << " addend=" << rel.Addend << " index=" << rel.Index
311 << " output offset=" << outputOffset << "\n");
Sam Clegg09137be2019-04-04 18:40:51 +0000312
313 // Get __memory_base
Rui Ueyama136d27a2019-07-11 05:40:30 +0000314 writeU8(os, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET");
315 writeUleb128(os, WasmSym::memoryBase->getGlobalIndex(), "memory_base");
Sam Clegg09137be2019-04-04 18:40:51 +0000316
317 // Add the offset of the relocation
Rui Ueyama136d27a2019-07-11 05:40:30 +0000318 writeU8(os, WASM_OPCODE_I32_CONST, "I32_CONST");
319 writeSleb128(os, outputOffset, "offset");
320 writeU8(os, WASM_OPCODE_I32_ADD, "ADD");
Sam Clegg09137be2019-04-04 18:40:51 +0000321
Rui Ueyama136d27a2019-07-11 05:40:30 +0000322 Symbol *sym = file->getSymbol(rel);
Sam Clegg09137be2019-04-04 18:40:51 +0000323 // Now figure out what we want to store
Rui Ueyama136d27a2019-07-11 05:40:30 +0000324 if (sym->hasGOTIndex()) {
325 writeU8(os, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET");
326 writeUleb128(os, sym->getGOTIndex(), "global index");
327 if (rel.Addend) {
328 writeU8(os, WASM_OPCODE_I32_CONST, "CONST");
329 writeSleb128(os, rel.Addend, "addend");
330 writeU8(os, WASM_OPCODE_I32_ADD, "ADD");
Sam Clegg09137be2019-04-04 18:40:51 +0000331 }
Sam Cleggb685ddf2019-04-25 17:11:54 +0000332 } else {
Rui Ueyama136d27a2019-07-11 05:40:30 +0000333 const GlobalSymbol* baseSymbol = WasmSym::memoryBase;
334 if (rel.Type == R_WASM_TABLE_INDEX_I32)
335 baseSymbol = WasmSym::tableBase;
336 writeU8(os, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET");
337 writeUleb128(os, baseSymbol->getGlobalIndex(), "base");
338 writeU8(os, WASM_OPCODE_I32_CONST, "CONST");
339 writeSleb128(os, file->calcNewValue(rel), "offset");
340 writeU8(os, WASM_OPCODE_I32_ADD, "ADD");
Sam Clegg09137be2019-04-04 18:40:51 +0000341 }
342
343 // Store that value at the virtual address
Rui Ueyama136d27a2019-07-11 05:40:30 +0000344 writeU8(os, WASM_OPCODE_I32_STORE, "I32_STORE");
345 writeUleb128(os, 2, "align");
346 writeUleb128(os, 0, "offset");
Sam Clegg09137be2019-04-04 18:40:51 +0000347 }
348}
Fangrui Song33c59ab2019-10-10 05:25:39 +0000349
350} // namespace wasm
351} // namespace lld