@@ -48,6 +48,9 @@ KaosIR* compile(ASTRoot* ast_root)
48
48
// Declare functions in all parsed files
49
49
declare_functions (ast_root , program );
50
50
51
+ // Determine whether the functions should be inlined or not
52
+ determine_inline_functions (ast_root );
53
+
51
54
// Compile functions in all parsed files
52
55
compile_functions (ast_root , program );
53
56
@@ -652,6 +655,12 @@ unsigned short compileExpr(KaosIR* program, Expr* expr)
652
655
enum ValueType value_type = compileExpr (program , expr ) - 1 ;
653
656
Symbol * parameter = function -> parameters [i - 1 ];
654
657
658
+ if (function -> should_inline ) {
659
+ Symbol * symbol_upper = getSymbol (expr_list -> exprs [i - 1 ]-> v .ident -> name );
660
+ Symbol * symbol_new = createCloneFromSymbol (parameter -> name , symbol_upper -> type , symbol_upper , symbol_upper -> type );
661
+ symbol_new -> addr = symbol_upper -> addr ;
662
+ }
663
+
655
664
strongly_type (parameter , NULL , function , expr , value_type );
656
665
657
666
enum Type type = parameter -> type ;
@@ -857,16 +866,23 @@ unsigned short compileExpr(KaosIR* program, Expr* expr)
857
866
} else {
858
867
}
859
868
860
- push_inst_ (program , PREPARE );
861
- for (size_t i = 0 ; i < putargr_stack_p ; i ++ )
862
- push_inst_r (program , PUTARGR , putargr_stack [i ]);
869
+ if (function -> should_inline ) {
870
+ Decl * decl = function -> ast ;
871
+ compileStmt (program , decl -> v .func_decl -> body );
872
+ if (decl -> v .func_decl -> decision != NULL )
873
+ compileSpec (program , decl -> v .func_decl -> decision );
874
+ } else {
875
+ push_inst_ (program , PREPARE );
876
+ for (size_t i = 0 ; i < putargr_stack_p ; i ++ )
877
+ push_inst_r (program , PUTARGR , putargr_stack [i ]);
863
878
864
- push_inst_i_i (program , CALL , function -> addr , op_counter ++ );
879
+ push_inst_i_i (program , CALL , function -> addr , op_counter ++ );
865
880
866
- function -> call_patches [function -> call_patches_size ++ ] = op_counter - 1 ;
881
+ function -> call_patches [function -> call_patches_size ++ ] = op_counter - 1 ;
867
882
868
- push_inst_r (program , RETVAL , R1 );
869
- push_inst_r_i (program , MOVI , R0 , 1 ); // TODO: temp, set it according to function return type
883
+ push_inst_r (program , RETVAL , R1 );
884
+ push_inst_r_i (program , MOVI , R0 , 1 ); // TODO: temp, set it according to function return type
885
+ }
870
886
871
887
return function -> value_type + 1 ;
872
888
break ;
@@ -1042,6 +1058,14 @@ void compileDecl(KaosIR* program, Decl* decl)
1042
1058
}
1043
1059
case FuncDecl_kind : {
1044
1060
_Function * function = startFunctionNew (decl -> v .func_decl -> name -> v .ident -> name );
1061
+ if (function -> should_inline ) {
1062
+ function -> ast = decl ;
1063
+ function_mode -> is_compiled = true;
1064
+ endFunction ();
1065
+ break ;
1066
+ }
1067
+
1068
+ function -> ast = decl ;
1045
1069
1046
1070
if (function -> is_compiled )
1047
1071
break ;
@@ -2145,6 +2169,111 @@ void compile_functions(ASTRoot* ast_root, KaosIR* program)
2145
2169
}
2146
2170
}
2147
2171
2172
+ void determine_inline_functions (ASTRoot * ast_root )
2173
+ {
2174
+ for (unsigned long i = 0 ; i < ast_root -> file_count ; i ++ ) {
2175
+ File * file = ast_root -> files [i ];
2176
+ current_file_index = i ;
2177
+ StmtList * stmt_list = file -> stmt_list ;
2178
+ pushModuleStack (file -> module_path , file -> module );
2179
+
2180
+ // Foreach function look for other functions' decision blocks for calls
2181
+ for (unsigned long j = stmt_list -> stmt_count ; 0 < j ; j -- ) {
2182
+ Stmt * stmt = stmt_list -> stmts [j - 1 ];
2183
+ if (stmt -> kind == DeclStmt_kind && stmt -> v .decl_stmt -> decl -> kind == FuncDecl_kind ) {
2184
+ Decl * decl = stmt -> v .decl_stmt -> decl ;
2185
+ _Function * function = startFunctionNew (decl -> v .func_decl -> name -> v .ident -> name );
2186
+ function -> should_inline = determine_inline_function (ast_root , function );
2187
+ endFunction ();
2188
+ }
2189
+ }
2190
+
2191
+ popModuleStack ();
2192
+ }
2193
+ }
2194
+
2195
+ bool determine_inline_function (ASTRoot * ast_root , _Function * function )
2196
+ {
2197
+ unsigned long call_counter = 0 ;
2198
+ // Look for all functions' decision blocks for all the files compiled
2199
+ for (unsigned long i = 0 ; i < ast_root -> file_count ; i ++ ) {
2200
+ File * file = ast_root -> files [i ];
2201
+ current_file_index = i ;
2202
+ StmtList * stmt_list = file -> stmt_list ;
2203
+ pushModuleStack (file -> module_path , file -> module );
2204
+
2205
+ for (unsigned long j = stmt_list -> stmt_count ; 0 < j ; j -- ) {
2206
+ Stmt * stmt = stmt_list -> stmts [j - 1 ];
2207
+ if (stmt -> kind == DeclStmt_kind && stmt -> v .decl_stmt -> decl -> kind == FuncDecl_kind ) {
2208
+ Decl * decl = stmt -> v .decl_stmt -> decl ;
2209
+ _Function * _function = startFunctionNew (decl -> v .func_decl -> name -> v .ident -> name );
2210
+ if (function == _function )
2211
+ continue ;
2212
+ if (decl -> v .func_decl -> decision != NULL ) {
2213
+ ExprList * expr_list = decl -> v .func_decl -> decision -> v .decision_block -> decisions ;
2214
+ for (unsigned long i = expr_list -> expr_count ; 0 < i ; i -- ) {
2215
+ Expr * expr = expr_list -> exprs [i - 1 ];
2216
+ if (does_decision_have_a_call (expr , function )) {
2217
+ call_counter ++ ;
2218
+ }
2219
+ }
2220
+ }
2221
+ endFunction ();
2222
+ }
2223
+ }
2224
+
2225
+ popModuleStack ();
2226
+ }
2227
+
2228
+ if (call_counter == 1 )
2229
+ return true;
2230
+ else
2231
+ return false;
2232
+ }
2233
+
2234
+ bool does_decision_have_a_call (Expr * expr , _Function * function )
2235
+ {
2236
+ Stmt * stmt = NULL ;
2237
+ switch (expr -> kind ) {
2238
+ case DecisionExpr_kind :
2239
+ stmt = expr -> v .decision_expr -> outcome ;
2240
+ break ;
2241
+ case DefaultExpr_kind :
2242
+ stmt = expr -> v .default_expr -> outcome ;
2243
+ break ;
2244
+ default :
2245
+ break ;
2246
+ }
2247
+
2248
+ return does_stmt_have_a_call (stmt , function );
2249
+ }
2250
+
2251
+ bool does_stmt_have_a_call (Stmt * stmt , _Function * function )
2252
+ {
2253
+ if (stmt -> kind == ExprStmt_kind && stmt -> v .expr_stmt -> x -> kind == CallExpr_kind ) {
2254
+ Expr * expr = stmt -> v .expr_stmt -> x ;
2255
+ _Function * _function = NULL ;
2256
+ switch (expr -> v .call_expr -> fun -> kind ) {
2257
+ case Ident_kind :
2258
+ _function = getFunction (expr -> v .call_expr -> fun -> v .ident -> name , NULL );
2259
+ break ;
2260
+ case SelectorExpr_kind :
2261
+ _function = getFunction (
2262
+ expr -> v .call_expr -> fun -> v .selector_expr -> sel -> v .ident -> name ,
2263
+ expr -> v .call_expr -> fun -> v .selector_expr -> x -> v .ident -> name
2264
+ );
2265
+ break ;
2266
+ default :
2267
+ break ;
2268
+ }
2269
+
2270
+ if (function == _function )
2271
+ return true;
2272
+ }
2273
+
2274
+ return false;
2275
+ }
2276
+
2148
2277
void strongly_type (Symbol * symbol_x , Symbol * symbol_y , _Function * function , Expr * expr , enum ValueType value_type )
2149
2278
{
2150
2279
if (expr != NULL ) {
0 commit comments