1// Copyright 2017 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "src/wasm/local-decl-encoder.h"
6
7#include "src/base/platform/wrappers.h"
8#include "src/codegen/signature.h"
9#include "src/wasm/leb-helper.h"
10
11namespace v8 {
12namespace internal {
13namespace wasm {
14
15// This struct is just a type tag for Zone::NewArray<T>(size_t) call.
16struct LocalDeclEncoderBuffer {};
17
18void LocalDeclEncoder::Prepend(Zone* zone, const byte** start,
19                               const byte** end) const {
20  size_t size = (*end - *start);
21  byte* buffer = zone->NewArray<byte, LocalDeclEncoderBuffer>(Size() + size);
22  size_t pos = Emit(buffer);
23  if (size > 0) {
24    memcpy(buffer + pos, *start, size);
25  }
26  pos += size;
27  *start = buffer;
28  *end = buffer + pos;
29}
30
31size_t LocalDeclEncoder::Emit(byte* buffer) const {
32  byte* pos = buffer;
33  LEBHelper::write_u32v(&pos, static_cast<uint32_t>(local_decls.size()));
34  for (auto& local_decl : local_decls) {
35    uint32_t locals_count = local_decl.first;
36    ValueType locals_type = local_decl.second;
37    LEBHelper::write_u32v(&pos, locals_count);
38    *pos = locals_type.value_type_code();
39    ++pos;
40    if (locals_type.is_rtt()) {
41      LEBHelper::write_u32v(&pos, locals_type.ref_index());
42    }
43    if (locals_type.encoding_needs_heap_type()) {
44      LEBHelper::write_i32v(&pos, locals_type.heap_type().code());
45    }
46  }
47  DCHECK_EQ(Size(), pos - buffer);
48  return static_cast<size_t>(pos - buffer);
49}
50
51uint32_t LocalDeclEncoder::AddLocals(uint32_t count, ValueType type) {
52  uint32_t result =
53      static_cast<uint32_t>(total + (sig ? sig->parameter_count() : 0));
54  total += count;
55  if (local_decls.size() > 0 && local_decls.back().second == type) {
56    count += local_decls.back().first;
57    local_decls.pop_back();
58  }
59  local_decls.push_back(std::pair<uint32_t, ValueType>(count, type));
60  return result;
61}
62
63// Size = (size of locals count) +
64// (for each local pair <reps, type>, (size of reps) + (size of type))
65size_t LocalDeclEncoder::Size() const {
66  size_t size = LEBHelper::sizeof_u32v(local_decls.size());
67  for (auto p : local_decls) {
68    size +=
69        LEBHelper::sizeof_u32v(p.first) +  // number of locals
70        1 +                                // Opcode
71        (p.second.encoding_needs_heap_type()
72             ? LEBHelper::sizeof_i32v(p.second.heap_type().code())
73             : 0) +
74        (p.second.is_rtt() ? LEBHelper::sizeof_u32v(p.second.ref_index()) : 0);
75  }
76  return size;
77}
78
79}  // namespace wasm
80}  // namespace internal
81}  // namespace v8
82