LCOV - code coverage report
Current view: top level - src/compiler - wasm-linkage.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 32 59 54.2 %
Date: 2017-10-20 Functions: 3 6 50.0 %

          Line data    Source code
       1             : // Copyright 2015 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/assembler-inl.h"
       6             : #include "src/base/lazy-instance.h"
       7             : #include "src/macro-assembler.h"
       8             : #include "src/register-configuration.h"
       9             : 
      10             : #include "src/compiler/linkage.h"
      11             : #include "src/compiler/wasm-compiler.h"
      12             : 
      13             : #include "src/zone/zone.h"
      14             : 
      15             : namespace v8 {
      16             : namespace internal {
      17             : namespace compiler {
      18             : 
      19             : using wasm::ValueType;
      20             : 
      21             : namespace {
      22             : 
      23     2651596 : MachineType MachineTypeFor(ValueType type) {
      24     2651596 :   switch (type) {
      25             :     case wasm::kWasmI32:
      26             :       return MachineType::Int32();
      27             :     case wasm::kWasmI64:
      28             :       return MachineType::Int64();
      29             :     case wasm::kWasmF64:
      30             :       return MachineType::Float64();
      31             :     case wasm::kWasmF32:
      32             :       return MachineType::Float32();
      33             :     case wasm::kWasmS128:
      34             :       return MachineType::Simd128();
      35             :     default:
      36           0 :       UNREACHABLE();
      37             :   }
      38             : }
      39             : 
      40             : LinkageLocation stackloc(int i, MachineType type) {
      41             :   return LinkageLocation::ForCallerFrameSlot(i, type);
      42             : }
      43             : 
      44             : 
      45             : #if V8_TARGET_ARCH_IA32
      46             : // ===========================================================================
      47             : // == ia32 ===================================================================
      48             : // ===========================================================================
      49             : #define GP_PARAM_REGISTERS esi, eax, edx, ecx, ebx
      50             : #define GP_RETURN_REGISTERS eax, edx
      51             : #define FP_PARAM_REGISTERS xmm1, xmm2, xmm3, xmm4, xmm5, xmm6
      52             : #define FP_RETURN_REGISTERS xmm1, xmm2
      53             : 
      54             : #elif V8_TARGET_ARCH_X64
      55             : // ===========================================================================
      56             : // == x64 ====================================================================
      57             : // ===========================================================================
      58             : #define GP_PARAM_REGISTERS rsi, rax, rdx, rcx, rbx, rdi
      59             : #define GP_RETURN_REGISTERS rax, rdx
      60             : #define FP_PARAM_REGISTERS xmm1, xmm2, xmm3, xmm4, xmm5, xmm6
      61             : #define FP_RETURN_REGISTERS xmm1, xmm2
      62             : 
      63             : #elif V8_TARGET_ARCH_ARM
      64             : // ===========================================================================
      65             : // == arm ====================================================================
      66             : // ===========================================================================
      67             : #define GP_PARAM_REGISTERS r3, r0, r1, r2
      68             : #define GP_RETURN_REGISTERS r0, r1
      69             : #define FP_PARAM_REGISTERS d0, d1, d2, d3, d4, d5, d6, d7
      70             : #define FP_RETURN_REGISTERS d0, d1
      71             : 
      72             : #elif V8_TARGET_ARCH_ARM64
      73             : // ===========================================================================
      74             : // == arm64 ====================================================================
      75             : // ===========================================================================
      76             : #define GP_PARAM_REGISTERS x7, x0, x1, x2, x3, x4, x5, x6
      77             : #define GP_RETURN_REGISTERS x0, x1
      78             : #define FP_PARAM_REGISTERS d0, d1, d2, d3, d4, d5, d6, d7
      79             : #define FP_RETURN_REGISTERS d0, d1
      80             : 
      81             : #elif V8_TARGET_ARCH_MIPS
      82             : // ===========================================================================
      83             : // == mips ===================================================================
      84             : // ===========================================================================
      85             : #define GP_PARAM_REGISTERS a0, a1, a2, a3
      86             : #define GP_RETURN_REGISTERS v0, v1
      87             : #define FP_PARAM_REGISTERS f2, f4, f6, f8, f10, f12, f14
      88             : #define FP_RETURN_REGISTERS f2, f4
      89             : 
      90             : #elif V8_TARGET_ARCH_MIPS64
      91             : // ===========================================================================
      92             : // == mips64 =================================================================
      93             : // ===========================================================================
      94             : #define GP_PARAM_REGISTERS a0, a1, a2, a3, a4, a5, a6, a7
      95             : #define GP_RETURN_REGISTERS v0, v1
      96             : #define FP_PARAM_REGISTERS f2, f4, f6, f8, f10, f12, f14
      97             : #define FP_RETURN_REGISTERS f2, f4
      98             : 
      99             : #elif V8_TARGET_ARCH_PPC || V8_TARGET_ARCH_PPC64
     100             : // ===========================================================================
     101             : // == ppc & ppc64 ============================================================
     102             : // ===========================================================================
     103             : #define GP_PARAM_REGISTERS r10, r3, r4, r5, r6, r7, r8, r9
     104             : #define GP_RETURN_REGISTERS r3, r4
     105             : #define FP_PARAM_REGISTERS d1, d2, d3, d4, d5, d6, d7, d8
     106             : #define FP_RETURN_REGISTERS d1, d2
     107             : 
     108             : #elif V8_TARGET_ARCH_S390X
     109             : // ===========================================================================
     110             : // == s390x ==================================================================
     111             : // ===========================================================================
     112             : #define GP_PARAM_REGISTERS r6, r2, r3, r4, r5
     113             : #define GP_RETURN_REGISTERS r2, r3
     114             : #define FP_PARAM_REGISTERS d0, d2, d4, d6
     115             : #define FP_RETURN_REGISTERS d0, d2, d4, d6
     116             : 
     117             : #elif V8_TARGET_ARCH_S390
     118             : // ===========================================================================
     119             : // == s390 ===================================================================
     120             : // ===========================================================================
     121             : #define GP_PARAM_REGISTERS r6, r2, r3, r4, r5
     122             : #define GP_RETURN_REGISTERS r2, r3
     123             : #define FP_PARAM_REGISTERS d0, d2
     124             : #define FP_RETURN_REGISTERS d0, d2
     125             : 
     126             : #else
     127             : // ===========================================================================
     128             : // == unknown ================================================================
     129             : // ===========================================================================
     130             : // Do not use any registers, we will just always use the stack.
     131             : #define GP_PARAM_REGISTERS
     132             : #define GP_RETURN_REGISTERS
     133             : #define FP_PARAM_REGISTERS
     134             : #define FP_RETURN_REGISTERS
     135             : 
     136             : #endif
     137             : 
     138             : 
     139             : // Helper for allocating either an GP or FP reg, or the next stack slot.
     140             : struct Allocator {
     141             :   constexpr Allocator(const Register* gp, int gpc, const DoubleRegister* fp,
     142             :                       int fpc)
     143             :       : gp_count(gpc),
     144             :         gp_offset(0),
     145             :         gp_regs(gp),
     146             :         fp_count(fpc),
     147             :         fp_offset(0),
     148             :         fp_regs(fp),
     149             :         stack_offset(0) {}
     150             : 
     151             :   int gp_count;
     152             :   int gp_offset;
     153             :   const Register* gp_regs;
     154             : 
     155             :   int fp_count;
     156             :   int fp_offset;
     157             :   const DoubleRegister* fp_regs;
     158             : 
     159             :   int stack_offset;
     160             : 
     161     2651583 :   LinkageLocation Next(ValueType type) {
     162     2651583 :     if (IsFloatingPoint(type)) {
     163             :       // Allocate a floating point register/stack location.
     164     1175275 :       if (fp_offset < fp_count) {
     165     1084996 :         DoubleRegister reg = fp_regs[fp_offset++];
     166             : #if V8_TARGET_ARCH_ARM
     167             :         // Allocate floats using a double register, but modify the code to
     168             :         // reflect how ARM FP registers alias.
     169             :         // TODO(bbudge) Modify wasm linkage to allow use of all float regs.
     170             :         if (type == wasm::kWasmF32) {
     171             :           int float_reg_code = reg.code() * 2;
     172             :           DCHECK_GT(RegisterConfiguration::kMaxFPRegisters, float_reg_code);
     173             :           return LinkageLocation::ForRegister(
     174             :               DoubleRegister::from_code(float_reg_code).code(),
     175             :               MachineTypeFor(type));
     176             :         }
     177             : #endif
     178     1084996 :         return LinkageLocation::ForRegister(reg.code(), MachineTypeFor(type));
     179             :       } else {
     180       90279 :         int offset = -1 - stack_offset;
     181       90279 :         stack_offset += Words(type);
     182       90279 :         return stackloc(offset, MachineTypeFor(type));
     183             :       }
     184             :     } else {
     185             :       // Allocate a general purpose register/stack location.
     186     1476308 :       if (gp_offset < gp_count) {
     187     1418831 :         return LinkageLocation::ForRegister(gp_regs[gp_offset++].code(),
     188     1418805 :                                             MachineTypeFor(type));
     189             :       } else {
     190       57503 :         int offset = -1 - stack_offset;
     191       57503 :         stack_offset += Words(type);
     192       57503 :         return stackloc(offset, MachineTypeFor(type));
     193             :       }
     194             :     }
     195             :   }
     196             :   bool IsFloatingPoint(ValueType type) {
     197     2651583 :     return type == wasm::kWasmF32 || type == wasm::kWasmF64;
     198             :   }
     199             :   int Words(ValueType type) {
     200             :     if (kPointerSize < 8 &&
     201             :         (type == wasm::kWasmI64 || type == wasm::kWasmF64)) {
     202             :       return 2;
     203             :     }
     204             :     return 1;
     205             :   }
     206             : };
     207             : 
     208             : static constexpr Register kGPReturnRegisters[] = {GP_RETURN_REGISTERS};
     209             : static constexpr DoubleRegister kFPReturnRegisters[] = {FP_RETURN_REGISTERS};
     210             : static constexpr Register kGPParamRegisters[] = {GP_PARAM_REGISTERS};
     211             : static constexpr DoubleRegister kFPParamRegisters[] = {FP_PARAM_REGISTERS};
     212             : static constexpr Allocator return_registers(kGPReturnRegisters,
     213             :                                             arraysize(kGPReturnRegisters),
     214             :                                             kFPReturnRegisters,
     215             :                                             arraysize(kFPReturnRegisters));
     216             : static constexpr Allocator parameter_registers(kGPParamRegisters,
     217             :                                                arraysize(kGPParamRegisters),
     218             :                                                kFPParamRegisters,
     219             :                                                arraysize(kFPParamRegisters));
     220             : 
     221             : }  // namespace
     222             : 
     223             : // General code uses the above configuration data.
     224     4391333 : CallDescriptor* GetWasmCallDescriptor(Zone* zone, wasm::FunctionSig* fsig,
     225             :                                       bool supports_tail_calls) {
     226             :   // The '+ 1' here is to accomodate the wasm_context as first parameter.
     227             :   LocationSignature::Builder locations(zone, fsig->return_count(),
     228      869866 :                                        fsig->parameter_count() + 1);
     229             : 
     230      869951 :   Allocator rets = return_registers;
     231             : 
     232             :   // Add return location(s).
     233      869951 :   const int return_count = static_cast<int>(locations.return_count_);
     234     1422913 :   for (int i = 0; i < return_count; i++) {
     235      552965 :     ValueType ret = fsig->GetReturn(i);
     236      552965 :     locations.AddReturn(rets.Next(ret));
     237             :   }
     238             : 
     239      869948 :   Allocator params = parameter_registers;
     240             : 
     241             :   // Add parameter for the wasm_context.
     242      869948 :   locations.AddParam(params.Next(MachineType::PointerRepresentation()));
     243             : 
     244             :   // Add register and/or stack parameter(s).
     245      869942 :   const int parameter_count = static_cast<int>(fsig->parameter_count());
     246     2098653 :   for (int i = 0; i < parameter_count; i++) {
     247     1228694 :     ValueType param = fsig->GetParam(i);
     248     1228694 :     locations.AddParam(params.Next(param));
     249             :   }
     250             : 
     251             :   const RegList kCalleeSaveRegisters = 0;
     252             :   const RegList kCalleeSaveFPRegisters = 0;
     253             : 
     254             :   // The target for wasm calls is always a code object.
     255             :   MachineType target_type = MachineType::AnyTagged();
     256             :   LinkageLocation target_loc = LinkageLocation::ForAnyRegister(target_type);
     257             : 
     258             :   CallDescriptor::Flags flags = CallDescriptor::kUseNativeStack;
     259      869959 :   if (supports_tail_calls) flags |= CallDescriptor::kSupportsTailCalls;
     260             :   return new (zone) CallDescriptor(       // --
     261             :       CallDescriptor::kCallCodeObject,    // kind
     262             :       target_type,                        // target MachineType
     263             :       target_loc,                         // target location
     264             :       locations.Build(),                  // location_sig
     265             :       params.stack_offset,                // stack_parameter_count
     266             :       compiler::Operator::kNoProperties,  // properties
     267             :       kCalleeSaveRegisters,               // callee-saved registers
     268             :       kCalleeSaveFPRegisters,             // callee-saved fp regs
     269             :       flags,                              // flags
     270     2609835 :       "wasm-call");
     271             : }
     272             : 
     273           0 : CallDescriptor* ReplaceTypeInCallDescriptorWith(
     274           0 :     Zone* zone, CallDescriptor* descriptor, size_t num_replacements,
     275             :     MachineType input_type, MachineRepresentation output_type) {
     276             :   size_t parameter_count = descriptor->ParameterCount();
     277             :   size_t return_count = descriptor->ReturnCount();
     278           0 :   for (size_t i = 0; i < descriptor->ParameterCount(); i++) {
     279           0 :     if (descriptor->GetParameterType(i) == input_type) {
     280           0 :       parameter_count += num_replacements - 1;
     281             :     }
     282             :   }
     283           0 :   for (size_t i = 0; i < descriptor->ReturnCount(); i++) {
     284           0 :     if (descriptor->GetReturnType(i) == input_type) {
     285           0 :       return_count += num_replacements - 1;
     286             :     }
     287             :   }
     288           0 :   if (parameter_count == descriptor->ParameterCount() &&
     289             :       return_count == descriptor->ReturnCount()) {
     290             :     return descriptor;
     291             :   }
     292             : 
     293             :   LocationSignature::Builder locations(zone, return_count, parameter_count);
     294             : 
     295           0 :   Allocator rets = return_registers;
     296             : 
     297           0 :   for (size_t i = 0; i < descriptor->ReturnCount(); i++) {
     298           0 :     if (descriptor->GetReturnType(i) == input_type) {
     299           0 :       for (size_t j = 0; j < num_replacements; j++) {
     300           0 :         locations.AddReturn(rets.Next(output_type));
     301             :       }
     302             :     } else {
     303             :       locations.AddReturn(
     304           0 :           rets.Next(descriptor->GetReturnType(i).representation()));
     305             :     }
     306             :   }
     307             : 
     308           0 :   Allocator params = parameter_registers;
     309             : 
     310           0 :   for (size_t i = 0; i < descriptor->ParameterCount(); i++) {
     311           0 :     if (descriptor->GetParameterType(i) == input_type) {
     312           0 :       for (size_t j = 0; j < num_replacements; j++) {
     313           0 :         locations.AddParam(params.Next(output_type));
     314             :       }
     315             :     } else {
     316             :       locations.AddParam(
     317           0 :           params.Next(descriptor->GetParameterType(i).representation()));
     318             :     }
     319             :   }
     320             : 
     321             :   return new (zone) CallDescriptor(          // --
     322             :       descriptor->kind(),                    // kind
     323             :       descriptor->GetInputType(0),           // target MachineType
     324             :       descriptor->GetInputLocation(0),       // target location
     325             :       locations.Build(),                     // location_sig
     326             :       params.stack_offset,                   // stack_parameter_count
     327             :       descriptor->properties(),              // properties
     328             :       descriptor->CalleeSavedRegisters(),    // callee-saved registers
     329             :       descriptor->CalleeSavedFPRegisters(),  // callee-saved fp regs
     330             :       descriptor->flags(),                   // flags
     331           0 :       descriptor->debug_name());
     332             : }
     333             : 
     334           0 : CallDescriptor* GetI32WasmCallDescriptor(Zone* zone,
     335             :                                          CallDescriptor* descriptor) {
     336             :   return ReplaceTypeInCallDescriptorWith(zone, descriptor, 2,
     337             :                                          MachineType::Int64(),
     338           0 :                                          MachineRepresentation::kWord32);
     339             : }
     340             : 
     341           0 : CallDescriptor* GetI32WasmCallDescriptorForSimd(Zone* zone,
     342             :                                                 CallDescriptor* descriptor) {
     343             :   return ReplaceTypeInCallDescriptorWith(zone, descriptor, 4,
     344             :                                          MachineType::Simd128(),
     345           0 :                                          MachineRepresentation::kWord32);
     346             : }
     347             : 
     348             : #undef GP_PARAM_REGISTERS
     349             : #undef GP_RETURN_REGISTERS
     350             : #undef FP_PARAM_REGISTERS
     351             : #undef FP_RETURN_REGISTERS
     352             : 
     353             : }  // namespace compiler
     354             : }  // namespace internal
     355             : }  // namespace v8

Generated by: LCOV version 1.10