| // 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/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 MachineType MachineTypeForC() { |
| while (false) { |
| // All other types T must be assignable to Object* |
| *(static_cast<Object* volatile*>(0)) = static_cast<T>(0); |
| } |
| return MachineType::AnyTagged(); |
| } |
| |
| #define DECLARE_TEMPLATE_SPECIALIZATION(ctype, mtype) \ |
| template <> \ |
| inline MachineType 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 P1 = void, typename P2 = void, typename P3 = void, |
| typename P4 = void, typename P5 = void> |
| static void VerifyParams(MachineSignature* sig) { |
| // Verifies the C signature against the machine types. Maximum {5} params. |
| CHECK_LT(sig->parameter_count(), 6u); |
| const int kMax = 5; |
| MachineType params[] = {MachineTypeForC<P1>(), MachineTypeForC<P2>(), |
| MachineTypeForC<P3>(), MachineTypeForC<P4>(), |
| MachineTypeForC<P5>()}; |
| for (int p = kMax - 1; p >= 0; p--) { |
| if (p < static_cast<int>(sig->parameter_count())) { |
| CHECK_EQ(sig->GetParam(p), params[p]); |
| } else { |
| CHECK_EQ(MachineType::None(), params[p]); |
| } |
| } |
| } |
| |
| static CSignature* FromMachine(Zone* zone, MachineSignature* msig) { |
| return reinterpret_cast<CSignature*>(msig); |
| } |
| |
| static CSignature* New(Zone* zone, MachineType ret, |
| MachineType p1 = MachineType::None(), |
| MachineType p2 = MachineType::None(), |
| MachineType p3 = MachineType::None(), |
| MachineType p4 = MachineType::None(), |
| MachineType p5 = MachineType::None()) { |
| MachineType* buffer = zone->NewArray<MachineType>(6); |
| int pos = 0; |
| size_t return_count = 0; |
| if (ret != MachineType::None()) { |
| buffer[pos++] = ret; |
| return_count++; |
| } |
| buffer[pos++] = p1; |
| buffer[pos++] = p2; |
| buffer[pos++] = p3; |
| buffer[pos++] = p4; |
| buffer[pos++] = p5; |
| size_t param_count = 5; |
| if (p5 == MachineType::None()) param_count--; |
| if (p4 == MachineType::None()) param_count--; |
| if (p3 == MachineType::None()) param_count--; |
| if (p2 == MachineType::None()) param_count--; |
| if (p1 == MachineType::None()) param_count--; |
| for (size_t i = 0; i < param_count; i++) { |
| // Check that there are no MachineType::None()'s in the middle of |
| // parameters. |
| CHECK_NE(MachineType::None(), buffer[return_count + i]); |
| } |
| return new (zone) CSignature(return_count, param_count, buffer); |
| } |
| }; |
| |
| |
| template <typename Ret, uint16_t kParamCount> |
| class CSignatureOf : public CSignature { |
| protected: |
| MachineType storage_[1 + kParamCount]; |
| |
| CSignatureOf() |
| : CSignature(MachineTypeForC<Ret>() != MachineType::None() ? 1 : 0, |
| kParamCount, reinterpret_cast<MachineType*>(&storage_)) { |
| if (return_count_ == 1) storage_[0] = MachineTypeForC<Ret>(); |
| } |
| void Set(int index, MachineType type) { |
| CHECK_LE(0, index); |
| CHECK_LT(index, kParamCount); |
| reps_[return_count_ + index] = type; |
| } |
| }; |
| |
| // Helper classes for instantiating Signature objects to be callable from C. |
| template <typename Ret> |
| class CSignature0 : public CSignatureOf<Ret, 0> { |
| public: |
| CSignature0() : CSignatureOf<Ret, 0>() {} |
| }; |
| |
| template <typename Ret, typename P1> |
| class CSignature1 : public CSignatureOf<Ret, 1> { |
| public: |
| CSignature1() : CSignatureOf<Ret, 1>() { |
| this->Set(0, MachineTypeForC<P1>()); |
| } |
| }; |
| |
| template <typename Ret, typename P1, typename P2> |
| class CSignature2 : public CSignatureOf<Ret, 2> { |
| public: |
| CSignature2() : CSignatureOf<Ret, 2>() { |
| this->Set(0, MachineTypeForC<P1>()); |
| this->Set(1, MachineTypeForC<P2>()); |
| } |
| }; |
| |
| template <typename Ret, typename P1, typename P2, typename P3> |
| class CSignature3 : public CSignatureOf<Ret, 3> { |
| public: |
| CSignature3() : CSignatureOf<Ret, 3>() { |
| this->Set(0, MachineTypeForC<P1>()); |
| this->Set(1, MachineTypeForC<P2>()); |
| this->Set(2, MachineTypeForC<P3>()); |
| } |
| }; |
| |
| typedef CSignature2<int32_t, int32_t, int32_t> CSignature_i_ii; |
| typedef CSignature2<uint32_t, uint32_t, uint32_t> CSignature_u_uu; |
| typedef CSignature2<float, float, float> CSignature_f_ff; |
| typedef CSignature2<double, double, double> CSignature_d_dd; |
| typedef CSignature2<Object*, Object*, Object*> CSignature_o_oo; |
| } // namespace compiler |
| } // namespace internal |
| } // namespace v8 |
| |
| #endif // V8_COMPILER_C_SIGNATURE_H_ |