1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
|
(* SymbolConversion.mod mapping between m2 symbols and gcc symbols.
Copyright (C) 2001-2025 Free Software Foundation, Inc.
Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>.
This file is part of GNU Modula-2.
GNU Modula-2 is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GNU Modula-2 is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Modula-2; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. *)
IMPLEMENTATION MODULE SymbolConversion ;
FROM NameKey IMPORT Name ;
FROM Indexing IMPORT Index, InitIndex, PutIndice, GetIndice, InBounds,
DebugIndex, InitIndexTuned, HighIndice ;
FROM SymbolTable IMPORT IsConst, PopValue, IsValueSolved, GetSymName,
GetType, SkipType, NulSym ;
FROM M2Error IMPORT InternalError ;
FROM M2ALU IMPORT PushTypeOfTree ;
FROM m2block IMPORT GetErrorNode, RememberConstant ;
FROM gcctypes IMPORT tree ;
FROM M2Printf IMPORT printf1 ;
FROM Storage IMPORT ALLOCATE ;
FROM SYSTEM IMPORT ADDRESS ;
CONST
USEPOISON = TRUE ;
GGCPOISON = 0A5A5A5A5H ; (* poisoned memory contains this code *)
TYPE
PtrToCardinal = POINTER TO CARDINAL ;
VAR
mod2gcc : Index ;
PoisonedSymbol: ADDRESS ;
(*
Mod2Gcc - given a modula-2 symbol, sym, return the gcc equivalent.
*)
PROCEDURE Mod2Gcc (sym: CARDINAL) : tree ;
VAR
n : Name ;
t : PtrToCardinal ;
tr: tree ;
BEGIN
IF USEPOISON
THEN
IF InBounds(mod2gcc, sym)
THEN
t := PtrToCardinal(GetIndice(mod2gcc, sym)) ;
IF (t#NIL) AND (t^=GGCPOISON)
THEN
InternalError ('gcc symbol has been poisoned')
END
END
END ;
IF InBounds(mod2gcc, sym)
THEN
tr := tree(GetIndice(mod2gcc, sym)) ;
IF tr=PoisonedSymbol
THEN
n := GetSymName(sym) ;
(* not poisoned by the garbage collector, but by the gm2 front end *)
printf1('the gm2 front end poisoned this symbol (%a)\n', n) ;
InternalError ('attempting to use a gcc symbol which is no longer in scope')
END ;
RETURN( tr )
ELSE
RETURN( NIL )
END
END Mod2Gcc ;
(*
Gcc2Mod - given a gcc tree return the modula-2 symbol.
*)
PROCEDURE Gcc2Mod (tree: tree) : CARDINAL ;
VAR
high, i: CARDINAL ;
BEGIN
i := 1 ;
high := HighIndice (mod2gcc) ;
WHILE i <= high DO
IF GetIndice (mod2gcc, i) = tree
THEN
RETURN i
END ;
INC (i)
END ;
RETURN NulSym
END Gcc2Mod ;
(*
AddModGcc - adds the tuple [ sym, gcc ] into the database.
*)
PROCEDURE AddModGcc (sym: CARDINAL; gcc: tree) ;
VAR
old: tree ;
t : PtrToCardinal ;
BEGIN
IF gcc=GetErrorNode()
THEN
InternalError ('error node generated during symbol conversion')
END ;
IF USEPOISON
THEN
t := PtrToCardinal(gcc) ;
IF (gcc#tree(NIL)) AND (t^=GGCPOISON)
THEN
InternalError ('gcc symbol has been poisoned')
END
END ;
old := Mod2Gcc(sym) ;
IF old=tree(NIL)
THEN
(* absent - add it *)
PutIndice(mod2gcc, sym, gcc) ;
IF GetIndice(mod2gcc, sym)#gcc
THEN
InternalError ('failed to add gcc <-> mod2 symbol')
END ;
gcc := RememberConstant(gcc)
ELSIF old=gcc
THEN
(* do nothing, as it is already stored *)
ELSIF old=GetErrorNode()
THEN
InternalError ('replacing a temporary symbol (currently unexpected)')
ELSE
InternalError ('should not be replacing a symbol')
END ;
IF IsConst(sym) AND (NOT IsValueSolved(sym))
THEN
PushTypeOfTree(sym, gcc) ;
PopValue(sym)
END
END AddModGcc ;
(*
RemoveMod2Gcc - removes the gcc symbol from the lookup table.
*)
PROCEDURE RemoveMod2Gcc (sym: CARDINAL) ;
BEGIN
PutIndice(mod2gcc, sym, NIL)
END RemoveMod2Gcc ;
(*
GccKnowsAbout - returns TRUE if gcc knows about the symbol, sym.
*)
PROCEDURE GccKnowsAbout (sym: CARDINAL) : BOOLEAN ;
BEGIN
RETURN( InBounds(mod2gcc, sym) AND (GetIndice(mod2gcc, sym)#NIL) )
END GccKnowsAbout ;
(*
AddTemporaryKnown - adds a temporary gcc symbol against the modula-2 sym.
*)
PROCEDURE AddTemporaryKnown (sym: CARDINAL) ;
BEGIN
(* we add the error node against symbol, sym. We expect it to be retacted later. *)
PutIndice (mod2gcc, sym, GetErrorNode ())
END AddTemporaryKnown ;
(*
RemoveTemporaryKnown - removes the temporary symbol.
*)
PROCEDURE RemoveTemporaryKnown (sym: CARDINAL) ;
BEGIN
IF Mod2Gcc(sym)=GetErrorNode()
THEN
PutIndice(mod2gcc, sym, NIL)
ELSE
InternalError ('attempting to remove a symbol which is not present in the tree')
END
END RemoveTemporaryKnown ;
(*
Mod2GccWithoutGCCPoison - given a modula-2 symbol, sym, return
the gcc equivalent, it does not check to see
whether the gcc symbol has been poisoned.
*)
PROCEDURE Mod2GccWithoutGCCPoison (sym: CARDINAL) : tree ;
VAR
n : Name ;
tr: tree ;
BEGIN
IF InBounds(mod2gcc, sym)
THEN
tr := tree(GetIndice(mod2gcc, sym)) ;
IF tr=PoisonedSymbol
THEN
n := GetSymName(sym) ;
(* not poisoned by the garbage collector, but by the gm2 front end. *)
printf1 ('the gm2 front end poisoned this symbol (%a)\n', n) ;
InternalError ('attempting to use a gcc symbol which is no longer in scope')
END ;
RETURN tr
ELSE
RETURN NIL
END
END Mod2GccWithoutGCCPoison ;
(*
Poison - poisons a symbol.
*)
PROCEDURE Poison (sym: WORD) ;
VAR
a: ADDRESS ;
BEGIN
IF NOT IsConst(sym)
THEN
a := Mod2GccWithoutGCCPoison(sym) ;
IF a#NIL
THEN
PutIndice(mod2gcc, sym, PoisonedSymbol)
END
END
END Poison ;
(*
Init - create both binary trees.
*)
PROCEDURE Init ;
BEGIN
mod2gcc := InitIndexTuned (1, 1024*1024 DIV 16, 16) ;
ALLOCATE (PoisonedSymbol, 1)
END Init ;
BEGIN
Init
END SymbolConversion.
|