| Index: src/compiler/wasm-linkage.cc
|
| diff --git a/src/compiler/wasm-linkage.cc b/src/compiler/wasm-linkage.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..98ec2c84bb1132a37c4b6138054aeaab68eeddbe
|
| --- /dev/null
|
| +++ b/src/compiler/wasm-linkage.cc
|
| @@ -0,0 +1,277 @@
|
| +// Copyright 2015 the V8 project authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "src/assembler.h"
|
| +#include "src/macro-assembler.h"
|
| +
|
| +#include "src/wasm/wasm-module.h"
|
| +
|
| +#include "src/compiler/linkage.h"
|
| +
|
| +#include "src/zone.h"
|
| +
|
| +namespace v8 {
|
| +namespace internal {
|
| +// TODO(titzer): this should not be in the WASM namespace.
|
| +namespace wasm {
|
| +
|
| +using compiler::LocationSignature;
|
| +using compiler::CallDescriptor;
|
| +using compiler::LinkageLocation;
|
| +
|
| +namespace {
|
| +MachineType MachineTypeFor(LocalType type) {
|
| + switch (type) {
|
| + case kAstI32:
|
| + return MachineType::Int32();
|
| + case kAstI64:
|
| + return MachineType::Int64();
|
| + case kAstF64:
|
| + return MachineType::Float64();
|
| + case kAstF32:
|
| + return MachineType::Float32();
|
| + default:
|
| + UNREACHABLE();
|
| + return MachineType::AnyTagged();
|
| + }
|
| +}
|
| +
|
| +
|
| +// Platform-specific configuration for C calling convention.
|
| +LinkageLocation regloc(Register reg) {
|
| + return LinkageLocation::ForRegister(reg.code());
|
| +}
|
| +
|
| +
|
| +LinkageLocation regloc(DoubleRegister reg) {
|
| + return LinkageLocation::ForRegister(reg.code());
|
| +}
|
| +
|
| +
|
| +LinkageLocation stackloc(int i) {
|
| + return LinkageLocation::ForCallerFrameSlot(i);
|
| +}
|
| +
|
| +
|
| +#if V8_TARGET_ARCH_IA32
|
| +// ===========================================================================
|
| +// == ia32 ===================================================================
|
| +// ===========================================================================
|
| +#define GP_PARAM_REGISTERS eax, edx, ecx, ebx, esi, edi
|
| +#define GP_RETURN_REGISTERS eax, edx
|
| +#define FP_PARAM_REGISTERS xmm1, xmm2, xmm3, xmm4, xmm5, xmm6
|
| +#define FP_RETURN_REGISTERS xmm1, xmm2
|
| +
|
| +#elif V8_TARGET_ARCH_X64
|
| +// ===========================================================================
|
| +// == x64 ====================================================================
|
| +// ===========================================================================
|
| +#define GP_PARAM_REGISTERS rax, rdx, rcx, rbx, rsi, rdi
|
| +#define GP_RETURN_REGISTERS rax, rdx
|
| +#define FP_PARAM_REGISTERS xmm1, xmm2, xmm3, xmm4, xmm5, xmm6
|
| +#define FP_RETURN_REGISTERS xmm1, xmm2
|
| +
|
| +#elif V8_TARGET_ARCH_X87
|
| +// ===========================================================================
|
| +// == x87 ====================================================================
|
| +// ===========================================================================
|
| +#define GP_PARAM_REGISTERS eax, edx, ecx, ebx, esi, edi
|
| +#define GP_RETURN_REGISTERS eax, edx
|
| +
|
| +#elif V8_TARGET_ARCH_ARM
|
| +// ===========================================================================
|
| +// == arm ====================================================================
|
| +// ===========================================================================
|
| +#define GP_PARAM_REGISTERS r0, r1, r2, r3
|
| +#define GP_RETURN_REGISTERS r0, r1
|
| +#define FP_PARAM_REGISTERS d0, d1, d2, d3, d4, d5, d6, d7
|
| +#define FP_RETURN_REGISTERS d0, d1
|
| +
|
| +#elif V8_TARGET_ARCH_ARM64
|
| +// ===========================================================================
|
| +// == arm64 ====================================================================
|
| +// ===========================================================================
|
| +#define GP_PARAM_REGISTERS x0, x1, x2, x3, x4, x5, x6, x7
|
| +#define GP_RETURN_REGISTERS x0, x1
|
| +#define FP_PARAM_REGISTERS d0, d1, d2, d3, d4, d5, d6, d7
|
| +#define FP_RETURN_REGISTERS d0, d1
|
| +
|
| +#elif V8_TARGET_ARCH_MIPS
|
| +// ===========================================================================
|
| +// == mips ===================================================================
|
| +// ===========================================================================
|
| +#define GP_PARAM_REGISTERS a0, a1, a2, a3
|
| +#define GP_RETURN_REGISTERS v0, v1
|
| +#define FP_PARAM_REGISTERS f2, f4, f6, f8, f10, f12, f14
|
| +#define FP_RETURN_REGISTERS f2, f4
|
| +
|
| +#elif V8_TARGET_ARCH_MIPS64
|
| +// ===========================================================================
|
| +// == mips64 =================================================================
|
| +// ===========================================================================
|
| +#define GP_PARAM_REGISTERS a0, a1, a2, a3, a4, a5, a6, a7
|
| +#define GP_RETURN_REGISTERS v0, v1
|
| +#define FP_PARAM_REGISTERS f2, f4, f6, f8, f10, f12, f14
|
| +#define FP_RETURN_REGISTERS f2, f4
|
| +
|
| +#elif V8_TARGET_ARCH_PPC || V8_TARGET_ARCH_PPC64
|
| +// ===========================================================================
|
| +// == ppc & ppc64 ============================================================
|
| +// ===========================================================================
|
| +#define GP_PARAM_REGISTERS r3, r4, r5, r6, r7, r8, r9, r10
|
| +#define GP_RETURN_REGISTERS r3, r4
|
| +#define FP_PARAM_REGISTERS d0, d1, d2, d3, d4, d5, d6, d7
|
| +#define FP_RETURN_REGISTERS d0, d1
|
| +
|
| +#else
|
| +// ===========================================================================
|
| +// == unknown ================================================================
|
| +// ===========================================================================
|
| +// Don't define anything. We'll just always use the stack.
|
| +#endif
|
| +
|
| +
|
| +// Helper for allocating either an GP or FP reg, or the next stack slot.
|
| +struct Allocator {
|
| + Allocator(const Register* gp, int gpc, const DoubleRegister* fp, int fpc)
|
| + : gp_count(gpc),
|
| + gp_offset(0),
|
| + gp_regs(gp),
|
| + fp_count(fpc),
|
| + fp_offset(0),
|
| + fp_regs(fp),
|
| + stack_offset(0) {}
|
| +
|
| + int gp_count;
|
| + int gp_offset;
|
| + const Register* gp_regs;
|
| +
|
| + int fp_count;
|
| + int fp_offset;
|
| + const DoubleRegister* fp_regs;
|
| +
|
| + int stack_offset;
|
| +
|
| + LinkageLocation Next(LocalType type) {
|
| + if (IsFloatingPoint(type)) {
|
| + // Allocate a floating point register/stack location.
|
| + if (fp_offset < fp_count) {
|
| + return regloc(fp_regs[fp_offset++]);
|
| + } else {
|
| + int offset = -1 - stack_offset;
|
| + stack_offset += Words(type);
|
| + return stackloc(offset);
|
| + }
|
| + } else {
|
| + // Allocate a general purpose register/stack location.
|
| + if (gp_offset < gp_count) {
|
| + return regloc(gp_regs[gp_offset++]);
|
| + } else {
|
| + int offset = -1 - stack_offset;
|
| + stack_offset += Words(type);
|
| + return stackloc(offset);
|
| + }
|
| + }
|
| + }
|
| + bool IsFloatingPoint(LocalType type) {
|
| + return type == kAstF32 || type == kAstF64;
|
| + }
|
| + int Words(LocalType type) {
|
| + if (kPointerSize < 8 && (type == kAstI64 || type == kAstF64)) {
|
| + return 2;
|
| + }
|
| + return 1;
|
| + }
|
| +};
|
| +} // namespace
|
| +
|
| +
|
| +// General code uses the above configuration data.
|
| +CallDescriptor* ModuleEnv::GetWasmCallDescriptor(Zone* zone,
|
| + FunctionSig* fsig) {
|
| + MachineSignature::Builder msig(zone, fsig->return_count(),
|
| + fsig->parameter_count());
|
| + LocationSignature::Builder locations(zone, fsig->return_count(),
|
| + fsig->parameter_count());
|
| +
|
| +#ifdef GP_RETURN_REGISTERS
|
| + static const Register kGPReturnRegisters[] = {GP_RETURN_REGISTERS};
|
| + static const int kGPReturnRegistersCount =
|
| + static_cast<int>(arraysize(kGPReturnRegisters));
|
| +#else
|
| + static const Register* kGPReturnRegisters = nullptr;
|
| + static const int kGPReturnRegistersCount = 0;
|
| +#endif
|
| +
|
| +#ifdef FP_RETURN_REGISTERS
|
| + static const DoubleRegister kFPReturnRegisters[] = {FP_RETURN_REGISTERS};
|
| + static const int kFPReturnRegistersCount =
|
| + static_cast<int>(arraysize(kFPReturnRegisters));
|
| +#else
|
| + static const DoubleRegister* kFPReturnRegisters = nullptr;
|
| + static const int kFPReturnRegistersCount = 0;
|
| +#endif
|
| +
|
| + Allocator rets(kGPReturnRegisters, kGPReturnRegistersCount,
|
| + kFPReturnRegisters, kFPReturnRegistersCount);
|
| +
|
| + // Add return location(s).
|
| + const int return_count = static_cast<int>(locations.return_count_);
|
| + for (int i = 0; i < return_count; i++) {
|
| + LocalType ret = fsig->GetReturn(i);
|
| + msig.AddReturn(MachineTypeFor(ret));
|
| + locations.AddReturn(rets.Next(ret));
|
| + }
|
| +
|
| +#ifdef GP_PARAM_REGISTERS
|
| + static const Register kGPParamRegisters[] = {GP_PARAM_REGISTERS};
|
| + static const int kGPParamRegistersCount =
|
| + static_cast<int>(arraysize(kGPParamRegisters));
|
| +#else
|
| + static const Register* kGPParamRegisters = nullptr;
|
| + static const int kGPParamRegistersCount = 0;
|
| +#endif
|
| +
|
| +#ifdef FP_PARAM_REGISTERS
|
| + static const DoubleRegister kFPParamRegisters[] = {FP_PARAM_REGISTERS};
|
| + static const int kFPParamRegistersCount =
|
| + static_cast<int>(arraysize(kFPParamRegisters));
|
| +#else
|
| + static const DoubleRegister* kFPParamRegisters = nullptr;
|
| + static const int kFPParamRegistersCount = 0;
|
| +#endif
|
| +
|
| + Allocator params(kGPParamRegisters, kGPParamRegistersCount, kFPParamRegisters,
|
| + kFPParamRegistersCount);
|
| +
|
| + // Add register and/or stack parameter(s).
|
| + const int parameter_count = static_cast<int>(fsig->parameter_count());
|
| + for (int i = 0; i < parameter_count; i++) {
|
| + LocalType param = fsig->GetParam(i);
|
| + msig.AddParam(MachineTypeFor(param));
|
| + locations.AddParam(params.Next(param));
|
| + }
|
| +
|
| + const RegList kCalleeSaveRegisters = 0;
|
| + const RegList kCalleeSaveFPRegisters = 0;
|
| +
|
| + // The target for WASM calls is always a code object.
|
| + MachineType target_type = MachineType::AnyTagged();
|
| + LinkageLocation target_loc = LinkageLocation::ForAnyRegister();
|
| + return new (zone) CallDescriptor( // --
|
| + CallDescriptor::kCallCodeObject, // kind
|
| + target_type, // target MachineType
|
| + target_loc, // target location
|
| + msig.Build(), // machine_sig
|
| + locations.Build(), // location_sig
|
| + params.stack_offset, // stack_parameter_count
|
| + compiler::Operator::kNoProperties, // properties
|
| + kCalleeSaveRegisters, // callee-saved registers
|
| + kCalleeSaveFPRegisters, // callee-saved fp regs
|
| + CallDescriptor::kUseNativeStack, // flags
|
| + "c-call");
|
| +}
|
| +} // namespace wasm
|
| +} // namespace internal
|
| +} // namespace v8
|
|
|