summaryrefslogtreecommitdiff
path: root/ortho/gcc/agcc-fe.adb
diff options
context:
space:
mode:
Diffstat (limited to 'ortho/gcc/agcc-fe.adb')
-rw-r--r--ortho/gcc/agcc-fe.adb776
1 files changed, 776 insertions, 0 deletions
diff --git a/ortho/gcc/agcc-fe.adb b/ortho/gcc/agcc-fe.adb
new file mode 100644
index 0000000..75ba795
--- /dev/null
+++ b/ortho/gcc/agcc-fe.adb
@@ -0,0 +1,776 @@
+-- Ortho implementation for GCC.
+-- 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 GCC; see the file COPYING. If not, write to the Free
+-- Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+-- 02111-1307, USA.
+with Ada.Unchecked_Deallocation;
+--with Agcc.Ggc; use Agcc.Ggc;
+with Agcc.Tm; use Agcc.Tm;
+with Agcc.Machmode; use Agcc.Machmode;
+with Agcc.Diagnostic;
+with Agcc.Input; use Agcc.Input;
+with Agcc.Options; use Agcc.Options;
+with Ortho_Gcc;
+with Ortho_Gcc_Front; use Ortho_Gcc_Front;
+
+package body Agcc.Fe is
+ File_Name : String_Acc;
+
+ Stdin_Filename : String_Acc := new String'("*stdin*" & Nul);
+
+ function Lang_Init_Options (Argc : Integer; Argv : C_String_Array)
+ return Integer
+ is
+ pragma Unreferenced (Argc);
+ pragma Unreferenced (Argv);
+ begin
+ return CL_vhdl;
+ end Lang_Init_Options;
+
+ function Lang_Handle_Option (Code : Opt_Code;
+ Arg : C_String;
+ Value : Integer)
+ return Integer
+ is
+ pragma Unreferenced (Value);
+ --type String_Acc_Array_Acc is access String_Acc_Array;
+
+ procedure Unchecked_Deallocation is new Ada.Unchecked_Deallocation
+ (Name => String_Acc, Object => String);
+ --procedure Unchecked_Deallocation is new Ada.Unchecked_Deallocation
+ -- (Name => String_Acc_Array_Acc, Object => String_Acc_Array);
+
+ --C_Opt : C_String := Argv (0);
+ --C_Arg : C_String;
+ --Opt : String := C_Opt (1 .. C_String_Len (C_Opt));
+ Res : Natural;
+ Opt : String_Acc;
+ Opt_Arg : String_Acc;
+ Len : Natural;
+ begin
+ if Arg /= C_String_Null then
+ Len := C_String_Len (Arg);
+ else
+ Len := 0;
+ end if;
+ Opt_Arg := null;
+ case Code is
+ when OPT_U_std_U =>
+ Opt := new String'("--std=" & Arg (1 .. Len));
+ when OPT_U_compile_standard =>
+ Opt := new String'("--compile-standard");
+ when OPT_U_bootstrap =>
+ Opt := new String'("--bootstrap");
+ when OPT_U_work_U =>
+ Opt := new String'("--work=" & Arg (1 .. Len));
+ when OPT_U_workdir_U =>
+ Opt := new String'("--workdir=" & Arg (1 .. Len));
+ when OPT_UP =>
+ Opt := new String'("-P" & Arg (1 .. Len));
+ when OPT_U_elab =>
+ Opt := new String'("--elab");
+ Opt_Arg := new String'(Arg (1 .. Len));
+ when OPT_U_anaelab =>
+ Opt := new String'("--anaelab");
+ Opt_Arg := new String'(Arg (1 .. Len));
+ when OPT_l =>
+ Opt := new String'("-l");
+ Opt_Arg := new String'(Arg (1 .. Len));
+ when OPT_c =>
+ Opt := new String'("-c");
+ Opt_Arg := new String'(Arg (1 .. Len));
+ when OPT_U_ghdl =>
+ Opt := new String'(Arg (1 .. Len));
+ when OPT_U_warn_U =>
+ Opt := new String'("--warn-" & Arg (1 .. Len));
+ when OPT_U_expect_failure =>
+ Opt := new String'("--expect-failure");
+ when OPT_U_no_vital_checks =>
+ Opt := new String'("--no-vital-checks");
+ when OPT_U_vital_checks =>
+ Opt := new String'("--vital-checks");
+ when OPT_fexplicit =>
+ Opt := new String'("-fexplicit");
+ when OPT_v =>
+ Opt := new String'("-v");
+ when others =>
+ return 0;
+ end case;
+ Res := Ortho_Gcc_Front.Decode_Option (Opt, Opt_Arg);
+ Unchecked_Deallocation (Opt);
+ Unchecked_Deallocation (Opt_Arg);
+ return Res;
+ end Lang_Handle_Option;
+
+ function Lang_Post_Options (Filename : C_String_Acc) return C_Bool
+ is
+ Filename_Len : Natural;
+ begin
+ if Filename.all = C_String_Null then
+ File_Name := null;
+ Filename.all := To_C_String (Stdin_Filename);
+ else
+ Filename_Len := C_String_Len (Filename.all);
+ File_Name := new String'(Filename.all (1 .. Filename_Len));
+ end if;
+
+ -- Run the back-end.
+ return C_False;
+ end Lang_Post_Options;
+
+
+ procedure Lang_Parse_File (Debug : C_Bool)
+ is
+ pragma Unreferenced (Debug);
+ begin
+ if not Ortho_Gcc_Front.Parse (File_Name) then
+ Agcc.Diagnostic.Set_Errorcount (1);
+ end if;
+ end Lang_Parse_File;
+
+ function Lang_Get_Alias_Set (T : Tree) return HOST_WIDE_INT
+ is
+ pragma Unreferenced (T);
+ begin
+ return -1;
+ end Lang_Get_Alias_Set;
+
+ --function Lang_Safe_From_P (Target : Rtx; Exp : Tree) return Boolean;
+
+ function Mark_Addressable (Exp : Tree) return C_Bool
+ is
+ N : Tree;
+ Code : Tree_Code;
+ begin
+ N := Exp;
+ loop
+ Code := Get_TREE_CODE (N);
+ case Code is
+ when VAR_DECL
+ | CONST_DECL
+ | PARM_DECL
+ | RESULT_DECL =>
+ Put_Var_Into_Stack (N, C_True);
+ Set_TREE_ADDRESSABLE (N, C_True);
+ return C_True;
+
+ when COMPONENT_REF
+ | ARRAY_REF =>
+ N := Get_TREE_OPERAND (N, 0);
+
+ when FUNCTION_DECL
+ | CONSTRUCTOR =>
+ Set_TREE_ADDRESSABLE (N, C_True);
+ return C_True;
+
+ when INDIRECT_REF =>
+ return C_True;
+
+ when others =>
+ raise Program_Error;
+ end case;
+ end loop;
+ end Mark_Addressable;
+
+ procedure Insert_Default_Attributes (Func : Tree)
+ is
+ pragma Unreferenced (Func);
+ begin
+ null;
+ end Insert_Default_Attributes;
+
+ -- These functions and variables deal with binding contours.
+
+ -- For each binding contour we allocate a binding_level structure which
+ -- records the entities defined or declared in that contour.
+ -- Contours include:
+ --
+ -- the global one
+ -- one for each subprogram definition
+ -- one for each compound statement (declare block)
+ --
+ -- Binding contours are used to create GCC tree BLOCK nodes.
+
+ -- BE CAREFUL: this structure is also declared in agcc-bindings.c
+ type Binding_Level;
+ type Binding_Level_Acc is access Binding_Level;
+ type Binding_Level is record
+ -- A chain of ..._DECL nodes for all variables, constants, functions,
+ -- parameters and type declarations. These ..._DECL nodes are chained
+ -- through the TREE_CHAIN field. Note that these ..._DECL nodes are
+ -- stored in the reverse of the order supplied to be compatible with
+ -- the back-end.
+ Names : Tree;
+
+ -- For each level (except the global one), a chain of BLOCK nodes for
+ -- all the levels that were entered and exited one level down from this
+ -- one.
+ Blocks : Tree;
+
+ -- The back end may need, for its own internal processing, to create a
+ -- BLOCK node. This field is set aside for this purpose. If this field
+ -- is non-null when the level is popped, i.e. when poplevel is invoked,
+ -- we will use such block instead of creating a new one from the
+ -- 'names' field, that is the ..._DECL nodes accumulated so far.
+ -- Typically the routine 'pushlevel' will be called before setting this
+ -- field, so that if the front-end had inserted ..._DECL nodes in the
+ -- current block they will not be lost.
+ Block_Created_By_Back_End : Tree;
+
+ -- The binding level containing this one (the enclosing binding level).
+ Level_Chain : Binding_Level_Acc;
+ end record;
+ pragma Convention (C, Binding_Level_Acc);
+ pragma Convention (C, Binding_Level);
+
+ -- The binding level currently in effect.
+ Current_Binding_Level : Binding_Level_Acc := null;
+ pragma Export (C, Current_Binding_Level);
+
+ -- The outermost binding level. This binding level is created when the
+ -- compiler is started and it will exist through the entire compilation.
+ Global_Binding_Level : Binding_Level_Acc;
+
+ -- Chain of unused binding levels, since they are never deallocated.
+ Old_Binding_Level : Binding_Level_Acc := null;
+ pragma Export (C, Old_Binding_Level);
+
+ function Alloc_Binding_Level return Binding_Level_Acc;
+ pragma Import (C, Alloc_Binding_Level);
+
+ -- Binding level structures are initialized by copying this one.
+ Clear_Binding_Level : constant Binding_Level :=
+ (Names => NULL_TREE,
+ Blocks => NULL_TREE,
+ Block_Created_By_Back_End => NULL_TREE,
+ Level_Chain => null);
+
+ -- Return non-zero if we are currently in the global binding level.
+ function Global_Bindings_P return Integer is
+ begin
+ if Current_Binding_Level = Global_Binding_Level then
+ return 1;
+ else
+ return 0;
+ end if;
+ end Global_Bindings_P;
+
+ -- Return the list of declarations in the current level. Note that this
+ -- list is in reverse order (it has to be so for back-end compatibility).
+ function Getdecls return Tree is
+ begin
+ return Current_Binding_Level.Names;
+ end Getdecls;
+
+ -- Nonzero if the current level needs to have a BLOCK made.
+-- function Kept_Level_P return Boolean is
+-- begin
+-- return Current_Binding_Level.Names /= NULL_TREE;
+-- end Kept_Level_P;
+
+ -- Enter a new binding level. The input parameter is ignored, but has to
+ -- be specified for back-end compatibility.
+ procedure Pushlevel (Inside : C_Bool)
+ is
+ pragma Unreferenced (Inside);
+ Newlevel : Binding_Level_Acc;
+
+ begin
+ if Old_Binding_Level /= null then
+ Newlevel := Old_Binding_Level;
+ Old_Binding_Level := Old_Binding_Level.Level_Chain;
+ else
+ Newlevel := Alloc_Binding_Level;
+ end if;
+ Newlevel.all := Clear_Binding_Level;
+
+ -- Add this level to the front of the chain (stack) of levels that are
+ -- active.
+ Newlevel.Level_Chain := Current_Binding_Level;
+ Current_Binding_Level := Newlevel;
+ end Pushlevel;
+
+ -- Exit a binding level.
+ -- Pop the level off, and restore the state of the identifier-decl mappings
+ -- that were in effect when this level was entered.
+ --
+ -- If KEEP is nonzero, this level had explicit declarations, so
+ -- and create a "block" (a BLOCK node) for the level
+ -- to record its declarations and subblocks for symbol table output.
+ --
+ -- If FUNCTIONBODY is nonzero, this level is the body of a function,
+ -- so create a block as if KEEP were set and also clear out all
+ -- label names.
+ --
+ -- If REVERSE is nonzero, reverse the order of decls before putting
+ -- them into the BLOCK.
+ function Exported_Poplevel
+ (Keep : C_Bool; Revers : C_Bool; Functionbody : C_Bool)
+ return Tree
+ is
+ -- Points to a BLOCK tree node. This is the BLOCK node construted for
+ -- the binding level that we are about to exit and which is returned
+ -- by this routine.
+ Block_Node : Tree := NULL_TREE;
+
+ Decl_Chain : Tree;
+ Subblock_Chain : Tree;
+ Subblock_Node : Tree;
+ Block_Created_By_Back_End : Tree;
+
+ N : Tree;
+ Tmp : Binding_Level_Acc;
+ begin
+ Decl_Chain := Current_Binding_Level.Names;
+ Block_Created_By_Back_End :=
+ Current_Binding_Level.Block_Created_By_Back_End;
+ Subblock_Chain := Current_Binding_Level.Blocks;
+
+ -- Pop the current level, and save it on the chain of old binding
+ -- levels.
+ Tmp := Current_Binding_Level;
+ Current_Binding_Level := Tmp.Level_Chain;
+ Tmp.Level_Chain := Old_Binding_Level;
+ Old_Binding_Level := Tmp;
+
+ -- Reverse the list of XXXX_DECL nodes if desired. Note that
+ -- the ..._DECL nodes chained through the `names' field of
+ -- current_binding_level are in reverse order except for PARM_DECL node,
+ -- which are explicitely stored in the right order.
+ if Revers /= C_False then
+ Decl_Chain := Nreverse (Decl_Chain);
+ end if;
+
+ if Block_Created_By_Back_End /= NULL_TREE then
+ Block_Node := Block_Created_By_Back_End;
+
+ -- Check if we are about to discard some information that was
+ -- gathered by the front-end. Nameley check if the back-end created
+ -- a new block without calling pushlevel first. To understand why
+ -- things are lost just look at the next case (i.e. no block
+ -- created by back-end. */
+ if (Keep /= C_False or Functionbody /= C_False)
+ and then (Decl_Chain /= NULL_TREE or Subblock_Chain /= NULL_TREE)
+ then
+ raise Program_Error;
+ end if;
+ elsif Keep /= C_False or Functionbody /= C_False then
+ -- If there were any declarations in the current binding level, or if
+ -- this binding level is a function body, or if there are any nested
+ -- blocks then create a BLOCK node to record them for the life of
+ -- this function.
+ if Keep /= C_False then
+ N := Decl_Chain;
+ else
+ N := NULL_TREE;
+ end if;
+ Block_Node := Build_Block
+ (N, NULL_TREE, Subblock_Chain, NULL_TREE, NULL_TREE);
+ end if;
+
+ -- Record the BLOCK node just built as the subblock its enclosing scope.
+ Subblock_Node := Subblock_Chain;
+ while Subblock_Node /= NULL_TREE loop
+ Set_BLOCK_SUPERCONTEXT (Subblock_Node, Block_Node);
+ Subblock_Node := Get_TREE_CHAIN (Subblock_Node);
+ end loop;
+
+ -- Clear out the meanings of the local variables of this level.
+ Subblock_Node := Decl_Chain;
+ while Subblock_Node /= NULL_TREE loop
+
+ if Get_DECL_NAME (Subblock_Node) /= NULL_TREE then
+ -- If the identifier was used or addressed via a local
+ -- extern decl, don't forget that fact.
+ if Get_DECL_EXTERNAL (Subblock_Node) /= C_False then
+ if Get_TREE_USED (Subblock_Node) /= C_False then
+ Set_TREE_USED (Get_DECL_NAME (Subblock_Node), C_True);
+ end if;
+ if Get_TREE_ADDRESSABLE (Subblock_Node) /= C_False then
+ Set_TREE_ADDRESSABLE
+ (Get_DECL_ASSEMBLER_NAME (Subblock_Node), C_True);
+ end if;
+ end if;
+ end if;
+ Subblock_Node := Get_TREE_CHAIN (Subblock_Node);
+ end loop;
+
+ if Functionbody /= C_False then
+ -- This is the top level block of a function. The ..._DECL chain
+ -- stored in BLOCK_VARS are the function's parameters (PARM_DECL
+ -- nodes). Don't leave them in the BLOCK because they are found
+ -- in the FUNCTION_DECL instead.
+ Set_DECL_INITIAL (Current_Function_Decl, Block_Node);
+ Set_BLOCK_VARS (Block_Node, NULL_TREE);
+ elsif Block_Node /= NULL_TREE then
+ if Block_Created_By_Back_End = NULL_TREE then
+ Current_Binding_Level.Blocks
+ := Chainon (Current_Binding_Level.Blocks, Block_Node);
+ end if;
+ elsif Subblock_Chain /= NULL_TREE then
+ -- If we did not make a block for the level just exited, any blocks
+ -- made for inner levels (since they cannot be recorded as subblocks
+ -- in that level) must be carried forward so they will later become
+ -- subblocks of something else.
+ Current_Binding_Level.Blocks
+ := Chainon (Current_Binding_Level.Blocks, Subblock_Chain);
+ end if;
+
+ if Block_Node /= NULL_TREE then
+ Set_TREE_USED (Block_Node, C_True);
+ end if;
+
+ return Block_Node;
+ end Exported_Poplevel;
+
+ -- Insert BLOCK at the end of the list of subblocks of the
+ -- current binding level. This is used when a BIND_EXPR is expanded,
+ -- to handle the BLOCK node inside the BIND_EXPR.
+ procedure Insert_Block (Block : Tree) is
+ begin
+ Set_TREE_USED (Block, C_True);
+ Current_Binding_Level.Blocks
+ := Chainon (Current_Binding_Level.Blocks, Block);
+ end Insert_Block;
+
+ -- Set the BLOCK node for the innermost scope (the one we are
+ -- currently in).
+ procedure Set_Block (Block : Tree) is
+ begin
+ Current_Binding_Level.Block_Created_By_Back_End := Block;
+ end Set_Block;
+
+ -- Records a ..._DECL node DECL as belonging to the current lexical scope.
+ -- Returns the ..._DECL node.
+ function Exported_Pushdecl (Decl : Tree) return Tree
+ is
+ begin
+ -- External objects aren't nested, other objects may be.
+ if Get_DECL_EXTERNAL (Decl) /= C_False then
+ Set_DECL_CONTEXT (Decl, NULL_TREE);
+ else
+ Set_DECL_CONTEXT (Decl, Current_Function_Decl);
+ end if;
+
+ -- Put the declaration on the list. The list of declarations is in
+ -- reverse order. The list will be reversed later if necessary. This
+ -- needs to be this way for compatibility with the back-end.
+ Set_TREE_CHAIN (Decl, Current_Binding_Level.Names);
+ Current_Binding_Level.Names := Decl;
+
+ -- For the declaration of a type, set its name if it is not already set.
+ if Get_TREE_CODE (Decl) = TYPE_DECL
+ and then Get_TYPE_NAME (Get_TREE_TYPE (Decl)) = NULL_TREE
+ then
+ Set_TYPE_NAME (Get_TREE_TYPE (Decl), Decl); -- DECL_NAME (decl);
+ end if;
+
+ return Decl;
+ end Exported_Pushdecl;
+
+ -- This variable keeps a table for types for each precision so that we only
+ -- allocate each of them once. Signed and unsigned types are kept separate.
+ type Signed_And_Unsigned_Types_Array_Type is
+ array (Natural range 0 .. MAX_BITS_PER_WORD, C_Boolean) of Tree;
+ Signed_And_Unsigned_Types : Signed_And_Unsigned_Types_Array_Type :=
+ (others => (others => NULL_TREE));
+ pragma Export (C, Signed_And_Unsigned_Types);
+
+ -- Return an integer type with the number of bits of precision given by
+ -- PRECISION. UNSIGNEDP is nonzero if the type is unsigned; otherwise
+ -- it is a signed type.
+ function Type_For_Size (Precision : Natural; Unsignedp : C_Bool)
+ return Tree
+ is
+ T : Tree;
+ begin
+ if Precision <= MAX_BITS_PER_WORD
+ and then Signed_And_Unsigned_Types (Precision, Unsignedp) /= NULL_TREE
+ then
+ return Signed_And_Unsigned_Types (Precision, Unsignedp);
+ end if;
+
+ if Unsignedp /= C_False then
+ T := Make_Unsigned_Type (Precision);
+ else
+ T := Make_Signed_Type (Precision);
+ end if;
+ if Precision <= MAX_BITS_PER_WORD then
+ Signed_And_Unsigned_Types (Precision, Unsignedp) := T;
+ end if;
+ return T;
+ end Type_For_Size;
+
+ -- Return a data type that has machine mode MODE. UNSIGNEDP selects
+ -- an unsigned type; otherwise a signed type is returned.
+ function Type_For_Mode (Mode : Machine_Mode; Unsignedp : C_Bool)
+ return Tree
+ is
+ begin
+ return Type_For_Size (GET_MODE_BITSIZE (Mode), Unsignedp);
+ end Type_For_Mode;
+
+ -- Return the unsigned version of a TYPE_NODE, a scalar type.
+ function Unsigned_Type (Type_Node : Tree) return Tree
+ is
+ begin
+ return Type_For_Size (Get_TYPE_PRECISION (Type_Node), C_True);
+ end Unsigned_Type;
+
+ -- Return the signed version of a TYPE_NODE, a scalar type.
+ function Signed_Type (Type_Node : Tree) return Tree
+ is
+ begin
+ return Type_For_Size (Get_TYPE_PRECISION (Type_Node), C_False);
+ end Signed_Type;
+
+ -- Return a type the same as TYPE except unsigned or signed according to
+ -- UNSIGNEDP.
+ function Signed_Or_Unsigned_Type (Unsignedp : C_Bool; Atype : Tree)
+ return Tree
+ is
+ begin
+ if INTEGRAL_TYPE_P (Atype) = C_False
+ or else Get_TREE_UNSIGNED (Atype) = Unsignedp
+ then
+ return Atype;
+ else
+ return Type_For_Size (Get_TYPE_PRECISION (Atype), Unsignedp);
+ end if;
+ end Signed_Or_Unsigned_Type;
+
+
+ --procedure Init_Type_For_Size;
+ --pragma Import (C, Init_Type_For_Size);
+
+ Int_Str : constant String := "int" & Nul;
+ Char_Str : constant String := "char" & Nul;
+
+ Builtin_Alloca_Str : constant String := "__builtin_alloca" & Nul;
+
+ function Lang_Init return C_Bool
+ is
+ --File : String renames Filename (1 .. Filename_Len);
+ Ptr_Ftype_Sizetype : Tree;
+ Alloca_Function : Tree;
+ begin
+ --Error_Mark_Node := Make_Node (ERROR_MARK);
+ --Set_TREE_TYPE (Error_Mark_Node, Error_Mark_Node);
+
+ --Initialize_Sizetypes;
+
+ -- The structure `tree_identifier' is the GCC tree data structure that
+ -- holds IDENTIFIER_NODE nodes. We need to call `set_identifier_size'
+ -- to tell GCC that we have not added any language specific fields to
+ -- IDENTIFIER_NODE nodes.
+ --Set_Identifier_Size (Tree_Identifier_Size);
+ Input_Location.Line := 0;
+
+ -- Make the binding_level structure for global names.
+ Pushlevel (C_False);
+ Global_Binding_Level := Current_Binding_Level;
+
+ Build_Common_Tree_Nodes (C_False);
+ Pushdecl (Build_Decl (TYPE_DECL, Get_Identifier (Int_Str'Address),
+ Integer_Type_Node));
+ Pushdecl (Build_Decl (TYPE_DECL, Get_Identifier (Char_Str'Address),
+ Char_Type_Node));
+ Set_Sizetype (Unsigned_Type_Node);
+ Build_Common_Tree_Nodes_2 (C_False);
+
+ --Init_Type_For_Size;
+
+ -- Create alloc builtin.
+ Ptr_Ftype_Sizetype := Build_Function_Type
+ (Ptr_Type_Node,
+ Tree_Cons (NULL_TREE, Get_TYPE_DOMAIN (Sizetype), NULL_TREE));
+ Alloca_Function := Builtin_Function
+ (Builtin_Alloca_Str'Address, Ptr_Ftype_Sizetype,
+ BUILT_IN_ALLOCA, BUILT_IN_NORMAL, System.Null_Address);
+ Ortho_Gcc.Alloca_Function_Ptr := Build1
+ (ADDR_EXPR, Build_Pointer_Type (Ptr_Ftype_Sizetype), Alloca_Function);
+-- Ggc_Add_Tree_Root (Ortho_Gcc.Alloca_Function_Ptr'Address, 1);
+
+ Ortho_Gcc.Init;
+
+ -- Continue.
+ return C_True;
+ end Lang_Init;
+
+ procedure Lang_Finish is
+ begin
+ null;
+ end Lang_Finish;
+
+ -- Return a definition for a builtin function named NAME and whose data
+ -- type is TYPE. TYPE should be a function type with argument types.
+ -- FUNCTION_CODE tells later passes how to compile calls to this function.
+ -- See tree.h for its possible values.
+ --
+ -- If LIBRARY_NAME is nonzero, use that for DECL_ASSEMBLER_NAME,
+ -- the name to be called if we can't opencode the function.
+ function Builtin_Function
+ (Name: System.Address;
+ Ftype : Tree;
+ Function_Code : Built_In_Function;
+ Class : Built_In_Class;
+ Library_Name : System.Address)
+ return Tree
+ is
+ use System;
+ Decl : Tree;
+ begin
+ Decl := Build_Decl (FUNCTION_DECL, Get_Identifier (Name), Ftype);
+ Set_DECL_EXTERNAL (Decl, C_True);
+ Set_TREE_PUBLIC (Decl, C_True);
+ if Library_Name /= Null_Address then
+ Set_DECL_ASSEMBLER_NAME (Decl, Get_Identifier (Library_Name));
+ end if;
+ Make_Decl_Rtl (Decl, NULL_Chars, C_True);
+ Pushdecl (Decl);
+ Set_DECL_BUILT_IN_CLASS (Decl, Class);
+ Set_DECL_FUNCTION_CODE (Decl, Function_Code);
+ return Decl;
+ end Builtin_Function;
+
+ procedure Set_Yydebug (Flag : C_Bool)
+ is
+ pragma Unreferenced (Flag);
+ begin
+ null;
+ end Set_Yydebug;
+
+ procedure Print_Lang_Decl (File : FILEs; Node : Tree; Indent : natural)
+ is
+ pragma Unreferenced (File);
+ pragma Unreferenced (Node);
+ pragma Unreferenced (Indent);
+ begin
+ null;
+ end Print_Lang_Decl;
+
+ procedure Print_Lang_Type (File : FILEs; Node : Tree; Indent : Natural)
+ is
+ pragma Unreferenced (File);
+ pragma Unreferenced (Node);
+ pragma Unreferenced (Indent);
+ begin
+ null;
+ end Print_Lang_Type;
+
+ procedure Print_Lang_Identifier
+ (File : FILEs; Node : Tree; Indent : Natural)
+ is
+ pragma Unreferenced (File);
+ pragma Unreferenced (Node);
+ pragma Unreferenced (Indent);
+ begin
+ null;
+ end Print_Lang_Identifier;
+
+ procedure Lang_Print_Xnode (File : FILEs; Node : Tree; Indent : Natural)
+ is
+ pragma Unreferenced (File);
+ pragma Unreferenced (Node);
+ pragma Unreferenced (Indent);
+ begin
+ -- There is no X nodes.
+ raise Program_Error;
+ end Lang_Print_Xnode;
+
+ procedure Print_Lang_Statistics is
+ begin
+ null;
+ end Print_Lang_Statistics;
+
+ procedure Copy_Lang_Decl (Node : Tree)
+ is
+ pragma Unreferenced (Node);
+ begin
+ null;
+ end Copy_Lang_Decl;
+
+ function Truthvalue_Conversion (Expr : Tree) return Tree
+ is
+ Expr_Type : Tree;
+ type Conv_Array is array (Boolean) of Tree;
+ Conv : Conv_Array;
+ begin
+ Expr_Type := Get_TREE_TYPE (Expr);
+ if Get_TREE_CODE (Expr_Type) /= BOOLEAN_TYPE then
+ Conv := (True => Integer_One_Node,
+ False => Integer_Zero_Node);
+ else
+ Conv := (False => Get_TYPE_MIN_VALUE (Expr_Type),
+ True => Get_TYPE_MAX_VALUE (Expr_Type));
+ end if;
+
+ -- From java/decl.c
+ -- It is simpler and generates better code to have only TRUTH_*_EXPR
+ -- or comparison expressions as truth values at this level.
+
+ case Get_TREE_CODE (Expr) is
+ when EQ_EXPR
+ | NE_EXPR
+ | LE_EXPR
+ | GE_EXPR
+ | LT_EXPR
+ | GT_EXPR
+ | TRUTH_ANDIF_EXPR
+ | TRUTH_ORIF_EXPR
+ | TRUTH_AND_EXPR
+ | TRUTH_OR_EXPR
+ | ERROR_MARK =>
+ return Expr;
+
+ when INTEGER_CST =>
+ if Integer_Zerop (Expr) = C_False then
+ -- EXPR is not 0, so EXPR is interpreted as TRUE.
+ return Conv (True);
+ else
+ return Conv (False);
+ end if;
+
+ when REAL_CST =>
+ if Real_Zerop (Expr) = C_False then
+ return Conv (True);
+ else
+ return Conv (False);
+ end if;
+
+ when others =>
+ raise Program_Error;
+ end case;
+ end Truthvalue_Conversion;
+
+ procedure Incomplete_Type_Error (Value : Tree; Atype : Tree)
+ is
+ pragma Unreferenced (Value);
+ pragma Unreferenced (Atype);
+ begin
+ -- Can never happen.
+ raise Program_Error;
+ end Incomplete_Type_Error;
+
+ function Maybe_Build_Cleanup (Decl : Tree) return Tree
+ is
+ pragma Unreferenced (Decl);
+ begin
+ return NULL_TREE;
+ end Maybe_Build_Cleanup;
+
+ Language_Name : constant String := "GNU vhdl" & Nul;
+ pragma Export (C, Language_Name);
+end Agcc.Fe;