aboutsummaryrefslogtreecommitdiffstats
path: root/src/vhdl/vhdl-evaluation.ads
blob: 5b7ad49b4d384dbb9613d85951b3a2924c4ad6cb (plain)
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
--  Evaluation of static expressions.
--  Copyright (C) 2002, 2003, 2004, 2005 Tristan Gingold
--
--  This program 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 2 of the License, or
--  (at your option) any later version.
--
--  This program 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 this program.  If not, see <gnu.org/licenses>.
with Types; use Types;
with Vhdl.Nodes; use Vhdl.Nodes;

package Vhdl.Evaluation is

   --  Evaluation is about compile-time computation of expressions, such as
   --  2 + 1 --> 3.  This is (of course) possible only with locally (and some
   --  globally) static expressions.  Evaluation is required during semantic
   --  analysis at many places (in fact those where locally static expression
   --  are required by the language).  For example, the type of O'Range (N)
   --  depends on N, so we need to evaluate N.
   --
   --  The result of evaluation is a literal (integer, enumeration, real,
   --  physical), a string or a simple aggregate.  For scalar types, the
   --  result is therefore normalized (there is only one kind of result), but
   --  for array types, the result isn't: in general it will be a string, but
   --  it may be a simple aggregate.  Strings are preferred (because they are
   --  more compact), but aren't possible in some cases.  For example, the
   --  evaluation of "Text" & NUL cannot be a string.
   --
   --  Some functions (like Eval_Static_Expr) simply returns a result (which
   --  may be a node of the expression), others returns a result and set the
   --  origin (Literal_Origin or Range_Origin) to remember the original
   --  expression that was evaluation.  The original expression is kept so that
   --  it is possible to print the original tree.

   --  Get the value of a physical integer literal or unit.  May propagate
   --  Constraint_Error.
   function Get_Physical_Value (Expr : Iir) return Int64;

   --  Get the parameter of an attribute, or 1 if doesn't exist.
   function Eval_Attribute_Parameter_Or_1 (Attr : Iir) return Natural;

   --  Evaluate the locally static expression EXPR (without checking that EXPR
   --  is locally static).  Return a literal or an aggregate, without setting
   --  the origin, and do not modify EXPR.  This can be used only to get the
   --  value of an expression, without replacing it.
   function Eval_Static_Expr (Expr: Iir) return Iir;

   --  Evaluate (ie compute) expression EXPR.
   --  EXPR is required to be a locally static expression, otherwise an error
   --  message is generated.
   --  The result is a literal with the origin set.
   function Eval_Expr (Expr: Iir) return Iir;

   --  Same as Eval_Expr, but if EXPR is not locally static, the result is
   --  EXPR.  Also, if EXPR is null_iir, then null_iir is returned.
   --  The purpose of this function is to evaluate an expression only if it
   --  is locally static.
   function Eval_Expr_If_Static (Expr : Iir) return Iir;

   --  Concatenate all the elements of OPERANDS.
   --  The first element of OPERANDS is the rightest one, the last the
   --  leftest one.  All the elements are concatenation operators.
   --  All the elements are static.
   function Eval_Concatenation (Operands : Iir_Array) return Iir;

   --  Evaluate a physical literal and return a normalized literal (using
   --  the primary unit as unit).
   function Eval_Physical_Literal (Expr : Iir) return Iir;

   --  Return TRUE if literal EXPR is in SUB_TYPE bounds.
   --  OVERFLOW is the value returned for overflow_literal.  The default is
   --   False because an overflow is never within the bounds (by definition).
   --   But if you use this function to report an error, you prefer to
   --   get True as you don't want to report a second error.
   function Eval_Is_In_Bound
     (Expr : Iir; Sub_Type : Iir; Overflow : Boolean := False) return Boolean;

   --  Emit an error if EXPR violates SUB_TYPE bounds.
   procedure Eval_Check_Bound (Expr : Iir; Sub_Type : Iir);

   --  Same as Eval_Expr, but a range check with SUB_TYPE is performed after
   --  computation.
   function Eval_Expr_Check (Expr : Iir; Sub_Type : Iir) return Iir;

   --  Call Eval_Expr_Check only if EXPR is static.
   function Eval_Expr_Check_If_Static (Expr : Iir; Atype : Iir) return Iir;

   --  For a locally static range RNG (a range expression, a range attribute
   --  or a name that denotes a type or a subtype) returns its corresponding
   --  locally static range_expression.  The bounds of the results are also
   --  literals.
   --  Return a range_expression or NULL_IIR for a non locally static range.
   function Eval_Static_Range (Rng : Iir) return Iir;

   --  Return a locally static range expression with the origin set for ARANGE.
   function Eval_Range (Arange : Iir) return Iir;

   --  If ARANGE is a locally static range, return locally static range
   --  expression (with the origin set), else return ARANGE.
   function Eval_Range_If_Static (Arange : Iir) return Iir;

   --  Emit an error if A_RANGE is not included in SUB_TYPE.  A_RANGE can be
   --  a range expression, a range attribute or a name that denotes a discrete
   --  type or subtype.  A_RANGE must be a locally static range.
   procedure Eval_Check_Range (A_Range : Iir; Sub_Type : Iir;
                               Any_Dir : Boolean);

   --  Return TRUE if A_RANGE is compatible with SUB_TYPE.  Compatibility is
   --  defined in LRM:
   --
   --  LRM08 5.2 Scalar types
   --  A range constraint is /compatible/ with a subtype if each bound of the
   --  range belongs to the subtype or if the range constraint defines a null
   --  range.
   function Eval_Is_Range_In_Bound
     (A_Range : Iir; Sub_Type : Iir; Any_Dir : Boolean)
     return Boolean;

   --  Return TRUE iff VAL belongs to BOUND.
   function Eval_Int_In_Range (Val : Int64; Bound : Iir) return Boolean;

   --  Return the length of the discrete range CONSTRAINT.
   function Eval_Discrete_Range_Length (Constraint : Iir) return Int64;

   --  Return the length of SUB_TYPE.
   function Eval_Discrete_Type_Length (Sub_Type : Iir) return Int64;

   --  Get the left bound of a range constraint.
   --  Note: the range constraint may be an attribute or a subtype.
   function Eval_Discrete_Range_Left (Constraint : Iir) return Iir;

   --  Return true iff RNG is a null range.
   function Eval_Is_Null_Discrete_Range (Rng : Iir) return Boolean;

   --  Return the position of EXPR, ie the result of sub_type'pos (EXPR), where
   --  sub_type is the type of expr.
   --  EXPR must be of a discrete subtype.
   function Eval_Pos (Expr : Iir) return Int64;

   --  Return True iff L and R (scalar literals) are equal.
   function Eval_Is_Eq (L, R : Iir) return Boolean;

   --  Replace ORIGIN (an overflow literal) with extreme positive value (if
   --  IS_POS is true) or extreme negative value.
   function Build_Extreme_Value (Is_Pos : Boolean; Origin : Iir) return Iir;

   --  Create a Iir_Kind_Overflow node of type EXPR_TYPE for ORIGIN.
   function Build_Overflow (Origin : Iir; Expr_Type : Iir) return Iir;

   --  Fill VECT with choices from CHOICES_CHAIN: each position of CHOICE_RANGE
   --  is associated with its corresponding choice from CHOICES_CHAIN.
   --  VECT bounds must be 0 .. Len - 1, where Len is the length of
   --  CHOICE_RANGE.
   procedure Build_Array_Choices_Vector
     (Vect : out Iir_Array; Choice_Range : Iir; Choices_Chain : Iir);

   --  Create an array subtype from LEN and BASE_TYPE, according to rules
   --  of LRM93 7.3.2.2. (which are the same as LRM93 7.2.4).
   function Create_Unidim_Array_By_Length
     (Base_Type : Iir; Len : Int64; Loc : Iir)
     return Iir_Array_Subtype_Definition;

   --  Create a subtype of A_TYPE whose length is LEN.
   --  This is used to create subtypes for strings or aggregates.
   function Create_Range_Subtype_By_Length
     (A_Type : Iir; Len : Int64; Loc : Location_Type)
     return Iir;

   --  Compute ATYPE'value (VALUE) using origin ORIG, but without checking
   --  bounds.
   function Eval_Value_Attribute
     (Value : String; Atype : Iir; Orig : Iir) return Iir;

   --  From one-dimensional array expression PREFIX extract element at
   --  offset OFF (from 0 to length - 1).  Note that the element is directly
   --  returned, not a copy of it (so it should be referenced if stored in
   --  the tree).
   function Eval_Indexed_Name_By_Offset (Prefix : Iir; Off : Iir_Index32)
                                        return Iir;

   --  Return the simple name, character literal or operator sumbol of ID,
   --  using the same format as SIMPLE_NAME attribute.
   function Eval_Simple_Name (Id : Name_Id) return String;

   --  Convert aggregate or string literal to a simple agggregate.
   function Eval_String_Literal (Str : Iir) return Iir;

   --  Compare two string literals (of same length).
   type Compare_Type is (Compare_Lt, Compare_Eq, Compare_Gt);
   function Compare_String_Literals (L, R : Iir) return Compare_Type;

   package String_Utils is
      type Str_Info (Is_String : Boolean := True) is record
         Len : Nat32;

         case Is_String is
            when True =>
               Id : String8_Id;
            when False =>
               --  A simple aggregate.  List of elements.
               List : Iir_Flist;
         end case;
      end record;

      --  Fill Res from EL.  This is used to speed up Lt and Eq operations.
      function Get_Str_Info (Expr : Iir) return Str_Info;

      --  Return the position of element IDX of STR.
      function Get_Pos (Str : Str_Info; Idx : Nat32) return Iir_Int32;
   end String_Utils;

   --  Return the local part of 'Instance_Name or 'Path_Name.
   type Path_Instance_Name_Type (Len : Natural) is record
      --  The node before suffix (entity, architecture or generate iterator).
      Path_Instance : Iir;

      --  The suffix
      Suffix : String (1 .. Len);
   end record;

   function Get_Path_Instance_Name_Suffix (Attr : Iir)
                                          return Path_Instance_Name_Type;

   --  Create a copy of VAL.
   function Copy_Constant (Val : Iir) return Iir;
end Vhdl.Evaluation;