1//
2// m3_bind.c
3//
4// Created by Steven Massey on 4/29/19.
5// Copyright © 2019 Steven Massey. All rights reserved.
6//
7
8#include "m3_env.h"
9#include "m3_exception.h"
10#include "m3_info.h"
11
12
13u8 ConvertTypeCharToTypeId (char i_code)
14{
15 switch (i_code) {
16 case 'v': return c_m3Type_none;
17 case 'i': return c_m3Type_i32;
18 case 'I': return c_m3Type_i64;
19 case 'f': return c_m3Type_f32;
20 case 'F': return c_m3Type_f64;
21 case '*': return c_m3Type_i32;
22 }
23 return c_m3Type_unknown;
24}
25
26
27M3Result SignatureToFuncType (IM3FuncType * o_functionType, ccstr_t i_signature)
28{
29 IM3FuncType funcType = NULL;
30
31_try {
32 if (not o_functionType)
33 _throw ("null function type");
34
35 if (not i_signature)
36 _throw ("null function signature");
37
38 cstr_t sig = i_signature;
39
40 size_t maxNumTypes = strlen (i_signature);
41
42 // assume min signature is "()"
43 _throwif (m3Err_malformedFunctionSignature, maxNumTypes < 2);
44 maxNumTypes -= 2;
45
46 _throwif (m3Err_tooManyArgsRets, maxNumTypes > d_m3MaxSaneFunctionArgRetCount);
47
48_ (AllocFuncType (& funcType, (u32) maxNumTypes));
49
50 u8 * typelist = funcType->types;
51
52 bool parsingRets = true;
53 while (* sig)
54 {
55 char typeChar = * sig++;
56
57 if (typeChar == '(')
58 {
59 parsingRets = false;
60 continue;
61 }
62 else if ( typeChar == ' ')
63 continue;
64 else if (typeChar == ')')
65 break;
66
67 u8 type = ConvertTypeCharToTypeId (typeChar);
68
69 _throwif ("unknown argument type char", c_m3Type_unknown == type);
70
71 if (type == c_m3Type_none)
72 continue;
73
74 if (parsingRets)
75 {
76 _throwif ("malformed signature; return count overflow", funcType->numRets >= maxNumTypes);
77 funcType->numRets++;
78 *typelist++ = type;
79 }
80 else
81 {
82 _throwif ("malformed signature; arg count overflow", (u32)(funcType->numRets) + funcType->numArgs >= maxNumTypes);
83 funcType->numArgs++;
84 *typelist++ = type;
85 }
86 }
87
88} _catch:
89
90 if (result)
91 m3_Free (funcType);
92
93 * o_functionType = funcType;
94
95 return result;
96}
97
98
99static
100M3Result ValidateSignature (IM3Function i_function, ccstr_t i_linkingSignature)
101{
102 M3Result result = m3Err_none;
103
104 IM3FuncType ftype = NULL;
105_ (SignatureToFuncType (& ftype, i_linkingSignature));
106
107 if (not AreFuncTypesEqual (ftype, i_function->funcType))
108 {
109 m3log (module, "expected: %s", SPrintFuncTypeSignature (ftype));
110 m3log (module, " found: %s", SPrintFuncTypeSignature (i_function->funcType));
111
112 _throw ("function signature mismatch");
113 }
114
115 _catch:
116
117 m3_Free (ftype);
118
119 return result;
120}
121
122
123M3Result FindAndLinkFunction (IM3Module io_module,
124 ccstr_t i_moduleName,
125 ccstr_t i_functionName,
126 ccstr_t i_signature,
127 voidptr_t i_function,
128 voidptr_t i_userdata)
129{
130_try {
131 _throwif(m3Err_moduleNotLinked, !io_module->runtime);
132
133 const bool wildcardModule = (strcmp (i_moduleName, "*") == 0);
134
135 result = m3Err_functionLookupFailed;
136
137 for (u32 i = 0; i < io_module->numFunctions; ++i)
138 {
139 const IM3Function f = & io_module->functions [i];
140
141 if (f->import.moduleUtf8 and f->import.fieldUtf8)
142 {
143 if (strcmp (f->import.fieldUtf8, i_functionName) == 0 and
144 (wildcardModule or strcmp (f->import.moduleUtf8, i_moduleName) == 0))
145 {
146 if (i_signature) {
147_ (ValidateSignature (f, i_signature));
148 }
149_ (CompileRawFunction (io_module, f, i_function, i_userdata));
150 }
151 }
152 }
153} _catch:
154 return result;
155}
156
157M3Result m3_LinkRawFunctionEx (IM3Module io_module,
158 const char * const i_moduleName,
159 const char * const i_functionName,
160 const char * const i_signature,
161 M3RawCall i_function,
162 const void * i_userdata)
163{
164 return FindAndLinkFunction (io_module, i_moduleName, i_functionName, i_signature, (voidptr_t)i_function, i_userdata);
165}
166
167M3Result m3_LinkRawFunction (IM3Module io_module,
168 const char * const i_moduleName,
169 const char * const i_functionName,
170 const char * const i_signature,
171 M3RawCall i_function)
172{
173 return FindAndLinkFunction (io_module, i_moduleName, i_functionName, i_signature, (voidptr_t)i_function, NULL);
174}
175
176