LCOV - code coverage report
Current view: top level - src/snapshot - embedded-file-writer.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 62 67 92.5 %
Date: 2019-04-19 Functions: 20 21 95.2 %

          Line data    Source code
       1             : // Copyright 2018 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-file-writer.h"
       6             : 
       7             : #include <algorithm>
       8             : #include <cinttypes>
       9             : 
      10             : #include "src/objects/code-inl.h"
      11             : 
      12             : namespace v8 {
      13             : namespace internal {
      14             : 
      15             : // V8_CC_MSVC is true for both MSVC and clang on windows. clang can handle
      16             : // __asm__-style inline assembly but MSVC cannot, and thus we need a more
      17             : // precise compiler detection that can distinguish between the two. clang on
      18             : // windows sets both __clang__ and _MSC_VER, MSVC sets only _MSC_VER.
      19             : #if defined(_MSC_VER) && !defined(__clang__)
      20             : #define V8_COMPILER_IS_MSVC
      21             : #endif
      22             : 
      23             : // MSVC uses MASM for x86 and x64, while it has a ARMASM for ARM32 and
      24             : // ARMASM64 for ARM64. Since ARMASM and ARMASM64 accept a slightly tweaked
      25             : // version of ARM assembly language, they are referred to together in Visual
      26             : // Studio project files as MARMASM.
      27             : //
      28             : // ARM assembly language docs:
      29             : // http://infocenter.arm.com/help/topic/com.arm.doc.dui0802b/index.html
      30             : // Microsoft ARM assembler and assembly language docs:
      31             : // https://docs.microsoft.com/en-us/cpp/assembler/arm/arm-assembler-reference
      32             : #if defined(V8_COMPILER_IS_MSVC)
      33             : #if defined(V8_TARGET_ARCH_ARM64) || defined(V8_TARGET_ARCH_ARM)
      34             : #define V8_ASSEMBLER_IS_MARMASM
      35             : #elif defined(V8_TARGET_ARCH_IA32) || defined(V8_TARGET_ARCH_X64)
      36             : #define V8_ASSEMBLER_IS_MASM
      37             : #else
      38             : #error Unknown Windows assembler target architecture.
      39             : #endif
      40             : #endif
      41             : 
      42             : // Name mangling.
      43             : // Symbols are prefixed with an underscore on 32-bit architectures.
      44             : #if defined(V8_TARGET_OS_WIN) && !defined(V8_TARGET_ARCH_X64) && \
      45             :     !defined(V8_TARGET_ARCH_ARM64)
      46             : #define SYMBOL_PREFIX "_"
      47             : #else
      48             : #define SYMBOL_PREFIX ""
      49             : #endif
      50             : 
      51             : // Platform-independent bits.
      52             : // -----------------------------------------------------------------------------
      53             : 
      54             : namespace {
      55             : 
      56             : DataDirective PointerSizeDirective() {
      57             :   if (kSystemPointerSize == 8) {
      58             :     return kQuad;
      59             :   } else {
      60             :     CHECK_EQ(4, kSystemPointerSize);
      61             :     return kLong;
      62             :   }
      63             : }
      64             : 
      65             : }  // namespace
      66             : 
      67       38663 : const char* DirectiveAsString(DataDirective directive) {
      68             : #if defined(V8_TARGET_OS_WIN) && defined(V8_ASSEMBLER_IS_MASM)
      69             :   switch (directive) {
      70             :     case kByte:
      71             :       return "BYTE";
      72             :     case kLong:
      73             :       return "DWORD";
      74             :     case kQuad:
      75             :       return "QWORD";
      76             :     default:
      77             :       UNREACHABLE();
      78             :   }
      79             : #elif defined(V8_TARGET_OS_WIN) && defined(V8_ASSEMBLER_IS_MARMASM)
      80             :   switch (directive) {
      81             :     case kByte:
      82             :       return "DCB";
      83             :     case kLong:
      84             :       return "DCDU";
      85             :     case kQuad:
      86             :       return "DCQU";
      87             :     default:
      88             :       UNREACHABLE();
      89             :   }
      90             : #elif defined(V8_OS_AIX)
      91             :   switch (directive) {
      92             :     case kByte:
      93             :       return ".byte";
      94             :     case kLong:
      95             :       return ".long";
      96             :     case kQuad:
      97             :       return ".llong";
      98             :     default:
      99             :       UNREACHABLE();
     100             :   }
     101             : #else
     102       38663 :   switch (directive) {
     103             :     case kByte:
     104             :       return ".byte";
     105             :     case kLong:
     106           1 :       return ".long";
     107             :     case kQuad:
     108           1 :       return ".quad";
     109             :     case kOcta:
     110       36030 :       return ".octa";
     111             :   }
     112           0 :   UNREACHABLE();
     113             : #endif
     114             : }
     115             : 
     116           1 : void EmbeddedFileWriter::PrepareBuiltinSourcePositionMap(Builtins* builtins) {
     117        3045 :   for (int i = 0; i < Builtins::builtin_count; i++) {
     118             :     // Retrieve the SourcePositionTable and copy it.
     119        1522 :     Code code = builtins->builtin(i);
     120             :     // Verify that the code object is still the "real code" and not a
     121             :     // trampoline (which wouldn't have source positions).
     122             :     DCHECK(!code->is_off_heap_trampoline());
     123             :     std::vector<unsigned char> data(
     124        3044 :         code->SourcePositionTable()->GetDataStartAddress(),
     125        3044 :         code->SourcePositionTable()->GetDataEndAddress());
     126        1522 :     source_positions_[i] = data;
     127             :   }
     128           1 : }
     129             : 
     130             : #if defined(V8_OS_WIN_X64)
     131             : std::string EmbeddedFileWriter::BuiltinsUnwindInfoLabel() const {
     132             :   char embedded_blob_data_symbol[kTemporaryStringLength];
     133             :   i::SNPrintF(i::Vector<char>(embedded_blob_data_symbol),
     134             :               "%s_Builtins_UnwindInfo", embedded_variant_);
     135             :   return embedded_blob_data_symbol;
     136             : }
     137             : 
     138             : void EmbeddedFileWriter::SetBuiltinUnwindData(
     139             :     int builtin_index, const win64_unwindinfo::BuiltinUnwindInfo& unwind_info) {
     140             :   DCHECK_LT(builtin_index, Builtins::builtin_count);
     141             :   unwind_infos_[builtin_index] = unwind_info;
     142             : }
     143             : 
     144             : void EmbeddedFileWriter::WriteUnwindInfoEntry(
     145             :     PlatformDependentEmbeddedFileWriter* w, uint64_t rva_start,
     146             :     uint64_t rva_end) const {
     147             :   w->DeclareRvaToSymbol(EmbeddedBlobDataSymbol().c_str(), rva_start);
     148             :   w->DeclareRvaToSymbol(EmbeddedBlobDataSymbol().c_str(), rva_end);
     149             :   w->DeclareRvaToSymbol(BuiltinsUnwindInfoLabel().c_str());
     150             : }
     151             : 
     152             : void EmbeddedFileWriter::WriteUnwindInfo(PlatformDependentEmbeddedFileWriter* w,
     153             :                                          const i::EmbeddedData* blob) const {
     154             :   // Emit an UNWIND_INFO (XDATA) struct, which contains the unwinding
     155             :   // information that is used for all builtin functions.
     156             :   DCHECK(win64_unwindinfo::CanEmitUnwindInfoForBuiltins());
     157             :   w->Comment("xdata for all the code in the embedded blob.");
     158             :   w->DeclareExternalFunction(CRASH_HANDLER_FUNCTION_NAME_STRING);
     159             : 
     160             :   w->StartXdataSection();
     161             :   {
     162             :     w->DeclareLabel(BuiltinsUnwindInfoLabel().c_str());
     163             :     std::vector<uint8_t> xdata =
     164             :         win64_unwindinfo::GetUnwindInfoForBuiltinFunctions();
     165             :     WriteBinaryContentsAsInlineAssembly(w, xdata.data(),
     166             :                                         static_cast<uint32_t>(xdata.size()));
     167             :     w->Comment("    ExceptionHandler");
     168             :     w->DeclareRvaToSymbol(CRASH_HANDLER_FUNCTION_NAME_STRING);
     169             :   }
     170             :   w->EndXdataSection();
     171             :   w->Newline();
     172             : 
     173             :   // Emit a RUNTIME_FUNCTION (PDATA) entry for each builtin function, as
     174             :   // documented here:
     175             :   // https://docs.microsoft.com/en-us/cpp/build/exception-handling-x64.
     176             :   w->Comment(
     177             :       "pdata for all the code in the embedded blob (structs of type "
     178             :       "RUNTIME_FUNCTION).");
     179             :   w->Comment("    BeginAddress");
     180             :   w->Comment("    EndAddress");
     181             :   w->Comment("    UnwindInfoAddress");
     182             :   w->StartPdataSection();
     183             :   {
     184             :     Address prev_builtin_end_offset = 0;
     185             :     for (int i = 0; i < Builtins::builtin_count; i++) {
     186             :       // Some builtins are leaf functions from the point of view of Win64 stack
     187             :       // walking: they do not move the stack pointer and do not require a PDATA
     188             :       // entry because the return address can be retrieved from [rsp].
     189             :       if (!blob->ContainsBuiltin(i)) continue;
     190             :       if (unwind_infos_[i].is_leaf_function()) continue;
     191             : 
     192             :       uint64_t builtin_start_offset = blob->InstructionStartOfBuiltin(i) -
     193             :                                       reinterpret_cast<Address>(blob->data());
     194             :       uint32_t builtin_size = blob->InstructionSizeOfBuiltin(i);
     195             : 
     196             :       const std::vector<int>& xdata_desc = unwind_infos_[i].fp_offsets();
     197             :       if (xdata_desc.empty()) {
     198             :         // Some builtins do not have any "push rbp - mov rbp, rsp" instructions
     199             :         // to start a stack frame. We still emit a PDATA entry as if they had,
     200             :         // relying on the fact that we can find the previous frame address from
     201             :         // rbp in most cases. Note that since the function does not really start
     202             :         // with a 'push rbp' we need to specify the start RVA in the PDATA entry
     203             :         // a few bytes before the beginning of the function, if it does not
     204             :         // overlap the end of the previous builtin.
     205             :         WriteUnwindInfoEntry(
     206             :             w,
     207             :             std::max(prev_builtin_end_offset,
     208             :                      builtin_start_offset - win64_unwindinfo::kRbpPrefixLength),
     209             :             builtin_start_offset + builtin_size);
     210             :       } else {
     211             :         // Some builtins have one or more "push rbp - mov rbp, rsp" sequences,
     212             :         // but not necessarily at the beginning of the function. In this case
     213             :         // we want to yield a PDATA entry for each block of instructions that
     214             :         // emit an rbp frame. If the function does not start with 'push rbp'
     215             :         // we also emit a PDATA entry for the initial block of code up to the
     216             :         // first 'push rbp', like in the case above.
     217             :         if (xdata_desc[0] > 0) {
     218             :           WriteUnwindInfoEntry(w,
     219             :                                std::max(prev_builtin_end_offset,
     220             :                                         builtin_start_offset -
     221             :                                             win64_unwindinfo::kRbpPrefixLength),
     222             :                                builtin_start_offset + xdata_desc[0]);
     223             :         }
     224             : 
     225             :         for (size_t j = 0; j < xdata_desc.size(); j++) {
     226             :           int chunk_start = xdata_desc[j];
     227             :           int chunk_end =
     228             :               (j < xdata_desc.size() - 1) ? xdata_desc[j + 1] : builtin_size;
     229             :           WriteUnwindInfoEntry(w, builtin_start_offset + chunk_start,
     230             :                                builtin_start_offset + chunk_end);
     231             :         }
     232             :       }
     233             : 
     234             :       prev_builtin_end_offset = builtin_start_offset + builtin_size;
     235             :       w->Newline();
     236             :     }
     237             :   }
     238             :   w->EndPdataSection();
     239             :   w->Newline();
     240             : }
     241             : #endif
     242             : 
     243             : // V8_OS_MACOSX
     244             : // Fuchsia target is explicitly excluded here for Mac hosts. This is to avoid
     245             : // generating uncompilable assembly files for the Fuchsia target.
     246             : // -----------------------------------------------------------------------------
     247             : 
     248             : #if defined(V8_OS_MACOSX) && !defined(V8_TARGET_OS_FUCHSIA)
     249             : 
     250             : void PlatformDependentEmbeddedFileWriter::SectionText() {
     251             :   fprintf(fp_, ".text\n");
     252             : }
     253             : 
     254             : void PlatformDependentEmbeddedFileWriter::SectionData() {
     255             :   fprintf(fp_, ".data\n");
     256             : }
     257             : 
     258             : void PlatformDependentEmbeddedFileWriter::SectionRoData() {
     259             :   fprintf(fp_, ".const_data\n");
     260             : }
     261             : 
     262             : void PlatformDependentEmbeddedFileWriter::DeclareUint32(const char* name,
     263             :                                                         uint32_t value) {
     264             :   DeclareSymbolGlobal(name);
     265             :   DeclareLabel(name);
     266             :   IndentedDataDirective(kLong);
     267             :   fprintf(fp_, "%d", value);
     268             :   Newline();
     269             : }
     270             : 
     271             : void PlatformDependentEmbeddedFileWriter::DeclarePointerToSymbol(
     272             :     const char* name, const char* target) {
     273             :   DeclareSymbolGlobal(name);
     274             :   DeclareLabel(name);
     275             :   fprintf(fp_, "  %s _%s\n", DirectiveAsString(PointerSizeDirective()), target);
     276             : }
     277             : 
     278             : void PlatformDependentEmbeddedFileWriter::DeclareSymbolGlobal(
     279             :     const char* name) {
     280             :   // TODO(jgruber): Investigate switching to .globl. Using .private_extern
     281             :   // prevents something along the compilation chain from messing with the
     282             :   // embedded blob. Using .global here causes embedded blob hash verification
     283             :   // failures at runtime.
     284             :   fprintf(fp_, ".private_extern _%s\n", name);
     285             : }
     286             : 
     287             : void PlatformDependentEmbeddedFileWriter::AlignToCodeAlignment() {
     288             :   fprintf(fp_, ".balign 32\n");
     289             : }
     290             : 
     291             : void PlatformDependentEmbeddedFileWriter::AlignToDataAlignment() {
     292             :   fprintf(fp_, ".balign 8\n");
     293             : }
     294             : 
     295             : void PlatformDependentEmbeddedFileWriter::Comment(const char* string) {
     296             :   fprintf(fp_, "// %s\n", string);
     297             : }
     298             : 
     299             : void PlatformDependentEmbeddedFileWriter::DeclareLabel(const char* name) {
     300             :   fprintf(fp_, "_%s:\n", name);
     301             : }
     302             : 
     303             : void PlatformDependentEmbeddedFileWriter::SourceInfo(int fileid,
     304             :                                                      const char* filename,
     305             :                                                      int line) {
     306             :   fprintf(fp_, ".loc %d %d\n", fileid, line);
     307             : }
     308             : 
     309             : void PlatformDependentEmbeddedFileWriter::DeclareFunctionBegin(
     310             :     const char* name) {
     311             :   DeclareLabel(name);
     312             : 
     313             :   // TODO(mvstanton): Investigate the proper incantations to mark the label as
     314             :   // a function on OSX.
     315             : }
     316             : 
     317             : void PlatformDependentEmbeddedFileWriter::DeclareFunctionEnd(const char* name) {
     318             : }
     319             : 
     320             : int PlatformDependentEmbeddedFileWriter::HexLiteral(uint64_t value) {
     321             :   return fprintf(fp_, "0x%" PRIx64, value);
     322             : }
     323             : 
     324             : void PlatformDependentEmbeddedFileWriter::FilePrologue() {}
     325             : 
     326             : void PlatformDependentEmbeddedFileWriter::DeclareExternalFilename(
     327             :     int fileid, const char* filename) {
     328             :   fprintf(fp_, ".file %d \"%s\"\n", fileid, filename);
     329             : }
     330             : 
     331             : void PlatformDependentEmbeddedFileWriter::FileEpilogue() {}
     332             : 
     333             : int PlatformDependentEmbeddedFileWriter::IndentedDataDirective(
     334             :     DataDirective directive) {
     335             :   return fprintf(fp_, "  %s ", DirectiveAsString(directive));
     336             : }
     337             : 
     338             : // V8_OS_AIX
     339             : // -----------------------------------------------------------------------------
     340             : 
     341             : #elif defined(V8_OS_AIX)
     342             : 
     343             : void PlatformDependentEmbeddedFileWriter::SectionText() {
     344             :   fprintf(fp_, ".csect .text[PR]\n");
     345             : }
     346             : 
     347             : void PlatformDependentEmbeddedFileWriter::SectionData() {
     348             :   fprintf(fp_, ".csect .data[RW]\n");
     349             : }
     350             : 
     351             : void PlatformDependentEmbeddedFileWriter::SectionRoData() {
     352             :   fprintf(fp_, ".csect[RO]\n");
     353             : }
     354             : 
     355             : void PlatformDependentEmbeddedFileWriter::DeclareUint32(const char* name,
     356             :                                                         uint32_t value) {
     357             :   DeclareSymbolGlobal(name);
     358             :   fprintf(fp_, ".align 2\n");
     359             :   fprintf(fp_, "%s:\n", name);
     360             :   IndentedDataDirective(kLong);
     361             :   fprintf(fp_, "%d\n", value);
     362             :   Newline();
     363             : }
     364             : 
     365             : void PlatformDependentEmbeddedFileWriter::DeclarePointerToSymbol(
     366             :     const char* name, const char* target) {
     367             :   AlignToCodeAlignment();
     368             :   DeclareLabel(name);
     369             :   fprintf(fp_, "  %s %s\n", DirectiveAsString(PointerSizeDirective()), target);
     370             :   Newline();
     371             : }
     372             : 
     373             : void PlatformDependentEmbeddedFileWriter::DeclareSymbolGlobal(
     374             :     const char* name) {
     375             :   fprintf(fp_, ".globl %s\n", name);
     376             : }
     377             : 
     378             : void PlatformDependentEmbeddedFileWriter::AlignToCodeAlignment() {
     379             :   fprintf(fp_, ".align 5\n");
     380             : }
     381             : 
     382             : void PlatformDependentEmbeddedFileWriter::AlignToDataAlignment() {
     383             :   fprintf(fp_, ".align 3\n");
     384             : }
     385             : 
     386             : void PlatformDependentEmbeddedFileWriter::Comment(const char* string) {
     387             :   fprintf(fp_, "// %s\n", string);
     388             : }
     389             : 
     390             : void PlatformDependentEmbeddedFileWriter::DeclareLabel(const char* name) {
     391             :   DeclareSymbolGlobal(name);
     392             :   fprintf(fp_, "%s:\n", name);
     393             : }
     394             : 
     395             : void PlatformDependentEmbeddedFileWriter::SourceInfo(int fileid,
     396             :                                                      const char* filename,
     397             :                                                      int line) {
     398             :   fprintf(fp_, ".xline %d, \"%s\"\n", line, filename);
     399             : }
     400             : 
     401             : void PlatformDependentEmbeddedFileWriter::DeclareFunctionBegin(
     402             :     const char* name) {
     403             :   Newline();
     404             :   DeclareSymbolGlobal(name);
     405             :   fprintf(fp_, ".csect %s[DS]\n", name); // function descriptor
     406             :   fprintf(fp_, "%s:\n", name);
     407             :   fprintf(fp_, ".llong .%s, 0, 0\n", name);
     408             :   SectionText();
     409             :   fprintf(fp_, ".%s:\n", name);
     410             : }
     411             : 
     412             : void PlatformDependentEmbeddedFileWriter::DeclareFunctionEnd(const char* name) {
     413             : }
     414             : 
     415             : int PlatformDependentEmbeddedFileWriter::HexLiteral(uint64_t value) {
     416             :   return fprintf(fp_, "0x%" PRIx64, value);
     417             : }
     418             : 
     419             : void PlatformDependentEmbeddedFileWriter::FilePrologue() {}
     420             : 
     421             : void PlatformDependentEmbeddedFileWriter::DeclareExternalFilename(
     422             :     int fileid, const char* filename) {
     423             :   // File name cannot be declared with an identifier on AIX.
     424             :   // We use the SourceInfo method to emit debug info in
     425             :   //.xline <line-number> <file-name> format.
     426             : }
     427             : 
     428             : void PlatformDependentEmbeddedFileWriter::FileEpilogue() {}
     429             : 
     430             : int PlatformDependentEmbeddedFileWriter::IndentedDataDirective(
     431             :     DataDirective directive) {
     432             :   return fprintf(fp_, "  %s ", DirectiveAsString(directive));
     433             : }
     434             : 
     435             : // V8_TARGET_OS_WIN (MSVC)
     436             : // -----------------------------------------------------------------------------
     437             : 
     438             : #elif defined(V8_TARGET_OS_WIN) && defined(V8_ASSEMBLER_IS_MASM)
     439             : 
     440             : // For MSVC builds we emit assembly in MASM syntax.
     441             : // See https://docs.microsoft.com/en-us/cpp/assembler/masm/directives-reference.
     442             : 
     443             : void PlatformDependentEmbeddedFileWriter::SectionText() {
     444             :   fprintf(fp_, ".CODE\n");
     445             : }
     446             : 
     447             : void PlatformDependentEmbeddedFileWriter::SectionData() {
     448             :   fprintf(fp_, ".DATA\n");
     449             : }
     450             : 
     451             : void PlatformDependentEmbeddedFileWriter::SectionRoData() {
     452             :   fprintf(fp_, ".CONST\n");
     453             : }
     454             : 
     455             : void PlatformDependentEmbeddedFileWriter::DeclareUint32(const char* name,
     456             :                                                         uint32_t value) {
     457             :   DeclareSymbolGlobal(name);
     458             :   fprintf(fp_, "%s%s %s %d\n", SYMBOL_PREFIX, name, DirectiveAsString(kLong),
     459             :           value);
     460             : }
     461             : 
     462             : void PlatformDependentEmbeddedFileWriter::DeclarePointerToSymbol(
     463             :     const char* name, const char* target) {
     464             :   DeclareSymbolGlobal(name);
     465             :   fprintf(fp_, "%s%s %s %s%s\n", SYMBOL_PREFIX, name,
     466             :           DirectiveAsString(PointerSizeDirective()), SYMBOL_PREFIX, target);
     467             : }
     468             : 
     469             : #if defined(V8_OS_WIN_X64)
     470             : 
     471             : void PlatformDependentEmbeddedFileWriter::StartPdataSection() {
     472             :   fprintf(fp_, "OPTION DOTNAME\n");
     473             :   fprintf(fp_, ".pdata SEGMENT DWORD READ ''\n");
     474             : }
     475             : 
     476             : void PlatformDependentEmbeddedFileWriter::EndPdataSection() {
     477             :   fprintf(fp_, ".pdata ENDS\n");
     478             : }
     479             : 
     480             : void PlatformDependentEmbeddedFileWriter::StartXdataSection() {
     481             :   fprintf(fp_, "OPTION DOTNAME\n");
     482             :   fprintf(fp_, ".xdata SEGMENT DWORD READ ''\n");
     483             : }
     484             : 
     485             : void PlatformDependentEmbeddedFileWriter::EndXdataSection() {
     486             :   fprintf(fp_, ".xdata ENDS\n");
     487             : }
     488             : 
     489             : void PlatformDependentEmbeddedFileWriter::DeclareExternalFunction(
     490             :     const char* name) {
     491             :   fprintf(fp_, "EXTERN %s : PROC\n", name);
     492             : }
     493             : 
     494             : void PlatformDependentEmbeddedFileWriter::DeclareRvaToSymbol(const char* name,
     495             :                                                              uint64_t offset) {
     496             :   if (offset > 0) {
     497             :     fprintf(fp_, "DD IMAGEREL %s+%llu\n", name, offset);
     498             :   } else {
     499             :     fprintf(fp_, "DD IMAGEREL %s\n", name);
     500             :   }
     501             : }
     502             : 
     503             : #endif  // defined(V8_OS_WIN_X64)
     504             : 
     505             : void PlatformDependentEmbeddedFileWriter::DeclareSymbolGlobal(
     506             :     const char* name) {
     507             :   fprintf(fp_, "PUBLIC %s%s\n", SYMBOL_PREFIX, name);
     508             : }
     509             : 
     510             : void PlatformDependentEmbeddedFileWriter::AlignToCodeAlignment() {
     511             :   // Diverges from other platforms due to compile error
     512             :   // 'invalid combination with segment alignment'.
     513             :   fprintf(fp_, "ALIGN 4\n");
     514             : }
     515             : 
     516             : void PlatformDependentEmbeddedFileWriter::AlignToDataAlignment() {
     517             :   fprintf(fp_, "ALIGN 4\n");
     518             : }
     519             : 
     520             : void PlatformDependentEmbeddedFileWriter::Comment(const char* string) {
     521             :   fprintf(fp_, "; %s\n", string);
     522             : }
     523             : 
     524             : void PlatformDependentEmbeddedFileWriter::DeclareLabel(const char* name) {
     525             :   fprintf(fp_, "%s%s LABEL %s\n", SYMBOL_PREFIX, name,
     526             :           DirectiveAsString(kByte));
     527             : }
     528             : 
     529             : void PlatformDependentEmbeddedFileWriter::SourceInfo(int fileid,
     530             :                                                      const char* filename,
     531             :                                                      int line) {
     532             :   // TODO(mvstanton): output source information for MSVC.
     533             :   // Its syntax is #line <line> "<filename>"
     534             : }
     535             : 
     536             : void PlatformDependentEmbeddedFileWriter::DeclareFunctionBegin(
     537             :     const char* name) {
     538             :   fprintf(fp_, "%s%s PROC\n", SYMBOL_PREFIX, name);
     539             : }
     540             : 
     541             : void PlatformDependentEmbeddedFileWriter::DeclareFunctionEnd(const char* name) {
     542             :   fprintf(fp_, "%s%s ENDP\n", SYMBOL_PREFIX, name);
     543             : }
     544             : 
     545             : int PlatformDependentEmbeddedFileWriter::HexLiteral(uint64_t value) {
     546             :   return fprintf(fp_, "0%" PRIx64 "h", value);
     547             : }
     548             : 
     549             : void PlatformDependentEmbeddedFileWriter::FilePrologue() {
     550             : #if !defined(V8_TARGET_ARCH_X64)
     551             :   fprintf(fp_, ".MODEL FLAT\n");
     552             : #endif
     553             : }
     554             : 
     555             : void PlatformDependentEmbeddedFileWriter::DeclareExternalFilename(
     556             :     int fileid, const char* filename) {}
     557             : 
     558             : void PlatformDependentEmbeddedFileWriter::FileEpilogue() {
     559             :   fprintf(fp_, "END\n");
     560             : }
     561             : 
     562             : int PlatformDependentEmbeddedFileWriter::IndentedDataDirective(
     563             :     DataDirective directive) {
     564             :   return fprintf(fp_, "  %s ", DirectiveAsString(directive));
     565             : }
     566             : 
     567             : #undef V8_ASSEMBLER_IS_MASM
     568             : 
     569             : #elif defined(V8_TARGET_OS_WIN) && defined(V8_ASSEMBLER_IS_MARMASM)
     570             : 
     571             : // The the AARCH64 ABI requires instructions be 4-byte-aligned and Windows does
     572             : // not have a stricter alignment requirement (see the TEXTAREA macro of
     573             : // kxarm64.h in the Windows SDK), so code is 4-byte-aligned.
     574             : // The data fields in the emitted assembly tend to be accessed with 8-byte
     575             : // LDR instructions, so data is 8-byte-aligned.
     576             : //
     577             : // armasm64's warning A4228 states
     578             : //     Alignment value exceeds AREA alignment; alignment not guaranteed
     579             : // To ensure that ALIGN directives are honored, their values are defined as
     580             : // equal to their corresponding AREA's ALIGN attributes.
     581             : 
     582             : #define ARM64_DATA_ALIGNMENT_POWER (3)
     583             : #define ARM64_DATA_ALIGNMENT (1 << ARM64_DATA_ALIGNMENT_POWER)
     584             : #define ARM64_CODE_ALIGNMENT_POWER (2)
     585             : #define ARM64_CODE_ALIGNMENT (1 << ARM64_CODE_ALIGNMENT_POWER)
     586             : 
     587             : void PlatformDependentEmbeddedFileWriter::SectionText() {
     588             :   fprintf(fp_, "  AREA |.text|, CODE, ALIGN=%d, READONLY\n",
     589             :           ARM64_CODE_ALIGNMENT_POWER);
     590             : }
     591             : 
     592             : void PlatformDependentEmbeddedFileWriter::SectionData() {
     593             :   fprintf(fp_, "  AREA |.data|, DATA, ALIGN=%d, READWRITE\n",
     594             :           ARM64_DATA_ALIGNMENT_POWER);
     595             : }
     596             : 
     597             : void PlatformDependentEmbeddedFileWriter::SectionRoData() {
     598             :   fprintf(fp_, "  AREA |.rodata|, DATA, ALIGN=%d, READONLY\n",
     599             :           ARM64_DATA_ALIGNMENT_POWER);
     600             : }
     601             : 
     602             : void PlatformDependentEmbeddedFileWriter::DeclareUint32(const char* name,
     603             :                                                         uint32_t value) {
     604             :   DeclareSymbolGlobal(name);
     605             :   fprintf(fp_, "%s%s %s %d\n", SYMBOL_PREFIX, name, DirectiveAsString(kLong),
     606             :           value);
     607             : }
     608             : 
     609             : void PlatformDependentEmbeddedFileWriter::DeclarePointerToSymbol(
     610             :     const char* name, const char* target) {
     611             :   DeclareSymbolGlobal(name);
     612             :   fprintf(fp_, "%s%s %s %s%s\n", SYMBOL_PREFIX, name,
     613             :           DirectiveAsString(PointerSizeDirective()), SYMBOL_PREFIX, target);
     614             : }
     615             : 
     616             : void PlatformDependentEmbeddedFileWriter::DeclareSymbolGlobal(
     617             :     const char* name) {
     618             :   fprintf(fp_, "  EXPORT %s%s\n", SYMBOL_PREFIX, name);
     619             : }
     620             : 
     621             : void PlatformDependentEmbeddedFileWriter::AlignToCodeAlignment() {
     622             :   fprintf(fp_, "  ALIGN %d\n", ARM64_CODE_ALIGNMENT);
     623             : }
     624             : 
     625             : void PlatformDependentEmbeddedFileWriter::AlignToDataAlignment() {
     626             :   fprintf(fp_, "  ALIGN %d\n", ARM64_DATA_ALIGNMENT);
     627             : }
     628             : 
     629             : void PlatformDependentEmbeddedFileWriter::Comment(const char* string) {
     630             :   fprintf(fp_, "; %s\n", string);
     631             : }
     632             : 
     633             : void PlatformDependentEmbeddedFileWriter::DeclareLabel(const char* name) {
     634             :   fprintf(fp_, "%s%s\n", SYMBOL_PREFIX, name);
     635             : }
     636             : 
     637             : void PlatformDependentEmbeddedFileWriter::SourceInfo(int fileid,
     638             :                                                      const char* filename,
     639             :                                                      int line) {
     640             :   // TODO(mvstanton): output source information for MSVC.
     641             :   // Its syntax is #line <line> "<filename>"
     642             : }
     643             : 
     644             : void PlatformDependentEmbeddedFileWriter::DeclareFunctionBegin(
     645             :     const char* name) {
     646             :   fprintf(fp_, "%s%s FUNCTION\n", SYMBOL_PREFIX, name);
     647             : }
     648             : 
     649             : void PlatformDependentEmbeddedFileWriter::DeclareFunctionEnd(const char* name) {
     650             :   fprintf(fp_, "  ENDFUNC\n");
     651             : }
     652             : 
     653             : int PlatformDependentEmbeddedFileWriter::HexLiteral(uint64_t value) {
     654             :   return fprintf(fp_, "0x%" PRIx64, value);
     655             : }
     656             : 
     657             : void PlatformDependentEmbeddedFileWriter::FilePrologue() {}
     658             : 
     659             : void PlatformDependentEmbeddedFileWriter::DeclareExternalFilename(
     660             :     int fileid, const char* filename) {}
     661             : 
     662             : void PlatformDependentEmbeddedFileWriter::FileEpilogue() {
     663             :   fprintf(fp_, "  END\n");
     664             : }
     665             : 
     666             : int PlatformDependentEmbeddedFileWriter::IndentedDataDirective(
     667             :     DataDirective directive) {
     668             :   return fprintf(fp_, "  %s ", DirectiveAsString(directive));
     669             : }
     670             : 
     671             : #undef V8_ASSEMBLER_IS_MARMASM
     672             : #undef ARM64_DATA_ALIGNMENT_POWER
     673             : #undef ARM64_DATA_ALIGNMENT
     674             : #undef ARM64_CODE_ALIGNMENT_POWER
     675             : #undef ARM64_CODE_ALIGNMENT
     676             : 
     677             : // Everything but AIX, Windows with MSVC, or OSX.
     678             : // -----------------------------------------------------------------------------
     679             : 
     680             : #else
     681             : 
     682           1 : void PlatformDependentEmbeddedFileWriter::SectionText() {
     683             : #if defined(V8_TARGET_OS_CHROMEOS)
     684             :   fprintf(fp_, ".section .text.hot.embedded\n");
     685             : #else
     686           1 :   fprintf(fp_, ".section .text\n");
     687             : #endif
     688           1 : }
     689             : 
     690           1 : void PlatformDependentEmbeddedFileWriter::SectionData() {
     691           1 :   fprintf(fp_, ".section .data\n");
     692           1 : }
     693             : 
     694           1 : void PlatformDependentEmbeddedFileWriter::SectionRoData() {
     695           2 :   if (i::FLAG_target_os == std::string("win"))
     696           0 :     fprintf(fp_, ".section .rdata\n");
     697             :   else
     698           1 :     fprintf(fp_, ".section .rodata\n");
     699           1 : }
     700             : 
     701           1 : void PlatformDependentEmbeddedFileWriter::DeclareUint32(const char* name,
     702             :                                                         uint32_t value) {
     703             :   DeclareSymbolGlobal(name);
     704             :   DeclareLabel(name);
     705           1 :   IndentedDataDirective(kLong);
     706           1 :   fprintf(fp_, "%d", value);
     707             :   Newline();
     708           1 : }
     709             : 
     710           1 : void PlatformDependentEmbeddedFileWriter::DeclarePointerToSymbol(
     711             :     const char* name, const char* target) {
     712             :   DeclareSymbolGlobal(name);
     713             :   DeclareLabel(name);
     714           1 :   fprintf(fp_, "  %s %s%s\n", DirectiveAsString(PointerSizeDirective()),
     715             :           SYMBOL_PREFIX, target);
     716           1 : }
     717             : 
     718             : #if defined(V8_OS_WIN_X64)
     719             : 
     720             : void PlatformDependentEmbeddedFileWriter::StartPdataSection() {
     721             :   fprintf(fp_, ".section .pdata\n");
     722             : }
     723             : 
     724             : void PlatformDependentEmbeddedFileWriter::EndPdataSection() {}
     725             : 
     726             : void PlatformDependentEmbeddedFileWriter::StartXdataSection() {
     727             :   fprintf(fp_, ".section .xdata\n");
     728             : }
     729             : 
     730             : void PlatformDependentEmbeddedFileWriter::EndXdataSection() {}
     731             : 
     732             : void PlatformDependentEmbeddedFileWriter::DeclareExternalFunction(
     733             :     const char* name) {}
     734             : 
     735             : void PlatformDependentEmbeddedFileWriter::DeclareRvaToSymbol(const char* name,
     736             :                                                              uint64_t offset) {
     737             :   if (offset > 0) {
     738             :     fprintf(fp_, ".rva %s + %llu\n", name, offset);
     739             :   } else {
     740             :     fprintf(fp_, ".rva %s\n", name);
     741             :   }
     742             : }
     743             : 
     744             : #endif  // defined(V8_OS_WIN_X64)
     745             : 
     746           0 : void PlatformDependentEmbeddedFileWriter::DeclareSymbolGlobal(
     747             :     const char* name) {
     748           2 :   fprintf(fp_, ".global %s%s\n", SYMBOL_PREFIX, name);
     749           0 : }
     750             : 
     751           1 : void PlatformDependentEmbeddedFileWriter::AlignToCodeAlignment() {
     752           1 :   fprintf(fp_, ".balign 32\n");
     753           1 : }
     754             : 
     755           2 : void PlatformDependentEmbeddedFileWriter::AlignToDataAlignment() {
     756             :   // On Windows ARM64, s390, PPC and possibly more platforms, aligned load
     757             :   // instructions are used to retrieve v8_Default_embedded_blob_ and/or
     758             :   // v8_Default_embedded_blob_size_. The generated instructions require the
     759             :   // load target to be aligned at 8 bytes (2^3).
     760           2 :   fprintf(fp_, ".balign 8\n");
     761           2 : }
     762             : 
     763           7 : void PlatformDependentEmbeddedFileWriter::Comment(const char* string) {
     764           7 :   fprintf(fp_, "// %s\n", string);
     765           7 : }
     766             : 
     767           1 : void PlatformDependentEmbeddedFileWriter::DeclareLabel(const char* name) {
     768        1525 :   fprintf(fp_, "%s%s:\n", SYMBOL_PREFIX, name);
     769           1 : }
     770             : 
     771        1108 : void PlatformDependentEmbeddedFileWriter::SourceInfo(int fileid,
     772             :                                                      const char* filename,
     773             :                                                      int line) {
     774        1108 :   fprintf(fp_, ".loc %d %d\n", fileid, line);
     775        1108 : }
     776             : 
     777        1522 : void PlatformDependentEmbeddedFileWriter::DeclareFunctionBegin(
     778             :     const char* name) {
     779             :   DeclareLabel(name);
     780             : 
     781        3044 :   if (i::FLAG_target_os == std::string("win")) {
     782             : #if defined(V8_TARGET_ARCH_ARM64)
     783             :     // Windows ARM64 assembly is in GAS syntax, but ".type" is invalid directive
     784             :     // in PE/COFF for Windows.
     785             : #else
     786             :     // The directives for inserting debugging information on Windows come
     787             :     // from the PE (Portable Executable) and COFF (Common Object File Format)
     788             :     // standards. Documented here:
     789             :     // https://docs.microsoft.com/en-us/windows/desktop/debug/pe-format
     790             :     //
     791             :     // .scl 2 means StorageClass external.
     792             :     // .type 32 means Type Representation Function.
     793           0 :     fprintf(fp_, ".def %s%s; .scl 2; .type 32; .endef;\n", SYMBOL_PREFIX, name);
     794             : #endif
     795             :   } else {
     796             : #if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_ARM64)
     797             :     // ELF format binaries on ARM use ".type <function name>, %function"
     798             :     // to create a DWARF subprogram entry.
     799             :     fprintf(fp_, ".type %s, %%function\n", name);
     800             : #else
     801             :     // Other ELF Format binaries use ".type <function name>, @function"
     802             :     // to create a DWARF subprogram entry.
     803        1522 :     fprintf(fp_, ".type %s, @function\n", name);
     804             : #endif
     805             :   }
     806        1522 : }
     807             : 
     808        1522 : void PlatformDependentEmbeddedFileWriter::DeclareFunctionEnd(const char* name) {
     809        1522 : }
     810             : 
     811       32112 : int PlatformDependentEmbeddedFileWriter::HexLiteral(uint64_t value) {
     812       64224 :   return fprintf(fp_, "0x%" PRIx64, value);
     813             : }
     814             : 
     815           1 : void PlatformDependentEmbeddedFileWriter::FilePrologue() {}
     816             : 
     817          50 : void PlatformDependentEmbeddedFileWriter::DeclareExternalFilename(
     818             :     int fileid, const char* filename) {
     819             :   // Replace any Windows style paths (backslashes) with forward
     820             :   // slashes.
     821          50 :   std::string fixed_filename(filename);
     822             :   std::replace(fixed_filename.begin(), fixed_filename.end(), '\\', '/');
     823          50 :   fprintf(fp_, ".file %d \"%s\"\n", fileid, fixed_filename.c_str());
     824          50 : }
     825             : 
     826           1 : void PlatformDependentEmbeddedFileWriter::FileEpilogue() {}
     827             : 
     828       38662 : int PlatformDependentEmbeddedFileWriter::IndentedDataDirective(
     829             :     DataDirective directive) {
     830       77324 :   return fprintf(fp_, "  %s ", DirectiveAsString(directive));
     831             : }
     832             : 
     833             : #endif
     834             : 
     835             : #undef SYMBOL_PREFIX
     836             : #undef V8_COMPILER_IS_MSVC
     837             : 
     838             : }  // namespace internal
     839           2 : }  // namespace v8

Generated by: LCOV version 1.10