OLD | NEW |
(Empty) | |
| 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.h" |
| 6 #include "src/macro-assembler.h" |
| 7 |
| 8 #include "src/wasm/wasm-module.h" |
| 9 |
| 10 #include "src/compiler/linkage.h" |
| 11 |
| 12 #include "src/zone.h" |
| 13 |
| 14 namespace v8 { |
| 15 namespace internal { |
| 16 // TODO(titzer): this should not be in the WASM namespace. |
| 17 namespace wasm { |
| 18 |
| 19 using compiler::LocationSignature; |
| 20 using compiler::CallDescriptor; |
| 21 using compiler::LinkageLocation; |
| 22 |
| 23 namespace { |
| 24 MachineType MachineTypeFor(LocalType type) { |
| 25 switch (type) { |
| 26 case kAstI32: |
| 27 return MachineType::Int32(); |
| 28 case kAstI64: |
| 29 return MachineType::Int64(); |
| 30 case kAstF64: |
| 31 return MachineType::Float64(); |
| 32 case kAstF32: |
| 33 return MachineType::Float32(); |
| 34 default: |
| 35 UNREACHABLE(); |
| 36 return MachineType::AnyTagged(); |
| 37 } |
| 38 } |
| 39 |
| 40 |
| 41 // Platform-specific configuration for C calling convention. |
| 42 LinkageLocation regloc(Register reg) { |
| 43 return LinkageLocation::ForRegister(reg.code()); |
| 44 } |
| 45 |
| 46 |
| 47 LinkageLocation regloc(DoubleRegister reg) { |
| 48 return LinkageLocation::ForRegister(reg.code()); |
| 49 } |
| 50 |
| 51 |
| 52 LinkageLocation stackloc(int i) { |
| 53 return LinkageLocation::ForCallerFrameSlot(i); |
| 54 } |
| 55 |
| 56 |
| 57 #if V8_TARGET_ARCH_IA32 |
| 58 // =========================================================================== |
| 59 // == ia32 =================================================================== |
| 60 // =========================================================================== |
| 61 #define GP_PARAM_REGISTERS eax, edx, ecx, ebx, esi, edi |
| 62 #define GP_RETURN_REGISTERS eax, edx |
| 63 #define FP_PARAM_REGISTERS xmm1, xmm2, xmm3, xmm4, xmm5, xmm6 |
| 64 #define FP_RETURN_REGISTERS xmm1, xmm2 |
| 65 |
| 66 #elif V8_TARGET_ARCH_X64 |
| 67 // =========================================================================== |
| 68 // == x64 ==================================================================== |
| 69 // =========================================================================== |
| 70 #define GP_PARAM_REGISTERS rax, rdx, rcx, rbx, rsi, rdi |
| 71 #define GP_RETURN_REGISTERS rax, rdx |
| 72 #define FP_PARAM_REGISTERS xmm1, xmm2, xmm3, xmm4, xmm5, xmm6 |
| 73 #define FP_RETURN_REGISTERS xmm1, xmm2 |
| 74 |
| 75 #elif V8_TARGET_ARCH_X87 |
| 76 // =========================================================================== |
| 77 // == x87 ==================================================================== |
| 78 // =========================================================================== |
| 79 #define GP_PARAM_REGISTERS eax, edx, ecx, ebx, esi, edi |
| 80 #define GP_RETURN_REGISTERS eax, edx |
| 81 |
| 82 #elif V8_TARGET_ARCH_ARM |
| 83 // =========================================================================== |
| 84 // == arm ==================================================================== |
| 85 // =========================================================================== |
| 86 #define GP_PARAM_REGISTERS r0, r1, r2, r3 |
| 87 #define GP_RETURN_REGISTERS r0, r1 |
| 88 #define FP_PARAM_REGISTERS d0, d1, d2, d3, d4, d5, d6, d7 |
| 89 #define FP_RETURN_REGISTERS d0, d1 |
| 90 |
| 91 #elif V8_TARGET_ARCH_ARM64 |
| 92 // =========================================================================== |
| 93 // == arm64 ==================================================================== |
| 94 // =========================================================================== |
| 95 #define GP_PARAM_REGISTERS x0, x1, x2, x3, x4, x5, x6, x7 |
| 96 #define GP_RETURN_REGISTERS x0, x1 |
| 97 #define FP_PARAM_REGISTERS d0, d1, d2, d3, d4, d5, d6, d7 |
| 98 #define FP_RETURN_REGISTERS d0, d1 |
| 99 |
| 100 #elif V8_TARGET_ARCH_MIPS |
| 101 // =========================================================================== |
| 102 // == mips =================================================================== |
| 103 // =========================================================================== |
| 104 #define GP_PARAM_REGISTERS a0, a1, a2, a3 |
| 105 #define GP_RETURN_REGISTERS v0, v1 |
| 106 #define FP_PARAM_REGISTERS f2, f4, f6, f8, f10, f12, f14 |
| 107 #define FP_RETURN_REGISTERS f2, f4 |
| 108 |
| 109 #elif V8_TARGET_ARCH_MIPS64 |
| 110 // =========================================================================== |
| 111 // == mips64 ================================================================= |
| 112 // =========================================================================== |
| 113 #define GP_PARAM_REGISTERS a0, a1, a2, a3, a4, a5, a6, a7 |
| 114 #define GP_RETURN_REGISTERS v0, v1 |
| 115 #define FP_PARAM_REGISTERS f2, f4, f6, f8, f10, f12, f14 |
| 116 #define FP_RETURN_REGISTERS f2, f4 |
| 117 |
| 118 #elif V8_TARGET_ARCH_PPC || V8_TARGET_ARCH_PPC64 |
| 119 // =========================================================================== |
| 120 // == ppc & ppc64 ============================================================ |
| 121 // =========================================================================== |
| 122 #define GP_PARAM_REGISTERS r3, r4, r5, r6, r7, r8, r9, r10 |
| 123 #define GP_RETURN_REGISTERS r3, r4 |
| 124 #define FP_PARAM_REGISTERS d0, d1, d2, d3, d4, d5, d6, d7 |
| 125 #define FP_RETURN_REGISTERS d0, d1 |
| 126 |
| 127 #else |
| 128 // =========================================================================== |
| 129 // == unknown ================================================================ |
| 130 // =========================================================================== |
| 131 // Don't define anything. We'll just always use the stack. |
| 132 #endif |
| 133 |
| 134 |
| 135 // Helper for allocating either an GP or FP reg, or the next stack slot. |
| 136 struct Allocator { |
| 137 Allocator(const Register* gp, int gpc, const DoubleRegister* fp, int fpc) |
| 138 : gp_count(gpc), |
| 139 gp_offset(0), |
| 140 gp_regs(gp), |
| 141 fp_count(fpc), |
| 142 fp_offset(0), |
| 143 fp_regs(fp), |
| 144 stack_offset(0) {} |
| 145 |
| 146 int gp_count; |
| 147 int gp_offset; |
| 148 const Register* gp_regs; |
| 149 |
| 150 int fp_count; |
| 151 int fp_offset; |
| 152 const DoubleRegister* fp_regs; |
| 153 |
| 154 int stack_offset; |
| 155 |
| 156 LinkageLocation Next(LocalType type) { |
| 157 if (IsFloatingPoint(type)) { |
| 158 // Allocate a floating point register/stack location. |
| 159 if (fp_offset < fp_count) { |
| 160 return regloc(fp_regs[fp_offset++]); |
| 161 } else { |
| 162 int offset = -1 - stack_offset; |
| 163 stack_offset += Words(type); |
| 164 return stackloc(offset); |
| 165 } |
| 166 } else { |
| 167 // Allocate a general purpose register/stack location. |
| 168 if (gp_offset < gp_count) { |
| 169 return regloc(gp_regs[gp_offset++]); |
| 170 } else { |
| 171 int offset = -1 - stack_offset; |
| 172 stack_offset += Words(type); |
| 173 return stackloc(offset); |
| 174 } |
| 175 } |
| 176 } |
| 177 bool IsFloatingPoint(LocalType type) { |
| 178 return type == kAstF32 || type == kAstF64; |
| 179 } |
| 180 int Words(LocalType type) { |
| 181 if (kPointerSize < 8 && (type == kAstI64 || type == kAstF64)) { |
| 182 return 2; |
| 183 } |
| 184 return 1; |
| 185 } |
| 186 }; |
| 187 } // namespace |
| 188 |
| 189 |
| 190 // General code uses the above configuration data. |
| 191 CallDescriptor* ModuleEnv::GetWasmCallDescriptor(Zone* zone, |
| 192 FunctionSig* fsig) { |
| 193 MachineSignature::Builder msig(zone, fsig->return_count(), |
| 194 fsig->parameter_count()); |
| 195 LocationSignature::Builder locations(zone, fsig->return_count(), |
| 196 fsig->parameter_count()); |
| 197 |
| 198 #ifdef GP_RETURN_REGISTERS |
| 199 static const Register kGPReturnRegisters[] = {GP_RETURN_REGISTERS}; |
| 200 static const int kGPReturnRegistersCount = |
| 201 static_cast<int>(arraysize(kGPReturnRegisters)); |
| 202 #else |
| 203 static const Register* kGPReturnRegisters = nullptr; |
| 204 static const int kGPReturnRegistersCount = 0; |
| 205 #endif |
| 206 |
| 207 #ifdef FP_RETURN_REGISTERS |
| 208 static const DoubleRegister kFPReturnRegisters[] = {FP_RETURN_REGISTERS}; |
| 209 static const int kFPReturnRegistersCount = |
| 210 static_cast<int>(arraysize(kFPReturnRegisters)); |
| 211 #else |
| 212 static const DoubleRegister* kFPReturnRegisters = nullptr; |
| 213 static const int kFPReturnRegistersCount = 0; |
| 214 #endif |
| 215 |
| 216 Allocator rets(kGPReturnRegisters, kGPReturnRegistersCount, |
| 217 kFPReturnRegisters, kFPReturnRegistersCount); |
| 218 |
| 219 // Add return location(s). |
| 220 const int return_count = static_cast<int>(locations.return_count_); |
| 221 for (int i = 0; i < return_count; i++) { |
| 222 LocalType ret = fsig->GetReturn(i); |
| 223 msig.AddReturn(MachineTypeFor(ret)); |
| 224 locations.AddReturn(rets.Next(ret)); |
| 225 } |
| 226 |
| 227 #ifdef GP_PARAM_REGISTERS |
| 228 static const Register kGPParamRegisters[] = {GP_PARAM_REGISTERS}; |
| 229 static const int kGPParamRegistersCount = |
| 230 static_cast<int>(arraysize(kGPParamRegisters)); |
| 231 #else |
| 232 static const Register* kGPParamRegisters = nullptr; |
| 233 static const int kGPParamRegistersCount = 0; |
| 234 #endif |
| 235 |
| 236 #ifdef FP_PARAM_REGISTERS |
| 237 static const DoubleRegister kFPParamRegisters[] = {FP_PARAM_REGISTERS}; |
| 238 static const int kFPParamRegistersCount = |
| 239 static_cast<int>(arraysize(kFPParamRegisters)); |
| 240 #else |
| 241 static const DoubleRegister* kFPParamRegisters = nullptr; |
| 242 static const int kFPParamRegistersCount = 0; |
| 243 #endif |
| 244 |
| 245 Allocator params(kGPParamRegisters, kGPParamRegistersCount, kFPParamRegisters, |
| 246 kFPParamRegistersCount); |
| 247 |
| 248 // Add register and/or stack parameter(s). |
| 249 const int parameter_count = static_cast<int>(fsig->parameter_count()); |
| 250 for (int i = 0; i < parameter_count; i++) { |
| 251 LocalType param = fsig->GetParam(i); |
| 252 msig.AddParam(MachineTypeFor(param)); |
| 253 locations.AddParam(params.Next(param)); |
| 254 } |
| 255 |
| 256 const RegList kCalleeSaveRegisters = 0; |
| 257 const RegList kCalleeSaveFPRegisters = 0; |
| 258 |
| 259 // The target for WASM calls is always a code object. |
| 260 MachineType target_type = MachineType::AnyTagged(); |
| 261 LinkageLocation target_loc = LinkageLocation::ForAnyRegister(); |
| 262 return new (zone) CallDescriptor( // -- |
| 263 CallDescriptor::kCallCodeObject, // kind |
| 264 target_type, // target MachineType |
| 265 target_loc, // target location |
| 266 msig.Build(), // machine_sig |
| 267 locations.Build(), // location_sig |
| 268 params.stack_offset, // stack_parameter_count |
| 269 compiler::Operator::kNoProperties, // properties |
| 270 kCalleeSaveRegisters, // callee-saved registers |
| 271 kCalleeSaveFPRegisters, // callee-saved fp regs |
| 272 CallDescriptor::kUseNativeStack, // flags |
| 273 "c-call"); |
| 274 } |
| 275 } // namespace wasm |
| 276 } // namespace internal |
| 277 } // namespace v8 |
OLD | NEW |