diff options
author | Tristan Gingold <tgingold@free.fr> | 2014-11-04 20:14:19 +0100 |
---|---|---|
committer | Tristan Gingold <tgingold@free.fr> | 2014-11-04 20:14:19 +0100 |
commit | 9c195bf5d86d67ea5eb419ccf6e48dc153e57c68 (patch) | |
tree | 575346e529b99e26382b4a06f6ff2caa0b391ab2 /sem_stmts.adb | |
parent | 184a123f91e07c927292d67462561dc84f3a920d (diff) | |
download | ghdl-9c195bf5d86d67ea5eb419ccf6e48dc153e57c68.tar.gz ghdl-9c195bf5d86d67ea5eb419ccf6e48dc153e57c68.tar.bz2 ghdl-9c195bf5d86d67ea5eb419ccf6e48dc153e57c68.zip |
Move sources to src/ subdirectory.
Diffstat (limited to 'sem_stmts.adb')
-rw-r--r-- | sem_stmts.adb | 2007 |
1 files changed, 0 insertions, 2007 deletions
diff --git a/sem_stmts.adb b/sem_stmts.adb deleted file mode 100644 index b5912fbc6..000000000 --- a/sem_stmts.adb +++ /dev/null @@ -1,2007 +0,0 @@ --- Semantic analysis. --- Copyright (C) 2002, 2003, 2004, 2005 Tristan Gingold --- --- GHDL 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, or (at your option) any later --- version. --- --- GHDL 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 GHDL; see the file COPYING. If not, write to the Free --- Software Foundation, 59 Temple Place - Suite 330, Boston, MA --- 02111-1307, USA. -with Errorout; use Errorout; -with Types; use Types; -with Flags; use Flags; -with Sem_Specs; use Sem_Specs; -with Std_Package; use Std_Package; -with Sem; use Sem; -with Sem_Decls; use Sem_Decls; -with Sem_Expr; use Sem_Expr; -with Sem_Names; use Sem_Names; -with Sem_Scopes; use Sem_Scopes; -with Sem_Types; -with Sem_Psl; -with Std_Names; -with Evaluation; use Evaluation; -with Iirs_Utils; use Iirs_Utils; -with Xrefs; use Xrefs; - -package body Sem_Stmts is - -- Process is the scope, this is also the process for which drivers can - -- be created. - -- Note: FIRST_STMT is the first statement, which can be get by: - -- get_sequential_statement_chain (usual) - -- get_associated_chain (for case statement). - procedure Sem_Sequential_Statements_Internal (First_Stmt : Iir); - - -- Access to the current subprogram or process. - Current_Subprogram: Iir := Null_Iir; - - function Get_Current_Subprogram return Iir is - begin - return Current_Subprogram; - end Get_Current_Subprogram; - - -- Access to the current concurrent statement. - -- Null_iir if no one. - Current_Concurrent_Statement : Iir := Null_Iir; - - function Get_Current_Concurrent_Statement return Iir is - begin - return Current_Concurrent_Statement; - end Get_Current_Concurrent_Statement; - - Current_Declarative_Region_With_Signals : - Implicit_Signal_Declaration_Type := (Null_Iir, Null_Iir); - - procedure Push_Signals_Declarative_Part - (Cell: out Implicit_Signal_Declaration_Type; Decls_Parent : Iir) is - begin - Cell := Current_Declarative_Region_With_Signals; - Current_Declarative_Region_With_Signals := (Decls_Parent, Null_Iir); - end Push_Signals_Declarative_Part; - - procedure Pop_Signals_Declarative_Part - (Cell: in Implicit_Signal_Declaration_Type) is - begin - Current_Declarative_Region_With_Signals := Cell; - end Pop_Signals_Declarative_Part; - - procedure Add_Declaration_For_Implicit_Signal (Sig : Iir) - is - Last : Iir renames - Current_Declarative_Region_With_Signals.Last_Decl; - begin - if Current_Declarative_Region_With_Signals.Decls_Parent = Null_Iir then - raise Internal_Error; - end if; - if Last = Null_Iir then - Last := Get_Declaration_Chain - (Current_Declarative_Region_With_Signals.Decls_Parent); - end if; - if Last = Null_Iir then - Set_Declaration_Chain - (Current_Declarative_Region_With_Signals.Decls_Parent, Sig); - else - while Get_Chain (Last) /= Null_Iir loop - Last := Get_Chain (Last); - end loop; - Set_Chain (Last, Sig); - end if; - Last := Sig; - end Add_Declaration_For_Implicit_Signal; - - -- LRM 8 Sequential statements. - -- All statements may be labeled. - -- Such labels are implicitly declared at the beginning of the declarative - -- part of the innermost enclosing process statement of subprogram body. - procedure Sem_Sequential_Labels (First_Stmt : Iir) - is - Stmt: Iir; - Label: Name_Id; - begin - Stmt := First_Stmt; - while Stmt /= Null_Iir loop - Label := Get_Label (Stmt); - if Label /= Null_Identifier then - Sem_Scopes.Add_Name (Stmt); - Name_Visible (Stmt); - Xref_Decl (Stmt); - end if; - - -- Some statements have sub-lists of statements. - case Get_Kind (Stmt) is - when Iir_Kind_For_Loop_Statement - | Iir_Kind_While_Loop_Statement => - Sem_Sequential_Labels (Get_Sequential_Statement_Chain (Stmt)); - when Iir_Kind_If_Statement => - declare - Clause : Iir; - begin - Clause := Stmt; - while Clause /= Null_Iir loop - Sem_Sequential_Labels - (Get_Sequential_Statement_Chain (Clause)); - Clause := Get_Else_Clause (Clause); - end loop; - end; - when Iir_Kind_Case_Statement => - declare - El : Iir; - begin - El := Get_Case_Statement_Alternative_Chain (Stmt); - while El /= Null_Iir loop - Sem_Sequential_Labels (Get_Associated_Chain (El)); - El := Get_Chain (El); - end loop; - end; - when others => - null; - end case; - Stmt := Get_Chain (Stmt); - end loop; - end Sem_Sequential_Labels; - - procedure Fill_Array_From_Aggregate_Associated - (Chain : Iir; Nbr : in out Natural; Arr : Iir_Array_Acc) - is - El : Iir; - Ass : Iir; - begin - El := Chain; - while El /= Null_Iir loop - Ass := Get_Associated_Expr (El); - if Get_Kind (Ass) = Iir_Kind_Aggregate then - Fill_Array_From_Aggregate_Associated - (Get_Association_Choices_Chain (Ass), Nbr, Arr); - else - if Arr /= null then - Arr (Nbr) := Ass; - end if; - Nbr := Nbr + 1; - end if; - El := Get_Chain (El); - end loop; - end Fill_Array_From_Aggregate_Associated; - - -- Return TRUE iff there is no common elements designed by N1 and N2. - -- N1 and N2 are static names. - -- FIXME: The current implementation is completly wrong; should check from - -- prefix to suffix. - function Is_Disjoint (N1, N2: Iir) return Boolean - is - List1, List2 : Iir_List; - El1, El2 : Iir; - begin - if N1 = N2 then - return False; - end if; - if Get_Kind (N1) = Iir_Kind_Indexed_Name - and then Get_Kind (N2) = Iir_Kind_Indexed_Name - then - if Is_Disjoint (Get_Prefix (N1), Get_Prefix (N2)) then - return True; - end if; - -- Check indexes. - List1 := Get_Index_List (N1); - List2 := Get_Index_List (N2); - for I in Natural loop - El1 := Get_Nth_Element (List1, I); - El2 := Get_Nth_Element (List2, I); - exit when El1 = Null_Iir; - El1 := Eval_Expr (El1); - Replace_Nth_Element (List1, I, El1); - El2 := Eval_Expr (El2); - Replace_Nth_Element (List2, I, El2); - -- EL are of discrete type. - if Get_Value (El1) /= Get_Value (El2) then - return True; - end if; - end loop; - return False; - elsif Get_Kind (N1) in Iir_Kinds_Denoting_Name - and then Get_Kind (N2) in Iir_Kinds_Denoting_Name - then - return Get_Named_Entity (N1) /= Get_Named_Entity (N2); - else - return True; - end if; - end Is_Disjoint; - - procedure Check_Uniq_Aggregate_Associated - (Aggr : Iir_Aggregate; Nbr : Natural) - is - Index : Natural; - Arr : Iir_Array_Acc; - Chain : Iir; - V_I, V_J : Iir; - begin - Chain := Get_Association_Choices_Chain (Aggr); - -- Count number of associated values, and create the array. - -- Already done: use nbr. - -- Fill_Array_From_Aggregate_Associated (List, Nbr, null); - Arr := new Iir_Array (0 .. Nbr - 1); - -- Fill the array. - Index := 0; - Fill_Array_From_Aggregate_Associated (Chain, Index, Arr); - if Index /= Nbr then - -- Should be the same. - raise Internal_Error; - end if; - -- Check each element is uniq. - for I in Arr.all'Range loop - V_I := Name_To_Object (Arr (I)); - if Get_Name_Staticness (V_I) = Locally then - for J in 0 .. I - 1 loop - V_J := Name_To_Object (Arr (J)); - if Get_Name_Staticness (V_J) = Locally - and then not Is_Disjoint (V_I, V_J) - then - Error_Msg_Sem ("target is assigned more than once", Arr (I)); - Error_Msg_Sem (" (previous assignment is here)", Arr (J)); - Free (Arr); - return; - end if; - end loop; - end if; - end loop; - Free (Arr); - return; - end Check_Uniq_Aggregate_Associated; - - -- Do checks for the target of an assignment. - procedure Check_Simple_Signal_Target - (Stmt : Iir; Target : Iir; Staticness : Iir_Staticness); - -- STMT is used to localize the error (if any). - procedure Check_Simple_Variable_Target - (Stmt : Iir; Target : Iir; Staticness : Iir_Staticness); - - -- Semantic associed with signal mode. - -- See §4.3.3 - type Boolean_Array_Of_Iir_Mode is array (Iir_Mode) of Boolean; - Iir_Mode_Readable : constant Boolean_Array_Of_Iir_Mode := - (Iir_Unknown_Mode => False, - Iir_In_Mode => True, - Iir_Out_Mode => False, - Iir_Inout_Mode => True, - Iir_Buffer_Mode => True, - Iir_Linkage_Mode => False); - Iir_Mode_Writable : constant Boolean_Array_Of_Iir_Mode := - (Iir_Unknown_Mode => False, - Iir_In_Mode => False, - Iir_Out_Mode => True, - Iir_Inout_Mode => True, - Iir_Buffer_Mode => True, - Iir_Linkage_Mode => False); - - procedure Check_Aggregate_Target - (Stmt : Iir; Target : Iir; Nbr : in out Natural) - is - Choice : Iir; - Ass : Iir; - begin - Choice := Get_Association_Choices_Chain (Target); - while Choice /= Null_Iir loop - case Get_Kind (Choice) is - when Iir_Kind_Choice_By_Range => - -- LRM93 8.4 - -- It is an error if an element association in such an - -- aggregate contains an OTHERS choice or a choice that is - -- a discrete range. - Error_Msg_Sem ("discrete range choice not allowed for target", - Choice); - when Iir_Kind_Choice_By_Others => - -- LRM93 8.4 - -- It is an error if an element association in such an - -- aggregate contains an OTHERS choice or a choice that is - -- a discrete range. - Error_Msg_Sem ("others choice not allowed for target", Choice); - when Iir_Kind_Choice_By_Expression - | Iir_Kind_Choice_By_Name - | Iir_Kind_Choice_By_None => - -- LRM93 9.4 - -- Such a target may not only contain locally static signal - -- names [...] - Ass := Get_Associated_Expr (Choice); - if Get_Kind (Ass) = Iir_Kind_Aggregate then - Check_Aggregate_Target (Stmt, Ass, Nbr); - else - if Get_Kind (Stmt) = Iir_Kind_Variable_Assignment_Statement - then - Check_Simple_Variable_Target (Stmt, Ass, Locally); - else - Check_Simple_Signal_Target (Stmt, Ass, Locally); - end if; - Nbr := Nbr + 1; - end if; - when others => - Error_Kind ("check_aggregate_target", Choice); - end case; - Choice := Get_Chain (Choice); - end loop; - end Check_Aggregate_Target; - - procedure Check_Simple_Signal_Target - (Stmt : Iir; Target : Iir; Staticness : Iir_Staticness) - is - Target_Object : Iir; - Target_Prefix : Iir; - Guarded_Target : Tri_State_Type; - Targ_Obj_Kind : Iir_Kind; - begin - Target_Object := Name_To_Object (Target); - if Target_Object = Null_Iir then - Error_Msg_Sem ("target is not a signal name", Target); - return; - end if; - - Target_Prefix := Get_Object_Prefix (Target_Object); - Targ_Obj_Kind := Get_Kind (Target_Prefix); - case Targ_Obj_Kind is - when Iir_Kind_Interface_Signal_Declaration => - if not Iir_Mode_Writable (Get_Mode (Target_Prefix)) then - Error_Msg_Sem - (Disp_Node (Target_Prefix) & " can't be assigned", Target); - else - Sem_Add_Driver (Target_Object, Stmt); - end if; - when Iir_Kind_Signal_Declaration => - Sem_Add_Driver (Target_Object, Stmt); - when Iir_Kind_Guard_Signal_Declaration => - Error_Msg_Sem ("implicit GUARD signal cannot be assigned", Stmt); - return; - when others => - Error_Msg_Sem ("target (" & Disp_Node (Get_Base_Name (Target)) - & ") is not a signal", Stmt); - return; - end case; - if Get_Name_Staticness (Target_Object) < Staticness then - Error_Msg_Sem ("signal name must be static", Stmt); - end if; - - -- LRM93 2.1.1.2 - -- A formal signal parameter is a guarded signal if and only if - -- it is associated with an actual signal that is a guarded - -- signal. - -- GHDL: a formal signal interface of a subprogram has no static - -- kind. This is determined at run-time, according to the actual - -- associated with the formal. - -- GHDL: parent of target cannot be a function. - if Targ_Obj_Kind = Iir_Kind_Interface_Signal_Declaration - and then - Get_Kind (Get_Parent (Target_Prefix)) = Iir_Kind_Procedure_Declaration - then - Guarded_Target := Unknown; - else - if Get_Signal_Kind (Target_Prefix) /= Iir_No_Signal_Kind then - Guarded_Target := True; - else - Guarded_Target := False; - end if; - end if; - - case Get_Guarded_Target_State (Stmt) is - when Unknown => - Set_Guarded_Target_State (Stmt, Guarded_Target); - when True - | False => - if Get_Guarded_Target_State (Stmt) /= Guarded_Target then - -- LRM93 9.5 - -- It is an error if the target of a concurrent signal - -- assignment is neither a guarded target nor an - -- unguarded target. - Error_Msg_Sem ("guarded and unguarded target", Target); - end if; - end case; - end Check_Simple_Signal_Target; - - procedure Check_Simple_Variable_Target - (Stmt : Iir; Target : Iir; Staticness : Iir_Staticness) - is - Target_Object : Iir; - Target_Prefix : Iir; - begin - Target_Object := Name_To_Object (Target); - if Target_Object = Null_Iir then - Error_Msg_Sem ("target is not a variable name", Stmt); - return; - end if; - Target_Prefix := Get_Object_Prefix (Target_Object); - case Get_Kind (Target_Prefix) is - when Iir_Kind_Interface_Variable_Declaration => - if not Iir_Mode_Writable (Get_Mode (Target_Prefix)) then - Error_Msg_Sem (Disp_Node (Target_Prefix) - & " cannot be written (bad mode)", Target); - return; - end if; - when Iir_Kind_Variable_Declaration => - null; - when Iir_Kind_Implicit_Dereference - | Iir_Kind_Dereference => - -- LRM 3.3 - -- An object designated by an access type is always an object of - -- class variable. - null; - when others => - Error_Msg_Sem (Disp_Node (Target_Prefix) - & " is not a variable to be assigned", Stmt); - return; - end case; - if Get_Name_Staticness (Target_Object) < Staticness then - Error_Msg_Sem - ("element of aggregate of variables must be a static name", Target); - end if; - end Check_Simple_Variable_Target; - - procedure Check_Target (Stmt : Iir; Target : Iir) - is - Nbr : Natural; - begin - if Get_Kind (Target) = Iir_Kind_Aggregate then - Nbr := 0; - Check_Aggregate_Target (Stmt, Target, Nbr); - Check_Uniq_Aggregate_Associated (Target, Nbr); - else - if Get_Kind (Stmt) = Iir_Kind_Variable_Assignment_Statement then - Check_Simple_Variable_Target (Stmt, Target, None); - else - Check_Simple_Signal_Target (Stmt, Target, None); - end if; - end if; - end Check_Target; - - -- Return FALSE in case of error. - function Sem_Signal_Assignment_Target_And_Option (Stmt: Iir; Sig_Type : Iir) - return Boolean - is - -- The target of the assignment. - Target: Iir; - -- The value that will be assigned. - Expr: Iir; - Ok : Boolean; - begin - Ok := True; - -- Find the signal. - Target := Get_Target (Stmt); - - if Sig_Type = Null_Iir - and then Get_Kind (Target) = Iir_Kind_Aggregate - then - -- Do not try to analyze an aggregate if its type is unknown. - -- A target cannot be a qualified type and its type should be - -- determine by the context (LRM93 7.3.2 Aggregates). - Ok := False; - else - -- Analyze the target - Target := Sem_Expression (Target, Sig_Type); - if Target /= Null_Iir then - Set_Target (Stmt, Target); - Check_Target (Stmt, Target); - Sem_Types.Set_Type_Has_Signal (Get_Type (Target)); - else - Ok := False; - end if; - end if; - - Expr := Get_Reject_Time_Expression (Stmt); - if Expr /= Null_Iir then - Expr := Sem_Expression (Expr, Time_Type_Definition); - if Expr /= Null_Iir then - Check_Read (Expr); - Set_Reject_Time_Expression (Stmt, Expr); - else - Ok := False; - end if; - end if; - return Ok; - end Sem_Signal_Assignment_Target_And_Option; - - -- Semantize a waveform_list WAVEFORM_LIST that is assigned via statement - -- ASSIGN_STMT to a subelement or a slice of a signal SIGNAL_DECL. - procedure Sem_Waveform_Chain - (Assign_Stmt: Iir; - Waveform_Chain : Iir_Waveform_Element; - Waveform_Type : in out Iir) - is - pragma Unreferenced (Assign_Stmt); - Expr: Iir; - We: Iir_Waveform_Element; - Time, Last_Time : Iir_Int64; - begin - if Waveform_Chain = Null_Iir then - -- Unaffected. - return; - end if; - - -- Start with -1 to allow after 0 ns. - Last_Time := -1; - We := Waveform_Chain; - while We /= Null_Iir loop - Expr := Get_We_Value (We); - if Get_Kind (Expr) = Iir_Kind_Null_Literal then - -- GHDL: allowed only if target is guarded; this is checked by - -- sem_check_waveform_list. - null; - else - if Get_Kind (Expr) = Iir_Kind_Aggregate - and then Waveform_Type = Null_Iir - then - Error_Msg_Sem - ("type of waveform is unknown, use qualified type", Expr); - else - Expr := Sem_Expression (Expr, Waveform_Type); - if Expr /= Null_Iir then - Check_Read (Expr); - Set_We_Value (We, Eval_Expr_If_Static (Expr)); - if Waveform_Type = Null_Iir then - Waveform_Type := Get_Type (Expr); - end if; - end if; - end if; - end if; - - if Get_Time (We) /= Null_Iir then - Expr := Sem_Expression (Get_Time (We), Time_Type_Definition); - if Expr /= Null_Iir then - Set_Time (We, Expr); - Check_Read (Expr); - - if Get_Expr_Staticness (Expr) = Locally - or else (Get_Kind (Expr) = Iir_Kind_Physical_Int_Literal - and then Flags.Flag_Time_64) - then - -- LRM 8.4 - -- It is an error if the time expression in a waveform - -- element evaluates to a negative value. - -- - -- LRM 8.4.1 - -- It is an error if the sequence of new transactions is not - -- in ascending order with repect to time. - -- GHDL: this must be checked at run-time, but this is also - -- checked now for static expressions. - if Get_Expr_Staticness (Expr) = Locally then - -- The expression is static, and therefore may be - -- evaluated. - Expr := Eval_Expr (Expr); - Set_Time (We, Expr); - Time := Get_Value (Expr); - else - -- The expression is a physical literal (common case). - -- Extract its value. - Time := Get_Physical_Value (Expr); - end if; - if Time < 0 then - Error_Msg_Sem - ("waveform time expression must be >= 0", Expr); - elsif Time <= Last_Time then - Error_Msg_Sem - ("time must be greather than previous transaction", - Expr); - else - Last_Time := Time; - end if; - end if; - end if; - else - if We /= Waveform_Chain then - -- Time expression must be in ascending order. - Error_Msg_Sem ("time expression required here", We); - end if; - - -- LRM93 12.6.4 - -- It is an error if the execution of any postponed process causes - -- a delta cycle to occur immediatly after the current simulation - -- cycle. - -- GHDL: try to warn for such an error; note the context may be - -- a procedure body. - if Current_Concurrent_Statement /= Null_Iir then - case Get_Kind (Current_Concurrent_Statement) is - when Iir_Kind_Sensitized_Process_Statement - | Iir_Kind_Process_Statement - | Iir_Kind_Concurrent_Conditional_Signal_Assignment - | Iir_Kind_Concurrent_Selected_Signal_Assignment => - if Get_Postponed_Flag (Current_Concurrent_Statement) then - Warning_Msg_Sem - ("waveform may cause a delta cycle in a " & - "postponed process", We); - end if; - when others => - -- Context is a subprogram. - null; - end case; - end if; - - Last_Time := 0; - end if; - We := Get_Chain (We); - end loop; - return; - end Sem_Waveform_Chain; - - -- Semantize a waveform chain WAVEFORM_CHAIN that is assigned via statement - -- ASSIGN_STMT to a subelement or a slice of a signal SIGNAL_DECL. - procedure Sem_Check_Waveform_Chain - (Assign_Stmt: Iir; Waveform_Chain: Iir_Waveform_Element) - is - We: Iir_Waveform_Element; - Expr : Iir; - Targ_Type : Iir; - begin - if Waveform_Chain = Null_Iir then - return; - end if; - - Targ_Type := Get_Type (Get_Target (Assign_Stmt)); - - We := Waveform_Chain; - while We /= Null_Iir loop - Expr := Get_We_Value (We); - if Get_Kind (Expr) = Iir_Kind_Null_Literal then - -- This is a null waveform element. - -- LRM93 8.4.1 - -- It is an error if the target of a signal assignment statement - -- containing a null waveform is not a guarded signal or an - -- aggregate of guarded signals. - if Get_Guarded_Target_State (Assign_Stmt) = False then - Error_Msg_Sem - ("null transactions can be assigned only to guarded signals", - Assign_Stmt); - end if; - else - if not Check_Implicit_Conversion (Targ_Type, Expr) then - Error_Msg_Sem - ("length of value does not match length of target", We); - end if; - end if; - We := Get_Chain (We); - end loop; - end Sem_Check_Waveform_Chain; - - procedure Sem_Signal_Assignment (Stmt: Iir) - is - Target : Iir; - Waveform_Type : Iir; - begin - Target := Get_Target (Stmt); - if Get_Kind (Target) /= Iir_Kind_Aggregate then - if not Sem_Signal_Assignment_Target_And_Option (Stmt, Null_Iir) then - return; - end if; - - -- check the expression. - Waveform_Type := Get_Type (Get_Target (Stmt)); - if Waveform_Type /= Null_Iir then - Sem_Waveform_Chain - (Stmt, Get_Waveform_Chain (Stmt), Waveform_Type); - Sem_Check_Waveform_Chain (Stmt, Get_Waveform_Chain (Stmt)); - end if; - else - Waveform_Type := Null_Iir; - Sem_Waveform_Chain (Stmt, Get_Waveform_Chain (Stmt), Waveform_Type); - if Waveform_Type = Null_Iir - or else - not Sem_Signal_Assignment_Target_And_Option (Stmt, Waveform_Type) - then - return; - end if; - Sem_Check_Waveform_Chain (Stmt, Get_Waveform_Chain (Stmt)); - end if; - end Sem_Signal_Assignment; - - procedure Sem_Variable_Assignment (Stmt: Iir) is - Target: Iir; - Expr: Iir; - Target_Type : Iir; - begin - -- Find the variable. - Target := Get_Target (Stmt); - Expr := Get_Expression (Stmt); - - -- LRM93 8.5 Variable assignment statement - -- If the target of the variable assignment statement is in the form of - -- an aggregate, then the type of the aggregate must be determinable - -- from the context, excluding the aggregate itself but including the - -- fact that the type of the aggregate must be a composite type. The - -- base type of the expression on the right-hand side must be the - -- same as the base type of the aggregate. - -- - -- GHDL: this means that the type can only be deduced from the - -- expression (and not from the target). - if Get_Kind (Target) = Iir_Kind_Aggregate then - if Get_Kind (Expr) = Iir_Kind_Aggregate then - Error_Msg_Sem ("can't determine type, use type qualifier", Expr); - return; - end if; - Expr := Sem_Composite_Expression (Get_Expression (Stmt)); - if Expr = Null_Iir then - return; - end if; - Check_Read (Expr); - Set_Expression (Stmt, Expr); - Target_Type := Get_Type (Expr); - - -- An aggregate cannot be analyzed without a type. - -- FIXME: partially analyze the aggregate ? - if Target_Type = Null_Iir then - return; - end if; - - -- FIXME: check elements are identified at most once. - else - Target_Type := Null_Iir; - end if; - - Target := Sem_Expression (Target, Target_Type); - if Target = Null_Iir then - return; - end if; - Set_Target (Stmt, Target); - - Check_Target (Stmt, Target); - - if Get_Kind (Target) /= Iir_Kind_Aggregate then - Expr := Sem_Expression (Expr, Get_Type (Target)); - if Expr /= Null_Iir then - Check_Read (Expr); - Expr := Eval_Expr_If_Static (Expr); - Set_Expression (Stmt, Expr); - end if; - end if; - if not Check_Implicit_Conversion (Get_Type (Target), Expr) then - Warning_Msg_Sem - ("expression length does not match target length", Stmt); - end if; - end Sem_Variable_Assignment; - - procedure Sem_Return_Statement (Stmt: Iir_Return_Statement) is - Expr: Iir; - begin - if Current_Subprogram = Null_Iir then - Error_Msg_Sem ("return statement not in a subprogram body", Stmt); - return; - end if; - Expr := Get_Expression (Stmt); - case Get_Kind (Current_Subprogram) is - when Iir_Kind_Procedure_Declaration => - if Expr /= Null_Iir then - Error_Msg_Sem - ("return in a procedure can't have an expression", Stmt); - end if; - return; - when Iir_Kind_Function_Declaration => - if Expr = Null_Iir then - Error_Msg_Sem - ("return in a function must have an expression", Stmt); - return; - end if; - when Iir_Kinds_Process_Statement => - Error_Msg_Sem ("return statement not allowed in a process", Stmt); - return; - when others => - Error_Kind ("sem_return_statement", Stmt); - end case; - Set_Type (Stmt, Get_Return_Type (Current_Subprogram)); - Expr := Sem_Expression (Expr, Get_Return_Type (Current_Subprogram)); - if Expr /= Null_Iir then - Check_Read (Expr); - Set_Expression (Stmt, Eval_Expr_If_Static (Expr)); - end if; - end Sem_Return_Statement; - - -- Sem for concurrent and sequential assertion statements. - procedure Sem_Report_Statement (Stmt : Iir) - is - Expr : Iir; - begin - Expr := Get_Report_Expression (Stmt); - if Expr /= Null_Iir then - Expr := Sem_Expression (Expr, String_Type_Definition); - Check_Read (Expr); - Expr := Eval_Expr_If_Static (Expr); - Set_Report_Expression (Stmt, Expr); - end if; - - Expr := Get_Severity_Expression (Stmt); - if Expr /= Null_Iir then - Expr := Sem_Expression (Expr, Severity_Level_Type_Definition); - Check_Read (Expr); - Set_Severity_Expression (Stmt, Expr); - end if; - end Sem_Report_Statement; - - procedure Sem_Assertion_Statement (Stmt: Iir) - is - Expr : Iir; - begin - Expr := Get_Assertion_Condition (Stmt); - Expr := Sem_Condition (Expr); - Expr := Eval_Expr_If_Static (Expr); - Set_Assertion_Condition (Stmt, Expr); - - Sem_Report_Statement (Stmt); - end Sem_Assertion_Statement; - - -- Semantize a list of case choice LIST, and check for correct CHOICE type. - procedure Sem_Case_Choices - (Choice : Iir; Chain : in out Iir; Loc : Location_Type) - is - -- Check restrictions on the expression of a One-Dimensional Character - -- Array Type (ODCAT) given by LRM 8.8 - -- Return FALSE in case of violation. - function Check_Odcat_Expression (Expr : Iir) return Boolean - is - Expr_Type : constant Iir := Get_Type (Expr); - begin - -- LRM 8.8 Case Statement - -- If the expression is of a one-dimensional character array type, - -- then the expression must be one of the following: - case Get_Kind (Expr) is - when Iir_Kinds_Object_Declaration - | Iir_Kind_Selected_Element => - -- FIXME: complete the list. - -- * the name of an object whose subtype is locally static. - if Get_Type_Staticness (Expr_Type) /= Locally then - Error_Msg_Sem ("object subtype is not locally static", - Choice); - return False; - end if; - when Iir_Kind_Indexed_Name => - -- LRM93 - -- * an indexed name whose prefix is one of the members of - -- this list and whose indexing expressions are locally - -- static expression. - if Flags.Vhdl_Std = Vhdl_87 then - Error_Msg_Sem ("indexed name not allowed here in vhdl87", - Expr); - return False; - end if; - if not Check_Odcat_Expression (Get_Prefix (Expr)) then - return False; - end if; - -- GHDL: I don't understand why the indexing expressions - -- must be locally static. So I don't check this in 93c. - if Flags.Vhdl_Std /= Vhdl_93c - and then - Get_Expr_Staticness (Get_First_Element - (Get_Index_List (Expr))) /= Locally - then - Error_Msg_Sem ("indexing expression must be locally static", - Expr); - return False; - end if; - when Iir_Kind_Slice_Name => - -- LRM93 - -- * a slice name whose prefix is one of the members of this - -- list and whose discrete range is a locally static - -- discrete range. - - -- LRM87/INT1991 IR96 - -- then the expression must be either a slice name whose - -- discrete range is locally static, or .. - if False and Flags.Vhdl_Std = Vhdl_87 then - Error_Msg_Sem - ("slice not allowed as case expression in vhdl87", Expr); - return False; - end if; - if not Check_Odcat_Expression (Get_Prefix (Expr)) then - return False; - end if; - if Get_Type_Staticness (Expr_Type) /= Locally then - Error_Msg_Sem ("slice discrete range must be locally static", - Expr); - return False; - end if; - when Iir_Kind_Function_Call => - -- LRM93 - -- * a function call whose return type mark denotes a - -- locally static subtype. - if Flags.Vhdl_Std = Vhdl_87 then - Error_Msg_Sem ("function call not allowed here in vhdl87", - Expr); - return False; - end if; - if Get_Type_Staticness (Expr_Type) /= Locally then - Error_Msg_Sem ("function call type is not locally static", - Expr); - end if; - when Iir_Kind_Qualified_Expression - | Iir_Kind_Type_Conversion => - -- * a qualified expression or type conversion whose type mark - -- denotes a locally static subtype. - if Get_Type_Staticness (Expr_Type) /= Locally then - Error_Msg_Sem ("type mark is not a locally static subtype", - Expr); - return False; - end if; - when Iir_Kind_Simple_Name - | Iir_Kind_Selected_Name => - return Check_Odcat_Expression (Get_Named_Entity (Expr)); - when others => - Error_Msg_Sem ("bad form of case expression (refer to LRM 8.8)", - Choice); - return False; - end case; - return True; - end Check_Odcat_Expression; - - Choice_Type : Iir; - Low, High : Iir; - El_Type : Iir; - begin - -- LRM 8.8 Case Statement - -- The expression must be of a discrete type, or of a one-dimensional - -- array type whose element base type is a character type. - Choice_Type := Get_Type (Choice); - case Get_Kind (Choice_Type) is - when Iir_Kinds_Discrete_Type_Definition => - Sem_Choices_Range - (Chain, Choice_Type, False, True, Loc, Low, High); - when Iir_Kind_Array_Subtype_Definition - | Iir_Kind_Array_Type_Definition => - if not Is_One_Dimensional_Array_Type (Choice_Type) then - Error_Msg_Sem - ("expression must be of a one-dimensional array type", - Choice); - return; - end if; - El_Type := Get_Base_Type (Get_Element_Subtype (Choice_Type)); - if Get_Kind (El_Type) /= Iir_Kind_Enumeration_Type_Definition then - -- FIXME: check character. - Error_Msg_Sem - ("element type of the expression must be a character type", - Choice); - return; - end if; - if not Check_Odcat_Expression (Choice) then - return; - end if; - Sem_String_Choices_Range (Chain, Choice); - when others => - Error_Msg_Sem ("type of expression must be discrete", Choice); - end case; - end Sem_Case_Choices; - - procedure Sem_Case_Statement (Stmt: Iir_Case_Statement) - is - Expr: Iir; - Chain : Iir; - El: Iir; - begin - Expr := Get_Expression (Stmt); - -- FIXME: overload. - Expr := Sem_Case_Expression (Expr); - if Expr = Null_Iir then - return; - end if; - Check_Read (Expr); - Set_Expression (Stmt, Expr); - Chain := Get_Case_Statement_Alternative_Chain (Stmt); - Sem_Case_Choices (Expr, Chain, Get_Location (Stmt)); - Set_Case_Statement_Alternative_Chain (Stmt, Chain); - -- Sem on associated. - El := Chain; - while El /= Null_Iir loop - Sem_Sequential_Statements_Internal (Get_Associated_Chain (El)); - El := Get_Chain (El); - end loop; - end Sem_Case_Statement; - - -- Sem the sensitivity list LIST. - procedure Sem_Sensitivity_List (List: Iir_Designator_List) - is - El: Iir; - Res: Iir; - Prefix : Iir; - begin - if List = Iir_List_All then - return; - end if; - - for I in Natural loop - -- El is an iir_identifier. - El := Get_Nth_Element (List, I); - exit when El = Null_Iir; - - Sem_Name (El); - - Res := Get_Named_Entity (El); - if Res = Error_Mark then - null; - elsif Is_Overload_List (Res) or else not Is_Object_Name (Res) then - Error_Msg_Sem ("a sensitivity element must be a signal name", El); - else - Res := Finish_Sem_Name (El); - Prefix := Get_Object_Prefix (Res); - case Get_Kind (Prefix) is - when Iir_Kind_Signal_Declaration - | Iir_Kind_Guard_Signal_Declaration - | Iir_Kinds_Signal_Attribute => - null; - when Iir_Kind_Interface_Signal_Declaration => - if not Iir_Mode_Readable (Get_Mode (Prefix)) then - Error_Msg_Sem - (Disp_Node (Res) & " of mode out" - & " can't be in a sensivity list", El); - end if; - when others => - Error_Msg_Sem (Disp_Node (Res) - & " is neither a signal nor a port", El); - end case; - -- LRM 9.2 - -- Only static signal names (see section 6.1) for which reading - -- is permitted may appear in the sensitivity list of a process - -- statement. - - -- LRM 8.1 Wait statement - -- Each signal name in the sensitivity list must be a static - -- signal name, and each name must denote a signal for which - -- reading is permitted. - if Get_Name_Staticness (Res) < Globally then - Error_Msg_Sem ("sensitivity element " & Disp_Node (Res) - & " must be a static name", El); - end if; - - Replace_Nth_Element (List, I, Res); - end if; - end loop; - end Sem_Sensitivity_List; - - procedure Sem_Wait_Statement (Stmt: Iir_Wait_Statement) - is - Expr: Iir; - Sensitivity_List : Iir_List; - begin - -- Check validity. - case Get_Kind (Current_Subprogram) is - when Iir_Kind_Process_Statement => - null; - when Iir_Kinds_Function_Declaration => - -- LRM93 §8.2 - -- It is an error if a wait statement appears in a function - -- subprogram [...] - Error_Msg_Sem - ("wait statement not allowed in a function subprogram", Stmt); - return; - when Iir_Kinds_Procedure_Declaration => - -- LRM93 §8.2 - -- [It is an error ...] or in a procedure that has a parent that - -- is a function subprogram. - -- LRM93 §8.2 - -- [...] or in a procedure that has a parent that is such a - -- process statement. - -- GHDL: this is checked at the end of analysis or during - -- elaboration. - Set_Wait_State (Current_Subprogram, True); - when Iir_Kind_Sensitized_Process_Statement => - -- LRM93 §8.2 - -- Furthermore, it is an error if a wait statement appears in an - -- explicit process statement that includes a sensitivity list, - -- [...] - Error_Msg_Sem - ("wait statement not allowed in a sensitized process", Stmt); - return; - when others => - raise Internal_Error; - end case; - - Sensitivity_List := Get_Sensitivity_List (Stmt); - if Sensitivity_List /= Null_Iir_List then - Sem_Sensitivity_List (Sensitivity_List); - end if; - Expr := Get_Condition_Clause (Stmt); - if Expr /= Null_Iir then - Expr := Sem_Condition (Expr); - Set_Condition_Clause (Stmt, Expr); - end if; - Expr := Get_Timeout_Clause (Stmt); - if Expr /= Null_Iir then - Expr := Sem_Expression (Expr, Time_Type_Definition); - if Expr /= Null_Iir then - Check_Read (Expr); - Expr := Eval_Expr_If_Static (Expr); - Set_Timeout_Clause (Stmt, Expr); - if Get_Expr_Staticness (Expr) = Locally - and then Get_Value (Expr) < 0 - then - Error_Msg_Sem ("timeout value must be positive", Stmt); - end if; - end if; - end if; - end Sem_Wait_Statement; - - procedure Sem_Exit_Next_Statement (Stmt : Iir) - is - Cond: Iir; - Loop_Label : Iir; - Loop_Stmt: Iir; - P : Iir; - begin - Cond := Get_Condition (Stmt); - if Cond /= Null_Iir then - Cond := Sem_Condition (Cond); - Set_Condition (Stmt, Cond); - end if; - - Loop_Label := Get_Loop_Label (Stmt); - if Loop_Label /= Null_Iir then - Loop_Label := Sem_Denoting_Name (Loop_Label); - Set_Loop_Label (Stmt, Loop_Label); - Loop_Stmt := Get_Named_Entity (Loop_Label); - case Get_Kind (Loop_Stmt) is - when Iir_Kind_For_Loop_Statement - | Iir_Kind_While_Loop_Statement => - null; - when others => - Error_Class_Match (Loop_Label, "loop statement"); - Loop_Stmt := Null_Iir; - end case; - else - Loop_Stmt := Null_Iir; - end if; - - -- Check the current statement is inside the labeled loop. - P := Stmt; - loop - P := Get_Parent (P); - case Get_Kind (P) is - when Iir_Kind_While_Loop_Statement - | Iir_Kind_For_Loop_Statement => - if Loop_Stmt = Null_Iir or else P = Loop_Stmt then - exit; - end if; - when Iir_Kind_If_Statement - | Iir_Kind_Elsif - | Iir_Kind_Case_Statement => - null; - when others => - -- FIXME: should emit a message for label mismatch. - Error_Msg_Sem ("exit/next must be inside a loop", Stmt); - exit; - end case; - end loop; - end Sem_Exit_Next_Statement; - - -- Process is the scope, this is also the process for which drivers can - -- be created. - procedure Sem_Sequential_Statements_Internal (First_Stmt : Iir) - is - Stmt: Iir; - begin - Stmt := First_Stmt; - while Stmt /= Null_Iir loop - case Get_Kind (Stmt) is - when Iir_Kind_Null_Statement => - null; - when Iir_Kind_If_Statement => - declare - Clause: Iir := Stmt; - Cond: Iir; - begin - while Clause /= Null_Iir loop - Cond := Get_Condition (Clause); - if Cond /= Null_Iir then - Cond := Sem_Condition (Cond); - Set_Condition (Clause, Cond); - end if; - Sem_Sequential_Statements_Internal - (Get_Sequential_Statement_Chain (Clause)); - Clause := Get_Else_Clause (Clause); - end loop; - end; - when Iir_Kind_For_Loop_Statement => - declare - Iterator: Iir; - begin - -- LRM 10.1 Declarative region - -- 9. A loop statement. - Open_Declarative_Region; - - Set_Is_Within_Flag (Stmt, True); - Iterator := Get_Parameter_Specification (Stmt); - Sem_Scopes.Add_Name (Iterator); - Sem_Iterator (Iterator, None); - Set_Visible_Flag (Iterator, True); - Sem_Sequential_Statements_Internal - (Get_Sequential_Statement_Chain (Stmt)); - Set_Is_Within_Flag (Stmt, False); - - Close_Declarative_Region; - end; - when Iir_Kind_While_Loop_Statement => - declare - Cond: Iir; - begin - Cond := Get_Condition (Stmt); - if Cond /= Null_Iir then - Cond := Sem_Condition (Cond); - Set_Condition (Stmt, Cond); - end if; - Sem_Sequential_Statements_Internal - (Get_Sequential_Statement_Chain (Stmt)); - end; - when Iir_Kind_Signal_Assignment_Statement => - Sem_Signal_Assignment (Stmt); - if Current_Concurrent_Statement /= Null_Iir and then - Get_Kind (Current_Concurrent_Statement) - in Iir_Kinds_Process_Statement - and then Get_Passive_Flag (Current_Concurrent_Statement) - then - Error_Msg_Sem - ("signal statement forbidden in passive process", Stmt); - end if; - when Iir_Kind_Variable_Assignment_Statement => - Sem_Variable_Assignment (Stmt); - when Iir_Kind_Return_Statement => - Sem_Return_Statement (Stmt); - when Iir_Kind_Assertion_Statement => - Sem_Assertion_Statement (Stmt); - when Iir_Kind_Report_Statement => - Sem_Report_Statement (Stmt); - when Iir_Kind_Case_Statement => - Sem_Case_Statement (Stmt); - when Iir_Kind_Wait_Statement => - Sem_Wait_Statement (Stmt); - when Iir_Kind_Procedure_Call_Statement => - Sem_Procedure_Call (Get_Procedure_Call (Stmt), Stmt); - when Iir_Kind_Next_Statement - | Iir_Kind_Exit_Statement => - Sem_Exit_Next_Statement (Stmt); - when others => - Error_Kind ("sem_sequential_statements_Internal", Stmt); - end case; - Stmt := Get_Chain (Stmt); - end loop; - end Sem_Sequential_Statements_Internal; - - procedure Sem_Sequential_Statements (Decl : Iir; Body_Parent : Iir) - is - Outer_Subprogram: Iir; - begin - Outer_Subprogram := Current_Subprogram; - Current_Subprogram := Decl; - - -- Sem declarations - Sem_Sequential_Labels (Get_Sequential_Statement_Chain (Body_Parent)); - Sem_Declaration_Chain (Body_Parent); - Sem_Specification_Chain (Body_Parent, Null_Iir); - - -- Sem statements. - Sem_Sequential_Statements_Internal - (Get_Sequential_Statement_Chain (Body_Parent)); - - Check_Full_Declaration (Body_Parent, Body_Parent); - - Current_Subprogram := Outer_Subprogram; - end Sem_Sequential_Statements; - - -- Sem the instantiated unit of STMT and return the node constaining - -- ports and generics (either a entity_declaration or a component - -- declaration). - function Sem_Instantiated_Unit - (Stmt : Iir_Component_Instantiation_Statement) - return Iir - is - Inst : Iir; - Comp_Name : Iir; - Comp : Iir; - begin - Inst := Get_Instantiated_Unit (Stmt); - - if Get_Kind (Inst) in Iir_Kinds_Denoting_Name then - Comp := Get_Named_Entity (Inst); - if Comp /= Null_Iir then - -- Already semantized before, while trying to separate - -- concurrent procedure calls from instantiation stmts. - pragma Assert (Get_Kind (Comp) = Iir_Kind_Component_Declaration); - return Comp; - end if; - -- The component may be an entity or a configuration. - Comp_Name := Sem_Denoting_Name (Inst); - Set_Instantiated_Unit (Stmt, Comp_Name); - Comp := Get_Named_Entity (Comp_Name); - if Get_Kind (Comp) /= Iir_Kind_Component_Declaration then - Error_Class_Match (Comp_Name, "component"); - return Null_Iir; - end if; - return Comp; - else - return Sem_Entity_Aspect (Inst); - end if; - end Sem_Instantiated_Unit; - - procedure Sem_Component_Instantiation_Statement - (Stmt: Iir_Component_Instantiation_Statement; Is_Passive : Boolean) - is - Decl : Iir; - Entity_Unit : Iir_Design_Unit; - Bind : Iir_Binding_Indication; - begin - -- FIXME: move this check in parse ? - if Is_Passive then - Error_Msg_Sem ("component instantiation forbidden in entity", Stmt); - end if; - - -- Check for label. - -- This cannot be moved in parse since a procedure_call may be revert - -- into a component instantiation. - if Get_Label (Stmt) = Null_Identifier then - Error_Msg_Sem ("component instantiation requires a label", Stmt); - end if; - - -- Look for the component. - Decl := Sem_Instantiated_Unit (Stmt); - if Decl = Null_Iir then - return; - end if; - - -- The association - Sem_Generic_Port_Association_Chain (Decl, Stmt); - - -- FIXME: add sources for signals, in order to detect multiple sources - -- to unresolved signals. - -- What happen if the component is not bound ? - - -- Create a default binding indication if necessary. - if Get_Component_Configuration (Stmt) = Null_Iir - and then Get_Kind (Decl) = Iir_Kind_Component_Declaration - then - Entity_Unit := Get_Visible_Entity_Declaration (Decl); - if Entity_Unit = Null_Iir then - if Flags.Warn_Default_Binding - and then not Flags.Flag_Elaborate - then - Warning_Msg_Sem ("no default binding for instantiation of " - & Disp_Node (Decl), Stmt); - Explain_No_Visible_Entity (Decl); - end if; - elsif Flags.Flag_Elaborate - and then (Flags.Flag_Elaborate_With_Outdated - or else Get_Date (Entity_Unit) in Date_Valid) - then - Bind := Sem_Create_Default_Binding_Indication - (Decl, Entity_Unit, Stmt, False); - Set_Default_Binding_Indication (Stmt, Bind); - end if; - end if; - end Sem_Component_Instantiation_Statement; - - -- Note: a statement such as - -- label1: name; - -- can be parsed as a procedure call statement or as a - -- component instantiation statement. - -- Check now and revert in case of error. - function Sem_Concurrent_Procedure_Call_Statement - (Stmt : Iir; Is_Passive : Boolean) return Iir - is - Call : Iir_Procedure_Call; - Decl : Iir; - Label : Name_Id; - N_Stmt : Iir_Component_Instantiation_Statement; - Imp : Iir; - begin - Call := Get_Procedure_Call (Stmt); - if Get_Parameter_Association_Chain (Call) = Null_Iir then - Imp := Get_Prefix (Call); - Sem_Name (Imp); - Set_Prefix (Call, Imp); - - Decl := Get_Named_Entity (Imp); - if Get_Kind (Decl) = Iir_Kind_Component_Declaration then - N_Stmt := Create_Iir (Iir_Kind_Component_Instantiation_Statement); - Label := Get_Label (Stmt); - Set_Label (N_Stmt, Label); - Set_Parent (N_Stmt, Get_Parent (Stmt)); - Set_Instantiated_Unit (N_Stmt, Finish_Sem_Name (Imp)); - Location_Copy (N_Stmt, Stmt); - - if Label /= Null_Identifier then - -- A component instantiation statement must have - -- a label, this condition is checked during the - -- sem of the statement. - Sem_Scopes.Replace_Name (Label, Stmt, N_Stmt); - end if; - - Free_Iir (Stmt); - Free_Iir (Call); - - Sem_Component_Instantiation_Statement (N_Stmt, Is_Passive); - return N_Stmt; - end if; - end if; - Sem_Procedure_Call (Call, Stmt); - - if Is_Passive then - Imp := Get_Implementation (Call); - if Get_Kind (Imp) = Iir_Kind_Procedure_Declaration then - Decl := Get_Interface_Declaration_Chain (Imp); - while Decl /= Null_Iir loop - if Get_Mode (Decl) in Iir_Out_Modes then - Error_Msg_Sem (Disp_Node (Imp) & " is not passive", Stmt); - exit; - end if; - Decl := Get_Chain (Decl); - end loop; - end if; - end if; - - return Stmt; - end Sem_Concurrent_Procedure_Call_Statement; - - procedure Sem_Block_Statement (Stmt: Iir_Block_Statement) - is - Expr: Iir; - Guard : Iir_Guard_Signal_Declaration; - Header : Iir_Block_Header; - Generic_Chain : Iir; - Port_Chain : Iir; - begin - -- LRM 10.1 Declarative region. - -- 7. A block statement. - Open_Declarative_Region; - - Set_Is_Within_Flag (Stmt, True); - - Header := Get_Block_Header (Stmt); - if Header /= Null_Iir then - Generic_Chain := Get_Generic_Chain (Header); - Sem_Interface_Chain (Generic_Chain, Generic_Interface_List); - Port_Chain := Get_Port_Chain (Header); - Sem_Interface_Chain (Port_Chain, Port_Interface_List); - - -- LRM 9.1 - -- Such actuals are evaluated in the context of the enclosing - -- declarative region. - -- GHDL: close the declarative region... - Set_Is_Within_Flag (Stmt, False); - Close_Declarative_Region; - - Sem_Generic_Port_Association_Chain (Header, Header); - - -- ... and reopen-it. - Open_Declarative_Region; - Set_Is_Within_Flag (Stmt, True); - Add_Declarations_From_Interface_Chain (Generic_Chain); - Add_Declarations_From_Interface_Chain (Port_Chain); - end if; - - -- LRM93 9.1 - -- If a guard expression appears after the reserved word BLOCK, then a - -- signal with the simple name GUARD of predefined type BOOLEAN is - -- implicitly declared at the beginning of the declarative part of the - -- block, and the guard expression defined the value of that signal at - -- any given time. - Guard := Get_Guard_Decl (Stmt); - if Guard /= Null_Iir then - -- LRM93 9.1 - -- The type of the guard expression must be type BOOLEAN. - -- GHDL: guard expression must be semantized before creating the - -- implicit GUARD signal, since the expression may reference GUARD. - Set_Expr_Staticness (Guard, None); - Set_Name_Staticness (Guard, Locally); - Expr := Get_Guard_Expression (Guard); - Expr := Sem_Condition (Expr); - if Expr /= Null_Iir then - Set_Guard_Expression (Guard, Expr); - end if; - - -- FIXME: should extract sensivity now and set the has_active flag - -- on signals, since the guard expression is evaluated when one of - -- its signal is active. However, how can a bug be introduced by - -- evaluating only when signals have events ? - - -- the guard expression is an implicit definition of a signal named - -- GUARD. Create this definition. This is necessary for the type. - Set_Identifier (Guard, Std_Names.Name_Guard); - Set_Type (Guard, Boolean_Type_Definition); - Set_Block_Statement (Guard, Stmt); - Sem_Scopes.Add_Name (Guard); - Set_Visible_Flag (Guard, True); - end if; - - Sem_Block (Stmt, True); - Set_Is_Within_Flag (Stmt, False); - Close_Declarative_Region; - end Sem_Block_Statement; - - procedure Sem_Generate_Statement (Stmt : Iir_Generate_Statement) - is - Scheme : Iir; - begin - -- LRM93 10.1 Declarative region. - -- 12. A generate statement. - Open_Declarative_Region; - - Scheme := Get_Generation_Scheme (Stmt); - if Get_Kind (Scheme) = Iir_Kind_Iterator_Declaration then - Sem_Scopes.Add_Name (Scheme); - -- LRM93 §7.4.2 (Globally Static Primaries) - -- 4. a generate parameter; - Sem_Iterator (Scheme, Globally); - Set_Visible_Flag (Scheme, True); - -- LRM93 §9.7 - -- The discrete range in a generation scheme of the first form must - -- be a static discrete range; - if Get_Type (Scheme) /= Null_Iir - and then Get_Type_Staticness (Get_Type (Scheme)) < Globally - then - Error_Msg_Sem ("range must be a static discrete range", Stmt); - end if; - else - Scheme := Sem_Condition (Scheme); - -- LRM93 §9.7 - -- the condition in a generation scheme of the second form must be - -- a static expression. - if Scheme /= Null_Iir - and then Get_Expr_Staticness (Scheme) < Globally - then - Error_Msg_Sem ("condition must be a static expression", Stmt); - else - Set_Generation_Scheme (Stmt, Scheme); - end if; - end if; - - Sem_Block (Stmt, True); -- Flags.Vhdl_Std /= Vhdl_87); - Close_Declarative_Region; - end Sem_Generate_Statement; - - procedure Sem_Process_Statement (Proc: Iir) is - begin - Set_Is_Within_Flag (Proc, True); - - -- LRM 10.1 - -- 8. A process statement - Open_Declarative_Region; - - -- Sem declarations - Sem_Sequential_Statements (Proc, Proc); - - Close_Declarative_Region; - - Set_Is_Within_Flag (Proc, False); - - if Get_Kind (Proc) = Iir_Kind_Sensitized_Process_Statement - and then Get_Callees_List (Proc) /= Null_Iir_List - then - -- Check there is no wait statement in subprograms called. - -- Also in the case of all-sensitized process, check that package - -- subprograms don't read signals. - Sem.Add_Analysis_Checks_List (Proc); - end if; - end Sem_Process_Statement; - - procedure Sem_Sensitized_Process_Statement - (Proc: Iir_Sensitized_Process_Statement) is - begin - Sem_Sensitivity_List (Get_Sensitivity_List (Proc)); - Sem_Process_Statement (Proc); - end Sem_Sensitized_Process_Statement; - - procedure Sem_Guard (Stmt: Iir) - is - Guard: Iir; - Guard_Interpretation : Name_Interpretation_Type; - begin - Guard := Get_Guard (Stmt); - if Guard = Null_Iir then - -- This assignment is not guarded. - - -- LRM93 9.5 - -- It is an error if a concurrent signal assignment is not a guarded - -- assignment, and the target of the concurrent signal assignment - -- is a guarded target. - if Get_Guarded_Target_State (Stmt) = True then - Error_Msg_Sem - ("not a guarded assignment for a guarded target", Stmt); - end if; - return; - end if; - if Guard /= Stmt then - -- if set, guard must be equal to stmt here. - raise Internal_Error; - end if; - Guard_Interpretation := Get_Interpretation (Std_Names.Name_Guard); - if not Valid_Interpretation (Guard_Interpretation) then - Error_Msg_Sem ("no guard signals for this guarded assignment", Stmt); - return; - end if; - - Guard := Get_Declaration (Guard_Interpretation); - -- LRM93 9.5: - -- The signal GUARD [...] an explicitly declared signal of type - -- BOOLEAN that is visible at the point of the concurrent signal - -- assignment statement - -- FIXME. - case Get_Kind (Guard) is - when Iir_Kind_Signal_Declaration - | Iir_Kind_Interface_Signal_Declaration - | Iir_Kind_Guard_Signal_Declaration => - null; - when others => - Error_Msg_Sem ("visible GUARD object is not a signal", Stmt); - Error_Msg_Sem ("GUARD object is " & Disp_Node (Guard), Stmt); - return; - end case; - - if Get_Type (Guard) /= Boolean_Type_Definition then - Error_Msg_Sem ("GUARD is not of boolean type", Guard); - end if; - Set_Guard (Stmt, Guard); - end Sem_Guard; - - procedure Sem_Concurrent_Conditional_Signal_Assignment - (Stmt: Iir_Concurrent_Conditional_Signal_Assignment) - is - Cond_Wf : Iir_Conditional_Waveform; - Expr : Iir; - Wf_Chain : Iir_Waveform_Element; - Target_Type : Iir; - Target : Iir; - begin - Target := Get_Target (Stmt); - if Get_Kind (Target) /= Iir_Kind_Aggregate then - if not Sem_Signal_Assignment_Target_And_Option (Stmt, Null_Iir) then - return; - end if; - Target := Get_Target (Stmt); - Target_Type := Get_Type (Target); - else - Target_Type := Null_Iir; - end if; - - Cond_Wf := Get_Conditional_Waveform_Chain (Stmt); - while Cond_Wf /= Null_Iir loop - Wf_Chain := Get_Waveform_Chain (Cond_Wf); - Sem_Waveform_Chain (Stmt, Wf_Chain, Target_Type); - Sem_Check_Waveform_Chain (Stmt, Wf_Chain); - Expr := Get_Condition (Cond_Wf); - if Expr /= Null_Iir then - Expr := Sem_Condition (Expr); - if Expr /= Null_Iir then - Set_Condition (Cond_Wf, Expr); - end if; - end if; - Cond_Wf := Get_Chain (Cond_Wf); - end loop; - Sem_Guard (Stmt); - if Get_Kind (Target) = Iir_Kind_Aggregate then - if not Sem_Signal_Assignment_Target_And_Option (Stmt, Target_Type) - then - return; - end if; - end if; - end Sem_Concurrent_Conditional_Signal_Assignment; - - procedure Sem_Concurrent_Selected_Signal_Assignment (Stmt: Iir) - is - Expr: Iir; - Chain : Iir; - El: Iir; - Waveform_Type : Iir; - Target : Iir; - Assoc_El : Iir; - begin - Target := Get_Target (Stmt); - Chain := Get_Selected_Waveform_Chain (Stmt); - Waveform_Type := Null_Iir; - - if Get_Kind (Target) = Iir_Kind_Aggregate then - -- LRM 9.5 Concurrent Signal Assgnment Statements. - -- The process statement equivalent to a concurrent signal assignment - -- statement [...] is constructed as follows: [...] - -- - -- LRM 9.5.2 Selected Signa Assignment - -- The characteristics of the selected expression, the waveforms and - -- the choices in the selected assignment statement must be such that - -- the case statement in the equivalent statement is a legal - -- statement - - -- Find the first waveform that will appear in the equivalent - -- process statement, and extract type from it. - Assoc_El := Null_Iir; - El := Chain; - - while El /= Null_Iir loop - Assoc_El := Get_Associated_Expr (El); - exit when Assoc_El /= Null_Iir; - El := Get_Chain (El); - end loop; - if Assoc_El = Null_Iir then - Error_Msg_Sem - ("cannot determine type of the aggregate target", Target); - else - Sem_Waveform_Chain (Stmt, Assoc_El, Waveform_Type); - end if; - if Waveform_Type = Null_Iir then - -- Type of target still unknown. - -- Since the target is an aggregate, we won't be able to - -- semantize it. - -- Avoid a crash. - return; - end if; - end if; - if not Sem_Signal_Assignment_Target_And_Option (Stmt, Waveform_Type) then - return; - end if; - Waveform_Type := Get_Type (Get_Target (Stmt)); - - -- Sem on associated. - if Waveform_Type /= Null_Iir then - El := Chain; - while El /= Null_Iir loop - Sem_Waveform_Chain - (Stmt, Get_Associated_Chain (El), Waveform_Type); - Sem_Check_Waveform_Chain (Stmt, Get_Associated_Chain (El)); - El := Get_Chain (El); - end loop; - end if; - - -- The choices. - Expr := Sem_Case_Expression (Get_Expression (Stmt)); - if Expr = Null_Iir then - return; - end if; - Check_Read (Expr); - Set_Expression (Stmt, Expr); - Sem_Case_Choices (Expr, Chain, Get_Location (Stmt)); - Set_Selected_Waveform_Chain (Stmt, Chain); - - Sem_Guard (Stmt); - end Sem_Concurrent_Selected_Signal_Assignment; - - procedure Simple_Simultaneous_Statement (Stmt : Iir) is - Left, Right : Iir; - Res_Type : Iir; - begin - Left := Get_Simultaneous_Left (Stmt); - Right := Get_Simultaneous_Right (Stmt); - - Left := Sem_Expression_Ov (Left, Null_Iir); - Right := Sem_Expression_Ov (Right, Null_Iir); - - -- Give up in case of error - if Left = Null_Iir or else Right = Null_Iir then - return; - end if; - - Res_Type := Search_Compatible_Type (Get_Type (Left), Get_Type (Right)); - if Res_Type = Null_Iir then - Error_Msg_Sem ("types of left and right expressions are incompatible", - Stmt); - return; - end if; - - -- FIXME: check for nature type... - end Simple_Simultaneous_Statement; - - procedure Sem_Concurrent_Statement_Chain (Parent : Iir) - is - Is_Passive : constant Boolean := - Get_Kind (Parent) = Iir_Kind_Entity_Declaration; - El: Iir; - Prev_El : Iir; - Prev_Concurrent_Statement : Iir; - Prev_Psl_Default_Clock : Iir; - begin - Prev_Concurrent_Statement := Current_Concurrent_Statement; - Prev_Psl_Default_Clock := Current_Psl_Default_Clock; - - El := Get_Concurrent_Statement_Chain (Parent); - Prev_El := Null_Iir; - while El /= Null_Iir loop - Current_Concurrent_Statement := El; - - case Get_Kind (El) is - when Iir_Kind_Concurrent_Conditional_Signal_Assignment => - if Is_Passive then - Error_Msg_Sem ("signal assignment forbidden in entity", El); - end if; - Sem_Concurrent_Conditional_Signal_Assignment (El); - when Iir_Kind_Concurrent_Selected_Signal_Assignment => - if Is_Passive then - Error_Msg_Sem ("signal assignment forbidden in entity", El); - end if; - Sem_Concurrent_Selected_Signal_Assignment (El); - when Iir_Kind_Sensitized_Process_Statement => - Set_Passive_Flag (El, Is_Passive); - Sem_Sensitized_Process_Statement (El); - when Iir_Kind_Process_Statement => - Set_Passive_Flag (El, Is_Passive); - Sem_Process_Statement (El); - when Iir_Kind_Component_Instantiation_Statement => - Sem_Component_Instantiation_Statement (El, Is_Passive); - when Iir_Kind_Concurrent_Assertion_Statement => - -- FIXME: must check assertion expressions does not contain - -- non-passive subprograms ?? - Sem_Assertion_Statement (El); - when Iir_Kind_Block_Statement => - if Is_Passive then - Error_Msg_Sem ("block forbidden in entity", El); - end if; - Sem_Block_Statement (El); - when Iir_Kind_Generate_Statement => - if Is_Passive then - Error_Msg_Sem ("generate statement forbidden in entity", El); - end if; - Sem_Generate_Statement (El); - when Iir_Kind_Concurrent_Procedure_Call_Statement => - declare - Next_El : Iir; - N_Stmt : Iir; - begin - Next_El := Get_Chain (El); - N_Stmt := Sem_Concurrent_Procedure_Call_Statement - (El, Is_Passive); - if N_Stmt /= El then - -- Replace this node. - El := N_Stmt; - if Prev_El = Null_Iir then - Set_Concurrent_Statement_Chain (Parent, El); - else - Set_Chain (Prev_El, El); - end if; - Set_Chain (El, Next_El); - end if; - end; - when Iir_Kind_Psl_Declaration => - Sem_Psl.Sem_Psl_Declaration (El); - when Iir_Kind_Psl_Assert_Statement - | Iir_Kind_Psl_Cover_Statement => - Sem_Psl.Sem_Psl_Assert_Statement (El); - when Iir_Kind_Psl_Default_Clock => - Sem_Psl.Sem_Psl_Default_Clock (El); - when Iir_Kind_Simple_Simultaneous_Statement => - Simple_Simultaneous_Statement (El); - when others => - Error_Kind ("sem_concurrent_statement_chain", El); - end case; - Prev_El := El; - El := Get_Chain (El); - end loop; - - Current_Concurrent_Statement := Prev_Concurrent_Statement; - Current_Psl_Default_Clock := Prev_Psl_Default_Clock; - end Sem_Concurrent_Statement_Chain; - - -- Put labels in declarative region. - procedure Sem_Labels_Chain (Parent : Iir) - is - Stmt: Iir; - Label: Name_Id; - begin - Stmt := Get_Concurrent_Statement_Chain (Parent); - while Stmt /= Null_Iir loop - - case Get_Kind (Stmt) is - when Iir_Kind_Psl_Declaration => - -- Special case for in-lined PSL declarations. - null; - when others => - Label := Get_Label (Stmt); - - if Label /= Null_Identifier then - Sem_Scopes.Add_Name (Stmt); - Name_Visible (Stmt); - Xref_Decl (Stmt); - end if; - end case; - - -- INT-1991/issue report 27 - -- Generate statements represent declarative region and have - -- implicit declarative part. - if False - and then Flags.Vhdl_Std = Vhdl_87 - and then Get_Kind (Stmt) = Iir_Kind_Generate_Statement - then - Sem_Labels_Chain (Stmt); - end if; - - Stmt := Get_Chain (Stmt); - end loop; - end Sem_Labels_Chain; - - procedure Sem_Block (Blk: Iir; Sem_Decls : Boolean) - is - Implicit : Implicit_Signal_Declaration_Type; - begin - Push_Signals_Declarative_Part (Implicit, Blk); - - if Sem_Decls then - Sem_Labels_Chain (Blk); - Sem_Declaration_Chain (Blk); - end if; - - Sem_Concurrent_Statement_Chain (Blk); - - if Sem_Decls then - -- FIXME: do it only if there is conf. spec. in the declarative - -- part. - Sem_Specification_Chain (Blk, Blk); - Check_Full_Declaration (Blk, Blk); - end if; - - Pop_Signals_Declarative_Part (Implicit); - end Sem_Block; - - -- Add a driver for SIG. - -- STMT is used in case of error (it is the statement that creates the - -- driver). - -- Do nothing if: - -- The current statement list does not belong to a process, - -- SIG is a formal signal interface. - procedure Sem_Add_Driver (Sig : Iir; Stmt : Iir) - is - Sig_Object : Iir; - Sig_Object_Type : Iir; - begin - if Sig = Null_Iir then - return; - end if; - Sig_Object := Get_Object_Prefix (Sig); - Sig_Object_Type := Get_Type (Sig_Object); - - -- LRM 4.3.1.2 Signal Declaration - -- It is an error if, after the elaboration of a description, a - -- signal has multiple sources and it is not a resolved signal. - - -- Check for multiple driver for a unresolved signal declaration. - -- Do this only if the object is a non-composite signal declaration. - -- NOTE: THIS IS DISABLED, since the assignment may be within a - -- generate statement. - if False - and then Get_Kind (Sig_Object) = Iir_Kind_Signal_Declaration - and then Get_Kind (Sig_Object_Type) - not in Iir_Kinds_Composite_Type_Definition - and then not Get_Resolved_Flag (Sig_Object_Type) - then - if Get_Signal_Driver (Sig_Object) /= Null_Iir and then - Get_Signal_Driver (Sig_Object) /= Current_Concurrent_Statement - then - Error_Msg_Sem ("unresolved " & Disp_Node (Sig_Object) - & " has already a driver at " - & Disp_Location (Get_Signal_Driver (Sig_Object)), - Stmt); - else - Set_Signal_Driver (Sig_Object, Current_Concurrent_Statement); - end if; - end if; - - -- LRM 8.4.1 - -- If a given procedure is declared by a declarative item that is not - -- contained within a process statement, and if a signal assignment - -- statement appears in that procedure, then the target of the - -- assignment statement must be a formal parameter of the given - -- procedure or of a parent of that procedure, or an aggregate of such - -- formal parameters. - -- Similarly, if a given procedure is declared by a declarative item - -- that is not contained within a process statement and if a signal is - -- associated with an INOUT or OUT mode signal parameter in a - -- subprogram call within that procedure, then the signal so associated - -- must be a formal parameter of the given procedure or of a parent of - -- that procedure. - if Current_Concurrent_Statement = Null_Iir - or else (Get_Kind (Current_Concurrent_Statement) - not in Iir_Kinds_Process_Statement) - then - -- Not within a process statement. - if Current_Subprogram = Null_Iir then - -- not within a subprogram: concurrent statement. - return; - end if; - - -- Within a subprogram. - if Get_Kind (Sig_Object) = Iir_Kind_Signal_Declaration - or else (Get_Kind (Get_Parent (Sig_Object)) - /= Iir_Kind_Procedure_Declaration) - then - Error_Msg_Sem - (Disp_Node (Sig_Object) & " is not a formal parameter", Stmt); - end if; - end if; - end Sem_Add_Driver; -end Sem_Stmts; |