LCOV - code coverage report
Current view: top level - src/wasm - wasm-linkage.h (source / functions) Hit Total Coverage
Test: app.info Lines: 9 9 100.0 %
Date: 2019-04-17 Functions: 1 1 100.0 %

          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             : #ifndef V8_WASM_WASM_LINKAGE_H_
       6             : #define V8_WASM_WASM_LINKAGE_H_
       7             : 
       8             : #include "src/assembler-arch.h"
       9             : #include "src/machine-type.h"
      10             : #include "src/signature.h"
      11             : #include "src/wasm/value-type.h"
      12             : 
      13             : namespace v8 {
      14             : namespace internal {
      15             : namespace wasm {
      16             : 
      17             : // TODO(wasm): optimize calling conventions to be both closer to C++ (to
      18             : // reduce adapter costs for fast WASM <-> C++ calls) and to be more efficient
      19             : // in general.
      20             : 
      21             : #if V8_TARGET_ARCH_IA32
      22             : // ===========================================================================
      23             : // == ia32 ===================================================================
      24             : // ===========================================================================
      25             : constexpr Register kGpParamRegisters[] = {esi, eax, edx, ecx};
      26             : constexpr Register kGpReturnRegisters[] = {eax, edx};
      27             : constexpr DoubleRegister kFpParamRegisters[] = {xmm1, xmm2, xmm3,
      28             :                                                 xmm4, xmm5, xmm6};
      29             : constexpr DoubleRegister kFpReturnRegisters[] = {xmm1, xmm2};
      30             : 
      31             : #elif V8_TARGET_ARCH_X64
      32             : // ===========================================================================
      33             : // == x64 ====================================================================
      34             : // ===========================================================================
      35             : constexpr Register kGpParamRegisters[] = {rsi, rax, rdx, rcx, rbx, r9};
      36             : constexpr Register kGpReturnRegisters[] = {rax, rdx};
      37             : constexpr DoubleRegister kFpParamRegisters[] = {xmm1, xmm2, xmm3,
      38             :                                                 xmm4, xmm5, xmm6};
      39             : constexpr DoubleRegister kFpReturnRegisters[] = {xmm1, xmm2};
      40             : 
      41             : #elif V8_TARGET_ARCH_ARM
      42             : // ===========================================================================
      43             : // == arm ====================================================================
      44             : // ===========================================================================
      45             : constexpr Register kGpParamRegisters[] = {r3, r0, r2, r6};
      46             : constexpr Register kGpReturnRegisters[] = {r0, r1};
      47             : // ARM d-registers must be in ascending order for correct allocation.
      48             : constexpr DoubleRegister kFpParamRegisters[] = {d0, d1, d2, d3, d4, d5, d6, d7};
      49             : constexpr DoubleRegister kFpReturnRegisters[] = {d0, d1};
      50             : 
      51             : #elif V8_TARGET_ARCH_ARM64
      52             : // ===========================================================================
      53             : // == arm64 ====================================================================
      54             : // ===========================================================================
      55             : constexpr Register kGpParamRegisters[] = {x7, x0, x2, x3, x4, x5, x6};
      56             : constexpr Register kGpReturnRegisters[] = {x0, x1};
      57             : constexpr DoubleRegister kFpParamRegisters[] = {d0, d1, d2, d3, d4, d5, d6, d7};
      58             : constexpr DoubleRegister kFpReturnRegisters[] = {d0, d1};
      59             : 
      60             : #elif V8_TARGET_ARCH_MIPS
      61             : // ===========================================================================
      62             : // == mips ===================================================================
      63             : // ===========================================================================
      64             : constexpr Register kGpParamRegisters[] = {a0, a2, a3};
      65             : constexpr Register kGpReturnRegisters[] = {v0, v1};
      66             : constexpr DoubleRegister kFpParamRegisters[] = {f2, f4, f6, f8, f10, f12, f14};
      67             : constexpr DoubleRegister kFpReturnRegisters[] = {f2, f4};
      68             : 
      69             : #elif V8_TARGET_ARCH_MIPS64
      70             : // ===========================================================================
      71             : // == mips64 =================================================================
      72             : // ===========================================================================
      73             : constexpr Register kGpParamRegisters[] = {a0, a2, a3, a4, a5, a6, a7};
      74             : constexpr Register kGpReturnRegisters[] = {v0, v1};
      75             : constexpr DoubleRegister kFpParamRegisters[] = {f2, f4, f6, f8, f10, f12, f14};
      76             : constexpr DoubleRegister kFpReturnRegisters[] = {f2, f4};
      77             : 
      78             : #elif V8_TARGET_ARCH_PPC || V8_TARGET_ARCH_PPC64
      79             : // ===========================================================================
      80             : // == ppc & ppc64 ============================================================
      81             : // ===========================================================================
      82             : constexpr Register kGpParamRegisters[] = {r10, r3, r5, r6, r7, r8, r9};
      83             : constexpr Register kGpReturnRegisters[] = {r3, r4};
      84             : constexpr DoubleRegister kFpParamRegisters[] = {d1, d2, d3, d4, d5, d6, d7, d8};
      85             : constexpr DoubleRegister kFpReturnRegisters[] = {d1, d2};
      86             : 
      87             : #elif V8_TARGET_ARCH_S390X
      88             : // ===========================================================================
      89             : // == s390x ==================================================================
      90             : // ===========================================================================
      91             : constexpr Register kGpParamRegisters[] = {r6, r2, r4, r5};
      92             : constexpr Register kGpReturnRegisters[] = {r2, r3};
      93             : constexpr DoubleRegister kFpParamRegisters[] = {d0, d2, d4, d6};
      94             : constexpr DoubleRegister kFpReturnRegisters[] = {d0, d2, d4, d6};
      95             : 
      96             : #elif V8_TARGET_ARCH_S390
      97             : // ===========================================================================
      98             : // == s390 ===================================================================
      99             : // ===========================================================================
     100             : constexpr Register kGpParamRegisters[] = {r6, r2, r4, r5};
     101             : constexpr Register kGpReturnRegisters[] = {r2, r3};
     102             : constexpr DoubleRegister kFpParamRegisters[] = {d0, d2};
     103             : constexpr DoubleRegister kFpReturnRegisters[] = {d0, d2};
     104             : 
     105             : #else
     106             : // ===========================================================================
     107             : // == unknown ================================================================
     108             : // ===========================================================================
     109             : // Do not use any registers, we will just always use the stack.
     110             : constexpr Register kGpParamRegisters[] = {};
     111             : constexpr Register kGpReturnRegisters[] = {};
     112             : constexpr DoubleRegister kFpParamRegisters[] = {};
     113             : constexpr DoubleRegister kFpReturnRegisters[] = {};
     114             : 
     115             : #endif
     116             : 
     117             : // The parameter index where the instance parameter should be placed in wasm
     118             : // call descriptors. This is used by the Int64Lowering::LowerNode method.
     119             : constexpr int kWasmInstanceParameterIndex = 0;
     120             : 
     121             : class LinkageAllocator {
     122             :  public:
     123             :   template <size_t kNumGpRegs, size_t kNumFpRegs>
     124             :   constexpr LinkageAllocator(const Register (&gp)[kNumGpRegs],
     125             :                              const DoubleRegister (&fp)[kNumFpRegs])
     126             :       : LinkageAllocator(gp, kNumGpRegs, fp, kNumFpRegs) {}
     127             : 
     128             :   constexpr LinkageAllocator(const Register* gp, int gpc,
     129             :                              const DoubleRegister* fp, int fpc)
     130       32712 :       : gp_count_(gpc), gp_regs_(gp), fp_count_(fpc), fp_regs_(fp) {}
     131             : 
     132             :   bool CanAllocateGP() const { return gp_offset_ < gp_count_; }
     133             :   bool CanAllocateFP(MachineRepresentation rep) const {
     134             : #if V8_TARGET_ARCH_ARM
     135             :     switch (rep) {
     136             :       case MachineRepresentation::kFloat32:
     137             :         return fp_offset_ < fp_count_ && fp_regs_[fp_offset_].code() < 16;
     138             :       case MachineRepresentation::kFloat64:
     139             :         return extra_double_reg_ >= 0 || fp_offset_ < fp_count_;
     140             :       case MachineRepresentation::kSimd128:
     141             :         return ((fp_offset_ + 1) & ~1) + 1 < fp_count_;
     142             :       default:
     143             :         UNREACHABLE();
     144             :         return false;
     145             :     }
     146             : #endif
     147             :     return fp_offset_ < fp_count_;
     148             :   }
     149             : 
     150             :   int NextGpReg() {
     151             :     DCHECK_LT(gp_offset_, gp_count_);
     152     5007728 :     return gp_regs_[gp_offset_++].code();
     153             :   }
     154             : 
     155             :   int NextFpReg(MachineRepresentation rep) {
     156             : #if V8_TARGET_ARCH_ARM
     157             :     switch (rep) {
     158             :       case MachineRepresentation::kFloat32: {
     159             :         // Liftoff uses only even-numbered f32 registers, and encodes them using
     160             :         // the code of the corresponding f64 register. This limits the calling
     161             :         // interface to only using the even-numbered f32 registers.
     162             :         int d_reg_code = NextFpReg(MachineRepresentation::kFloat64);
     163             :         DCHECK_GT(16, d_reg_code);  // D-registers 16 - 31 can't split.
     164             :         return d_reg_code * 2;
     165             :       }
     166             :       case MachineRepresentation::kFloat64: {
     167             :         // Use the extra D-register if there is one.
     168             :         if (extra_double_reg_ >= 0) {
     169             :           int reg_code = extra_double_reg_;
     170             :           extra_double_reg_ = -1;
     171             :           return reg_code;
     172             :         }
     173             :         DCHECK_LT(fp_offset_, fp_count_);
     174             :         return fp_regs_[fp_offset_++].code();
     175             :       }
     176             :       case MachineRepresentation::kSimd128: {
     177             :         // Q-register must be an even-odd pair, so we must try to allocate at
     178             :         // the end, not using extra_double_reg_. If we are at an odd D-register,
     179             :         // skip past it (saving it to extra_double_reg_).
     180             :         DCHECK_LT(((fp_offset_ + 1) & ~1) + 1, fp_count_);
     181             :         int d_reg1_code = fp_regs_[fp_offset_++].code();
     182             :         if (d_reg1_code % 2 != 0) {
     183             :           // If we're misaligned then extra_double_reg_ must have been consumed.
     184             :           DCHECK_EQ(-1, extra_double_reg_);
     185             :           int odd_double_reg = d_reg1_code;
     186             :           d_reg1_code = fp_regs_[fp_offset_++].code();
     187             :           extra_double_reg_ = odd_double_reg;
     188             :         }
     189             :         // Combine the current D-register with the next to form a Q-register.
     190             :         int d_reg2_code = fp_regs_[fp_offset_++].code();
     191             :         DCHECK_EQ(0, d_reg1_code % 2);
     192             :         DCHECK_EQ(d_reg1_code + 1, d_reg2_code);
     193             :         USE(d_reg2_code);
     194             :         return d_reg1_code / 2;
     195             :       }
     196             :       default:
     197             :         UNREACHABLE();
     198             :     }
     199             : #else
     200             :     DCHECK_LT(fp_offset_, fp_count_);
     201      520678 :     return fp_regs_[fp_offset_++].code();
     202             : #endif
     203             :   }
     204             : 
     205             :   // Stackslots are counted upwards starting from 0 (or the offset set by
     206             :   // {SetStackOffset}.
     207             :   int NumStackSlots(MachineRepresentation type) {
     208      350046 :     return std::max(1, ElementSizeInBytes(type) / kSystemPointerSize);
     209             :   }
     210             : 
     211             :   // Stackslots are counted upwards starting from 0 (or the offset set by
     212             :   // {SetStackOffset}. If {type} needs more than
     213             :   // one stack slot, the lowest used stack slot is returned.
     214      175023 :   int NextStackSlot(MachineRepresentation type) {
     215             :     int num_stack_slots = NumStackSlots(type);
     216      175023 :     int offset = stack_offset_;
     217      175023 :     stack_offset_ += num_stack_slots;
     218      175023 :     return offset;
     219             :   }
     220             : 
     221             :   // Set an offset for the stack slots returned by {NextStackSlot} and
     222             :   // {NumStackSlots}. Can only be called before any call to {NextStackSlot}.
     223             :   void SetStackOffset(int num) {
     224             :     DCHECK_LE(0, num);
     225             :     DCHECK_EQ(0, stack_offset_);
     226     2521897 :     stack_offset_ = num;
     227             :   }
     228             : 
     229             :   int NumStackSlots() const { return stack_offset_; }
     230             : 
     231             :  private:
     232             :   const int gp_count_;
     233             :   int gp_offset_ = 0;
     234             :   const Register* const gp_regs_;
     235             : 
     236             :   const int fp_count_;
     237             :   int fp_offset_ = 0;
     238             :   const DoubleRegister* const fp_regs_;
     239             : 
     240             : #if V8_TARGET_ARCH_ARM
     241             :   // Track fragments of registers below fp_offset_ here. There can only be one
     242             :   // extra double register.
     243             :   int extra_double_reg_ = -1;
     244             : #endif
     245             : 
     246             :   int stack_offset_ = 0;
     247             : };
     248             : 
     249             : }  // namespace wasm
     250             : }  // namespace internal
     251             : }  // namespace v8
     252             : 
     253             : #endif  // V8_WASM_WASM_LINKAGE_H_

Generated by: LCOV version 1.10