aboutsummaryrefslogtreecommitdiffstats
path: root/include/package-defaults.mk
Commit message (Expand)AuthorAgeFilesLines
* add special handling for the adm5120 target, which uses subtargets for differ...Imre Kaloz2009-08-031-1/+5
* revert 17050 this was not the right way to fix thisFlorian Fainelli2009-08-011-3/+3
* use board names instead of arch in packagesImre Kaloz2009-07-311-1/+1
* move the global ipv6 option to the very bottom of the options passed to confi...Florian Fainelli2009-07-301-3/+3
* globally define IPv6 support or not in OpenWrt, just like for largefiles, ipv...Florian Fainelli2009-07-251-1/+3
* Fix configure script path when not at the root of $(PKG_BUILD_DIR), thanks Da...Florian Fainelli2009-07-021-1/+1
* add dist and distcheck target (to create new source balls)Ralph Hempel2009-05-311-1/+9
* remove 2 old interfering variables, probably missed from [15299]Nicolas Thill2009-04-221-2/+0
* move pkg config stuff to per-target exports to prevent interference with host...Felix Fietkau2009-04-201-3/+0
* replace a few unnecessary $(shell) callsFelix Fietkau2009-03-031-1/+1
* initialize the url field for packagesFelix Fietkau2009-02-231-0/+1
* eliminate redundancy by creating the quilt_used stampfile in the right placeFelix Fietkau2009-02-221-1/+0
* add support for build-only packages which do not appear in menuconfigFelix Fietkau2009-01-131-0/+1
* make config.{guess,sub} writable before attempting to overwrite them (many pa...Felix Fietkau2009-01-061-1/+1
* add default Build/Install template, which is activated by setting PKG_INSTALL=1Felix Fietkau2008-09-031-0/+11
* replace config.guess and config.sub properly, even if they are in a subdirectoryFelix Fietkau2008-08-051-1/+4
* export PKG_CONFIG_PATH and PKG_CONFIG_LIBDIR by default (#3376)Felix Fietkau2008-07-311-2/+5
* add a configurable prefix for ./configureFelix Fietkau2007-12-271-8/+9
* add STAGING_DIR_HOST to PKG_CONFIG_PATHFelix Fietkau2007-12-231-1/+1
* DESCRIPTION:= is obselete, so complain if it is used and use TITLE if no desc...John Crispin2007-10-141-1/+0
* move a stampfile to make it easier to override the patch templateFelix Fietkau2007-09-291-0/+1
* fix typo (thanks to jonasg[1] on irc)Nicolas Thill2007-09-051-1/+1
* move TARGET_* flags from ./include/package-default.mk to ./rules.mk, remove E...Nicolas Thill2007-09-031-9/+4
* dynamically enable/disable kernel config options for kmod packages based on b...Felix Fietkau2007-07-181-0/+1
* use newer config.guess and config.sub for packages then the shipped onesImre Kaloz2007-06-081-0/+1
* Add quilt integration for packagesFelix Fietkau2007-06-031-3/+2
* split CONFIGURE_PATH into CONFIGURE_PATH and CONFIGURE_CMD for better handlin...Felix Fietkau2007-03-241-3/+4
* fix CONFIGURE_PATH and add MAKE_PATHFelix Fietkau2007-03-241-2/+4
* use recursive variable expansion for CONFIGURE_*, MAKE_* variables in the pac...Felix Fietkau2007-03-241-7/+7
* split package.mk and clean up build system code (based on patch by mbm), make...Felix Fietkau2007-03-151-0/+106
13' href='#n413'>413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262
--  Iir to ortho translator.
--  Copyright (C) 2002 - 2014 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 GCC; see the file COPYING.  If not, write to the Free
--  Software Foundation, 59 Temple Place - Suite 330, Boston, MA
--  02111-1307, USA.

with Name_Table;
with Std_Names;
with Std_Package; use Std_Package;
with Errorout; use Errorout;
with Sem_Inst;
with Nodes_Meta;
with Iirs_Utils; use Iirs_Utils;
with Trans.Chap3;
with Trans.Chap4;
with Trans.Chap5;
with Trans.Chap6;
with Trans.Chap8;
with Trans.Rtis;
with Trans_Decls; use Trans_Decls;
with Translation; use Translation;

package body Trans.Chap2 is
   use Trans.Subprgs;
   use Trans.Helpers;

   procedure Elab_Package (Spec : Iir_Package_Declaration);

   type Name_String_Xlat_Array is array (Name_Id range <>) of
     String (1 .. 4);
   Operator_String_Xlat : constant
     Name_String_Xlat_Array (Std_Names.Name_Id_Operators) :=
     (Std_Names.Name_Op_Equality => "OPEq",
      Std_Names.Name_Op_Inequality => "OPNe",
      Std_Names.Name_Op_Less => "OPLt",
      Std_Names.Name_Op_Less_Equal => "OPLe",
      Std_Names.Name_Op_Greater => "OPGt",
      Std_Names.Name_Op_Greater_Equal => "OPGe",
      Std_Names.Name_Op_Plus => "OPPl",
      Std_Names.Name_Op_Minus => "OPMi",
      Std_Names.Name_Op_Mul => "OPMu",
      Std_Names.Name_Op_Div => "OPDi",
      Std_Names.Name_Op_Exp => "OPEx",
      Std_Names.Name_Op_Concatenation => "OPCc",
      Std_Names.Name_Op_Condition => "OPCd",
      Std_Names.Name_Op_Match_Equality => "OPQe",
      Std_Names.Name_Op_Match_Inequality => "OPQi",
      Std_Names.Name_Op_Match_Less => "OPQL",
      Std_Names.Name_Op_Match_Less_Equal => "OPQl",
      Std_Names.Name_Op_Match_Greater => "OPQG",
      Std_Names.Name_Op_Match_Greater_Equal => "OPQg");

   --  Set the identifier prefix with the subprogram identifier and
   --  overload number if any.
   procedure Push_Subprg_Identifier (Spec : Iir; Mark : out Id_Mark_Type)
   is
      Id : Name_Id;
   begin
      --  FIXME: name_shift_operators, name_logical_operators,
      --   name_word_operators, name_mod, name_rem
      Id := Get_Identifier (Spec);
      if Id in Std_Names.Name_Id_Operators then
         Push_Identifier_Prefix
           (Mark, Operator_String_Xlat (Id), Get_Overload_Number (Spec));
      else
         Push_Identifier_Prefix (Mark, Id, Get_Overload_Number (Spec));
      end if;
   end Push_Subprg_Identifier;

   procedure Translate_Subprogram_Interfaces (Spec : Iir)
   is
      Inter : Iir;
      Mark  : Id_Mark_Type;
   begin
      --  Set the identifier prefix with the subprogram identifier and
      --  overload number if any.
      Push_Subprg_Identifier (Spec, Mark);

      --  Translate interface types.
      Inter := Get_Interface_Declaration_Chain (Spec);
      while Inter /= Null_Iir loop
         Chap3.Translate_Object_Subtype (Inter);
         Inter := Get_Chain (Inter);
      end loop;
      Pop_Identifier_Prefix (Mark);
   end Translate_Subprogram_Interfaces;

   procedure Elab_Subprogram_Interfaces (Spec : Iir)
   is
      Inter : Iir;
   begin
      --  Translate interface types.
      Inter := Get_Interface_Declaration_Chain (Spec);
      while Inter /= Null_Iir loop
         Chap3.Elab_Object_Subtype (Get_Type (Inter));
         Inter := Get_Chain (Inter);
      end loop;
   end Elab_Subprogram_Interfaces;


   --  Return the type of a subprogram interface.
   --  Return O_Tnode_Null if the parameter is passed through the
   --  interface record.
   function Translate_Interface_Type (Inter : Iir) return O_Tnode
   is
      Mode  : Object_Kind_Type;
      Tinfo : constant Type_Info_Acc := Get_Info (Get_Type (Inter));
   begin
      case Get_Kind (Inter) is
         when Iir_Kind_Interface_Constant_Declaration
            | Iir_Kind_Interface_Variable_Declaration
            | Iir_Kind_Interface_File_Declaration =>
            Mode := Mode_Value;
         when Iir_Kind_Interface_Signal_Declaration =>
            Mode := Mode_Signal;
         when others =>
            Error_Kind ("translate_interface_type", Inter);
      end case;
      case Tinfo.Type_Mode is
         when Type_Mode_Unknown =>
            raise Internal_Error;
         when Type_Mode_By_Value =>
            return Tinfo.Ortho_Type (Mode);
         when Type_Mode_By_Copy
            | Type_Mode_By_Ref =>
            return Tinfo.Ortho_Ptr_Type (Mode);
      end case;
   end Translate_Interface_Type;

   procedure Translate_Subprogram_Declaration (Spec : Iir)
   is
      Info              : constant Subprg_Info_Acc := Get_Info (Spec);
      Is_Func           : constant Boolean :=
        Get_Kind (Spec) = Iir_Kind_Function_Declaration;
      Inter             : Iir;
      Inter_Type        : Iir;
      Arg_Info          : Ortho_Info_Acc;
      Tinfo             : Type_Info_Acc;
      Interface_List    : O_Inter_List;
      Has_Result_Record : Boolean;
      El_List           : O_Element_List;
      Mark              : Id_Mark_Type;
      Rtype             : Iir;
      Id                : O_Ident;
      Storage           : O_Storage;
      Foreign           : Foreign_Info_Type := Foreign_Bad;
   begin
      --  Set the identifier prefix with the subprogram identifier and
      --  overload number if any.
      Push_Subprg_Identifier (Spec, Mark);

      if Get_Foreign_Flag (Spec) then
         --  Special handling for foreign subprograms.
         Foreign := Translate_Foreign_Id (Spec);
         case Foreign.Kind is
            when Foreign_Unknown =>
               Id := Create_Identifier;
            when Foreign_Intrinsic =>
               Id := Create_Identifier;
            when Foreign_Vhpidirect =>
               Id := Get_Identifier
                 (Name_Table.Name_Buffer (Foreign.Subprg_First
                  .. Foreign.Subprg_Last));
         end case;
         Storage := O_Storage_External;
      else
         Id := Create_Identifier;
         Storage := Global_Storage;
      end if;

      if Is_Func then
         --  If the result of a function is a composite type for ortho,
         --  the result is allocated by the caller and an access to it is
         --  given to the function.
         Rtype := Get_Return_Type (Spec);
         Info.Use_Stack2 := False;
         Tinfo := Get_Info (Rtype);

         if Is_Composite (Tinfo) then
            Start_Procedure_Decl (Interface_List, Id, Storage);
            New_Interface_Decl
              (Interface_List, Info.Res_Interface,
               Get_Identifier ("RESULT"),
               Tinfo.Ortho_Ptr_Type (Mode_Value));
            --  Furthermore, if the result type is unconstrained, the
            --  function will allocate it on a secondary stack.
            if not Is_Fully_Constrained_Type (Rtype) then
               Info.Use_Stack2 := True;
            end if;
         else
            --  Normal function.
            Start_Function_Decl
              (Interface_List, Id, Storage, Tinfo.Ortho_Type (Mode_Value));
            Info.Res_Interface := O_Dnode_Null;
         end if;
      else
         --  Create info for each interface of the procedure.
         --  For parameters passed via copy and that needs a copy-out,
         --  gather them in a record.  An access to the record is then
         --  passed to the procedure.
         Has_Result_Record := False;
         Inter := Get_Interface_Declaration_Chain (Spec);
         while Inter /= Null_Iir loop
            Arg_Info := Add_Info (Inter, Kind_Interface);
            Inter_Type := Get_Type (Inter);
            Tinfo := Get_Info (Inter_Type);
            if Get_Kind (Inter) = Iir_Kind_Interface_Variable_Declaration
              and then Get_Mode (Inter) in Iir_Out_Modes
              and then Tinfo.Type_Mode not in Type_Mode_By_Ref
              and then Tinfo.Type_Mode /= Type_Mode_File
            then
               --  This interface is done via the result record.
               --  Note: file passed through variables are vhdl87 files,
               --        which are initialized at elaboration and thus
               --        behave like an IN parameter.
               if not Has_Result_Record then
                  --  Create the record.
                  Start_Record_Type (El_List);
                  Has_Result_Record := True;
               end if;
               --  Add a field to the record.
               New_Record_Field (El_List, Arg_Info.Interface_Field,
                                 Create_Identifier_Without_Prefix (Inter),
                                 Tinfo.Ortho_Type (Mode_Value));
            else
               Arg_Info.Interface_Field := O_Fnode_Null;
            end if;
            Inter := Get_Chain (Inter);
         end loop;
         if Has_Result_Record then
            --  Declare the record type and an access to the record.
            Finish_Record_Type (El_List, Info.Res_Record_Type);
            New_Type_Decl (Create_Identifier ("RESTYPE"),
                           Info.Res_Record_Type);
            Info.Res_Record_Ptr := New_Access_Type (Info.Res_Record_Type);
            New_Type_Decl (Create_Identifier ("RESPTR"),
                           Info.Res_Record_Ptr);
         else
            Info.Res_Interface := O_Dnode_Null;
         end if;

         Start_Procedure_Decl (Interface_List, Id, Storage);

         if Has_Result_Record then
            --  Add the record parameter.
            New_Interface_Decl (Interface_List, Info.Res_Interface,
                                Get_Identifier ("RESULT"),
                                Info.Res_Record_Ptr);
         end if;
      end if;

      --  Instance parameter if any.
      if not Get_Foreign_Flag (Spec) then
         Subprgs.Create_Subprg_Instance (Interface_List, Spec);
      end if;

      --  Translate interfaces.
      Inter := Get_Interface_Declaration_Chain (Spec);
      while Inter /= Null_Iir loop
         if Is_Func then
            --  Create the info.
            Arg_Info := Add_Info (Inter, Kind_Interface);
            Arg_Info.Interface_Field := O_Fnode_Null;
         else
            --  The info was already created (just above)
            Arg_Info := Get_Info (Inter);
         end if;

         if Arg_Info.Interface_Field = O_Fnode_Null then
            --  Not via the RESULT parameter.
            Arg_Info.Interface_Type := Translate_Interface_Type (Inter);
            New_Interface_Decl
              (Interface_List, Arg_Info.Interface_Node,
               Create_Identifier_Without_Prefix (Inter),
               Arg_Info.Interface_Type);
         end if;
         Inter := Get_Chain (Inter);
      end loop;
      Finish_Subprogram_Decl (Interface_List, Info.Ortho_Func);

      --  Call the hook for foreign subprograms.
      if Get_Foreign_Flag (Spec) and then Foreign_Hook /= null then
         Foreign_Hook.all (Spec, Foreign, Info.Ortho_Func);
      end if;

      Save_Local_Identifier (Info.Subprg_Local_Id);
      Pop_Identifier_Prefix (Mark);
   end Translate_Subprogram_Declaration;

   --  Return TRUE iff subprogram specification SPEC is translated in an
   --  ortho function.
   function Is_Subprogram_Ortho_Function (Spec : Iir) return Boolean
   is
   begin
      if Get_Kind (Spec) = Iir_Kind_Procedure_Declaration then
         return False;
      end if;
      if Get_Info (Spec).Res_Interface /= O_Dnode_Null then
         return False;
      end if;
      return True;
   end Is_Subprogram_Ortho_Function;

   --  Return TRUE iif SUBPRG_BODY declares explicitely or implicitely
   --  (or even implicitely by translation) a subprogram.
   function Has_Nested_Subprograms (Subprg_Body : Iir) return Boolean
   is
      Decl  : Iir;
      Atype : Iir;
   begin
      Decl := Get_Declaration_Chain (Subprg_Body);
      while Decl /= Null_Iir loop
         case Get_Kind (Decl) is
            when Iir_Kind_Function_Declaration
               | Iir_Kind_Procedure_Declaration =>
               return True;
            when Iir_Kind_Function_Body
               | Iir_Kind_Procedure_Body =>
               --  The declaration preceed the body.
               raise Internal_Error;
            when Iir_Kind_Type_Declaration
               | Iir_Kind_Anonymous_Type_Declaration =>
               Atype := Get_Type_Definition (Decl);
               case Iir_Kinds_Type_And_Subtype_Definition
                 (Get_Kind (Atype)) is
                  when Iir_Kinds_Scalar_Type_Definition =>
                     null;
                  when Iir_Kind_Access_Type_Definition
                     | Iir_Kind_Access_Subtype_Definition =>
                     null;
                  when Iir_Kind_File_Type_Definition =>
                     return True;
                  when Iir_Kind_Protected_Type_Declaration =>
                     raise Internal_Error;
                  when Iir_Kinds_Composite_Type_Definition =>
                     --  At least for "=".
                     return True;
                  when Iir_Kind_Incomplete_Type_Definition =>
                     null;
               end case;
            when others =>
               null;
         end case;
         Decl := Get_Chain (Decl);
      end loop;
      return False;
   end Has_Nested_Subprograms;

   procedure Translate_Subprogram_Body (Subprg : Iir)
   is
      Spec : constant Iir := Get_Subprogram_Specification (Subprg);
      Info : constant Ortho_Info_Acc := Get_Info (Spec);

      Old_Subprogram : Iir;
      Mark           : Id_Mark_Type;
      Final          : Boolean;
      Is_Ortho_Func  : Boolean;

      --  Set for a public method.  In this case, the lock must be acquired
      --  and retained.
      Is_Prot : Boolean := False;

      --  True if the body has local (nested) subprograms.
      Has_Nested : Boolean;

      Frame_Ptr_Type : O_Tnode;
      Upframe_Field  : O_Fnode;

      Frame     : O_Dnode;
      Frame_Ptr : O_Dnode;

      Has_Return : Boolean;

      Prev_Subprg_Instances : Subprgs.Subprg_Instance_Stack;
   begin
      --  Do not translate body for foreign subprograms.
      if Get_Foreign_Flag (Spec) then
         return;
      end if;

      --  Check if there are nested subprograms to unnest.  In that case,
      --  a frame record is created, which is less efficient than the
      --  use of local variables.
      if Flag_Unnest_Subprograms then
         Has_Nested := Has_Nested_Subprograms (Subprg);
      else
         Has_Nested := False;
      end if;

      --  Set the identifier prefix with the subprogram identifier and
      --  overload number if any.
      Push_Subprg_Identifier (Spec, Mark);
      Restore_Local_Identifier (Info.Subprg_Local_Id);

      if Has_Nested then
         --  Unnest subprograms.
         --  Create an instance for the local declarations.
         Push_Instance_Factory (Info.Subprg_Frame_Scope'Access);
         Add_Subprg_Instance_Field (Upframe_Field);

         if Info.Res_Record_Ptr /= O_Tnode_Null then
            Info.Res_Record_Var :=
              Create_Var (Create_Var_Identifier ("RESULT"),
                          Info.Res_Record_Ptr);
         end if;

         --  Create fields for parameters.
         --  FIXME: do it only if they are referenced in nested
         --  subprograms.
         declare
            Inter      : Iir;
            Inter_Info : Inter_Info_Acc;
         begin
            Inter := Get_Interface_Declaration_Chain (Spec);
            while Inter /= Null_Iir loop
               Inter_Info := Get_Info (Inter);
               if Inter_Info.Interface_Node /= O_Dnode_Null then
                  Inter_Info.Interface_Field :=
                    Add_Instance_Factory_Field
                      (Create_Identifier_Without_Prefix (Inter),
                       Inter_Info.Interface_Type);
               end if;
               Inter := Get_Chain (Inter);
            end loop;
         end;

         Chap4.Translate_Declaration_Chain (Subprg);
         Pop_Instance_Factory (Info.Subprg_Frame_Scope'Access);

         New_Type_Decl (Create_Identifier ("_FRAMETYPE"),
                        Get_Scope_Type (Info.Subprg_Frame_Scope));
         Declare_Scope_Acc
           (Info.Subprg_Frame_Scope,
            Create_Identifier ("_FRAMEPTR"), Frame_Ptr_Type);

         Rtis.Generate_Subprogram_Body (Subprg);

         --  Local frame
         Subprgs.Push_Subprg_Instance
           (Info.Subprg_Frame_Scope'Access, Frame_Ptr_Type,
            Wki_Upframe, Prev_Subprg_Instances);
         --  Link to previous frame
         Subprgs.Start_Prev_Subprg_Instance_Use_Via_Field
           (Prev_Subprg_Instances, Upframe_Field);

         Chap4.Translate_Declaration_Chain_Subprograms (Subprg);

         --  Link to previous frame
         Subprgs.Finish_Prev_Subprg_Instance_Use_Via_Field
           (Prev_Subprg_Instances, Upframe_Field);
         --  Local frame
         Subprgs.Pop_Subprg_Instance (Wki_Upframe, Prev_Subprg_Instances);
      end if;

      --  Create the body

      Start_Subprogram_Body (Info.Ortho_Func);

      Start_Subprg_Instance_Use (Spec);

      --  Variables will be created on the stack.
      Push_Local_Factory;

      --  Code has access to local (and outer) variables.
      --  FIXME: this is not necessary if Has_Nested is set
      Subprgs.Clear_Subprg_Instance (Prev_Subprg_Instances);

      --  There is a local scope for temporaries.
      Open_Local_Temp;

      if not Has_Nested then
         Chap4.Translate_Declaration_Chain (Subprg);
         Rtis.Generate_Subprogram_Body (Subprg);
         Chap4.Translate_Declaration_Chain_Subprograms (Subprg);
      else
         New_Var_Decl (Frame, Wki_Frame, O_Storage_Local,
                       Get_Scope_Type (Info.Subprg_Frame_Scope));

         New_Var_Decl (Frame_Ptr, Get_Identifier ("FRAMEPTR"),
                       O_Storage_Local, Frame_Ptr_Type);
         New_Assign_Stmt (New_Obj (Frame_Ptr),
                          New_Address (New_Obj (Frame), Frame_Ptr_Type));

         --  FIXME: use direct reference (ie Frame instead of Frame_Ptr)
         Set_Scope_Via_Param_Ptr (Info.Subprg_Frame_Scope, Frame_Ptr);

         --  Set UPFRAME.
         Subprgs.Set_Subprg_Instance_Field
           (Frame_Ptr, Upframe_Field, Info.Subprg_Instance);

         if Info.Res_Record_Type /= O_Tnode_Null then
            --  Initialize the RESULT field
            New_Assign_Stmt (Get_Var (Info.Res_Record_Var),
                             New_Obj_Value (Info.Res_Interface));
            --  Do not reference the RESULT field in the subprogram body,
            --  directly reference the RESULT parameter.
            --  FIXME: has a flag (see below for parameters).
            Info.Res_Record_Var := Null_Var;
         end if;

         --  Copy parameters to FRAME.
         declare
            Inter      : Iir;
            Inter_Info : Inter_Info_Acc;
         begin
            Inter := Get_Interface_Declaration_Chain (Spec);
            while Inter /= Null_Iir loop
               Inter_Info := Get_Info (Inter);
               if Inter_Info.Interface_Node /= O_Dnode_Null then
                  New_Assign_Stmt
                    (New_Selected_Element (New_Obj (Frame),
                     Inter_Info.Interface_Field),
                     New_Obj_Value (Inter_Info.Interface_Node));

                  --  Forget the reference to the field in FRAME, so that
                  --  this subprogram will directly reference the parameter
                  --  (and not its copy in the FRAME).
                  Inter_Info.Interface_Field := O_Fnode_Null;
               end if;
               Inter := Get_Chain (Inter);
            end loop;
         end;
      end if;

      --  Init out parameters passed by value/copy.
      declare
         Inter      : Iir;
         Inter_Type : Iir;
         Type_Info  : Type_Info_Acc;
      begin
         Inter := Get_Interface_Declaration_Chain (Spec);
         while Inter /= Null_Iir loop
            if Get_Kind (Inter) = Iir_Kind_Interface_Variable_Declaration
              and then Get_Mode (Inter) = Iir_Out_Mode
            then
               Inter_Type := Get_Type (Inter);
               Type_Info := Get_Info (Inter_Type);
               if (Type_Info.Type_Mode in Type_Mode_By_Value
                   or Type_Info.Type_Mode in Type_Mode_By_Copy)
                 and then Type_Info.Type_Mode /= Type_Mode_File
               then
                  Chap4.Init_Object
                    (Chap6.Translate_Name (Inter), Inter_Type);
               end if;
            end if;
            Inter := Get_Chain (Inter);
         end loop;
      end;

      Chap4.Elab_Declaration_Chain (Subprg, Final);

      --  If finalization is required, create a dummy loop around the
      --  body and convert returns into exit out of this loop.
      --  If the subprogram is a function, also create a variable for the
      --  result.
      Is_Prot := Is_Subprogram_Method (Spec);
      if Final or Is_Prot then
         if Is_Prot then
            --  Lock the object.
            Chap3.Call_Ghdl_Protected_Procedure (Get_Method_Type (Spec),
                                                 Ghdl_Protected_Enter);
         end if;
         Is_Ortho_Func := Is_Subprogram_Ortho_Function (Spec);
         if Is_Ortho_Func then
            New_Var_Decl
              (Info.Subprg_Result, Get_Identifier ("RESULT"),
               O_Storage_Local,
               Get_Ortho_Type (Get_Return_Type (Spec), Mode_Value));
         end if;
         Start_Loop_Stmt (Info.Subprg_Exit);
      end if;

      Old_Subprogram := Current_Subprogram;
      Current_Subprogram := Spec;
      Has_Return := Chap8.Translate_Statements_Chain_Has_Return
        (Get_Sequential_Statement_Chain (Subprg));
      Current_Subprogram := Old_Subprogram;

      if Final or Is_Prot then
         --  Create a barrier to catch missing return statement.
         if Get_Kind (Spec) = Iir_Kind_Procedure_Declaration then
            New_Exit_Stmt (Info.Subprg_Exit);
         else
            if not Has_Return then
               --  Missing return
               Chap6.Gen_Program_Error
                 (Subprg, Chap6.Prg_Err_Missing_Return);
            end if;
         end if;
         Finish_Loop_Stmt (Info.Subprg_Exit);
         Chap4.Final_Declaration_Chain (Subprg, False);

         if Is_Prot then
            --  Unlock the object.
            Chap3.Call_Ghdl_Protected_Procedure (Get_Method_Type (Spec),
                                                 Ghdl_Protected_Leave);
         end if;
         if Is_Ortho_Func then
            New_Return_Stmt (New_Obj_Value (Info.Subprg_Result));
         end if;
      else
         if Get_Kind (Spec) = Iir_Kind_Function_Declaration
           and then not Has_Return
         then
            --  Missing return
            Chap6.Gen_Program_Error
              (Subprg, Chap6.Prg_Err_Missing_Return);
         end if;
      end if;

      if Has_Nested then
         Clear_Scope (Info.Subprg_Frame_Scope);
      end if;

      Subprgs.Pop_Subprg_Instance (O_Ident_Nul, Prev_Subprg_Instances);
      Close_Local_Temp;
      Pop_Local_Factory;

      Finish_Subprg_Instance_Use (Spec);

      Finish_Subprogram_Body;

      Pop_Identifier_Prefix (Mark);
   end Translate_Subprogram_Body;

   procedure Translate_Package_Declaration (Decl : Iir_Package_Declaration)
   is
      Header               : constant Iir := Get_Package_Header (Decl);
      Info                 : Ortho_Info_Acc;
      Interface_List       : O_Inter_List;
      Prev_Subprg_Instance : Subprgs.Subprg_Instance_Stack;
   begin
      Info := Add_Info (Decl, Kind_Package);

      --  Translate declarations.
      if Is_Uninstantiated_Package (Decl) then
         --  Create an instance for the spec.
         Push_Instance_Factory (Info.Package_Spec_Scope'Access);
         Chap4.Translate_Generic_Chain (Header);
         Chap4.Translate_Declaration_Chain (Decl);
         Info.Package_Elab_Var := Create_Var
           (Create_Var_Identifier ("ELABORATED"), Ghdl_Bool_Type);
         Pop_Instance_Factory (Info.Package_Spec_Scope'Access);

         --  Name the spec instance and create a pointer.
         New_Type_Decl (Create_Identifier ("SPECINSTTYPE"),
                        Get_Scope_Type (Info.Package_Spec_Scope));
         Declare_Scope_Acc (Info.Package_Spec_Scope,
                            Create_Identifier ("SPECINSTPTR"),
                            Info.Package_Spec_Ptr_Type);

         --  Create an instance and its pointer for the body.
         Chap2.Declare_Inst_Type_And_Ptr
           (Info.Package_Body_Scope'Access, Info.Package_Body_Ptr_Type);

         --  Each subprogram has a body instance argument.
         Subprgs.Push_Subprg_Instance
           (Info.Package_Body_Scope'Access, Info.Package_Body_Ptr_Type,
            Wki_Instance, Prev_Subprg_Instance);
      else
         Chap4.Translate_Declaration_Chain (Decl);
         Info.Package_Elab_Var := Create_Var
           (Create_Var_Identifier ("ELABORATED"), Ghdl_Bool_Type);
      end if;

      --  Translate subprograms declarations.
      Chap4.Translate_Declaration_Chain_Subprograms (Decl);

      --  Declare elaborator for the body.
      Start_Procedure_Decl
        (Interface_List, Create_Identifier ("ELAB_BODY"), Global_Storage);
      Subprgs.Add_Subprg_Instance_Interfaces
        (Interface_List, Info.Package_Elab_Body_Instance);
      Finish_Subprogram_Decl
        (Interface_List, Info.Package_Elab_Body_Subprg);

      if Is_Uninstantiated_Package (Decl) then
         Subprgs.Pop_Subprg_Instance (Wki_Instance, Prev_Subprg_Instance);

         --  The spec elaborator has a spec instance argument.
         Subprgs.Push_Subprg_Instance
           (Info.Package_Spec_Scope'Access, Info.Package_Spec_Ptr_Type,
            Wki_Instance, Prev_Subprg_Instance);
      end if;

      Start_Procedure_Decl
        (Interface_List, Create_Identifier ("ELAB_SPEC"), Global_Storage);
      Subprgs.Add_Subprg_Instance_Interfaces
        (Interface_List, Info.Package_Elab_Spec_Instance);
      Finish_Subprogram_Decl
        (Interface_List, Info.Package_Elab_Spec_Subprg);

      if Flag_Rti then
         --  Generate RTI.
         Rtis.Generate_Unit (Decl);
      end if;

      if Global_Storage = O_Storage_Public then
         --  Create elaboration procedure for the spec
         Elab_Package (Decl);
      end if;

      if Is_Uninstantiated_Package (Decl) then
         Subprgs.Pop_Subprg_Instance (Wki_Instance, Prev_Subprg_Instance);
      end if;
      Save_Local_Identifier (Info.Package_Local_Id);
   end Translate_Package_Declaration;

   procedure Translate_Package_Body (Decl : Iir_Package_Body)
   is
      Spec : constant Iir_Package_Declaration := Get_Package (Decl);
      Info : constant Ortho_Info_Acc := Get_Info (Spec);
      Prev_Subprg_Instance : Subprgs.Subprg_Instance_Stack;
   begin
      --  Translate declarations.
      if Is_Uninstantiated_Package (Spec) then
         Push_Instance_Factory (Info.Package_Body_Scope'Access);
         Info.Package_Spec_Field := Add_Instance_Factory_Field
           (Get_Identifier ("SPEC"),
            Get_Scope_Type (Info.Package_Spec_Scope));

         Chap4.Translate_Declaration_Chain (Decl);

         Pop_Instance_Factory (Info.Package_Body_Scope'Access);

         if Global_Storage = O_Storage_External then
            return;
         end if;
      else
         --  May be called during elaboration to generate RTI.
         if Global_Storage = O_Storage_External then
            return;
         end if;

         Restore_Local_Identifier (Get_Info (Spec).Package_Local_Id);

         Chap4.Translate_Declaration_Chain (Decl);
      end if;

      if Flag_Rti then
         Rtis.Generate_Unit (Decl);
      end if;

      if Is_Uninstantiated_Package (Spec) then
         Subprgs.Push_Subprg_Instance
           (Info.Package_Body_Scope'Access, Info.Package_Body_Ptr_Type,
            Wki_Instance, Prev_Subprg_Instance);
         Set_Scope_Via_Field (Info.Package_Spec_Scope,
                              Info.Package_Spec_Field,
                              Info.Package_Body_Scope'Access);
      end if;

      Chap4.Translate_Declaration_Chain_Subprograms (Decl);

      if Is_Uninstantiated_Package (Spec) then
         Clear_Scope (Info.Package_Spec_Scope);
         Subprgs.Pop_Subprg_Instance (Wki_Instance, Prev_Subprg_Instance);
      end if;

      Elab_Package_Body (Spec, Decl);
   end Translate_Package_Body;

   procedure Elab_Package (Spec : Iir_Package_Declaration)
   is
      Info   : constant Ortho_Info_Acc := Get_Info (Spec);
      Final  : Boolean;
      Constr : O_Assoc_List;