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