1 /* simple constant folding for universal integers
2 
3    Copyright (C) 2000 Marius Vollmer
4 
5    VAUL is free software; you can redistribute it and/or modify it
6    under the terms of the GNU Library General Public License as
7    published by the Free Software Foundation; either version 2 of the
8    License, or (at your option) any later version.
9 
10    VAUL is distributed in the hope that it will be useful, but WITHOUT
11    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General
13    Public License for more details.
14 
15    You should have received a copy of the GNU Library General Public
16    License along with VAUL; see the file COPYING.LIB.  If not, write
17    to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18    Boston, MA 02111-1307 USA.
19 
20 
21 */
22 
23 #include <freehdl/vaul-parser.h>
24 #include <freehdl/vaul-chunk.h>
25 #include <freehdl/vaul-dunit.h>
26 #include <freehdl/vaul-util.h>
27 
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <assert.h>
31 
32 #define psr vaul_parser
33 
34 bool
evaluate_locally_static_universal_integer(pIIR_Expression e,int & n)35 psr::evaluate_locally_static_universal_integer (pIIR_Expression e, int &n)
36 {
37   // XXX - should be done by the backend but we decided to have a
38   // simple version here to reduce dependencies while the code
39   // generator is still changing rapidly.
40 
41   if (e->static_level < IR_LOCALLY_STATIC)
42     {
43       error ("%:%n is not locally static", e, e);
44       return false;
45     }
46 
47   if (e->is(IR_ABSTRACT_LITERAL_EXPRESSION))
48     {
49       pIIR_AbstractLiteralExpression ale = pIIR_AbstractLiteralExpression(e);
50       n = 0;
51       if (ale->value->is(IR_INTEGER_LITERAL))
52 	{
53 	  pIIR_IntegerLiteral l = pIIR_IntegerLiteral(ale->value);
54 	  for (int i = 0; i < l->text.len(); i++)
55 	    {
56 	      IR_Character c = l->text[i];
57 	      if(c == '_')
58 		continue;
59 	      if(c >= '0' && c <= '9')
60 		n = n*10 + c-'0';
61 	      else
62 		{
63 		  info ("XXX - unsupported abstract literal syntax");
64 		  return false;
65 		}
66 	    }
67 
68 	  if (e->is(IR_PHYSICAL_LITERAL))
69 	    {
70 	      // account for unit
71 	      pIIR_PhysicalUnit u = pIIR_PhysicalLiteral(e)->unit;
72 	      if (u->multiplier)
73 		{
74 		  int m;
75 		  if (!evaluate_locally_static_universal_integer
76 		      (u->multiplier, m))
77 		    return false;
78 		  n *= m;
79 		}
80 	    }
81 
82 	  return true;
83 	}
84       else
85 	{
86 	  info ("XXX - unsupported literal: %n", ale);
87 	  return false;
88 	}
89     }
90   else if (e->is(IR_SIMPLE_REFERENCE))
91     {
92       pIIR_ObjectDeclaration d = pIIR_SimpleReference(e)->object;
93       if (d->is(IR_CONSTANT_DECLARATION))
94 	return evaluate_locally_static_universal_integer (d->initial_value,
95 							  n);
96     }
97   else if (e->is(IR_FUNCTION_CALL))
98     {
99       pIIR_FunctionCall fc = pIIR_FunctionCall(e);
100       pIIR_AssociationList pal = fc->parameter_association_list;
101       pIIR_FunctionDeclaration f = fc->function;
102 
103       if (pal == NULL || (pal->rest && pal->rest->rest != NULL))
104 	{
105 	  error ("%:%n can not be used in a locally static"
106 		 " integer expression", e, f);
107 	  return false;
108 	}
109 
110       int arg1;
111       if (!evaluate_locally_static_universal_integer(pal->first->actual, arg1))
112 	return false;
113 
114       if (pal->rest == NULL)   // one arg
115 	{
116 	  if (vaul_name_eq (f->declarator, "\"+\""))
117 	    n = arg1;
118 	  else if (vaul_name_eq (f->declarator, "\"-\""))
119 	    n = -arg1;
120 	  else if (vaul_name_eq (f->declarator, "abs"))
121 	    n = abs (arg1);
122 	  else
123 	    {
124 	      error ("%:%n can not be used in a locally static"
125 		     " integer expression", e, f);
126 	      return false;
127 	    }
128 	  return true;
129 	}
130 
131       int arg2;
132       if (!evaluate_locally_static_universal_integer (pal->rest->first->actual,
133 						      arg2))
134 	return false;
135 
136       if (vaul_name_eq (f->declarator, "\"+\""))
137 	n = arg1 + arg2;
138       else if (vaul_name_eq (f->declarator, "\"-\""))
139 	n = arg1 - arg2;
140       else if (vaul_name_eq (f->declarator, "\"*\""))
141 	n = arg1 * arg2;
142       else if (vaul_name_eq (f->declarator, "\"/\""))
143 	{
144 #if 0
145 	  if (pal->first->actual->subtype->is (IR_PHYSICAL_TYPE))
146 	    {
147 	      info ("XXX - no physical types allowed here yet");
148 	      return false;
149 	    }
150 #endif
151 	  n = arg1 / arg2;
152 	}
153       else if (vaul_name_eq (f->declarator, "\"mod\""))
154 	n = arg1 % arg2;  // XXX - correct?
155       else if (vaul_name_eq (f->declarator, "\"rem\""))
156 	n = arg1 % arg2;  // XXX - correct?
157       else
158 	{
159 	  error ("%:%n can not be used in a locally static"
160 		 " integer expression", e, f);
161 	  return false;
162 	}
163       return true;
164     }
165 
166   info("%:XXX - %s should not appear in a locally static "
167        "integer expression",  e, e->kind_name());
168   return false;
169 }
170