/* File: cg.c Author: John van Groningen At: University of Nijmegen */ #ifdef THINK_C # define USER_INTERFACE #endif #include #include "cgport.h" #ifdef ALIGN_C_CALLS # define CG_PPC_XO #endif #include #include #if ! (defined (M68000) && defined (SUN)) # define GENERATE_OBJECT_FILE #endif #ifdef POWER # define USE_SYSTEM_ALLOC 1 /* # include "Memory.h" */ # include "MacMemory.h" #else # define USE_SYSTEM_ALLOC 0 #endif /* #define PERFORMANCE */ #include "MAIN_CLM.d" #ifdef PERFORMANCE #include TP2PerfGlobals ThePGlobals; #endif #ifdef THINK_C # include # define NO_TOPOLOGY #ifdef USER_INTERFACE # include "system.h" #else # include "types.t" #endif #endif #include "cgrconst.h" #include "cgtypes.h" #include "cgcode.h" #include "cglin.h" #include "cgopt.h" #ifdef I486 # include "cgias.h" # include "cgiwas.h" #else # ifdef ARM # include "cgarmas.h" # include "cgarmwas.h" # else # ifdef SOLARIS # include "cgswas.h" # else # ifdef G_POWER # include "cgpas.h" # include "cgpwas.h" # else # include "cgas.h" # include "cgwas.h" # endif # endif # endif #endif #include "cgstack.h" #include "cg.h" #ifdef USER_INTERFACE # include "cginterface.t" # include "cginterface.h" #endif #include "cginput.h" #ifdef G_POWER # include "cgptoc.h" #endif #include static jmp_buf error_jmp; static void exit_code_generator (int r) { longjmp (error_jmp,r); } int list_flag; int check_stack; int assembly_flag; int mc68000_flag; int mc68881_flag; int parallel_flag; int check_index_flag; int module_info_flag=1; int profile_table_flag; #ifdef G_POWER int fmadd_flag=1; #endif #if (defined (LINUX) && defined (G_AI64)) || defined (ARM) int pic_flag=0; #endif #if defined (LINUX) && defined (G_AI64) int rts_got_flag=0; char **sl_mods; char *no_sl_mods=NULL; #endif #ifdef USER_INTERFACE # define print_error(s1) FPrintF (StdError,"%s\n",s1) # define exit exit_code_generator #else # ifdef MAIN_CLM # ifdef MAKE_MPW_TOOL # define print_error(s1) printf("%s\n",s1) # else # ifdef CG_PPC_XO static char *return_error_string; # else extern char return_error_string[]; # endif # define print_error(s1) strcpy (return_error_string,s1); # endif # define exit exit_code_generator # else /* # define print_error(s1) printf("%s\n",s1) */ # define print_error(s1) fprintf(stderr,"%s\n",s1) # endif #endif void warning (char *error_string) { print_error (error_string); } void warning_s (char *error_string,char *string) { char error[300]; sprintf (error,error_string,string); print_error (error); } void warning_i (char *error_string,int integer) { char error[300]; sprintf (error,error_string,integer); print_error (error); } void warning_si (char *error_string,char *string,int i) { char error[300]; sprintf (error,error_string,string,i); print_error (error); } void error (char *error_string) { warning (error_string); #ifdef PERFORMANCE PerfDump (ThePGlobals,"\pPerform.out",0,0); TermPerf (ThePGlobals); #endif exit (-1); } void error_i (char *error_string,int integer) { warning_i (error_string,integer); #ifdef PERFORMANCE PerfDump (ThePGlobals,"\pPerform.out",0,0); TermPerf (ThePGlobals); #endif exit (-1); } void error_s (char *error_string,char *string) { warning_s (error_string,string); #ifdef PERFORMANCE PerfDump (ThePGlobals,"\pPerform.out",0,0); TermPerf (ThePGlobals); #endif exit (-1); } void error_si (char *error_string,char *string,int i) { warning_si (error_string,string,i); #ifdef PERFORMANCE PerfDump (ThePGlobals,"\pPerform.out",0,0); TermPerf (ThePGlobals); #endif exit (-1); } void internal_error (char *error_string) { error_s ("Internal error: %s",error_string); } void internal_error_in_function (char *function_name) { error_s ("Internal error in function: %s",function_name); } void *memory_allocate (int size) { void *memory_block; memory_block=malloc (size); if (memory_block==NULL) error ("Out of memory"); return memory_block; } #if USE_SYSTEM_ALLOC #define system_memory_allocate_type(t) ((t*)system_memory_allocate(sizeof (t))) static void *system_memory_allocate (int size) { char *memory_block; memory_block=NewPtr (size); if (memory_block==NULL) error ("Out of memory"); return memory_block; } #endif void memory_free (void *memory_block) { free (memory_block); } #if USE_SYSTEM_ALLOC static void system_memory_free (void *memory_block) { DisposePtr ((char*)memory_block); } #endif #ifdef THINK_C # define MEM_BLOCK_SIZE 16380 #else # if defined (__MWERKS__) || defined (__MRC__) # define MEM_BLOCK_SIZE 16384 # else # define MEM_BLOCK_SIZE 4092 # endif #endif struct memory_block_list { char mem_block [MEM_BLOCK_SIZE]; struct memory_block_list * mem_next_block; }; static struct memory_block_list *heap; static int first_mem_block_size; void *allocate_memory_from_heap (int size) { #ifdef sparc size = (size+7) & ~7; #else size = (size+3) & ~3; #endif if (first_mem_block_size+size<=MEM_BLOCK_SIZE){ char *mem_block; mem_block=&heap->mem_block[first_mem_block_size]; first_mem_block_size+=size; return mem_block; } else { struct memory_block_list *new_mem_block_list; #if USE_SYSTEM_ALLOC new_mem_block_list=system_memory_allocate_type (struct memory_block_list); #else new_mem_block_list=memory_allocate (sizeof (struct memory_block_list)); #endif new_mem_block_list->mem_next_block=heap; heap=new_mem_block_list; first_mem_block_size=size; return new_mem_block_list->mem_block; } } void release_heap (VOID) { while (heap->mem_next_block!=NULL){ struct memory_block_list *next_mem_block; next_mem_block=heap->mem_next_block; #if USE_SYSTEM_ALLOC system_memory_free (heap); #else memory_free (heap); #endif heap=next_mem_block; } } static struct memory_block_list *memory_list; static char *fast_mem_block; static int fast_mem_block_size; static void initialize_memory (VOID) { memory_list=NULL; first_mem_block_size=0; #if USE_SYSTEM_ALLOC heap=system_memory_allocate_type (struct memory_block_list); #else heap=memory_allocate (sizeof (struct memory_block_list)); #endif heap->mem_next_block=NULL; fast_mem_block_size=0; #if USE_SYSTEM_ALLOC memory_list=system_memory_allocate_type (struct memory_block_list); #else memory_list=memory_allocate (sizeof (struct memory_block_list)); #endif memory_list->mem_next_block=NULL; fast_mem_block=memory_list->mem_block; } void *fast_memory_allocate (int size) { #ifdef sparc size=(size+7) & ~7; #else size=(size+3) & ~3; #endif if (fast_mem_block_size+size<=MEM_BLOCK_SIZE){ char *memory_block; memory_block=&fast_mem_block[fast_mem_block_size]; fast_mem_block_size+=size; return memory_block; } else { struct memory_block_list *new_memory_block; #if USE_SYSTEM_ALLOC new_memory_block=system_memory_allocate_type (struct memory_block_list); #else new_memory_block=memory_allocate (sizeof (struct memory_block_list)); #endif new_memory_block->mem_next_block=memory_list; memory_list=new_memory_block; fast_mem_block=new_memory_block->mem_block; fast_mem_block_size=size; return fast_mem_block; } } static void release_memory (VOID) { while (memory_list!=NULL){ struct memory_block_list *next_mem_block; next_mem_block=memory_list->mem_next_block; #if USE_SYSTEM_ALLOC system_memory_free (memory_list); #else memory_free (memory_list); #endif memory_list=next_mem_block; } release_heap(); #if USE_SYSTEM_ALLOC system_memory_free (heap); #else memory_free (heap); #endif } #define IO_BUF_SIZE 8192 char *this_module_name; #ifdef GNU_C # define FOLDER_SEPARATOR '/' #else # define FOLDER_SEPARATOR ':' #endif #if defined (POWER) && defined (GNU_C) static FILE *fopen_with_file_name_conversion (char *file_name,char *mode) { CFURLRef hfs_url; CFStringRef hfs_string, posix_string; char buffer[512+1]; hfs_string = CFStringCreateWithCString (NULL/*kCFAllocatorDefault*/,file_name,kCFStringEncodingMacRoman); hfs_url = CFURLCreateWithFileSystemPath (NULL/*kCFAllocatorDefault*/,hfs_string,kCFURLHFSPathStyle,/*isDirectory*/false); CFRelease (hfs_string); posix_string = CFURLCopyFileSystemPath (hfs_url,kCFURLPOSIXPathStyle); CFRelease (hfs_url); if (! CFStringGetCString (posix_string,buffer,512,kCFStringEncodingMacRoman)){ CFRelease (posix_string); return NULL; } file_name=buffer; return fopen (file_name,mode); } # define fopen fopen_with_file_name_conversion #endif #ifdef USER_INTERFACE extern File abc_file; static File obj_file,assembly_file; extern int system_file; int generate_code (char *file_name,target_machine_type target_machine,int flags) { int r; char *module_name; int object_file_type; /* InitProfile (400,200); freopen ("profile","w",stdout); */ system_file=0; obj_file=NULL; assembly_file=NULL; abc_file=NULL; if (!(r=setjmp (error_jmp))){ initialize_memory(); mc68000_flag=0; mc68881_flag=1; switch (target_machine){ case MAC_II: break; case MAC_I: mc68000_flag=1; mc68881_flag=0; break; case MAC_IISANE: mc68881_flag=0; break; default: error ("Unknown target machine"); } list_flag=0; check_stack=(flags & STACK_CHECKS)!=0; assembly_flag=(flags & ASSEMBLY)!=0; parallel_flag=(flags & DO_PARALLEL)!=0; check_index_flag=(flags & CHECK_INDICES)!=0; profile_table_flag=0; #ifndef GENERATE_OBJECT_FILE assembly_flag=1; #endif initialize_parser(); initialize_coding(); initialize_linearization(); initialize_stacks(); object_file_type= mc68000_flag ? obj00File : (mc68881_flag ? obj81File : obj20File); module_name=file_name+strlen (file_name); while (module_name>file_name && module_name[-1]!=FOLDER_SEPARATOR) --module_name; this_module_name=module_name; abc_file=FOpen (file_name,abcFile,"r"); if (abc_file==NULL){ fprintf (stderr,"file \"%s.abc\" could not be opened.\n",file_name); exit (-1); } setvbuf (abc_file,NULL,_IOFBF,8192); #if defined (M68000) && !defined (SUN) obj_file=FOpen (file_name,object_file_type,"wb"); if (obj_file==NULL) error_s ("Can't create the output file [%s]",this_module_name); setvbuf (obj_file,NULL,_IOFBF,IO_BUF_SIZE); #endif if (assembly_flag){ #ifdef MACH_O assembly_file=FOpen (file_name,assFile,"wb"); #else assembly_file=FOpen (file_name,assFile,"w"); #endif if (assembly_file==NULL) error_s ("Can't create the assembly file [%s]",this_module_name); setvbuf (assembly_file,NULL,_IOFBF,IO_BUF_SIZE); } #ifdef GENERATE_OBJECT_FILE initialize_assembler (obj_file); #endif if (assembly_flag) initialize_write_assembly (assembly_file); #ifdef G_POWER initialize_toc(); #endif if (parse_file (abc_file)!=0){ if (abc_file!=NULL){ FClose (abc_file); abc_file=NULL; } #ifdef PERFORMANCE PerfDump (ThePGlobals,"\pPerform.out",0,0); TermPerf (ThePGlobals); #endif exit (-1); } if (abc_file!=NULL){ FClose (abc_file); abc_file=NULL; } if (profile_table_flag) write_profile_table(); optimize_jumps(); #if 0 if (list_flag){ show_code(); show_imports_and_exports(); } #endif #ifdef GENERATE_OBJECT_FILE assemble_code(); #endif if (assembly_flag) write_assembly(); #if defined (M68000) && !defined (SUN) if (fclose (obj_file)!=0){ obj_file=NULL; FDelete (file_name,object_file_type); error_s ("Error while writing object file [%s]",this_module_name); } #endif if (assembly_flag && fclose (assembly_file)!=0){ assembly_file=NULL; FDelete (file_name,assFile); error_s ("Error while writing assembly file [%s]",this_module_name); } if (!(flags & KEEP_ABC) && !system_file) FDelete (file_name,abcFile); } else { /* if an error occurrs : */ if (obj_file!=NULL){ fclose (obj_file); FDelete (file_name,object_file_type); } if (assembly_file!=NULL){ fclose (assembly_file); FDelete (file_name,assFile); } if (abc_file!=NULL){ FClose (abc_file); abc_file=NULL; } } release_memory(); return r; } #else static void argument_error (VOID) { error ("Usage: cg [options] file [-o object_file] [-s assembly_file]"); } #if defined (LINUX) && defined (G_AI64) static char **make_sl_mods (char *module_list) { char **modules,**module_p,*module_name,*p; int n_modules; if (*module_list=='\0') n_modules = 0; else { n_modules = 1; for (p=module_list; *p!='\0'; ++p) if (*p==',') ++n_modules; } p = (char*)memory_allocate (strlen (module_list)+1); strcpy (p,module_list); modules=(char**)memory_allocate (sizeof (char*) * (n_modules+1)); module_p=modules; module_name=p; while (*p!='\0'){ if (*p==','){ *p='\0'; *module_p++ = module_name; module_name=p+1; } ++p; } if (module_name!=p) *module_p++ = module_name; *module_p=NULL; return modules; } #endif #if defined(MAIN_CLM) && (defined (POWER) && !defined (CG_PPC_XO)) extern int compiler_id; #endif #ifdef I486 extern int intel_asm; #endif #ifdef G_AI64 extern int sse_128; #endif #ifdef MAIN_CLM # if !(defined (__MWERKS__) && defined (__cplusplus)) # ifdef CG_PPC_XO # ifdef MACH_O int generate_code_o (int argc,char **argv,char *return_error_string_p,int *compiler_id_p) # else int generate_code_xo (int argc,char **argv,char *return_error_string_p,int *compiler_id_p) # endif # else int generate_code (int argc,char **argv) # endif # else int generate_code68 (int argc,char **argv) # endif #else int main (int argc,char **argv) #endif { char *file_name; static FILE *abc_file,*obj_file,*assembly_file; int arg_n,r,file_name_length; char *abc_file_name=NULL,*object_file_name_s=NULL,*assembly_file_name_s=NULL; char *module_name,*object_file_name,*assembly_file_name; #if defined (MAIN_CLM) && defined (CG_PPC_XO) return_error_string=return_error_string_p; #endif #if defined (THINK_C) argc = ccommand (&argv); #endif #ifdef PERFORMANCE ThePGlobals=NULL; if (!InitPerf (&ThePGlobals,4,8,1,1,"\pCODE",0,"",0,0,0,0)){ printf ("Can't initialize performance measurement\n"); exit (-1); } PerfControl (ThePGlobals,1); #endif obj_file=NULL; assembly_file=NULL; abc_file=NULL; #if defined (LINUX) && defined (G_AI64) sl_mods=&no_sl_mods; #endif if (!(r=setjmp (error_jmp))){ initialize_memory(); list_flag=0; check_stack=0; mc68000_flag=0; mc68881_flag=1; parallel_flag=0; check_index_flag=0; assembly_flag=0; #if defined (G_POWER) && !defined (MACH_O) profile_table_flag=1; #else profile_table_flag=0; #endif for (arg_n=1; arg_n=argc) argument_error(); file_name=argv[arg_n++]; module_name=file_name+strlen (file_name); while (module_name>file_name && module_name[-1]!=FOLDER_SEPARATOR) --module_name; this_module_name=module_name; file_name_length=strlen (file_name); abc_file_name=(char*)memory_allocate (file_name_length+5); strcpy (abc_file_name,file_name); strcat (abc_file_name,".abc"); object_file_name_s=(char*)memory_allocate (file_name_length+6); strcpy (object_file_name_s,file_name); #if defined (G_POWER) || defined (_WINDOWS_) || defined (LINUX) || defined (sparc) # if defined (G_POWER) && !defined (MACH_O) # ifdef ALIGN_C_CALLS strcat (object_file_name_s,".xo"); # else strcat (object_file_name_s,".cxo"); # endif # else strcat (object_file_name_s,".o"); # endif #else # ifdef I486 strcat (object_file_name_s,".obj"); # else strcat (object_file_name_s,mc68000_flag ? ".obj0" : mc68881_flag ? ".obj2" : ".obj1"); # endif #endif object_file_name=object_file_name_s; assembly_file_name_s=(char*)memory_allocate (file_name_length+3); strcpy (assembly_file_name_s,file_name); #if (defined (M68000) && !defined (SUN)) || (defined (G_POWER) && !defined (LINUX_ELF)) strcat (assembly_file_name_s,".a"); #else strcat (assembly_file_name_s,".s"); #endif assembly_file_name=assembly_file_name_s; while (arg_n