@@ -42,6 +42,18 @@ function ir.VarDecl(name, typ)
4242 }
4343end
4444
45+ function ir .ForLoop ()
46+ return {
47+ step_is_positive = false , -- boolean
48+ prep_block_id = false , -- block_id
49+ body_first_block_id = false , -- block_id
50+ body_last_block_id = false , -- block_id
51+ iteration_variable_id = false , -- v_id
52+ limit_value = false , -- ir.Value
53+ loc = false , -- Location
54+ }
55+ end
56+
4557function ir .Function (loc , name , typ )
4658 return {
4759 loc = loc , -- Location
@@ -53,6 +65,7 @@ function ir.Function(loc, name, typ)
5365 f_id_of_local = {}, -- { v_id => integer }
5466 blocks = {}, -- { ir.BasicBlock }
5567 ret_vars = {}, -- { v_id }, list of return variables
68+ for_loops = {}, -- { ir.ForLoop }
5669 }
5770end
5871
@@ -125,6 +138,15 @@ define_union("Value", {
125138 Upvalue = {" id" },
126139})
127140
141+ function ir .is_constant (value )
142+ local tag = value ._tag
143+ return tag == " ir.Value.Nil" or
144+ tag == " ir.Value.Bool" or
145+ tag == " ir.Value.Integer" or
146+ tag == " ir.Value.Float" or
147+ tag == " ir.Value.String"
148+ end
149+
128150-- define_union("Cmd"
129151local ir_cmd_constructors = {
130152 -- [IMPORTANT] Please use this naming convention:
@@ -148,6 +170,7 @@ local ir_cmd_constructors = {
148170
149171 -- Arrays
150172 NewArr = {" loc" , " dst" , " src_size" },
173+ RenormArr = {" loc" , " src_arr" , " src_i" }, -- renormalize array
151174
152175 GetArr = {" loc" , " dst_typ" , " dst" , " src_arr" , " src_i" },
153176 SetArr = {" loc" , " src_typ" , " src_arr" , " src_i" , " src_v" },
@@ -209,6 +232,8 @@ local ir_cmd_constructors = {
209232 Jmp = {" target" },
210233 JmpIf = {" loc" , " src_cond" , " target_true" , " target_false" },
211234
235+ Nop = {}, -- does nothing
236+
212237 -- Garbage Collection (appears after memory allocations)
213238 CheckGC = {},
214239}
@@ -277,13 +302,13 @@ function ir.BasicBlock()
277302 }
278303end
279304
280- local function is_jump (cmd )
305+ function ir . is_jump (cmd )
281306 return cmd ._tag == " ir.Cmd.Jmp" or cmd ._tag == " ir.Cmd.JmpIf"
282307end
283308
284309function ir .get_jump (block )
285310 local cmd = block .cmds [# block .cmds ]
286- if not cmd or not is_jump (cmd ) then
311+ if not cmd or not ir . is_jump (cmd ) then
287312 return false
288313 end
289314 return cmd
@@ -394,29 +419,41 @@ function ir.get_predecessor_depth_search_topological_sort(predecessor_list)
394419 return reverse_order
395420end
396421
397- -- Iterate over the cmds of basic blocks using a naive ordering.
398- function ir .iter (block_list )
399- local function go ()
400- for _ ,block in ipairs (block_list ) do
401- for _ , cmd in ipairs (block .cmds ) do
402- coroutine.yield (cmd )
422+ -- Inserts a block into a given index on a function's block list and updates block index references
423+ -- accordingly.
424+ function ir .insert_block (func , new_block , index )
425+ assert (index > 0 )
426+ for _ , block in ipairs (func .blocks ) do
427+ for _ , cmd in ipairs (block .cmds ) do
428+ if cmd ._tag == " ir.Cmd.Jmp" then
429+ cmd .target = cmd .target + (cmd .target >= index and 1 or 0 )
430+ elseif cmd ._tag == " ir.Cmd.JmpIf" then
431+ cmd .target_true = cmd .target_true + (cmd .target_true >= index and 1 or 0 )
432+ cmd .target_false = cmd .target_false + (cmd .target_false >= index and 1 or 0 )
403433 end
404434 end
405435 end
406- return coroutine.wrap (function () go () end )
407- end
408436
409- function ir .flatten_cmd (block_list )
410- local res = {}
411- for _ ,block in ipairs (block_list ) do
412- for _ ,cmd in ipairs (block .cmds ) do
413- table.insert (res , cmd )
437+ for _ , loop in ipairs (func .for_loops ) do
438+ loop .prep_block_id = loop .prep_block_id + (loop .prep_block_id >= index and 1 or 0 )
439+ loop .body_first_block_id = loop .body_first_block_id + (loop .body_first_block_id >= index and 1 or 0 )
440+ loop .body_last_block_id = loop .body_last_block_id + (loop .body_last_block_id >= index and 1 or 0 )
441+ end
442+
443+ local offset = index - 1
444+ for _ , cmd in ipairs (new_block .cmds ) do
445+ if cmd ._tag == " ir.Cmd.Jmp" then
446+ cmd .target = cmd .target + offset
447+ elseif cmd ._tag == " ir.Cmd.JmpIf" then
448+ cmd .target_true = cmd .target_true + offset
449+ cmd .target_false = cmd .target_false + offset
414450 end
415451 end
416- return res
452+
453+ table.insert (func .blocks , index , new_block )
417454end
418455
419- -- Remove jumps that are never taken
456+ -- Remove jumps that are never taken.
420457function ir .clean (func )
421458 for _ , block in ipairs (func .blocks ) do
422459 local jump = ir .get_jump (block )
0 commit comments