1// Copyright 2019 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/snapshot/embedded/platform-embedded-file-writer-base.h"
6
7#include <string>
8
9#include "src/base/platform/wrappers.h"
10#include "src/common/globals.h"
11#include "src/snapshot/embedded/platform-embedded-file-writer-aix.h"
12#include "src/snapshot/embedded/platform-embedded-file-writer-generic.h"
13#include "src/snapshot/embedded/platform-embedded-file-writer-mac.h"
14#include "src/snapshot/embedded/platform-embedded-file-writer-win.h"
15
16namespace v8 {
17namespace internal {
18
19DataDirective PointerSizeDirective() {
20  if (kSystemPointerSize == 8) {
21    return kQuad;
22  } else {
23    CHECK_EQ(4, kSystemPointerSize);
24    return kLong;
25  }
26}
27
28int PlatformEmbeddedFileWriterBase::HexLiteral(uint64_t value) {
29  return fprintf(fp_, "0x%" PRIx64, value);
30}
31
32int DataDirectiveSize(DataDirective directive) {
33  switch (directive) {
34    case kByte:
35      return 1;
36    case kLong:
37      return 4;
38    case kQuad:
39      return 8;
40    case kOcta:
41      return 16;
42  }
43  UNREACHABLE();
44}
45
46int PlatformEmbeddedFileWriterBase::WriteByteChunk(const uint8_t* data) {
47  size_t kSize = DataDirectiveSize(ByteChunkDataDirective());
48  size_t kHalfSize = kSize / 2;
49  uint64_t high = 0, low = 0;
50
51  switch (kSize) {
52    case 1:
53      low = *data;
54      break;
55    case 4:
56      low = *reinterpret_cast<const uint32_t*>(data);
57      break;
58    case 8:
59      low = *reinterpret_cast<const uint64_t*>(data);
60      break;
61    case 16:
62#ifdef V8_TARGET_BIG_ENDIAN
63      memcpy(&high, data, kHalfSize);
64      memcpy(&low, data + kHalfSize, kHalfSize);
65#else
66      memcpy(&high, data + kHalfSize, kHalfSize);
67      memcpy(&low, data, kHalfSize);
68#endif  // V8_TARGET_BIG_ENDIAN
69      break;
70    default:
71      UNREACHABLE();
72  }
73
74  if (high != 0) {
75    return fprintf(fp(), "0x%" PRIx64 "%016" PRIx64, high, low);
76  } else {
77    return fprintf(fp(), "0x%" PRIx64, low);
78  }
79}
80
81namespace {
82
83EmbeddedTargetArch DefaultEmbeddedTargetArch() {
84#if defined(V8_TARGET_ARCH_ARM)
85  return EmbeddedTargetArch::kArm;
86#elif defined(V8_TARGET_ARCH_ARM64)
87  return EmbeddedTargetArch::kArm64;
88#elif defined(V8_TARGET_ARCH_IA32)
89  return EmbeddedTargetArch::kIA32;
90#elif defined(V8_TARGET_ARCH_X64)
91  return EmbeddedTargetArch::kX64;
92#else
93  return EmbeddedTargetArch::kGeneric;
94#endif
95}
96
97EmbeddedTargetArch ToEmbeddedTargetArch(const char* s) {
98  if (s == nullptr) {
99    return DefaultEmbeddedTargetArch();
100  }
101
102  std::string string(s);
103  if (string == "arm") {
104    return EmbeddedTargetArch::kArm;
105  } else if (string == "arm64") {
106    return EmbeddedTargetArch::kArm64;
107  } else if (string == "ia32") {
108    return EmbeddedTargetArch::kIA32;
109  } else if (string == "x64") {
110    return EmbeddedTargetArch::kX64;
111  } else {
112    return EmbeddedTargetArch::kGeneric;
113  }
114}
115
116EmbeddedTargetOs DefaultEmbeddedTargetOs() {
117#if defined(V8_OS_AIX)
118  return EmbeddedTargetOs::kAIX;
119#elif defined(V8_OS_DARWIN)
120  return EmbeddedTargetOs::kMac;
121#elif defined(V8_OS_WIN)
122  return EmbeddedTargetOs::kWin;
123#else
124  return EmbeddedTargetOs::kGeneric;
125#endif
126}
127
128EmbeddedTargetOs ToEmbeddedTargetOs(const char* s) {
129  if (s == nullptr) {
130    return DefaultEmbeddedTargetOs();
131  }
132
133  std::string string(s);
134  if (string == "aix") {
135    return EmbeddedTargetOs::kAIX;
136  } else if (string == "chromeos") {
137    return EmbeddedTargetOs::kChromeOS;
138  } else if (string == "fuchsia") {
139    return EmbeddedTargetOs::kFuchsia;
140  } else if (string == "ios" || string == "mac") {
141    return EmbeddedTargetOs::kMac;
142  } else if (string == "win") {
143    return EmbeddedTargetOs::kWin;
144  } else if (string == "starboard") {
145    return EmbeddedTargetOs::kStarboard;
146  } else {
147    return EmbeddedTargetOs::kGeneric;
148  }
149}
150
151}  // namespace
152
153std::unique_ptr<PlatformEmbeddedFileWriterBase> NewPlatformEmbeddedFileWriter(
154    const char* target_arch, const char* target_os) {
155  auto embedded_target_arch = ToEmbeddedTargetArch(target_arch);
156  auto embedded_target_os = ToEmbeddedTargetOs(target_os);
157
158  if (embedded_target_os == EmbeddedTargetOs::kStarboard) {
159    // target OS is "Starboard" for all starboard build so we need to
160    // use host OS macros to decide which writer to use.
161    // Cobalt also has Windows-based Posix target platform,
162    // in which case generic writer should be used.
163    switch (DefaultEmbeddedTargetOs()) {
164      case EmbeddedTargetOs::kMac:
165#if defined(V8_TARGET_OS_WIN)
166      case EmbeddedTargetOs::kWin:
167        // V8_TARGET_OS_WIN is used to enable WINDOWS-specific assembly code,
168        // for windows-hosted non-windows targets, we should still fallback to
169        // the generic writer.
170#endif
171        embedded_target_os = DefaultEmbeddedTargetOs();
172        break;
173      default:
174        // In the block below, we will use WriterGeneric for other cases.
175        break;
176    }
177  }
178
179  if (embedded_target_os == EmbeddedTargetOs::kAIX) {
180    return std::make_unique<PlatformEmbeddedFileWriterAIX>(embedded_target_arch,
181                                                           embedded_target_os);
182  } else if (embedded_target_os == EmbeddedTargetOs::kMac) {
183    return std::make_unique<PlatformEmbeddedFileWriterMac>(embedded_target_arch,
184                                                           embedded_target_os);
185  } else if (embedded_target_os == EmbeddedTargetOs::kWin) {
186    return std::make_unique<PlatformEmbeddedFileWriterWin>(embedded_target_arch,
187                                                           embedded_target_os);
188  } else {
189    return std::make_unique<PlatformEmbeddedFileWriterGeneric>(
190        embedded_target_arch, embedded_target_os);
191  }
192
193  UNREACHABLE();
194}
195
196}  // namespace internal
197}  // namespace v8
198