compiler: 32/64 bit bootstrap
[sdk] / compiler / ecc / ecc.ec
1 #ifdef ECERE_STATIC
2 import static "ecere"
3 import static "ec"
4 #else
5 import "ecere"
6 import "ec"
7 #endif
8
9 //#include <stdarg.h>
10
11 static Context globalContext { };
12 static Module privateModule;
13 static ModuleImport mainModule;
14 static OldList _excludedSymbols { offset = (uint)&((Symbol)0).left }; 
15 static OldList defines, imports;
16 static NameSpace globalData
17 {
18    classes.CompareKey = (void *)BinaryTree::CompareString;
19    defines.CompareKey = (void *)BinaryTree::CompareString;
20    functions.CompareKey = (void *)BinaryTree::CompareString;
21    nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
22 };
23 static OldList _precompDefines;
24
25 static void OutputImports(char * fileName)
26 {
27    File f = FileOpen(fileName, write);
28    if(f)
29    {
30       if(imports.first)
31       {
32          ModuleImport module;
33          f.Printf("[Imported Modules]\n");
34          for(module = imports.first; module; module = module.next)
35          {
36             ClassImport _class;
37             FunctionImport function;
38
39             if(module.name)
40                f.Printf("   %s\n", module.name);
41             else
42                f.Printf("   [This]\n");
43             if(module.importType == staticImport)
44                f.Printf("      [Static]\n");
45             else if(module.importType == remoteImport)
46                f.Printf("      [Remote]\n");
47
48             if(module.importAccess == privateAccess)
49                f.Printf("      [Private]\n");
50             else
51                f.Printf("      [Public]\n");
52
53             if(module.classes.first)
54             {
55                f.Printf("      [Imported Classes]\n");
56                for(_class = module.classes.first; _class; _class = _class.next)
57                {
58                   f.Printf("         %s\n", _class.name);
59                   if(_class.itself)
60                   {
61                      f.Printf("            [Instantiated]\n");
62                   }
63                   if(_class.isRemote)
64                   {
65                      f.Printf("            [Remote]\n");
66                   }
67
68                   if(_class.methods.first)
69                   {
70                      MethodImport method;
71                      f.Printf("            [Imported Methods]\n");
72                      for(method = _class.methods.first; method; method = method.next)
73                      {
74                         f.Printf("               %s\n", method.name);
75                         if(method.isVirtual)
76                            f.Printf("                  [Virtual]\n");
77
78                      }
79                      f.Printf("               .\n");
80                   }
81
82                   if(_class.properties.first)
83                   {
84                      PropertyImport prop;
85                      f.Printf("            [Imported Properties]\n");
86                      for(prop = _class.properties.first; prop; prop = prop.next)
87                      {
88                         f.Printf("               %s\n", prop.name);
89                         if(prop.isVirtual)
90                            f.Printf("                  [Virtual]\n");
91                         if(prop.hasSet)
92                            f.Printf("                  [Set]\n");
93                         if(prop.hasGet)
94                            f.Printf("                  [Get]\n");
95                      }
96                      f.Printf("               .\n");
97                   }
98                }
99                f.Printf("        .\n");
100             }
101             if(module.functions.first)
102             {
103                f.Printf("      [Imported Functions]\n");
104                for(function = module.functions.first; function; function = function.next)
105                {
106                   f.Printf("         %s\n", function.name);
107                }
108                f.Printf("        .\n");
109             }
110          }
111          f.Printf("   .\n");
112       }
113    }
114    delete f;
115 }
116
117 class CompilerApp : Application
118 {
119    void Main()
120    {
121       char * cppCommand = null;
122       char * cppOptions = null;
123       int cppOptionsLen = 0;
124       /*char ** argv = null;
125       int argc = 0;*/
126       int c;
127       bool valid = true;
128       char defaultOutputFile[MAX_LOCATION];
129       bool buildingBootStrap = false;
130
131       Platform targetPlatform = GetRuntimePlatform();
132       int targetBits = GetHostBits();
133
134       SetSymbolsDir("");
135
136       /*for(c = 0; c<this.argc; c++)
137       {
138          char * arg = this.argv[c];
139          int argLen = strlen(arg);
140
141          argv = renew argv char *[argc + 1];
142          argv[argc] = new char[argLen+1];
143          strcpy(argv[argc], arg);
144
145          while(argv[argc][argLen-1] == '\\' && c < this.argc-1)
146          {
147             int len;
148
149             c++;
150             arg = this.argv[c];
151             len = strlen(arg);
152             argv[argc] = renew argv[argc] char[argLen + len + 1];
153
154             argv[argc][argLen-1] = ' ';
155             strcpy(argv[argc] + argLen, arg);
156             argLen += len;
157          }
158          argc++;
159       }*/
160
161       for(c = 1; c<argc; c++)
162       {
163          char * arg = argv[c];
164          if(arg[0] == '-')
165          {
166             if(!strcmp(arg + 1, "m32") || !strcmp(arg + 1, "m64"))
167             {
168                int argLen = strlen(arg);
169                int newLen = cppOptionsLen + 1 + argLen;
170                cppOptions = renew cppOptions char[newLen + 1];
171                cppOptions[cppOptionsLen] = ' ';
172                strcpy(cppOptions + cppOptionsLen + 1, arg);
173                cppOptionsLen = newLen;
174                targetBits = !strcmp(arg + 1, "m32") ? 32 : 64;
175             }
176             else if(arg[1] == 'D')
177             {
178                int argLen = strlen(arg);
179                int newLen = cppOptionsLen + 1 + argLen;
180                cppOptions = renew cppOptions char[newLen + 1];
181                cppOptions[cppOptionsLen] = ' ';
182                strcpy(cppOptions + cppOptionsLen + 1, arg); 
183                cppOptionsLen = newLen;
184                if(!strcmp(arg, "-DBUILDING_ECERE_COM"))
185                   SetBuildingEcereCom(true);
186                else if(!strcmp(arg, "-DECERE_COM_MODULE"))
187                   SetBuildingEcereComModule(true);
188                else if(!strcmp(arg, "-DECERE_BOOTSTRAP"))
189                   buildingBootStrap = true;
190             }
191             else if(arg[1] == 'I')
192             {
193                int argLen = strlen(arg);
194                int newLen = cppOptionsLen + argLen + 3;
195                cppOptions = renew cppOptions char[newLen + 1];
196                cppOptions[cppOptionsLen] = ' ';
197                cppOptions[cppOptionsLen+1] = '-';
198                cppOptions[cppOptionsLen+2] = 'I';
199                cppOptions[cppOptionsLen+3] = '"';
200                strcpy(cppOptions + cppOptionsLen + 4, arg+2); 
201                cppOptions[newLen-1] = '\"';
202                cppOptions[newLen] = '\0';
203                cppOptionsLen = newLen;
204             }
205             else if(!strcmp(arg+1, "t"))
206             {
207                if(++c < argc)
208                   targetPlatform = argv[c];
209                else
210                   valid = false;
211             }
212             else if(!strcmp(arg+1, "cpp"))
213             {
214                if(++c < argc)
215                   cppCommand = CopyString(argv[c]);
216                else
217                   valid = false;
218             }
219             else if(!strcmp(arg+1, "o"))
220             {
221                if(!GetOutputFile() && c + 1 < argc)
222                {
223                   SetOutputFile(argv[c+1]);
224                   c++;
225                }
226                else
227                   valid = false;
228             }
229             else if(!strcmp(arg+1, "c"))
230             {
231                if(!GetSourceFile() && c + 1 < argc)
232                {
233                   SetSourceFile(argv[c+1]);
234                   c++;
235                }
236                else
237                   valid = false;
238             }
239             else if(!strcmp(arg+1, "isystem") || !strcmp(arg+1, "isysroot"))
240             {
241                if(c + 1 < argc)
242                {
243                   int argLen = strlen(arg);
244                   int arg1Len = strlen(argv[c+1]);
245                   int newLen = cppOptionsLen + argLen + arg1Len + 4;
246                   cppOptions = renew cppOptions char[newLen + 1];
247                   cppOptions[cppOptionsLen] = ' ';
248                   strcpy(cppOptions + cppOptionsLen + 1, arg); 
249                   cppOptions[cppOptionsLen+argLen+1] = ' ';
250                   cppOptions[cppOptionsLen+argLen+2] = '"';
251                   arg = argv[++c];
252                   strcpy(cppOptions + cppOptionsLen + argLen + 3, arg); 
253                   cppOptions[newLen-1] = '\"';
254                   cppOptions[newLen] = '\0';
255                   cppOptionsLen = newLen;
256                }
257                else
258                   valid = false;
259             }
260             else if(!strcmp(arg+1, "symbols"))
261             {
262                if(c + 1 < argc)
263                {
264                   SetSymbolsDir(argv[c+1]);
265                   c++;
266                }
267                else
268                   valid = false;
269             }
270             else if(!strcmp(arg+1, "memguard"))
271             {
272                SetMemoryGuard(true);
273             }
274             else if(!strcmp(arg+1, "defaultns"))
275             {
276                if(c + 1 < argc)
277                {
278                   SetDefaultNameSpace(argv[c+1]);
279                   //defaultNameSpaceLen = strlen(defaultNameSpace);
280                   c++;
281                }
282                else
283                   valid = false;
284             }
285             else if(!strcmp(arg+1, "strictns"))
286             {
287                SetStrictNameSpaces(true);
288             }
289             else if(!strcmp(arg+1, "nolinenumbers"))
290             {
291                SetOutputLineNumbers(false);
292             }
293          }
294          else
295             valid = false;
296       }
297       if(valid)
298       {
299          if(!cppCommand)
300             cppCommand = CopyString("gcc");
301          if(!GetSourceFile())
302             valid = false;
303          else if(!GetOutputFile())
304          {
305             strcpy(defaultOutputFile, "");
306             PathCat(defaultOutputFile, GetSourceFile());
307             ChangeExtension(defaultOutputFile, "c", defaultOutputFile);
308             SetOutputFile(defaultOutputFile);
309          }
310       }
311
312       if(!valid)
313          printf($"Syntax:\n   ecc [-t <target platform>] [-cpp <c preprocessor>] [-o <output>] [-symbols <outputdir>] [-I<includedir>]* [-isystem <sysincludedir>]* [-D<definition>]* -c <input>\n");
314       else
315       {
316          DualPipe cppOutput;
317          // TODO: Improve this
318          char command[MAX_F_STRING*3];
319          SetGlobalData(&globalData);
320          SetExcludedSymbols(&_excludedSymbols);
321          SetGlobalContext(globalContext);
322          SetCurrentContext(globalContext);
323          SetTopContext(globalContext);
324          SetDefines(&::defines);
325          SetImports(&imports);
326          SetInCompiler(true);
327          SetTargetPlatform(targetPlatform);
328          SetTargetBits(targetBits);
329          SetEchoOn(false);
330
331          privateModule = (Module)__ecere_COM_Initialize(true | (targetBits == sizeof(uintptr)*8 ? 0 : targetBits == 64 ? 2 : targetBits==32 ? 4 : 0) | 8, 1, null);
332          SetPrivateModule(privateModule);
333
334          globalContext.types.Add((BTNode)Symbol { string = CopyString("uint"), type = ProcessTypeString("unsigned int", false) });
335          globalContext.types.Add((BTNode)Symbol { string = CopyString("uint64"), type = ProcessTypeString("unsigned int64", false) });
336          globalContext.types.Add((BTNode)Symbol { string = CopyString("uint32"), type = ProcessTypeString("unsigned int", false) });
337          globalContext.types.Add((BTNode)Symbol { string = CopyString("uint16"), type = ProcessTypeString("unsigned short", false) });
338          globalContext.types.Add((BTNode)Symbol { string = CopyString("byte"), type = ProcessTypeString("unsigned char", false) });
339          if(buildingBootStrap)
340          {
341             // Do not define this when we pre-include stdint.h or the eC compiler will be confused when parsing these types (External prioritization in pass15.ec will fail)
342             globalContext.types.Add((BTNode)Symbol { string = CopyString("intptr_t"), type = ProcessTypeString("intptr", false) });
343             globalContext.types.Add((BTNode)Symbol { string = CopyString("uintptr_t"), type = ProcessTypeString("uintptr", false) });
344          }
345
346          {
347             GlobalData data { fullName = CopyString("__thisModule"), dataTypeString = CopyString("Module"), module = privateModule };
348             data.key = (uintptr)data.fullName;
349             globalData.functions.Add((BTNode)data);
350          }
351
352          snprintf(command, sizeof(command), "%s%s -x c -E %s\"%s\"", cppCommand, cppOptions ? cppOptions : "", buildingBootStrap ? "" : "-include stdint.h ", GetSourceFile());
353          command[sizeof(command)-1] = 0;
354          if((cppOutput = DualPipeOpen({ output = true }, command)))
355          {
356             char impFile[MAX_LOCATION];
357             ImportedModule module;
358             char mainModuleName[MAX_FILENAME];
359             int exitCode;
360             OldList * ast;
361
362             TempFile fileInput { };
363             SetFileInput(fileInput);
364
365             imports.Add((mainModule = ModuleImport { }));
366             SetMainModule(mainModule);
367
368             GetLastDirectory(GetSourceFile(), mainModuleName);
369
370 #if 0
371             // TEMP: UNTIL WE CAN HAVE PER SOURCE FILE PREPROCESSOR DEFINITIONS...
372             if(GetBuildingEcereCom() && 
373                !(strcmpi(mainModuleName, "instance.ec") && strcmpi(mainModuleName, "BinaryTree.ec") &&
374                strcmpi(mainModuleName, "dataTypes.ec") && strcmpi(mainModuleName, "OldList.ec") &&
375                strcmpi(mainModuleName, "String.ec") && strcmpi(mainModuleName, "BTNode.ec") &&
376                strcmpi(mainModuleName, "Array.ec") && strcmpi(mainModuleName, "AVLTree.ec") &&
377                strcmpi(mainModuleName, "BuiltInContainer.ec") && strcmpi(mainModuleName, "Container.ec") &&
378                strcmpi(mainModuleName, "CustomAVLTree.ec") && strcmpi(mainModuleName, "LinkList.ec") &&
379                strcmpi(mainModuleName, "List.ec") && strcmpi(mainModuleName, "Map.ec") &&
380                strcmpi(mainModuleName, "Mutex.ec")))
381                SetBuildingEcereComModule(true);
382             if(GetBuildingEcereCom() && 
383                !(strcmpi(mainModuleName, "instance.ec") && strcmpi(mainModuleName, "BinaryTree.ec") &&
384                /*strcmpi(mainModuleName, "dataTypes.ec") && strcmpi(mainModuleName, "OldList.ec") &&*/
385                /*strcmpi(mainModuleName, "String.ec") && */strcmpi(mainModuleName, "BTNode.ec") &&
386                strcmpi(mainModuleName, "Mutex.ec") && strcmpi(mainModuleName, "Thread.ec")))
387             //if(GetBuildingEcereCom() && !strcmpi(mainModuleName, "instance.ec"))
388                SetMemoryGuard(false);
389 #endif            
390
391             StripExtension(mainModuleName);
392             module = ImportedModule { name = CopyString(mainModuleName), type = moduleDefinition };
393             ::defines.AddName(module);
394
395             resetScanner();
396             while(!cppOutput.Eof())
397             {
398                char junk[4096];
399                int count = cppOutput.Read(junk, 1, 4096);
400                fileInput.Write(junk, 1, count);
401             }
402             exitCode = cppOutput.GetExitCode();
403             delete cppOutput;
404
405             fileInput.Seek(0, start);
406
407    #ifdef _DEBUG
408             // SetYydebug(true);
409    #endif
410
411             // Predeclare all classes
412             {
413                char symFile[MAX_FILENAME];
414                char symLocation[MAX_LOCATION];
415                ImportedModule module, next;
416
417                GetLastDirectory(GetSourceFile(), symFile);
418                ChangeExtension(symFile, "sym", symFile);
419
420                strcpy(symLocation, GetSymbolsDir());
421                PathCat(symLocation, symFile);
422                
423                // LoadSymbols(symLocation, normalImport, true);
424                LoadSymbols(symLocation, preDeclImport, false);
425                
426                for(module = ::defines.first; module; module = next)
427                {
428                   next = module.next;
429                   if(module.type == moduleDefinition && strcmpi(module.name, mainModuleName))
430                   {
431                      delete module.name;
432                      ::defines.Delete(module);
433                   }
434                }
435
436                if(!GetEcereImported() && !GetBuildingEcereCom())
437                   eModule_LoadStrict(privateModule, "ecereCOM", publicAccess /*privateAccess*/);
438             }
439
440             ParseEc();
441
442             CheckDataRedefinitions();
443
444             SetYydebug(false);
445             SetCurrentNameSpace(null);
446             SetDefaultNameSpace(null);
447             SetDeclMode(privateAccess);
448
449             delete fileInput;
450             SetFileInput(null);
451
452             ast = GetAST();
453
454             if(/*ast /*&& !parseError*/ /*&& */!exitCode)
455             {
456                ProcessDBTableDefinitions();
457
458                // *** PASS 0 - Register all classes, methods, properties and members ***
459                // ***          Build the constructors, destructors, properties as    ***
460                // ***          class functions                                       ***
461                PrePreProcessClassDefinitions();
462                ComputeModuleClasses(privateModule);
463                PreProcessClassDefinitions();
464
465                // For classes defined in this module...
466                ComputeModuleClasses(privateModule);
467
468                
469                // *** PASS 1 - Turn the class functions into functions               ***
470                // *** Write the RegisterModule (Register classes)                    ***
471                ProcessClassDefinitions();
472
473                // *** PASS 1.5 - Replace members by this.member, figure out types, do type checking / conversions
474                ComputeDataTypes();
475
476                // *** PASS 1.6 - Replace instantiations
477                ProcessInstantiations();
478
479                // *** PASS 2 - Replace Member Access ***
480                ProcessMemberAccess();
481
482                // *** PASS 3 - Replace pointers to objects by "Instance *" ***
483                ProcessInstanceDeclarations();
484
485                strcpy(impFile, GetSymbolsDir());
486                {
487                   char fileName[MAX_FILENAME];
488                   GetLastDirectory(GetSourceFile(), fileName);
489                   PathCat(impFile, fileName);
490                   ChangeExtension(impFile, "imp", impFile);
491                }
492                if(imports.first)
493                   OutputImports(impFile);
494                // For now use precomp to generate sym file only...
495
496                if(/*!strcmp(targetExt, "c") && */!this.exitCode)
497                {
498                   File output = FileOpen(GetOutputFile(), write);
499                   if(output)
500                   {
501                      output.Printf("#if defined(__GNUC__)\n");
502                         output.Printf("typedef long long int64;\n");
503                         output.Printf("typedef unsigned long long uint64;\n");
504                         output.Printf("#ifndef _WIN32\n");
505                            output.Printf("#define __declspec(x)\n");
506                         output.Printf("#endif\n");
507                      output.Printf("#elif defined(__TINYC__)\n");
508                         output.Printf("#include <stdarg.h>\n");
509                         output.Printf("#define __builtin_va_list va_list\n");
510                         output.Printf("#define __builtin_va_start va_start\n");
511                         output.Printf("#define __builtin_va_end va_end\n");
512                         output.Printf("#ifdef _WIN32\n");
513                            output.Printf("#define strcasecmp stricmp\n");
514                            output.Printf("#define strncasecmp strnicmp\n");
515                            output.Printf("#define __declspec(x) __attribute__((x))\n");
516                         output.Printf("#else\n");
517                            output.Printf("#define __declspec(x)\n");
518                         output.Printf("#endif\n");
519                         output.Printf("typedef long long int64;\n");
520                         output.Printf("typedef unsigned long long uint64;\n");
521                      output.Printf("#else\n");
522                         output.Printf("typedef __int64 int64;\n");
523                         output.Printf("typedef unsigned __int64 uint64;\n");
524                      output.Printf("#endif\n");
525                      output.Printf("#ifdef __BIG_ENDIAN__\n");
526                         output.Printf("#define __ENDIAN_PAD(x) (8 - (x))\n");
527                      output.Printf("#else\n");
528                         output.Printf("#define __ENDIAN_PAD(x) 0\n");
529                      output.Printf("#endif\n");
530                      if(buildingBootStrap)
531                      {
532                         //output.Printf("#ifdef __MINGW32__\n");
533                         //output.Printf("#ifdef _WIN64\n");
534                         /*
535                         output.Printf("#if defined(_WIN64) || WORDSIZE == 64\n");
536                         output.Printf("typedef unsigned long long int uintptr_t;\n");
537                         output.Printf("typedef long long int intptr_t;\n");
538                         output.Printf("#else\n");
539                         output.Printf("typedef unsigned int uintptr_t;\n");
540                         output.Printf("typedef int intptr_t;\n");
541                         output.Printf("#endif\n");
542                         */
543                         //output.Printf("#else\n");
544                         output.Printf("#include <stdint.h>\n");
545                         //output.Printf("#endif\n");
546                      }
547
548                      // NOTE: If anything is changed up there, the start outputLine must be updated in libec's output.c or Debugging lines will be wrong
549
550                      if(ast)
551                         OutputTree(ast, output);
552                      delete output;
553                   }
554                }
555                /*
556                else if(!strcmp(targetExt, "o"))
557                {
558                   // Compile right away
559                   File output = FileOpen(GetOutputFile(), Write);
560                   output.Printf("#include <ecereCOM.h>\n\n");
561                   OutputTree(ast, output);
562                   delete output;
563                }*/
564             }
565             else
566                this.exitCode = exitCode;
567
568             if(ast)
569             {
570                FreeASTTree(ast);
571             }
572          }
573
574          FreeContext(globalContext);
575          FreeExcludedSymbols(_excludedSymbols);
576
577          ::defines.Free(FreeModuleDefine);
578          imports.Free(FreeModuleImport);
579
580          FreeTypeData(privateModule);
581          FreeIncludeFiles();
582          FreeGlobalData(globalData);
583
584          delete privateModule;
585       }
586
587       delete cppCommand;
588       delete cppOptions;
589
590       /*for(c = 0; c<argc; c++)
591          delete argv[c];
592       delete argv;
593       */
594       SetSymbolsDir(null); // Free symbols dir
595
596       OutputIntlStrings();
597
598 #if defined(_DEBUG) && defined(__WIN32__)
599       if(exitCode || GetNumWarnings())
600          getch();
601 #endif
602    }
603 }