/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /*! * Copyright (c) 2018 by Contributors * \brief gotvm native interface definition * \file gotvm.cxx */ // Standard includes #include <stddef.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <stdint.h> // golang string compatible definition typedef struct { char *p; int n; } _gostring_; #include <string> #ifdef __cplusplus extern "C" { #endif // TVM runtime C interface #include <tvm/runtime/c_runtime_api.h> #include <dlpack/dlpack.h> /*! * \brief Convert native char array to _gostring_ structure. * _gostring_ structure represents the same memory footprint as golang string object. * * \param p is char pointer to a char array. * \param l is the size of the char array. this method exclusively need length as * its possible to have a bytearray in a string. * * \return _gostring_ object corresponding to native char array. * Caller is responsible to free the memory block allocated here. */ static _gostring_ _native_to_gostring(const char *p, size_t l) { _gostring_ ret; ret.p = reinterpret_cast<char*>(malloc(l)); if (NULL == ret.p) { ret.n = 0; return ret; } memcpy(ret.p, p, l); ret.n = l; return ret; } /*! * \brief embeds a 64bit uint value inside a string to serialize the data. * * \param s is string object. * \param off is the offset in the string object. * \param v is the uint64_t value which need to embed into given string. */ static void putuint64(std::string *s, size_t off, uint64_t v) { for (int i = 0; i < 8; i++) { (*s)[off + i] = (v >> (i * 8)) & 0xff; } } // TVM runtime C interface wrappers /*! * \brief Native interface to query TVM_VERSION in golang string format. * * \return char pointer to TVM-VERSION */ const char* _TVM_VERSION(void) { const char *version = TVM_VERSION; return version; } /*! * \brief Native interface for getting TVMGlobal function list. * * \param names return by argument to return the function names. * We wrap all strings into single string joined by (len+string) * which is unpacked and processed in golang. * * \return c_runtime_api return status. */ int _TVMFuncListGlobalNames(_gostring_* names) { int names_size; char **names_array; int result; result = TVMFuncListGlobalNames(&names_size, (char const ***)&names_array); if (result) { return result; } size_t tot = 8; for (int ii = 0; ii < names_size ; ++ii) { tot += 8 + strlen(names_array[ii]); } std::string str; str.resize(tot); putuint64(&str, 0, names_size); size_t off = 8; for (int64_t ii = 0; ii < names_size ; ++ii) { putuint64(&str, off, strlen(names_array[ii])); off += 8; str.replace(off, strlen(names_array[ii]), names_array[ii]); off += strlen(names_array[ii]); } *names = _native_to_gostring(str.data(), str.size()); if (str.size() != names->n) { TVMAPISetLastError("malloc failed during _native_to_gostring"); result = 1; } return result; } // Helpers for TVMValue /*! * \brief Native helper to copy TVMValue from golang slice to native array. * this helper is need as underlying momory for golang slice is not continueous. * * \param to_ptr is the native pointer of TVMValue array. * \param from_ptr pointer to TVMValue in golang slice. * \param array index in native array. */ void _TVMValueNativeSet(void* to_ptr, void* from_ptr, int ind) { TVMValue *from_p = reinterpret_cast<TVMValue*>(from_ptr); TVMValue *to_p = reinterpret_cast<TVMValue*>(to_ptr); memcpy(to_p+ind, from_p, sizeof(TVMValue)); } /*! * \brief Native helper to copy TVMValue from golang slice to native array. * this helper is need as underlying momory for golang slice is not continueous. * * \param to_ptr pointer to TVMValue in golang slice. * \param from_ptr is the native pointer of TVMValue array. * \param array index in native array. */ void _TVMValueNativeGet(void* to_ptr, void* from_ptr, int ind) { TVMValue *from_p = reinterpret_cast<TVMValue*>(from_ptr); TVMValue *to_p = reinterpret_cast<TVMValue*>(to_ptr); memcpy(to_p, from_p+ind, sizeof(TVMValue)); } extern int goTVMCallback(void*, void*, int, void*, void*); /*! * \brief _TVMCallback is the TVM runtime callback function for PackedFunction system. * * \param args is an array of TVMValue * \param type_codes is an array of int * \param num_args is int representing number of in arguments * \param ret is the return value handle to set the packed function return. * \param resource_handle is the golang private data pointer. * * \returns the error status as TVM_DLL */ int _TVMCallback(TVMValue* args, int* type_codes, int num_args, TVMRetValueHandle ret, void* resource_handle) { return goTVMCallback(args, type_codes, num_args, ret, resource_handle); } /*! * _TVMPackedCFuncFinalizer is finalizer for packed function system. * */ void _TVMPackedCFuncFinalizer(void* resource_handle) { return; } /*! * /brief _ConvertFunction creates a packed function for with given resource handle. * * /param fptr is the pointer to golang resource handle. * /param *fhandle is the return argument holding packed function. * * /return is an int indicating the return status. */ int _ConvertFunction(void* fptr, TVMFunctionHandle *fhandle) { int ret = TVMFuncCreateFromCFunc(_TVMCallback, fptr, _TVMPackedCFuncFinalizer, fhandle); return ret; } #ifdef __cplusplus } #endif