blob: c25fe5735d5a76abde48cfa167d377909b00aafa [file] [log] [blame]
(* 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.