1 /*
2  * Copyright (c) 1993-2018, NVIDIA CORPORATION.  All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17 
18 /** \file
19  * \brief ILI directive module
20  *
21  * Utility routines are valid after the semantic analyzer and after basic
22  * blocks have been created for a function.
23  */
24 
25 #include "ilidir.h"
26 #include "gbldefs.h"
27 #include "global.h"
28 #include "error.h"
29 #include "symtab.h"
30 #include "direct.h"
31 
32 #if DEBUG
33 #define TR0(s)         \
34   if (DBGBIT(1, 2048)) \
35     fprintf(gbl.dbgfil, s);
36 #define TR1(s, a)      \
37   if (DBGBIT(1, 2048)) \
38     fprintf(gbl.dbgfil, s, a);
39 #define TR2(s, a, b)   \
40   if (DBGBIT(1, 2048)) \
41     fprintf(gbl.dbgfil, s, a, b);
42 #define TR3(s, a, b, c) \
43   if (DBGBIT(1, 2048))  \
44     fprintf(gbl.dbgfil, s, a, b, c);
45 
46 #else
47 #define TR0(s)
48 #define TR1(s, a)
49 #define TR2(s, a, b)
50 #define TR3(s, a, b, c)
51 
52 #endif
53 
54 static int first;      /* beginning loopset index for function; 0 => doesn't
55                         * exist */
56 static bool opened; /* TRUE if open_pragma found a set which applies to a
57                         * loop */
58 
59 static int find_lpprg(int);
60 
61 /** \brief All blocks have been created for a function (called at end of
62  * expand).
63  */
64 void
ili_lpprg_init(void)65 ili_lpprg_init(void)
66 {
67   int i;
68   LPPRG *lpprg;
69 
70   if (direct.lpg.avail <= 1) {
71     first = 0;
72     return;
73   }
74   first = 1;
75   TR1("ili_lpprg_init: %s\n", SYMNAME(GBL_CURRFUNC));
76   for (i = first; i < direct.lpg.avail; i++) {
77     lpprg = direct.lpg.stgb + i;
78     if (lpprg->beg_line < 0)
79       break;
80     TR3("indx %d, begline %d, endline %d\n", i, lpprg->beg_line,
81         lpprg->end_line);
82   }
83 
84 }
85 
86 /** \brief Find and open the set of loop pragmas associated with a line number.
87  *
88  * SHOULD have a matching close_pragma().
89  */
90 void
open_pragma(int line)91 open_pragma(int line)
92 {
93   int i;
94   LPPRG *lpprg;
95   int match;
96 
97   opened = false;
98   match = find_lpprg(line);
99   if (match) {
100     lpprg = direct.lpg.stgb + match;
101     TR2("    begline %d, endline %d\n", lpprg->beg_line, lpprg->end_line);
102     load_dirset(&lpprg->dirset);
103     opened = true;
104 #ifdef FE90
105     direct.indep = lpprg->indep;
106     direct.index_reuse_list = lpprg->index_reuse_list;
107 #endif
108   }
109 
110 }
111 
112 /** \brief Close the current pragmas => load the pragmas which have routine
113  * scope.
114  */
115 void
close_pragma(void)116 close_pragma(void)
117 {
118   if (opened) {
119     load_dirset(&direct.rou_begin);
120     opened = false;
121 #ifdef FE90
122     direct.indep = NULL;
123     direct.index_reuse_list = NULL;
124 #endif
125   }
126 
127 }
128 
129 #ifdef FE90
130 void
open_dynpragma(int std,int lineno)131 open_dynpragma(int std, int lineno)
132 {
133   int i;
134   LPPRG *lpprg;
135 
136   for (i = 1; i < direct.dynlpg.avail; i++) {
137     lpprg = direct.dynlpg.stgb + i;
138     if (lpprg->beg_line != std)
139       continue;
140     load_dirset(&lpprg->dirset);
141     direct.indep = lpprg->indep;
142     direct.index_reuse_list = lpprg->index_reuse_list;
143     opened = TRUE;
144     return;
145   }
146   open_pragma(lineno);
147 }
148 
149 /** \brief Save the current pragma for std. */
150 void
save_dynpragma(int std)151 save_dynpragma(int std)
152 {
153   int i;
154   LPPRG *lpprg;
155 
156   for (i = 1; i < direct.dynlpg.avail; i++) {
157     lpprg = direct.dynlpg.stgb + i;
158     if (lpprg->beg_line != std)
159       continue;
160     store_dirset(&lpprg->dirset);
161     lpprg->indep = direct.indep;
162     lpprg->index_reuse_list = direct.index_reuse_list;
163     opened = TRUE; /* so close_pragma will work */
164     close_pragma();
165     return;
166   }
167   i = direct.dynlpg.avail++;
168   NEED(direct.dynlpg.avail, direct.dynlpg.stgb, LPPRG, direct.dynlpg.size,
169        direct.dynlpg.size + 8);
170   lpprg = direct.dynlpg.stgb + i;
171   lpprg->beg_line = std;
172   store_dirset(&lpprg->dirset);
173   lpprg->indep = direct.indep;
174   lpprg->index_reuse_list = direct.index_reuse_list;
175   opened = TRUE; /* so close_pragma will work */
176   close_pragma();
177 }
178 #endif
179 
180 /** \brief Find the set of loop pragmas associated with a line number (the
181  * set's beginning and ending line numbers enclose the requested line number).
182  *
183  * Since the loop sets occur in lexical order, the last loop set found is the
184  * set with beginning line number is the floor of the requested line number.
185  */
186 static int
find_lpprg(int line)187 find_lpprg(int line)
188 {
189   int i;
190   LPPRG *lpprg;
191   int match;
192 
193   if (first == 0 || line == 0)
194     return 0;
195 
196   match = 0;
197   for (i = first; i < direct.lpg.avail; i++) {
198     lpprg = direct.lpg.stgb + i;
199     if (lpprg->beg_line < 0 || lpprg->beg_line > line)
200       break;
201     if (lpprg->beg_line <= line && line <= lpprg->end_line)
202       match = i;
203   }
204   TR2("find_lpprg:for line %d, match = %d\n", line, match);
205 
206   return match;
207 }
208 
209 #define STK_SZ 128
210 
211 static int stk[STK_SZ]; /* should be dynamic ? */
212 static int top = 0;     /* first entry in stack is reserved -- the
213                          * value is zero => use routine's pragmas */
214 
215 /** \brief Find and open and stack the set of loop pragmas associated with a
216  * line number.
217  *
218  * MUST have a matching pop_pragma().  If a match isn't found, push the
219  * routine's set.
220  */
221 void
push_pragma(int line)222 push_pragma(int line)
223 {
224   LPPRG *lpprg;
225   int match;
226 
227   top++;
228   if (top >= STK_SZ) {
229 #if DEBUG
230     interr("push_pragma:stkovflw", line, ERR_Severe);
231 #endif
232     top = STK_SZ - 1;
233   }
234   match = find_lpprg(line);
235   stk[top] = match;
236   if (match) {
237     lpprg = direct.lpg.stgb + match;
238     TR2("    push: begline %d, endline %d\n", lpprg->beg_line, lpprg->end_line);
239     load_dirset(&lpprg->dirset);
240   } else {
241     TR0("    push: using routine\n");
242     load_dirset(&direct.rou_begin);
243   }
244 
245 }
246 
247 /** \brief Pop the set from the stack and open/restore the set which is on the
248  * top of stack.
249  */
250 void
pop_pragma(void)251 pop_pragma(void)
252 {
253   LPPRG *lpprg;
254   int match;
255 
256 #if DEBUG
257   if (top <= 0) {
258     interr("pop_pragma:stkuflw", gbl.lineno, ERR_Severe);
259     load_dirset(&direct.rou_begin);
260     return;
261   }
262 #endif
263   top--;
264   match = stk[top];
265   if (match) {
266     lpprg = direct.lpg.stgb + match;
267     TR1("    pop: using %d\n", match);
268     load_dirset(&lpprg->dirset);
269   } else {
270     TR0("    pop: using routine\n");
271     load_dirset(&direct.rou_begin);
272   }
273 
274 }
275