Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 0.0% 0 / 0 / 20
Functions: -% 0 / 1 / 1
Branches: 0.0% 0 / 0 / 14

OMCompiler/Compiler/MidCode/MidToMid.mo
Line Branch Exec Source
1 /*
2 * This file is part of OpenModelica.
3 *
4 * Copyright (c) 1998-2026, Open Source Modelica Consortium (OSMC),
5 * c/o Linköpings universitet, Department of Computer and Information Science,
6 * SE-58183 Linköping, Sweden.
7 *
8 * All rights reserved.
9 *
10 * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF AGPL VERSION 3 LICENSE OR
11 * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.8.
12 * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES
13 * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GNU AGPL
14 * VERSION 3, ACCORDING TO RECIPIENTS CHOICE.
15 *
16 * The OpenModelica software and the OSMC (Open Source Modelica Consortium)
17 * Public License (OSMC-PL) are obtained from OSMC, either from the above
18 * address, from the URLs:
19 * http://www.openmodelica.org or
20 * https://github.com/OpenModelica/ or
21 * http://www.ida.liu.se/projects/OpenModelica,
22 * and in the OpenModelica distribution.
23 *
24 * GNU AGPL version 3 is obtained from:
25 * https://www.gnu.org/licenses/licenses.html#GPL
26 *
27 * This program is distributed WITHOUT ANY WARRANTY; without
28 * even the implied warranty of MERCHANTABILITY or FITNESS
29 * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH
30 * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL.
31 *
32 * See the full OSMC Public License conditions for more details.
33 *
34 */
35
36 encapsulated package MidToMid
37
38 public
39 import MidCode;
40
41 /*
42 Longjmps are not allowed to land in the same function.
43 This is handled in midtomid.
44 Handling it here allows other tranformations to
45 deal with goto instead of longjmp, which might enable
46 further transformation.
47
48 pushpopjmp possible.
49 can remove push-pop -jmp pairs if there is no possible longjmp in between.
50
51 Typechecking possible.
52 Useful for correctness of midcode transformations.
53
54 Normalisation possble. (AKA canonicalisation)
55 Probably essential to simplify other transformations.
56 Remove greater than comparisons and similar.
57
58 Inlining possible.
59 Important catalyst for other optimisations.
60
61 Common subexpression elimination possible.
62 But requires some data flow and side effect analysis.
63 Some SSA variables and purity marked functions perhaps.
64
65 */
66
67
68 function longJmpGoto
69 "
70 Replace a longjmp within a function call with goto.
71 longjmp within function calls isn't allowed so
72 this is necessary to form correct c form midcode.
73 "
74 input MidCode.Function oldFunction;
75 output MidCode.Function newFunction;
76 protected
77 list<MidCode.Block> newBody, oldBody;
78 MidCode.Block newBlock, oldBlock;
79 Integer node,jump;
80 list<Integer> jumps;
81 list<Integer> nodes_tmp, checkedNodes;
82 list<tuple<list<Integer>,Integer>> tasks, tasks_tmp; // [ ([Int], Int) ]
83 algorithm
84 /*
85 do depth first search
86 keep a stack of jmp_targets
87 when encoutering a PUSHJMP: push the target label onto jmp_targets
88 when encountering a LONGJMP and jmp_targets in't empty: replace with goto the top of jmp_targets
89 when encountering a POPJMP: pop jmp_targets
90 */
91 /*
92 How to depth first
93 maybe not use program stack ~1000 blocks might cause stack overflow
94 so jmp_targets is a list
95 while loop with empty check on nodes
96 start wih entryId-block
97 keep list of used ids, alreadyChecked
98 need to look up blockId in Function structure
99 find the successors of current node, add all that are not in alreadyChecked
100 build a new list of blocks with terminators maybe replaced
101 replace the body part of function
102 */
103 /*
104 Leave the buffer variables in the function still declared.
105 */
106 ✗ oldBody := oldFunction.body;
107 newBody := {};
108 ✗ checkedNodes := {oldFunction.entryId};
109 ✗ tasks := {({},oldFunction.entryId)};
110
111 ✗ while not listEmpty(tasks) loop
112 ✗ (jumps,node) :: tasks := tasks; // pop
113 ✗ oldBlock := lookupId(oldBody,node); // O(length(oldBody))
114 newBlock := oldBlock; // don't change the block by defualt
115 ✗ if isPushJmp(oldBlock.terminator) then
116 ✗ jumps := (listHead(getSuccessors(oldBlock)) :: jumps); // push
117 elseif isLongJmp(oldBlock.terminator) and not listEmpty(jumps) then
118 ✗ jump :: _ := jumps; // peek
119 ✗ newBlock := MidCode.BLOCK(id=oldBlock.id,stmts=oldBlock.stmts, terminator=MidCode.GOTO(jump));
120 elseif isPopJmp(oldBlock.terminator) then
121 ✗ _ :: jumps := jumps; // pop
122 end if;
123 newBody := newBlock :: newBody;
124
125 ✗ nodes_tmp := List.setDifference(getSuccessors(oldBlock), checkedNodes);
126 ✗ checkedNodes := listAppend(nodes_tmp, checkedNodes);
127 ✗ tasks_tmp := list( (jumps,node_tmp) for node_tmp in nodes_tmp );
128 ✗ tasks := listAppend(tasks_tmp, tasks);
129 end while;
130 ✗ newBody := listReverse(newBody);
131
132 ✗ newFunction := MidCode.FUNCTION(
133 name=oldFunction.name
134 ,locals=oldFunction.locals
135 ,localBufs=oldFunction.localBufs
136 ,localBufPtrs=oldFunction.localBufPtrs
137 ,inputs=oldFunction.inputs
138 ,outputs=oldFunction.outputs
139 ,body=newBody
140 ,entryId=oldFunction.entryId
141 ,exitId=oldFunction.exitId
142 );
143 end longJmpGoto;
144
145 function lookupId
146 input list<MidCode.Block> blocks;
147 input Integer id;
148 output MidCode.Block block_;
149 protected
150 list<MidCode.Block> blocks_local;
151 MidCode.Block block_local;
152 algorithm
153 block_ := match blocks
154 case block_local :: _ guard (block_local.id == id) then block_local;
155 ✗ case _ :: blocks_local then lookupId(blocks_local, id);
156 //else listHead(blocks);
157 end match;
158 end lookupId;
159
160 protected
161 import List;
162
163 function getSuccessors
164 input MidCode.Block block_;
165 output list<Integer> neighbours;
166 protected
167 Integer l0,l1;
168 list<tuple<Integer,Integer>> switchList;
169 algorithm
170 neighbours := match block_.terminator
171 case MidCode.GOTO(l0) then {l0};
172 case MidCode.BRANCH(_,l0,l1) then {l0,l1};
173 case MidCode.CALL(_,_,_,_,l0) then {l0};
174 case MidCode.RETURN() then {};
175 ✗ case MidCode.SWITCH(_,switchList) then list(tupleSnd(x) for x in switchList);
176 case MidCode.LONGJMP() then {};
177 case MidCode.PUSHJMP(_,_,l0) then {l0};
178 case MidCode.POPJMP(_,l0) then {l0};
179 end match;
180 end getSuccessors;
181
182 function tupleSnd
183 input tuple<Integer, Integer> t;
184 output Integer i;
185 algorithm
186 ✗ (_,i) := t;
187 end tupleSnd;
188
189 function isLongJmp
190 input MidCode.Terminator t;
191 output Boolean b;
192 algorithm
193 b := match t
194 case MidCode.LONGJMP() then true;
195 else false;
196 end match;
197 end isLongJmp;
198
199 function isPushJmp
200 input MidCode.Terminator t;
201 output Boolean b;
202 algorithm
203 b := match t
204 case MidCode.PUSHJMP(_,_,_) then true;
205 else false;
206 end match;
207 end isPushJmp;
208
209 function isPopJmp
210 input MidCode.Terminator t;
211 output Boolean b;
212 algorithm
213 b := match t
214 case MidCode.POPJMP(_,_) then true;
215 else false;
216 end match;
217 end isPopJmp;
218
219 annotation(__OpenModelica_Interface="backend_tools");
220
221 end MidToMid;
222