compiler: (WIP) Fixes for MinGW/GCC 5
[sdk] / compiler / libec / src / ecdefs.ec
index 911bc60..ca0a95e 100644 (file)
@@ -63,6 +63,7 @@ public enum TokenType
   _int = INT,
   _uint = UINT,
   _int64 = INT64,
+  _int128 = INT128,
   _long = LONG,
   _signed = SIGNED,
   _unsigned = UNSIGNED,
@@ -80,7 +81,7 @@ public enum TokenType
   _default = DEFAULT,
   _if = IF,
   _switch = SWITCH,
-  _whilte = WHILE,
+  _while = WHILE,
   _do = DO,
   _for = FOR,
   _goto = GOTO,
@@ -183,6 +184,9 @@ class DBIndexItem : struct
 bool inCompiler = false;
 public void SetInCompiler(bool b) { inCompiler = b; }
 
+bool inDebugger = false;
+public void SetInDebugger(bool b) { inDebugger = b; }
+
 Context curContext;
 Context globalContext;
 OldList * excludedSymbols;
@@ -229,30 +233,31 @@ public void FixModuleName(char *moduleName)
 // todo support %var% variables for windows and $var for linux?
 public char * PassArg(char * output, const char * input)
 {
-#ifdef __WIN32__
-//define windowsFileNameCharsNeedEscaping = " !%&'()+,;=[]^`{}~"; // "#$-.@_" are ok
-   const char * escChars = " !\"%&'()+,;=[]^`{}~"; // windowsFileNameCharsNeedEscaping;
-   const char * escCharsQuoted = "\"";
-#else
-//define linuxFileNameCharsNeedEscaping = " !\"$&'()*:;<=>?[\\`{|"; // "#%+,-.@]^_}~" are ok
-   const char * escChars = " !\"$&'()*:;<=>?[\\`{|"; // linuxFileNameCharsNeedEscaping;
-   const char * escCharsQuoted = "\"()$";
-#endif
+   const char * escChars, * escCharsQuoted;
    bool quoting = false;
    char *o = output;
    const char *i = input, *l = input;
-#ifdef __WIN32__
-   while(*l && !strchr(escChars, *l)) l++;
-   if(*l) quoting = true;
-#else
-   if(*i == '-')
+   if(__runtimePlatform == win32)
    {
-      l++;
+//define windowsFileNameCharsNeedEscaping = " !%&'()+,;=[]^`{}~"; // "#$-.@_" are ok
+      escChars = " !\"%&'()+,;=[]^`{}~"; // windowsFileNameCharsNeedEscaping;
+      escCharsQuoted = "\"";
       while(*l && !strchr(escChars, *l)) l++;
       if(*l) quoting = true;
-      *o++ = *i++;
    }
-#endif
+//define linuxFileNameCharsNeedEscaping = " !\"$&'()*:;<=>?[\\`{|"; // "#%+,-.@]^_}~" are ok
+   else
+   {
+      escChars = " !\"$&'()*:;<=>?[\\`{|"; // linuxFileNameCharsNeedEscaping;
+      escCharsQuoted = "\"()$";
+      if(*i == '-')
+      {
+         l++;
+         while(*l && !strchr(escChars, *l)) l++;
+         if(*l) quoting = true;
+         *o++ = *i++;
+      }
+   }
    if(quoting)
       *o++ = '\"';
    while(*i)
@@ -412,7 +417,8 @@ public enum ExpressionType
    extensionCompoundExp, classExp, classDataExp, new0Exp, renew0Exp,
    dbopenExp, dbfieldExp, dbtableExp, dbindexExp, extensionExpressionExp, extensionInitializerExp,
    vaArgExp, arrayExp, typeAlignExp,
-   memberPropertyErrorExp, functionCallErrorExp, divideBy0ErrorExp
+   memberPropertyErrorExp, functionCallErrorExp, divideBy0ErrorExp,
+   offsetOfExp
 };
 
 public enum MemberType
@@ -490,6 +496,7 @@ public:
          char * name;
          Symbol symbol;
          OldList/*<TemplateArgument>*/ * templateArgs;
+         Specifier nsSpec;
       };
       struct
       {
@@ -640,6 +647,11 @@ public:
          Expression exp;
          TypeName typeName;
       } vaArg;
+      struct
+      {
+         TypeName typeName;
+         Identifier id;
+      } offset;
    };
 
    bool debugValue;
@@ -661,6 +673,9 @@ public:
    bool needCast;
    bool thisPtr;
    bool opDestType;
+   bool usedInComparison;
+   bool ambiguousUnits;
+   bool parentOpDestType;
    uint needTemplateCast;
 
    void Clear()
@@ -681,6 +696,8 @@ public:
       needCast = false;
       thisPtr = false;
       opDestType = false;
+      parentOpDestType = false;
+      usedInComparison = false;
       needTemplateCast = 0;
    }
 };
@@ -1019,7 +1036,6 @@ public:
    Symbol symbol;
    Location blockStart;
    Location nameLoc;
-   int endid;
    AccessMode declMode;
    bool deleteWatchable;
 };
@@ -1090,6 +1106,14 @@ public:
    void * object;
 };
 
+// An 'edge from' is a 'dependency on'
+class TopoEdge : struct
+{
+   public LinkElement<TopoEdge> in, out;
+   External from, to;
+   bool breakable;
+};
+
 public enum ExternalType { functionExternal, declarationExternal, classExternal, importExternal, nameSpaceExternal, dbtableExternal };
 
 public class External : struct
@@ -1109,6 +1133,109 @@ public:
       DBTableDef table;
    };
    ImportType importType;
+
+   // For the TopoSort
+   External fwdDecl;
+   LinkList<TopoEdge, link = out> outgoing { };
+   LinkList<TopoEdge, link = in> incoming { };
+   int nonBreakableIncoming;
+
+   void CreateUniqueEdge(External from, bool soft)
+   {
+      for(i : from.outgoing; i.to == this)
+      {
+         if(i.breakable && !soft)
+         {
+#ifdef _DEBUG
+            if(from == this)
+               PrintLn("bug: self-dependency");
+#endif
+            i.breakable = false;
+            nonBreakableIncoming++;
+         }
+         return;
+      }
+      CreateEdge(from, soft);
+   }
+
+   void CreateEdge(External from, bool soft)
+   {
+      TopoEdge e { from = from, to = this, breakable = soft };
+
+#ifdef _DEBUG
+      if(from == this && !soft)
+         PrintLn("bug: self-dependency");
+
+      /*for(i : from.outgoing)
+      {
+         if(i.to == this)
+            PrintLn("Warning: adding a duplicate edge");
+      }*/
+#endif
+
+      from.outgoing.Add(e);
+      incoming.Add(e);
+      if(!soft)
+         nonBreakableIncoming++;
+   }
+
+   External ForwardDeclare()
+   {
+      External f = null;
+      Context tmpContext = curContext;
+
+      switch(type)
+      {
+         case declarationExternal:
+         {
+            if(declaration.type == initDeclaration)
+            {
+               OldList * specs = declaration.specifiers;
+               if(specs)
+               {
+                  Specifier s;
+                  for(s = specs->first; s; s = s.next)
+                  {
+                     if(s.type == structSpecifier || s.type == unionSpecifier)
+                        break;
+                  }
+                  if(s)
+                  {
+                     curContext = null;
+                     f = MkExternalDeclaration(MkDeclaration(MkListOne(MkStructOrUnion(s.type, CopyIdentifier(s.id), null)), null));
+                     curContext = tmpContext;
+                  }
+               }
+            }
+            break;
+         }
+         case functionExternal:
+         {
+            curContext = null;
+            f = MkExternalDeclaration(MkDeclaration(CopyList(function.specifiers, CopySpecifier), MkListOne(MkInitDeclarator(CopyDeclarator(function.declarator), null))));
+            curContext = tmpContext;
+            f.symbol = symbol;
+
+            DeclareTypeForwardDeclare(f, symbol.type, false, false);
+            break;
+         }
+      }
+
+      /*
+      for(i : m.protoDepsExternal)
+      {
+         // If the edge is already added, don't bother
+         if(i.incoming.count)
+            CreateEdge(f, i.fwdDecl ? i.fwdDecl : i, i.fwdDecl ? false : true);
+      }
+      */
+
+      fwdDecl = f;
+
+      if(!f)
+         PrintLn("warning: unhandled forward declaration requested");
+      return f;
+   }
 };
 
 public class Context : struct
@@ -1143,7 +1270,7 @@ public:
       Property _property;
       Class registered;
    };
-   int id, idCode;
+   bool notYetDeclared;
    union
    {
       struct
@@ -1188,6 +1315,7 @@ public:
    Context ctx;
    int isIterator;
    Expression propCategory;
+   bool mustRegister;   // Must register the class within the RegisterClass (also used to check whether this class is declared in this module)
 };
 
 // For the .imp file:
@@ -1238,12 +1366,13 @@ public:
 };
 
 // For the .sym file:
+// BEWARE: Adding a value in the middle of this list has very arcane bootstrapping implications!!
 public enum TypeKind
 {
    voidType, charType, shortType, intType, int64Type, longType, floatType,
    doubleType, classType, structType, unionType, functionType, arrayType, pointerType,
    ellipsisType, enumType, methodType, vaListType, /*typedObjectType, anyObjectType, classPointerType, */ dummyType,
-   subClassType, templateType, thisClassType, intPtrType, intSizeType, _BoolType
+   subClassType, templateType, thisClassType, intPtrType, intSizeType, _BoolType, int128Type /* TODO! */
 };
 
 public class Type : struct
@@ -1293,12 +1422,15 @@ public:
    uint size;
    char * name;
    char * typeName;
+   Class thisClassFrom;
+   TypeKind promotedFrom;
 
    ClassObjectType classObjectType;
    int alignment;
    uint offset;
    int bitFieldCount;
-   int count;
+   int count;  // This is used to avoid outputting warnings when non-zero
+   int bitMemberSize;
 
    bool isSigned:1;
    bool constant:1;
@@ -1314,6 +1446,10 @@ public:
    bool declaredWithStruct:1;
    bool typedByReference:1;      // Originally typed by reference, regardless of class type
    bool casted:1;
+   bool pointerAlignment:1; // true if the alignment is the pointer size
+   bool isLong:1;    // true if this is truly a long set as a int/int64 (need to improve long support)
+   bool signedBeforePromotion:1;
+   bool isVector:1; // For __attribute__((__vector_size(..))
    // bool wasThisClass:1;
    // TODO: Add _Complex & _Imaginary support
    // bool complex:1, imaginary:1;
@@ -1342,6 +1478,44 @@ public:
       }
    }
 
+   // Used for generating calls to eClass_AddDataMember (differs slightly from 'isPointerType' below), meant to return true where ComputeTypeSize returns targetBits / 8
+   property bool isPointerTypeSize
+   {
+      get
+      {
+         bool result = false;
+         if(this)
+         {
+            switch(kind)
+            {
+               case classType:
+               {
+                  Class _class = this._class ? this._class.registered : null;
+                  if(!_class || (_class.type != structClass && _class.type != unitClass && _class.type != enumClass && _class.type != bitClass))
+                     result = true;
+                  break;
+               }
+               case pointerType:
+               case subClassType:
+               case thisClassType:
+               case intPtrType:
+               case intSizeType:
+                  result = true;
+                  break;
+               case templateType:
+               {
+                  TemplateParameter param = templateParameter;
+                  Type baseType = ProcessTemplateParameterType(param);
+                  if(baseType)
+                     result = baseType.isPointerTypeSize;
+                  break;
+               }
+            }
+         }
+         return result;
+      }
+   }
+
    property bool isPointerType
    {
       get
@@ -1357,6 +1531,8 @@ public:
                   Class c = _class.registered;
                   if(c.type == bitClass || c.type == unitClass || c.type == enumClass || c.type == systemClass)
                      return false;
+                  else if(c.type == structClass && !byReference)
+                     return false;
                }
                return true;
             }