On Friday, May 11, 2012 4:49:07 AM UTC+1, Patrick wrote:
> What is the situation with Ada? I was hoping to target various M68K related architectures, ARM and AVR.
As linked to a number of times, my tamp repo on github (above) has some code that will build for an arm board and can be run on it, doesn't do anything though :D
With Ada, you can pass a number of compilation units to the compiler and it will build them, some of these units can be what is the equivalent of a "main." What GNAT does with this is as follows, gnatbind is called to generate a new file b~<your entry procedure name>.adb, this file contains procedures for calling the elaboration code (to set up arrays and other data), then calls your entry point and on exit calls an exit procedure.
An example is best, so given the following entry point:
procedure test is
a : string(1 .. 5) := "hello";
begin
null;
end test;
and compiled with:
$ gnatmake -c test.adb
gcc-4.6 -c test.adb
$ gnatmake -b test.adb
gnatbind -x test.ali
you are left with the following b~
test.ad[sb]:
pragma Ada_95;
with System;
package ada_main is
pragma Warnings (Off);
gnat_argc : Integer;
gnat_argv : System.Address;
gnat_envp : System.Address;
pragma Import (C, gnat_argc);
pragma Import (C, gnat_argv);
pragma Import (C, gnat_envp);
gnat_exit_status : Integer;
pragma Import (C, gnat_exit_status);
GNAT_Version : constant String :=
"GNAT Version: 4.6" & ASCII.NUL;
pragma Export (C, GNAT_Version, "__gnat_version");
Ada_Main_Program_Name : constant String := "_ada_test" & ASCII.NUL;
pragma Export (C, Ada_Main_Program_Name, "__gnat_ada_main_program_name");
procedure adafinal;
pragma Export (C, adafinal, "adafinal");
procedure adainit;
pragma Export (C, adainit, "adainit");
procedure Break_Start;
pragma Import (C, Break_Start, "__gnat_break_start");
function main
(argc : Integer;
argv : System.Address;
envp : System.Address)
return Integer;
pragma Export (C, main, "main");
type Version_32 is mod 2 ** 32;
u00001 : constant Version_32 := 16#2951576a#;
pragma Export (C, u00001, "testB");
u00002 : constant Version_32 := 16#ba46b2cd#;
pragma Export (C, u00002, "system__standard_libraryB");
u00003 : constant Version_32 := 16#1e2e640d#;
pragma Export (C, u00003, "system__standard_libraryS");
u00004 : constant Version_32 := 16#23e1f70b#;
pragma Export (C, u00004, "systemS");
u00005 : constant Version_32 := 16#0936cab5#;
pragma Export (C, u00005, "system__memoryB");
u00006 : constant Version_32 := 16#e96a4b1e#;
pragma Export (C, u00006, "system__memoryS");
u00007 : constant Version_32 := 16#3ffc8e18#;
pragma Export (C, u00007, "adaS");
u00008 : constant Version_32 := 16#9229643d#;
pragma Export (C, u00008, "ada__exceptionsB");
u00009 : constant Version_32 := 16#e3df9d67#;
pragma Export (C, u00009, "ada__exceptionsS");
u00010 : constant Version_32 := 16#95643e9a#;
pragma Export (C, u00010, "ada__exceptions__last_chance_handlerB");
u00011 : constant Version_32 := 16#03cf4fc2#;
pragma Export (C, u00011, "ada__exceptions__last_chance_handlerS");
u00012 : constant Version_32 := 16#30ec78bc#;
pragma Export (C, u00012, "system__soft_linksB");
u00013 : constant Version_32 := 16#e2ebe502#;
pragma Export (C, u00013, "system__soft_linksS");
u00014 : constant Version_32 := 16#0d2b82ae#;
pragma Export (C, u00014, "system__parametersB");
u00015 : constant Version_32 := 16#bfbc74f1#;
pragma Export (C, u00015, "system__parametersS");
u00016 : constant Version_32 := 16#72905399#;
pragma Export (C, u00016, "system__secondary_stackB");
u00017 : constant Version_32 := 16#378fd0a5#;
pragma Export (C, u00017, "system__secondary_stackS");
u00018 : constant Version_32 := 16#ace32e1e#;
pragma Export (C, u00018, "system__storage_elementsB");
u00019 : constant Version_32 := 16#d92c8a93#;
pragma Export (C, u00019, "system__storage_elementsS");
u00020 : constant Version_32 := 16#4f750b3b#;
pragma Export (C, u00020, "system__stack_checkingB");
u00021 : constant Version_32 := 16#80434b27#;
pragma Export (C, u00021, "system__stack_checkingS");
u00022 : constant Version_32 := 16#a7343537#;
pragma Export (C, u00022, "system__exception_tableB");
u00023 : constant Version_32 := 16#8120f83b#;
pragma Export (C, u00023, "system__exception_tableS");
u00024 : constant Version_32 := 16#ff3fa16b#;
pragma Export (C, u00024, "system__htableB");
u00025 : constant Version_32 := 16#cc3e5bd4#;
pragma Export (C, u00025, "system__htableS");
u00026 : constant Version_32 := 16#8b7dad61#;
pragma Export (C, u00026, "system__string_hashB");
u00027 : constant Version_32 := 16#057d2f9f#;
pragma Export (C, u00027, "system__string_hashS");
u00028 : constant Version_32 := 16#6a8a6a74#;
pragma Export (C, u00028, "system__exceptionsB");
u00029 : constant Version_32 := 16#86f01d0a#;
pragma Export (C, u00029, "system__exceptionsS");
u00030 : constant Version_32 := 16#b012ff50#;
pragma Export (C, u00030, "system__img_intB");
u00031 : constant Version_32 := 16#213a17c9#;
pragma Export (C, u00031, "system__img_intS");
u00032 : constant Version_32 := 16#dc8e33ed#;
pragma Export (C, u00032, "system__tracebackB");
u00033 : constant Version_32 := 16#4266237e#;
pragma Export (C, u00033, "system__tracebackS");
u00034 : constant Version_32 := 16#4900ab7d#;
pragma Export (C, u00034, "system__unsigned_typesS");
u00035 : constant Version_32 := 16#907d882f#;
pragma Export (C, u00035, "system__wch_conB");
u00036 : constant Version_32 := 16#9c0ad936#;
pragma Export (C, u00036, "system__wch_conS");
u00037 : constant Version_32 := 16#22fed88a#;
pragma Export (C, u00037, "system__wch_stwB");
u00038 : constant Version_32 := 16#b11bf537#;
pragma Export (C, u00038, "system__wch_stwS");
u00039 : constant Version_32 := 16#5d4d477e#;
pragma Export (C, u00039, "system__wch_cnvB");
u00040 : constant Version_32 := 16#82f45fe0#;
pragma Export (C, u00040, "system__wch_cnvS");
u00041 : constant Version_32 := 16#f77d8799#;
pragma Export (C, u00041, "interfacesS");
u00042 : constant Version_32 := 16#75729fba#;
pragma Export (C, u00042, "system__wch_jisB");
u00043 : constant Version_32 := 16#d686c4f4#;
pragma Export (C, u00043, "system__wch_jisS");
u00044 : constant Version_32 := 16#ada34a87#;
pragma Export (C, u00044, "system__traceback_entriesB");
u00045 : constant Version_32 := 16#71c0194a#;
pragma Export (C, u00045, "system__traceback_entriesS");
u00046 : constant Version_32 := 16#13cbc5a8#;
pragma Export (C, u00046, "system__crtlS");
-- BEGIN ELABORATION ORDER
-- ada%s
-- interfaces%s
-- system%s
-- system.htable%s
-- system.img_int%s
-- system.img_int%b
-- system.parameters%s
-- system.parameters%b
-- system.crtl%s
-- system.standard_library%s
-- system.exceptions%s
-- system.exceptions%b
-- system.storage_elements%s
-- system.storage_elements%b
-- system.stack_checking%s
-- system.stack_checking%b
-- system.string_hash%s
-- system.string_hash%b
-- system.htable%b
-- system.traceback_entries%s
-- system.traceback_entries%b
-- ada.exceptions%s
-- system.soft_links%s
-- system.unsigned_types%s
-- system.wch_con%s
-- system.wch_con%b
-- system.wch_cnv%s
-- system.wch_jis%s
-- system.wch_jis%b
-- system.wch_cnv%b
-- system.wch_stw%s
-- system.wch_stw%b
-- ada.exceptions.last_chance_handler%s
-- ada.exceptions.last_chance_handler%b
-- system.exception_table%s
-- system.exception_table%b
-- system.memory%s
-- system.memory%b
-- system.standard_library%b
-- system.secondary_stack%s
-- system.soft_links%b
-- system.secondary_stack%b
-- system.traceback%s
-- ada.exceptions%b
-- system.traceback%b
-- test%b
-- END ELABORATION ORDER
end ada_main;
pragma Ada_95;
pragma Source_File_Name (ada_main, Spec_File_Name => "b~test.ads");
pragma Source_File_Name (ada_main, Body_File_Name => "b~test.adb");
package body ada_main is
pragma Warnings (Off);
procedure Do_Finalize;
pragma Import (C, Do_Finalize, "system__standard_library__adafinal");
Local_Priority_Specific_Dispatching : constant String := "";
Local_Interrupt_States : constant String := "";
procedure adainit is
E13 : Boolean; pragma Import (Ada, E13, "system__soft_links_E");
E23 : Boolean; pragma Import (Ada, E23, "system__exception_table_E");
E17 : Boolean; pragma Import (Ada, E17, "system__secondary_stack_E");
Main_Priority : Integer;
pragma Import (C, Main_Priority, "__gl_main_priority");
Time_Slice_Value : Integer;
pragma Import (C, Time_Slice_Value, "__gl_time_slice_val");
WC_Encoding : Character;
pragma Import (C, WC_Encoding, "__gl_wc_encoding");
Locking_Policy : Character;
pragma Import (C, Locking_Policy, "__gl_locking_policy");
Queuing_Policy : Character;
pragma Import (C, Queuing_Policy, "__gl_queuing_policy");
Task_Dispatching_Policy : Character;
pragma Import (C, Task_Dispatching_Policy, "__gl_task_dispatching_policy");
Priority_Specific_Dispatching : System.Address;
pragma Import (C, Priority_Specific_Dispatching, "__gl_priority_specific_dispatching");
Num_Specific_Dispatching : Integer;
pragma Import (C, Num_Specific_Dispatching, "__gl_num_specific_dispatching");
Main_CPU : Integer;
pragma Import (C, Main_CPU, "__gl_main_cpu");
Interrupt_States : System.Address;
pragma Import (C, Interrupt_States, "__gl_interrupt_states");
Num_Interrupt_States : Integer;
pragma Import (C, Num_Interrupt_States, "__gl_num_interrupt_states");
Unreserve_All_Interrupts : Integer;
pragma Import (C, Unreserve_All_Interrupts, "__gl_unreserve_all_interrupts");
Zero_Cost_Exceptions : Integer;
pragma Import (C, Zero_Cost_Exceptions, "__gl_zero_cost_exceptions");
Detect_Blocking : Integer;
pragma Import (C, Detect_Blocking, "__gl_detect_blocking");
Default_Stack_Size : Integer;
pragma Import (C, Default_Stack_Size, "__gl_default_stack_size");
Leap_Seconds_Support : Integer;
pragma Import (C, Leap_Seconds_Support, "__gl_leap_seconds_support");
procedure Install_Handler;
pragma Import (C, Install_Handler, "__gnat_install_handler");
Handler_Installed : Integer;
pragma Import (C, Handler_Installed, "__gnat_handler_installed");
begin
Main_Priority := -1;
Time_Slice_Value := -1;
WC_Encoding := 'b';
Locking_Policy := ' ';
Queuing_Policy := ' ';
Task_Dispatching_Policy := ' ';
Priority_Specific_Dispatching :=
Local_Priority_Specific_Dispatching'Address;
Num_Specific_Dispatching := 0;
Main_CPU := -1;
Interrupt_States := Local_Interrupt_States'Address;
Num_Interrupt_States := 0;
Unreserve_All_Interrupts := 0;
Zero_Cost_Exceptions := 1;
Detect_Blocking := 0;
Default_Stack_Size := -1;
Leap_Seconds_Support := 0;
if Handler_Installed = 0 then
Install_Handler;
end if;
System.Exception_Table'Elab_Body;
E23 := True;
System.Soft_Links'Elab_Body;
E13 := True;
System.Secondary_Stack'Elab_Body;
E17 := True;
end adainit;
procedure adafinal is
begin
Do_Finalize;
end adafinal;
function main
(argc : Integer;
argv : System.Address;
envp : System.Address)
return Integer
is
procedure initialize (Addr : System.Address);
pragma Import (C, initialize, "__gnat_initialize");
procedure finalize;
pragma Import (C, finalize, "__gnat_finalize");
procedure Ada_Main_Program;
pragma Import (Ada, Ada_Main_Program, "_ada_test");
SEH : aliased array (1 .. 2) of Integer;
Ensure_Reference : aliased System.Address := Ada_Main_Program_Name'Address;
pragma Volatile (Ensure_Reference);
begin
gnat_argc := argc;
gnat_argv := argv;
gnat_envp := envp;
Initialize (SEH'Address);
adainit;
Break_Start;
Ada_Main_Program;
Do_Finalize;
Finalize;
return (gnat_exit_status);
end;
-- BEGIN Object file/option list
-- ./test.o
-- -L./
-- -L/usr/lib/gcc/x86_64-linux-gnu/4.6/adalib/
-- -shared
-- -lgnat-4.6
-- END Object file/option list
end ada_main;
Lots of stuff in there, but you get the idea. See the "main" procedure? That call's adainit, then the actual procedure Ada_Main_Program_Name - test.
So, for bare hardware you need to mess around with the gnatbind step like this so that it doesn't generate some stuff, my b~blink.adb main is:
procedure main is
procedure Ada_Main_Program;
pragma Import (Ada, Ada_Main_Program, "_ada_blink");
Ensure_Reference : aliased System.Address := Ada_Main_Program_Name'Address;
pragma Volatile (Ensure_Reference);
begin
adainit;
Break_Start;
Ada_Main_Program;
end;
I just use the default discovery startup code which calls main from some assembly after setting up the hardware.
Luke.