| // Copyright 2014 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. |
| |
| #ifndef V8_COMPILER_C_SIGNATURE_H_ |
| #define V8_COMPILER_C_SIGNATURE_H_ |
| |
| #include "src/codegen/machine-type.h" |
| |
| namespace v8 { |
| namespace internal { |
| namespace compiler { |
| |
| #define FOREACH_CTYPE_MACHINE_TYPE_MAPPING(V) \ |
| V(void, MachineType::None()) \ |
| V(bool, MachineType::Uint8()) \ |
| V(int8_t, MachineType::Int8()) \ |
| V(uint8_t, MachineType::Uint8()) \ |
| V(int16_t, MachineType::Int16()) \ |
| V(uint16_t, MachineType::Uint16()) \ |
| V(int32_t, MachineType::Int32()) \ |
| V(uint32_t, MachineType::Uint32()) \ |
| V(int64_t, MachineType::Int64()) \ |
| V(uint64_t, MachineType::Uint64()) \ |
| V(float, MachineType::Float32()) \ |
| V(double, MachineType::Float64()) \ |
| V(void*, MachineType::Pointer()) \ |
| V(int*, MachineType::Pointer()) |
| |
| template <typename T> |
| inline constexpr MachineType MachineTypeForC() { |
| static_assert(std::is_convertible<T, Object>::value, |
| "all non-specialized types must be convertible to Object"); |
| return MachineType::AnyTagged(); |
| } |
| |
| #define DECLARE_TEMPLATE_SPECIALIZATION(ctype, mtype) \ |
| template <> \ |
| inline MachineType constexpr MachineTypeForC<ctype>() { \ |
| return mtype; \ |
| } |
| FOREACH_CTYPE_MACHINE_TYPE_MAPPING(DECLARE_TEMPLATE_SPECIALIZATION) |
| #undef DECLARE_TEMPLATE_SPECIALIZATION |
| |
| // Helper for building machine signatures from C types. |
| class CSignature : public MachineSignature { |
| protected: |
| CSignature(size_t return_count, size_t parameter_count, MachineType* reps) |
| : MachineSignature(return_count, parameter_count, reps) {} |
| |
| public: |
| template <typename... Params> |
| static void VerifyParams(MachineSignature* sig) { |
| // Verifies the C signature against the machine types. |
| std::array<MachineType, sizeof...(Params)> params{ |
| {MachineTypeForC<Params>()...}}; |
| for (size_t p = 0; p < params.size(); ++p) { |
| CHECK_EQ(sig->GetParam(p), params[p]); |
| } |
| } |
| |
| static CSignature* FromMachine(Zone* zone, MachineSignature* msig) { |
| return reinterpret_cast<CSignature*>(msig); |
| } |
| |
| template <typename... ParamMachineTypes> |
| static CSignature* New(Zone* zone, MachineType ret, |
| ParamMachineTypes... params) { |
| constexpr size_t param_count = sizeof...(params); |
| std::array<MachineType, param_count> param_arr{{params...}}; |
| const size_t buffer_size = |
| param_count + (ret == MachineType::None() ? 0 : 1); |
| MachineType* buffer = zone->NewArray<MachineType>(buffer_size); |
| size_t pos = 0; |
| size_t return_count = 0; |
| if (ret != MachineType::None()) { |
| buffer[pos++] = ret; |
| return_count++; |
| } |
| for (MachineType p : param_arr) { |
| // Check that there are no MachineType::None()'s in the parameters. |
| CHECK_NE(MachineType::None(), p); |
| buffer[pos++] = p; |
| } |
| DCHECK_EQ(buffer_size, pos); |
| return new (zone) CSignature(return_count, param_count, buffer); |
| } |
| }; |
| |
| // Helper classes for instantiating Signature objects to be callable from C. |
| template <typename Ret, typename... Params> |
| class CSignatureOf : public CSignature { |
| public: |
| CSignatureOf() : CSignature(kReturnCount, kParamCount, storage_) { |
| constexpr std::array<MachineType, kParamCount> param_types{ |
| MachineTypeForC<Params>()...}; |
| if (kReturnCount == 1) storage_[0] = MachineTypeForC<Ret>(); |
| static_assert( |
| std::is_same<decltype(*reps_), decltype(*param_types.data())>::value, |
| "type mismatch, cannot memcpy"); |
| memcpy(storage_ + kReturnCount, param_types.data(), |
| sizeof(*storage_) * kParamCount); |
| } |
| |
| private: |
| static constexpr size_t kReturnCount = |
| MachineTypeForC<Ret>() == MachineType::None() ? 0 : 1; |
| static constexpr size_t kParamCount = sizeof...(Params); |
| |
| MachineType storage_[kReturnCount + kParamCount]; |
| }; |
| |
| using CSignature_i_ii = CSignatureOf<int32_t, int32_t, int32_t>; |
| using CSignature_u_uu = CSignatureOf<uint32_t, uint32_t, uint32_t>; |
| using CSignature_f_ff = CSignatureOf<float, float, float>; |
| using CSignature_d_dd = CSignatureOf<double, double, double>; |
| using CSignature_o_oo = CSignatureOf<Object, Object, Object>; |
| |
| } // namespace compiler |
| } // namespace internal |
| } // namespace v8 |
| |
| #endif // V8_COMPILER_C_SIGNATURE_H_ |