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