compiler/ecere: completed intptr/uintptr support
[sdk] / compiler / libec / src / pass3.ec
1 import "ecdefs"
2
3 #define YYLTYPE Location
4 #include "grammar.h"
5
6 extern External curExternal;
7 ///////////////// INSTANCE DECLARATION PASS ///////////////////////
8
9 // Returns true if we should add a * to the declarator
10 static bool ReplaceClassSpec(OldList specs, Specifier spec, bool param)
11 {
12    if(spec.type == templateTypeSpecifier)
13    {
14       TemplateParameter parameter = spec.templateParameter;
15       
16       if(!param && parameter.dataTypeString)
17       {
18          OldList * newSpecs = MkList();
19          Declarator decl = SpecDeclFromString(parameter.dataTypeString, newSpecs, null);
20          if(newSpecs->first)
21          {
22             Specifier newSpec = CopySpecifier(newSpecs->first);
23             *spec = *newSpec;
24             delete newSpec;
25          }
26          FreeList(newSpecs, FreeSpecifier);
27          
28          if(decl)
29          {
30             bool isPointer = decl.type == pointerDeclarator;
31             if(decl)
32                FreeDeclarator(decl);
33             if(isPointer)
34                return true;
35          }
36       }
37       else if(!param && parameter.dataType)
38       {
39          OldList * newSpecs = parameter.dataType.specifiers;
40          Declarator decl = parameter.dataType.decl;
41          if(newSpecs->first)
42          {
43             Specifier newSpec = CopySpecifier(newSpecs->first);
44             *spec = *newSpec;
45             delete newSpec;
46          }
47          
48          if(decl)
49          {
50             bool isPointer = decl.type == pointerDeclarator;
51             if(isPointer)
52                return true;
53          }
54       }
55       else
56       {
57          spec.type = nameSpecifier;
58          spec.name = CopyString("uint64");
59          spec.symbol = FindClass("uint64");
60       }
61    }
62
63    if(spec.type == nameSpecifier || spec.type == subClassSpecifier)
64    {
65       // TODO: Apply more care because nameSpecifier / subClassSpecifier use different parts of the union!
66       Symbol classSym = spec.symbol;
67       if(spec.type == subClassSpecifier)
68       {
69          classSym = FindClass("ecere::com::Class");
70       }
71
72       if(classSym)
73       {
74          Class _class = classSym.registered;
75          spec.type = nameSpecifier;
76
77          if(spec.templateArgs)
78          {
79             FreeList(spec.templateArgs, FreeTemplateArgument);
80             spec.templateArgs = null;
81          }
82
83          if(_class && _class.type == structClass)
84          {
85             //Externalexternal;
86             char name[1024];
87             name[0] = 0;
88             FullClassNameCat(name, _class.fullName, false);
89             //spec.name = CopyString(name);
90             delete spec.name;
91             spec.type = structSpecifier;
92             spec.baseSpecs = null;
93             spec.id = MkIdentifier(name);
94             spec.list = null;
95             spec.definitions = null;
96             spec.ctx = null;
97             spec.addNameSpace = false;
98          }
99          else if(_class && _class.type == noHeadClass)
100          {
101             char name[1024] = "";
102             FullClassNameCat(name, _class.fullName, false);
103             delete spec.name;
104             spec.type = structSpecifier;
105             spec.baseSpecs = null;
106             spec.id = MkIdentifier(name);
107             spec.list = null;
108             spec.definitions = null;
109             spec.ctx = null;
110             spec.addNameSpace = false;
111          }
112          else if(_class)
113          {
114             if((_class.type != systemClass ||
115                !strcmp(_class.fullName, "enum") ||
116                !strcmp(_class.fullName, "ecere::com::Instance") ||
117                (_class.dataTypeString && !strcmp(_class.dataTypeString, "char *")) ||
118                //strcmp(_class.fullName, "bool") &&
119                !strcmp(_class.fullName, "uint64") ||
120                !strcmp(_class.fullName, "uint32") ||
121                !strcmp(_class.fullName, "uint16") ||
122                !strcmp(_class.fullName, "uintptr") ||
123                !strcmp(_class.fullName, "intptr") ||
124                !strcmp(_class.fullName, "uint") ||
125                !strcmp(_class.fullName, "byte")))
126             {
127                delete spec.name;
128                if(_class.dataTypeString)
129                {
130                   if(!strcmp(_class.dataTypeString, "uint64") ||
131                      !strcmp(_class.dataTypeString, "uint32") ||
132                      !strcmp(_class.dataTypeString, "uint16") ||
133                      !strcmp(_class.dataTypeString, "uintptr") ||
134                      !strcmp(_class.dataTypeString, "intptr") ||
135                      !strcmp(_class.dataTypeString, "uint") ||
136                      !strcmp(_class.dataTypeString, "byte"))
137                   {
138                      if(!_class.dataType)
139                         _class.dataType = ProcessTypeString(_class.dataTypeString, false);
140                      if(_class.dataType && _class.dataType.kind == classType) 
141                         classSym = _class.dataType._class;
142                      else
143                         classSym = FindClass(_class.dataTypeString);
144                      _class = classSym ? classSym.registered : null;
145                   }
146
147                   if(!strcmp(_class.dataTypeString, "char *"))
148                      spec.name = CopyString("char");
149                   else
150                      spec.name = CopyString(_class.dataTypeString);
151                   spec.symbol = null;
152                }
153                else
154                {
155                   spec.name = CopyString(null);
156                   spec.symbol = null;
157                }
158             }
159             else if(!_class.base)
160             {
161                delete spec.name;
162                spec.type = baseSpecifier;
163                spec.specifier = VOID;
164                return true;
165             }
166          }
167          else
168          {
169             delete spec.name;
170             spec.type = structSpecifier;
171             spec.id = MkIdentifier("__ecereNameSpace__ecere__com__Instance");
172             spec.list = null;
173             spec.baseSpecs = null;
174             spec.definitions = null;
175             spec.ctx = null;
176             spec.addNameSpace = false;
177          }
178
179          if(_class && _class.dataTypeString && !strcmp(_class.dataTypeString, "char *"))
180             return true; //false;
181          if(!_class || _class.type == normalClass || _class.type == noHeadClass || !strcmp(_class.fullName, "ecere::com::Instance"))
182             return true;
183          else if(param && _class.type == structClass)
184             return 2;
185       }
186    }
187    else if(spec.type == baseSpecifier)
188    {
189       if(spec.specifier == ANY_OBJECT)
190       {
191          spec.specifier = VOID;
192          return true;
193       }
194    }
195    return false;
196 }
197
198 static void ReplaceByInstancePtr(Specifier spec, Declarator * declPtr, int type)
199 {
200    Declarator decl = *declPtr;
201    if(decl && decl.type == pointerDeclarator)
202    {
203       // Pointers to simple classes shouldn't be added pointers
204       if(type == 2);
205       else
206       // Add pointer
207          decl.pointer.pointer = MkPointer(null, decl.pointer.pointer);
208    }
209    else
210    {
211       Declarator newDecl { };
212       if(decl)
213       {
214          *newDecl = *decl;
215          decl.declarator = newDecl;
216       }
217       else
218          decl = newDecl;
219       decl.type = pointerDeclarator;
220       decl.pointer.pointer = MkPointer(null, null);      
221       *declPtr = decl;
222    }
223 }
224
225 static void InstDeclPassSpecifier(Specifier spec)
226 {
227    switch(spec.type)
228    {
229       case baseSpecifier:
230          if(spec.specifier == TYPED_OBJECT)
231          {
232             spec.type = extendedSpecifier;
233             spec.extDecl = MkExtDeclString(CopyString("struct __ecereNameSpace__ecere__com__Class * class, void *"));
234          }
235          break;
236       case nameSpecifier:
237          break;
238       case enumSpecifier:
239       {
240          Enumerator e;
241          if(spec.list)
242          {
243             for(e = spec.list->first; e; e = e.next)
244             {
245             
246             }
247          }
248          break;
249       }
250       case structSpecifier:
251       case unionSpecifier:
252       {
253          if(spec.definitions)
254          {
255             ClassDef def;
256             for(def = spec.definitions->first; def; def = def.next)
257                if(def.decl)
258                   InstDeclPassDeclaration(def.decl);
259          }
260          if(spec.id)
261             InstDeclPassIdentifier(spec.id);
262          break;
263       }
264       case extendedSpecifier:
265          if(spec.extDecl && spec.extDecl.type == extDeclString && spec.extDecl.s && !strcmp(spec.extDecl.s, "dllexport"))
266          {
267             Specifier prevSpec;
268             delete spec.extDecl.s;
269             for(prevSpec = spec.prev; prevSpec; prevSpec = prevSpec.prev)
270                if(prevSpec.type == baseSpecifier && prevSpec.specifier == EXTERN)
271                   break;
272             if(prevSpec)
273             {
274                if(targetPlatform == win32)
275                   spec.extDecl.s = CopyString("__declspec(dllexport)");
276                else
277                   spec.extDecl.s = CopyString("__attribute__ ((visibility(\"default\")))");
278             }
279             else
280             {
281                if(targetPlatform == win32)
282                   spec.extDecl.s = CopyString("extern __declspec(dllexport)");
283                else
284                   spec.extDecl.s = CopyString("extern __attribute__ ((visibility(\"default\")))");
285             }
286          }
287          break;
288    }
289 }
290
291 static void InstDeclPassDeclarator(Declarator decl)
292 {
293    switch(decl.type)
294    {
295       case structDeclarator:
296          if(decl.declarator)
297             InstDeclPassDeclarator(decl.declarator);
298          break;
299       case identifierDeclarator:
300       {
301          if(decl.identifier)
302             InstDeclPassIdentifier(decl.identifier);
303          break;
304       }
305       case bracketsDeclarator:
306          if(decl.declarator)
307             InstDeclPassDeclarator(decl.declarator);
308          break;
309       case arrayDeclarator:
310          if(decl.declarator)
311             InstDeclPassDeclarator(decl.declarator);
312          break;
313       case functionDeclarator:
314       {
315          if(decl.declarator)
316             InstDeclPassDeclarator(decl.declarator);
317          if(decl.function.parameters)
318          {
319             TypeName type;
320             if(decl.declarator)
321                InstDeclPassDeclarator(decl.declarator);
322             for(type = decl.function.parameters->first; type; type = type.next)
323             {
324                bool typedObject = false;
325                Specifier spec = null;
326                if(type.qualifiers)
327                {
328                   spec = (Specifier)type.qualifiers->first;
329                   if(spec && spec.type == nameSpecifier && !strcmp(spec.name, "class"))
330                      typedObject = true;
331                }
332
333                InstDeclPassTypeName(type, true);
334                if(typedObject)
335                {
336                   TypeName _class
337                   {
338                      qualifiers = MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier("__ecereNameSpace__ecere__com__Class"), null));
339                      declarator = MkDeclaratorPointer(MkPointer(null,null), MkDeclaratorIdentifier(MkIdentifier("class")));
340                   };
341                   decl.function.parameters->Insert(spec.prev, _class);
342                }
343             }
344          }
345          break;
346       }
347       case pointerDeclarator:
348       case extendedDeclarator:
349       case extendedDeclaratorEnd:
350          if((decl.type == extendedDeclarator || decl.type == extendedDeclaratorEnd) && decl.extended.extended)
351          {
352             if(decl.extended.extended.type == extDeclString && decl.extended.extended.s && !strcmp(decl.extended.extended.s, "dllexport"))
353             {
354                delete decl.extended.extended.s;
355                if(targetPlatform == win32)
356                   decl.extended.extended.s = CopyString("extern __declspec(dllexport)");
357                else
358                   decl.extended.extended.s = CopyString("extern __attribute__ ((visibility(\"default\")))");
359             }
360             else if(decl.extended.extended.type == extDeclString && decl.extended.extended.s &&
361                (!strcmp(decl.extended.extended.s, "stdcall") || !strcmp(decl.extended.extended.s, "_stdcall") || 
362                !strcmp(decl.extended.extended.s, "__stdcall") || !strcmp(decl.extended.extended.s, "__stdcall__")))
363             {
364                delete decl.extended.extended.s;
365                if(targetPlatform == win32)
366                   decl.extended.extended.s = CopyString("__attribute__((__stdcall__))");
367                else
368                   decl.extended.extended.s = CopyString("");
369             }
370          }
371          if(decl.declarator)
372             InstDeclPassDeclarator(decl.declarator);
373          break;
374    }
375 }
376
377 /*static */void InstDeclPassTypeName(TypeName type, bool param)
378 {
379    if(type.qualifiers)
380    {
381       Specifier spec;
382       for(spec = type.qualifiers->first; spec; spec = spec.next)
383       {
384          int result;
385          if((result = ReplaceClassSpec(type.qualifiers, spec, param)))
386             ReplaceByInstancePtr(spec, &type.declarator, result);
387          else
388          {
389             Symbol classSym = (spec.type == nameSpecifier) ? spec.symbol /*FindClass(spec.name)*/ : null;
390             if(type.classObjectType && (!classSym || (classSym && classSym.registered && 
391                (classSym.registered.type == enumClass || classSym.registered.type == bitClass || classSym.registered.type == unitClass || 
392                (classSym.registered.type == systemClass && strcmp(classSym.string, "ecere::com::Instance") && strcmp(classSym.string, "ecere::com::Class"))))))
393                ReplaceByInstancePtr(spec, &type.declarator, 2);
394          }
395          InstDeclPassSpecifier(spec);
396       }
397    }
398    if(type.declarator)
399       InstDeclPassDeclarator(type.declarator);
400 }
401
402 static void InstDeclPassIdentifier(Identifier id)
403 {
404    if(strchr(id.string, ':'))
405    {
406       char newID[1024];
407       int c;
408       char ch;
409       int len;
410       strcpy(newID, "__ecereNameSpace__");
411       len = strlen(newID);
412
413       for(c = 0; (ch = id.string[c]); c++)
414       {
415          if(ch == ':') ch = '_';
416
417          newID[len++] = ch;
418       }
419       newID[len] = 0;
420       delete id.string;
421       id.string = CopyString(newID);
422    }
423 }
424
425 static void InstDeclPassExpression(Expression exp)
426 {
427    switch(exp.type)
428    {
429       case identifierExp:
430       {
431          if(exp.identifier)
432             InstDeclPassIdentifier(exp.identifier);
433          break;
434       }
435       case constantExp:
436          break;
437       case stringExp:
438          break;
439       case opExp:
440          if(exp.op.exp1)
441             InstDeclPassExpression(exp.op.exp1);
442          if(exp.op.exp2)
443             InstDeclPassExpression(exp.op.exp2);
444          break;
445       case extensionExpressionExp:
446       case bracketsExp:
447       {
448          Expression e;
449          for(e = exp.list->first; e; e = e.next)
450             InstDeclPassExpression(e);
451          break;
452       }
453       case indexExp:
454       {
455          Expression e;
456          InstDeclPassExpression(exp.index.exp);
457          for(e = exp.index.index->first; e; e = e.next)
458             InstDeclPassExpression(e);
459          break;
460       }
461       case callExp:
462       {
463          Expression e;
464          InstDeclPassExpression(exp.call.exp);
465          if(exp.call.arguments)
466          {
467             for(e = exp.call.arguments->first; e; e = e.next)
468                InstDeclPassExpression(e);
469          }
470          break;
471       }
472       case memberExp:
473       {
474          InstDeclPassExpression(exp.member.exp);
475          break;
476       }
477       case pointerExp:
478       {
479          InstDeclPassExpression(exp.member.exp);
480          break;
481       }
482       case typeSizeExp:
483          InstDeclPassTypeName(exp.typeName, false);
484          break;
485       case castExp:
486       {
487          Type type = exp.expType;
488          // Remove casts to simple structs... (Watch out for pointers later...)
489          if(type && type.kind == classType && type._class.registered && type._class.registered.type == structClass)
490          {
491             Expression castExp = exp.cast.exp;
492             Expression prev = exp.prev, next = exp.next;
493             exp.cast.exp = null;
494             FreeExpContents(exp);
495             FreeType(exp.expType);
496             FreeType(exp.destType);
497             *exp = *castExp;
498             delete castExp;
499             exp.prev = prev;
500             exp.next = next;
501             InstDeclPassExpression(exp);
502          }
503          else
504          {
505             InstDeclPassTypeName(exp.cast.typeName, false);
506             if(exp.cast.exp)
507                InstDeclPassExpression(exp.cast.exp);
508          }
509          break;
510       }
511       case conditionExp:
512       {
513          Expression e;
514          InstDeclPassExpression(exp.cond.cond);
515          for(e = exp.cond.exp->first; e; e = e.next)
516             InstDeclPassExpression(e);
517          InstDeclPassExpression(exp.cond.elseExp);
518          break;
519       }
520       case extensionCompoundExp:
521       {
522          InstDeclPassStatement(exp.compound);
523          break;
524       }
525       case vaArgExp:
526       {
527          InstDeclPassExpression(exp.vaArg.exp);
528          break;
529       }
530       case extensionInitializerExp:
531       {
532          InstDeclPassTypeName(exp.initializer.typeName, false);
533          InstDeclPassInitializer(exp.initializer.initializer);
534          break;
535       }
536    }
537 }
538
539 static void InstDeclPassInitializer(Initializer init)
540 {
541    switch(init.type)
542    {
543       case expInitializer:
544          InstDeclPassExpression(init.exp);
545          break;
546       case listInitializer:
547       {
548          Initializer i;
549          for(i = init.list->first; i; i = i.next)
550             InstDeclPassInitializer(i);
551          break;
552       }
553    }
554 }
555
556 static void InstDeclPassDeclaration(Declaration decl)
557 {
558    switch(decl.type)
559    {
560       case initDeclaration:
561       {
562          if(decl.specifiers)
563          {
564             Specifier spec;
565             for(spec = decl.specifiers->first; spec; spec = spec.next)
566             {
567                int type;
568                if((type = ReplaceClassSpec(decl.specifiers, spec, false)))
569                {
570                   InitDeclarator d;
571                   if(decl.declarators)
572                   {
573                      for(d = decl.declarators->first; d; d = d.next)
574                         ReplaceByInstancePtr(spec, &d.declarator, type);
575                   }
576                }
577                InstDeclPassSpecifier(spec);
578             }
579          }
580          if(decl.declarators)
581          {
582             InitDeclarator d;
583             for(d = decl.declarators->first; d; d = d.next)
584             {
585                InstDeclPassDeclarator(d.declarator);
586                if(d.initializer)
587                   InstDeclPassInitializer(d.initializer);
588             }
589          }
590          break;
591       }
592       case structDeclaration:
593       {
594          if(decl.specifiers)
595          {
596             Specifier spec;
597             for(spec = decl.specifiers->first; spec; spec = spec.next)
598             {
599                int type;
600                if((type = ReplaceClassSpec(decl.specifiers, spec, false)))
601                {
602                   if(decl.declarators)
603                   {
604                      Declarator d;
605                      for(d = decl.declarators->first; d; d = d.next)
606                         ReplaceByInstancePtr(spec, &d, type);
607                   }
608                }
609                InstDeclPassSpecifier(spec);
610             }
611          }
612
613          if(decl.declarators)
614          {
615             Declarator d;
616             for(d = decl.declarators->first; d; d = d.next)
617                InstDeclPassDeclarator(d);
618          }
619          break;
620       }
621       // This should be removed by now?
622       case instDeclaration:
623          // InstDeclPassInstantiation(decl.inst);
624          break;
625    }
626 }
627
628 static void InstDeclPassStatement(Statement stmt)
629 {
630    switch(stmt.type)
631    {
632       case labeledStmt:
633          InstDeclPassStatement(stmt.labeled.stmt);
634          break;
635       case caseStmt:
636          // This expression should be constant...
637          if(stmt.caseStmt.exp)
638             InstDeclPassExpression(stmt.caseStmt.exp);
639          if(stmt.caseStmt.stmt)
640             InstDeclPassStatement(stmt.caseStmt.stmt);
641          break;
642       case compoundStmt:
643       {
644          Declaration decl;
645          Statement s;
646          Context prevContext = curContext;
647
648          if(!stmt.compound.isSwitch)
649             curContext = stmt.compound.context;
650          
651          if(stmt.compound.declarations)
652          {
653             for(decl = stmt.compound.declarations->first; decl; decl = decl.next)
654                InstDeclPassDeclaration(decl);
655          }
656          if(stmt.compound.statements)
657          {
658             for(s = stmt.compound.statements->first; s; s = s.next)
659                InstDeclPassStatement(s);
660          }
661          curContext = prevContext;
662          break;
663       }
664       case expressionStmt:
665       {
666          if(stmt.expressions)
667          {
668             Expression exp;
669             for(exp = stmt.expressions->first; exp; exp = exp.next)
670                InstDeclPassExpression(exp);
671          }
672          break;
673       }
674       case ifStmt:
675       {
676          if(stmt.ifStmt.exp)
677          {
678             Expression exp;
679             for(exp = stmt.ifStmt.exp->first; exp; exp = exp.next)
680                InstDeclPassExpression(exp);
681          }
682          if(stmt.ifStmt.stmt)
683             InstDeclPassStatement(stmt.ifStmt.stmt);
684          if(stmt.ifStmt.elseStmt)
685             InstDeclPassStatement(stmt.ifStmt.elseStmt);
686          break;
687       }
688       case switchStmt:
689       {
690          Expression exp;
691          for(exp = stmt.switchStmt.exp->first; exp; exp = exp.next)
692             InstDeclPassExpression(exp);
693          InstDeclPassStatement(stmt.switchStmt.stmt);
694          break;
695       }
696       case whileStmt:
697       {
698          Expression exp;
699          for(exp = stmt.whileStmt.exp->first; exp; exp = exp.next)
700             InstDeclPassExpression(exp);
701          InstDeclPassStatement(stmt.whileStmt.stmt);
702          break;
703       }
704       case doWhileStmt:
705       {
706          if(stmt.doWhile.exp)
707          {
708             Expression exp;
709             for(exp = stmt.doWhile.exp->first; exp; exp = exp.next)
710                InstDeclPassExpression(exp);
711          }
712          if(stmt.doWhile.stmt)
713             InstDeclPassStatement(stmt.doWhile.stmt);
714          break;
715       }
716       case forStmt:
717       {
718          Expression exp;
719          if(stmt.forStmt.init)
720             InstDeclPassStatement(stmt.forStmt.init);
721          if(stmt.forStmt.check)
722             InstDeclPassStatement(stmt.forStmt.check);
723          if(stmt.forStmt.increment)
724          {
725             for(exp = stmt.forStmt.increment->first; exp; exp = exp.next)
726                InstDeclPassExpression(exp);
727          }
728          if(stmt.forStmt.stmt)
729             InstDeclPassStatement(stmt.forStmt.stmt);
730          break;
731       }
732       case gotoStmt:
733          break;
734       case continueStmt:
735          break;
736       case breakStmt:
737          break;
738       case returnStmt:
739       {
740          Expression exp;
741          if(stmt.expressions)
742          {
743             for(exp = stmt.expressions->first; exp; exp = exp.next)
744                InstDeclPassExpression(exp);
745          }
746          break;
747       }
748       case asmStmt:
749       {
750          AsmField field;
751          if(stmt.asmStmt.inputFields)
752          {
753             for(field = stmt.asmStmt.inputFields->first; field; field = field.next)
754                if(field.expression)
755                   InstDeclPassExpression(field.expression);
756          }
757          if(stmt.asmStmt.outputFields)
758          {
759             for(field = stmt.asmStmt.outputFields->first; field; field = field.next)
760                if(field.expression)
761                   InstDeclPassExpression(field.expression);
762          }
763          if(stmt.asmStmt.clobberedFields)
764          {
765             for(field = stmt.asmStmt.clobberedFields->first; field; field = field.next)
766                if(field.expression)
767                   InstDeclPassExpression(field.expression);
768          }
769          break;
770       }
771    }
772 }
773
774 public void ProcessInstanceDeclarations()
775 {
776    External external;
777    curContext = globalContext;
778    for(external = ast->first; external; external = external.next)
779    {
780       curExternal = external;
781       if(external.type == functionExternal)
782       {
783          FunctionDefinition func = external.function;
784          if(func.specifiers)
785          {
786             Specifier spec;
787             for(spec = func.specifiers->first; spec; spec = spec.next)
788             {
789                int type;
790                if((type = ReplaceClassSpec(func.specifiers, spec, false)))
791                   ReplaceByInstancePtr(spec, &func.declarator, type);
792                InstDeclPassSpecifier(spec);
793             }
794          }
795          InstDeclPassDeclarator(func.declarator);
796          if(func.body)
797             InstDeclPassStatement(func.body);
798       }
799       else if(external.type == declarationExternal)
800       {
801          if(external.declaration)
802             InstDeclPassDeclaration(external.declaration);         
803       }
804    }
805 }