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
16 namespace v8 {
17 namespace internal {
18
PointerSizeDirective()19 DataDirective PointerSizeDirective() {
20 if (kSystemPointerSize == 8) {
21 return kQuad;
22 } else {
23 CHECK_EQ(4, kSystemPointerSize);
24 return kLong;
25 }
26 }
27
HexLiteral(uint64_t value)28 int PlatformEmbeddedFileWriterBase::HexLiteral(uint64_t value) {
29 return fprintf(fp_, "0x%" PRIx64, value);
30 }
31
DataDirectiveSize(DataDirective directive)32 int 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
WriteByteChunk(const uint8_t * data)46 int 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
81 namespace {
82
DefaultEmbeddedTargetArch()83 EmbeddedTargetArch 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
ToEmbeddedTargetArch(const char * s)97 EmbeddedTargetArch 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
DefaultEmbeddedTargetOs()116 EmbeddedTargetOs 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
ToEmbeddedTargetOs(const char * s)128 EmbeddedTargetOs 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
NewPlatformEmbeddedFileWriter(const char * target_arch,const char * target_os)153 std::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