|
| 1 | +/* |
| 2 | + * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| 4 | + * |
| 5 | + * The Universal Permissive License (UPL), Version 1.0 |
| 6 | + * |
| 7 | + * Subject to the condition set forth below, permission is hereby granted to any |
| 8 | + * person obtaining a copy of this software, associated documentation and/or |
| 9 | + * data (collectively the "Software"), free of charge and under any and all |
| 10 | + * copyright rights in the Software, and any and all patent rights owned or |
| 11 | + * freely licensable by each licensor hereunder covering either (i) the |
| 12 | + * unmodified Software as contributed to or provided by such licensor, or (ii) |
| 13 | + * the Larger Works (as defined below), to deal in both |
| 14 | + * |
| 15 | + * (a) the Software, and |
| 16 | + * |
| 17 | + * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if |
| 18 | + * one is included with the Software each a "Larger Work" to which the Software |
| 19 | + * is contributed by such licensors), |
| 20 | + * |
| 21 | + * without restriction, including without limitation the rights to copy, create |
| 22 | + * derivative works of, display, perform, and distribute the Software and make, |
| 23 | + * use, sell, offer for sale, import, export, have made, and have sold the |
| 24 | + * Software and the Larger Work(s), and to sublicense the foregoing rights on |
| 25 | + * either these or other terms. |
| 26 | + * |
| 27 | + * This license is subject to the following condition: |
| 28 | + * |
| 29 | + * The above copyright notice and either this complete permission notice or at a |
| 30 | + * minimum a reference to the UPL must be included in all copies or substantial |
| 31 | + * portions of the Software. |
| 32 | + * |
| 33 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 34 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 35 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 36 | + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 37 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 38 | + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| 39 | + * SOFTWARE. |
| 40 | + */ |
| 41 | +#include "hpy.h" |
| 42 | +#include <polyglot.h> |
| 43 | +#include <truffle.h> |
| 44 | + |
| 45 | +#include <wchar.h> |
| 46 | + |
| 47 | +#define SRC_CS "utf-8" |
| 48 | + |
| 49 | +POLYGLOT_DECLARE_TYPE(HPy); |
| 50 | +POLYGLOT_DECLARE_STRUCT(_HPyContext_s); |
| 51 | +POLYGLOT_DECLARE_TYPE(HPyMethodDef); |
| 52 | +POLYGLOT_DECLARE_TYPE(HPyModuleDef); |
| 53 | +POLYGLOT_DECLARE_TYPE(wchar_t); |
| 54 | + |
| 55 | +int graal_hpy_init(void *initObject) { |
| 56 | + // register the native type of HPy |
| 57 | + polyglot_invoke(initObject, "setHPyContextNativeType", polyglot__HPyContext_s_typeid()); |
| 58 | + polyglot_invoke(initObject, "setHPyNativeType", polyglot_HPy_typeid()); |
| 59 | + polyglot_invoke(initObject, "setHPyArrayNativeType", polyglot_array_typeid(polyglot_HPy_typeid(), 0)); |
| 60 | + |
| 61 | + // register null handle |
| 62 | + polyglot_invoke(initObject, "setHPyNullHandle", HPy_NULL); |
| 63 | + |
| 64 | + // register size of wchar_t |
| 65 | + polyglot_invoke(initObject, "setWcharSize", sizeof(wchar_t)); |
| 66 | + |
| 67 | + return 0; |
| 68 | +} |
| 69 | + |
| 70 | + |
| 71 | +void* graal_hpy_from_HPy_array(void *arr, uint64_t len) { |
| 72 | + return polyglot_from_HPy_array(arr, len); |
| 73 | +} |
| 74 | + |
| 75 | +void* graal_hpy_from_i8_array(void *arr, uint64_t len) { |
| 76 | + return polyglot_from_i8_array(arr, len); |
| 77 | +} |
| 78 | + |
| 79 | +wchar_t* graal_hpy_from_wchar_array(wchar_t *arr, uint64_t len) { |
| 80 | + if (len == -1) { |
| 81 | + len = (uint64_t) wcslen(arr); |
| 82 | + } |
| 83 | + return polyglot_from_wchar_t_array(arr, len); |
| 84 | +} |
| 85 | + |
| 86 | +void* graal_hpy_from_HPyMethodDef(void *ptr) { |
| 87 | + return polyglot_from_HPyMethodDef(ptr); |
| 88 | +} |
| 89 | + |
| 90 | +void* graal_hpy_from_HPyModuleDef(void *ptr) { |
| 91 | + return polyglot_from_HPyModuleDef(ptr); |
| 92 | +} |
| 93 | + |
| 94 | +void* graal_hpy_get_m_name(HPyModuleDef *moduleDef) { |
| 95 | + return polyglot_from_string(moduleDef->m_name, SRC_CS); |
| 96 | +} |
| 97 | + |
| 98 | +void* graal_hpy_get_m_doc(HPyModuleDef *moduleDef) { |
| 99 | + const char *m_doc = moduleDef->m_doc; |
| 100 | + if (m_doc) { |
| 101 | + return polyglot_from_string(m_doc, SRC_CS); |
| 102 | + } |
| 103 | + return polyglot_from_string("", SRC_CS); |
| 104 | +} |
| 105 | + |
| 106 | +void* graal_hpy_get_ml_name(HPyMethodDef *methodDef) { |
| 107 | + return polyglot_from_string(methodDef->ml_name, SRC_CS); |
| 108 | +} |
| 109 | + |
| 110 | +void* graal_hpy_get_ml_doc(HPyMethodDef *methodDef) { |
| 111 | + return polyglot_from_string(methodDef->ml_doc, SRC_CS); |
| 112 | +} |
| 113 | + |
| 114 | +void* graal_hpy_get_m_methods(HPyModuleDef *moduleDef) { |
| 115 | + uint64_t len=0; |
| 116 | + while ((moduleDef->m_methods[len]).ml_name != NULL) { |
| 117 | + len++; |
| 118 | + } |
| 119 | + return polyglot_from_HPyMethodDef_array(moduleDef->m_methods, len); |
| 120 | +} |
| 121 | + |
| 122 | +void* graal_hpy_from_string(const char *ptr) { |
| 123 | + return polyglot_from_string(ptr, SRC_CS); |
| 124 | +} |
| 125 | + |
| 126 | +/* |
| 127 | + * Casts a 'wchar_t*' array to an 'int8_t*' array and also associates the proper length. |
| 128 | + * The length is determined using 'wcslen' if 'len == -1'. |
| 129 | + */ |
| 130 | +int8_t* graal_hpy_i8_from_wchar_array(wchar_t *arr, uint64_t len) { |
| 131 | + if (len == -1) { |
| 132 | + len = (uint64_t) (wcslen(arr) * sizeof(wchar_t)); |
| 133 | + } |
| 134 | + return polyglot_from_i8_array((int8_t *) arr, len); |
| 135 | +} |
| 136 | + |
| 137 | +typedef void* VoidPtr; |
| 138 | +POLYGLOT_DECLARE_TYPE(VoidPtr); |
| 139 | + |
| 140 | +typedef union { |
| 141 | + void *ptr; |
| 142 | + float f; |
| 143 | + double d; |
| 144 | + int64_t i64; |
| 145 | + int32_t i32; |
| 146 | + int16_t i16; |
| 147 | + int8_t i8; |
| 148 | + uint64_t u64; |
| 149 | + uint32_t u32; |
| 150 | + uint16_t u16; |
| 151 | + uint8_t u8; |
| 152 | + /* TODO(fa) this should be a Py_complex; is there any equivalent ? */ |
| 153 | + uint64_t c; |
| 154 | +} OutVar; |
| 155 | + |
| 156 | +POLYGLOT_DECLARE_TYPE(OutVar); |
| 157 | +typedef struct { OutVar *content; } OutVarPtr; |
| 158 | +POLYGLOT_DECLARE_TYPE(OutVarPtr); |
| 159 | +OutVarPtr* graal_hpy_allocate_outvar() { |
| 160 | + return polyglot_from_OutVarPtr(truffle_managed_malloc(sizeof(OutVarPtr))); |
| 161 | +} |
| 162 | + |
| 163 | +/* |
| 164 | + * Transforms a Java handle array to native. |
| 165 | + * TODO(fa): This currently uses a workaround because Sulong does not fully |
| 166 | + * support passing structs via interop. Therefore, we pretend to have 'void *' |
| 167 | + * array and convert to handle using 'HPy_FromVoidP'. |
| 168 | + */ |
| 169 | +HPy* graal_hpy_array_to_native(VoidPtr *source, uint64_t len) { |
| 170 | + uint64_t i; |
| 171 | + HPy *dest = (HPy *)malloc(len*sizeof(HPy)); |
| 172 | + for (i=0; i < len; i++) { |
| 173 | + dest[i] = HPy_FromVoidP(source[i]); |
| 174 | + } |
| 175 | + return dest; |
| 176 | +} |
| 177 | + |
| 178 | +void get_next_vaarg(va_list *p_va, OutVarPtr *p_outvar) { |
| 179 | + p_outvar->content = (OutVar *)va_arg(*p_va, void *); |
| 180 | +} |
| 181 | + |
| 182 | +void* graal_hpy_context_to_native(void* cobj) { |
| 183 | + return truffle_deref_handle_for_managed(cobj); |
| 184 | +} |
| 185 | + |
| 186 | +#define PRIMITIVE_ARRAY_TO_NATIVE(__jtype__, __ctype__, __polyglot_type__, __element_cast__) \ |
| 187 | + void* graal_hpy_##__jtype__##_array_to_native(const void* jarray, int64_t len) { \ |
| 188 | + int64_t i; \ |
| 189 | + int64_t size = len + 1; \ |
| 190 | + __ctype__* carr = (__ctype__*) malloc(size * sizeof(__ctype__)); \ |
| 191 | + carr[len] = (__ctype__)0; \ |
| 192 | + for (i=0; i < len; i++) { \ |
| 193 | + carr[i] = __element_cast__(polyglot_get_array_element(jarray, i)); \ |
| 194 | + } \ |
| 195 | + return polyglot_from_##__polyglot_type__##_array(carr, len); \ |
| 196 | + } \ |
| 197 | + |
| 198 | +PRIMITIVE_ARRAY_TO_NATIVE(byte, int8_t, i8, polyglot_as_i8); |
| 199 | +PRIMITIVE_ARRAY_TO_NATIVE(int, int32_t, i32, polyglot_as_i32); |
| 200 | +PRIMITIVE_ARRAY_TO_NATIVE(long, int64_t, i64, polyglot_as_i64); |
| 201 | +PRIMITIVE_ARRAY_TO_NATIVE(double, double, double, polyglot_as_double); |
| 202 | +PRIMITIVE_ARRAY_TO_NATIVE(pointer, VoidPtr, VoidPtr, (VoidPtr)); |
0 commit comments