88#include "m3_exec.h"
99#include "m3_env.h"
1010#include "m3_exception.h"
11+ #include "m3_info.h"
12+
1113
12- static
1314u8 ConvertTypeCharToTypeId (char i_code )
1415{
1516 switch (i_code ) {
@@ -23,28 +24,40 @@ u8 ConvertTypeCharToTypeId (char i_code)
2324 return c_m3Type_none ;
2425}
2526
26- static
27- M3Result ValidateSignature (IM3Function i_function , ccstr_t i_linkingSignature )
27+
28+ M3Result SignatureToFuncType (IM3FuncType * o_functionType , ccstr_t i_signature )
2829{
2930 M3Result result = m3Err_none ;
3031
31- cstr_t sig = i_linkingSignature ;
32+ IM3FuncType funcType = NULL ;
33+ _try {
34+ if (not o_functionType )
35+ _throw ("null function type" );
36+
37+ if (not i_signature )
38+ _throw ("null function signature" );
39+
40+ cstr_t sig = i_signature ;
3241
3342 bool hasReturn = false;
34- u32 numArgs = 0 ;
43+
44+ size_t maxNumArgs = strlen (i_signature );
45+ _throwif (m3Err_malformedFunctionSignature , maxNumArgs < 3 );
46+
47+ maxNumArgs -= 3 ; // "v()"
48+ _throwif ("insane argument count" , maxNumArgs > d_m3MaxSaneFunctionArgCount );
49+
50+ _ (AllocFuncType (& funcType , (u32 ) maxNumArgs ));
3551
3652 bool parsingArgs = false;
3753 while (* sig )
3854 {
39- if (numArgs >= d_m3MaxNumFunctionArgs )
40- _throw ("arg count overflow" );
41-
4255 char typeChar = * sig ++ ;
4356
4457 if (typeChar == '(' )
4558 {
4659 if (not hasReturn )
47- _throw ( "malformed function signature; missing return type" ) ;
60+ break ;
4861
4962 parsingArgs = true;
5063 continue ;
@@ -56,30 +69,76 @@ M3Result ValidateSignature (IM3Function i_function, ccstr_t i_linkingSignature
5669
5770 u8 type = ConvertTypeCharToTypeId (typeChar );
5871
59- if (type )
72+ if (not type )
73+ _throw ("unknown argument type char" );
74+
75+ if (not parsingArgs )
6076 {
61- if (not parsingArgs )
62- {
63- if (hasReturn )
64- _throw ("malformed function signature; too many return types" );
77+ if (hasReturn )
78+ _throw ("malformed function signature; too many return types" );
6579
66- hasReturn = true;
67- }
68- else
80+ hasReturn = true;
81+
82+ // M3FuncType doesn't speak 'void'
83+ if (type == c_m3Type_void )
84+ type = c_m3Type_none ;
85+ if (type == c_m3Type_ptr )
86+ type = c_m3Type_i32 ;
87+
88+ funcType -> returnType = type ;
89+ }
90+ else
91+ {
92+ _throwif (m3Err_malformedFunctionSignature , funcType -> numArgs >= maxNumArgs ); // forgot trailing ')' ?
93+
94+ if (type != c_m3Type_runtime )
6995 {
70- if (type != c_m3Type_runtime )
71- ++ numArgs ;
96+ if (type == c_m3Type_ptr )
97+ type = c_m3Type_i32 ;
98+
99+ funcType -> argTypes [funcType -> numArgs ++ ] = type ;
72100 }
73101 }
74- else _throw ("unknown argument type char" );
75102 }
76103
77- if (GetFunctionNumArgs (i_function ) != numArgs )
78- _throw ("function arg count mismatch" );
104+ if (not hasReturn )
105+ _throw (m3Err_funcSignatureMissingReturnType );
106+
107+ } _catch :
108+
109+ if (result )
110+ m3Free (funcType ); // nulls funcType
111+
112+ * o_functionType = funcType ;
113+
114+ return result ;
115+ }
116+
117+
118+ static
119+ M3Result ValidateSignature (IM3Function i_function , ccstr_t i_linkingSignature )
120+ {
121+ M3Result result = m3Err_none ;
122+
123+ IM3FuncType ftype = NULL ;
124+ _ (SignatureToFuncType (& ftype , i_linkingSignature ));
125+
126+ if (not AreFuncTypesEqual (ftype , i_function -> funcType ))
127+ {
128+ m3log (module , "expected: %s" , SPrintFuncTypeSignature (ftype ));
129+ m3log (module , " found: %s" , SPrintFuncTypeSignature (i_function -> funcType ));
130+
131+ _throw ("function signature mismatch" );
132+ }
133+
134+ _catch :
135+
136+ m3Free (ftype );
79137
80- _catch : return result ;
138+ return result ;
81139}
82140
141+
83142typedef M3Result (* M3Linker ) (IM3Module io_module , IM3Function io_function , const char * const i_signature , const void * i_function );
84143
85144M3Result FindAndLinkFunction (IM3Module io_module ,
@@ -92,7 +151,7 @@ M3Result FindAndLinkFunction (IM3Module io_module,
92151 M3Result result = m3Err_functionLookupFailed ;
93152
94153 bool wildcardModule = (strcmp (i_moduleName , "*" ) == 0 );
95-
154+
96155 for (u32 i = 0 ; i < io_module -> numFunctions ; ++ i )
97156 {
98157 IM3Function f = & io_module -> functions [i ];
@@ -147,3 +206,70 @@ M3Result m3_LinkRawFunction (IM3Module io_module,
147206{
148207 return FindAndLinkFunction (io_module , i_moduleName , i_functionName , i_signature , (voidptr_t )i_function , LinkRawFunction );
149208}
209+
210+ // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------
211+
212+ IM3Function FindFunction (IM3Module io_module ,
213+ ccstr_t i_moduleName ,
214+ ccstr_t i_functionName ,
215+ ccstr_t i_signature )
216+ {
217+ bool wildcardModule = (strcmp (i_moduleName , "*" ) == 0 );
218+
219+ for (u32 i = 0 ; i < io_module -> numFunctions ; ++ i )
220+ {
221+ IM3Function f = & io_module -> functions [i ];
222+
223+ if (f -> import .moduleUtf8 and f -> import .fieldUtf8 )
224+ {
225+ if (strcmp (f -> import .fieldUtf8 , i_functionName ) == 0 and
226+ (wildcardModule or strcmp (f -> import .moduleUtf8 , i_moduleName ) == 0 ))
227+ {
228+ return f ;
229+ }
230+ }
231+ }
232+
233+ return NULL ;
234+ }
235+
236+ M3Result LinkRawFunctionEx (IM3Module io_module , IM3Function io_function , ccstr_t signature , const void * i_function , void * cookie )
237+ {
238+ M3Result result = m3Err_none ; d_m3Assert (io_module -> runtime );
239+
240+ _try {
241+ _ (ValidateSignature (io_function , signature ));
242+
243+ IM3CodePage page = AcquireCodePageWithCapacity (io_module -> runtime , 3 );
244+
245+ if (page )
246+ {
247+ io_function -> compiled = GetPagePC (page );
248+ io_function -> module = io_module ;
249+
250+ EmitWord (page , op_CallRawFunctionEx );
251+ EmitWord (page , i_function );
252+ EmitWord (page , cookie );
253+
254+ ReleaseCodePage (io_module -> runtime , page );
255+ }
256+ else _throw (m3Err_mallocFailedCodePage );
257+
258+ } _catch :
259+ return result ;
260+ }
261+
262+ M3Result m3_LinkRawFunctionEx (IM3Module io_module ,
263+ const char * const i_moduleName ,
264+ const char * const i_functionName ,
265+ const char * const i_signature ,
266+ M3RawCallEx i_function ,
267+ void * i_cookie )
268+ {
269+ IM3Function f = FindFunction (io_module , i_moduleName , i_functionName , i_signature );
270+ if (f == NULL )
271+ return m3Err_functionLookupFailed ;
272+
273+ M3Result result = LinkRawFunctionEx (io_module , f , i_signature , (voidptr_t )i_function , i_cookie );
274+ return result ;
275+ }
0 commit comments