Exemple #1
0
 public void AddField(string name, FrontendType type)
 {
     fields.Add(new Field {
         name = name, type = type
     });
     calcTypeName();
 }
Exemple #2
0
 public void AddParam(string name, FrontendType type, bool optional = false, bool embed = false)
 {
     parameters.Add(new Param {
         name = name, type = type, optional = optional, embed = embed
     });
     calcTypeName();
 }
Exemple #3
0
 public FrontendNumberType(bool floatLiteral)
 {
     name           = "$$__number__$$";
     others         = new List <FrontendNumberType>();
     boundType      = null;
     this.floatType = floatLiteral;
 }
Exemple #4
0
        public static bool IsFloatType(FrontendType t)
        {
            bool result = false;

            result |= t.Equals(f32);
            result |= t.Equals(f64);
            return(result);
        }
Exemple #5
0
 public FrontendArrayType(FrontendType elementType, List <int> dim)
     : base("")
 {
     this.elementType = elementType;
     this.dims        = new List <int>();
     this.dims.AddRange(dim);
     name = $"[({string.Join(", ", dim)}) x {elementType}]";
 }
Exemple #6
0
        public static bool AllowedTypeCastAndLateBind(FrontendType a, FrontendType b)
        {
            var a_is_number = a is FrontendNumberType;
            var b_is_number = b is FrontendNumberType;

            if (a_is_number || b_is_number)
            {
                if (a_is_number && b_is_number)
                {
                    var an = a as FrontendNumberType;
                    var bn = b as FrontendNumberType;
                    an.others.Add(bn);
                    bn.others.Add(an);
                    if (an.floatType || bn.floatType)
                    {
                        an.floatType = true;
                        bn.floatType = true;
                    }
                    return(true);
                }

                if (a_is_number)
                {
                    if (IsIntegerType(b))
                    {
                        var an = a as FrontendNumberType;
                        if (!an.floatType)
                        {
                            an.Bind(b);
                        }
                    }
                    else if (IsFloatType(b))
                    {
                        (a as FrontendNumberType).Bind(b);
                    }
                }
                if (b_is_number)
                {
                    if (IsIntegerType(a))
                    {
                        var bn = b as FrontendNumberType;
                        if (!bn.floatType)
                        {
                            bn.Bind(a);
                        }
                    }
                    else if (IsFloatType(a))
                    {
                        (b as FrontendNumberType).Bind(a);
                    }
                }
            }
            // TODO: actually check if cast is allowed here!
            return(true);
        }
Exemple #7
0
        public static bool IsIntegerType(FrontendType t)
        {
            bool result = false;

            result |= t.Equals(i8);
            result |= t.Equals(i16);
            result |= t.Equals(i32);
            result |= t.Equals(i64);
            result |= t.Equals(mm);
            return(result);
        }
Exemple #8
0
 public FrontendSliceType(FrontendType elementType, string structName = "")
     : base(structName)
 {
     this.elementType = elementType;
     AddField("length", FrontendType.i32);
     AddField("capacity", FrontendType.i32);
     AddField("data", new FrontendPointerType(elementType));
     if (string.IsNullOrEmpty(structName))
     {
         name = "[" + elementType + "]";
     }
 }
Exemple #9
0
 void bind(FrontendType type, HashSet <FrontendNumberType> visited)
 {
     visited.Add(this);
     boundType = type;
     foreach (var other in others)
     {
         if (!visited.Contains(other))
         {
             other.bind(type, visited);
         }
     }
 }
Exemple #10
0
        int GetAlignmentOfFrontendType(FrontendType t)
        {
            switch (t)
            {
            case var _ when t.Equals(FrontendType.i8):
                return(1);

            case var _ when t.Equals(FrontendType.i16):
                return(2);

            case var _ when t.Equals(FrontendType.i32):
                return(4);

            case var _ when t.Equals(FrontendType.i64):
                return(8);

            case var _ when t.Equals(FrontendFunctionType.f32):
                return(4);

            case var _ when t.Equals(FrontendFunctionType.f64):
                return(8);

            case var _ when t.Equals(FrontendType.bool_):
                return(1);    // TODO(pragma): switch to b8 b16 b32?

            case var _ when t.Equals(FrontendType.mm):
                return(8);

            case FrontendPointerType _:
                return(8);

            case FrontendFunctionType _:
                return(8);

            case FrontendStructType fst:
                return(GetAlignmentOfStruct(fst));

            case FrontendArrayType fat:
                return(SizeOfArrayType(fat));

            case FrontendEnumType fet:
                return(GetAlignmentOfFrontendType(fet.integerType));

            case FrontendVectorType fvt:
                return(16);
                // return GetSizeOfFrontendType(fvt.elementType) * fvt.length;
            }
            Debug.Assert(false);
            return(-1);
        }
Exemple #11
0
 public static bool IsIntegerOrLateBind(FrontendType t)
 {
     if (IsIntegerType(t))
     {
         return(true);
     }
     if (t is FrontendNumberType)
     {
         var tn = t as FrontendNumberType;
         if (tn.floatType)
         {
             return(false);
         }
         tn.Bind(tn.Default());
         return(true);
     }
     return(false);
 }
Exemple #12
0
 public static bool IsBoolType(FrontendType t)
 {
     return(t.Equals(bool_));
 }
 public ParserVariableTypeMismatch(FrontendType varType, FrontendType otherType, Token t)
     : base(string.Format("Type of expression does not match variable type: variable type \"{0}\" != expression type {1}", varType.ToString(), otherType.ToString()), t)
 {
 }
 public ParserTypeMismatch(FrontendType type1, FrontendType type2, Token t)
     : base(string.Format("Type mismatch: type {0} is not equal to {1}", type1.ToString(), type2.ToString()), t)
 {
 }
Exemple #15
0
        // http://www.catb.org/esr/structure-packing/
        int GetDIType(FrontendType ft, bool noFunctionPointer = false)
        {
            if (!debugInfoTypeLookup.TryGetValue(ft, out int typeIdx))
            {
                string nodeString = null;
                if (FrontendType.IsIntegerType(ft))
                {
                    nodeString = $"!DIBasicType(name: \"{ft.name}\", size: {8 * GetSizeOfFrontendType(ft)}, encoding: DW_ATE_signed)";
                }
                else if (FrontendType.IsFloatType(ft))
                {
                    nodeString = $"!DIBasicType(name: \"{ft.name}\", size: {8 * GetSizeOfFrontendType(ft)}, encoding: DW_ATE_float)";
                }
                else if (FrontendType.IsBoolType(ft))
                {
                    nodeString = $"!DIBasicType(name: \"bool\", size: {8 * GetSizeOfFrontendType(ft)}, encoding: DW_ATE_boolean)";
                }
                else if (ft is FrontendFunctionType fft)
                {
                    string tl;
                    if (FrontendType.IsVoidType(fft.returnType))
                    {
                        if (fft.parameters.Count > 0)
                        {
                            tl = "null, " + String.Join(", ", fft.parameters.Select(p => { return("!" + GetDIType(p.type).ToString()); }));
                        }
                        else
                        {
                            tl = "null";
                        }
                    }
                    else
                    {
                        var types = new List <FrontendType>();
                        types.Add(fft.returnType);
                        types.AddRange(fft.parameters.Select(p => p.type));
                        tl = String.Join(", ", types.Select(t => { return("!" + GetDIType(t).ToString()); }));
                    }

                    var typeListNodeString = $"!{{{tl}}}";
                    var typeListIdx        = AddDebugInfoNode(typeListNodeString);

                    var functionNodeString = $"!DISubroutineType(types: !{typeListIdx})";
                    if (noFunctionPointer)
                    {
                        nodeString = functionNodeString;
                    }
                    else
                    {
                        var functionTypeIdx = AddDebugInfoNode(functionNodeString);
                        nodeString = $"!DIDerivedType(tag: DW_TAG_pointer_type, baseType: !{functionTypeIdx}, size: {8 * GetSizeOfFrontendType(FrontendType.ptr)})";
                    }
                }
                else if (ft is FrontendStructType fst)
                {
                    // reserve slot for new struct type
                    // if recursive calls want same type use reserved slot idx
                    // to avoid stack overflow
                    // assumes that struct has not already been defined. We _really_ need our type system to have exactly one
                    // frontendtype class per type so we can use it as keys in dict
                    var placeholder = System.Guid.NewGuid().ToString();
                    var structIdx   = AddDebugInfoNode(placeholder);
                    debugInfoTypeLookup.Add(ft, structIdx);

                    var node = (AST.StructDeclaration)typeChecker.GetTypeRoot(fst);
                    var memberListIndices = new List <int>();
                    var offsets           = GetOffsetsOfStruct(fst);
                    for (int idx = 0; idx < fst.fields.Count; ++idx)
                    {
                        var    f = fst.fields[idx];
                        string memberNodeString;

                        if (node != null)
                        {
                            var ts = node.fields[idx].typeString;
                            memberNodeString = $"!DIDerivedType(tag: DW_TAG_member, name: \"{f.name}\", scope: !{structIdx}, file: !{GetDIFile(ts)}, line: {ts.token.Line}, baseType: !{GetDIType(f.type)}, size: {8 * GetSizeOfFrontendType(f.type)}, offset: {8 * offsets[idx]})";
                        }
                        else
                        {
                            memberNodeString = $"!DIDerivedType(tag: DW_TAG_member, name: \"{f.name}\", scope: !{structIdx}, baseType: !{GetDIType(f.type)}, size: {8 * GetSizeOfFrontendType(f.type)}, offset: {8 * offsets[idx]})";
                        }
                        memberListIndices.Add(AddDebugInfoNode(memberNodeString));
                        // token is in node.fields.typeString.token
                    }
                    var memberListNodeString = $"!{{{String.Join(", ", memberListIndices.Select(t_idx => "!" + t_idx))}}}";
                    var memberListIdx        = AddDebugInfoNode(memberListNodeString);
                    nodeString = $"distinct !DICompositeType(tag: DW_TAG_structure_type, name: \"{fst}\", size: {8 * GetDISizeOfStruct(fst)}, elements: !{memberListIdx})";

                    debugInfoNodeLookup.Remove(placeholder);
                    debugInfoNodeLookup.Add(nodeString, structIdx);
                    return(structIdx);
                }
                else if (ft is FrontendPointerType fpt)
                {
                    nodeString = $"!DIDerivedType(tag: DW_TAG_pointer_type, baseType: !{GetDIType(fpt.elementType)}, size: {8 * GetSizeOfFrontendType(fpt)})";
                }
                else if (ft is FrontendArrayType fat)
                {
                    var subranges = new List <string>();
                    for (int i = 0; i < fat.dims.Count; ++i)
                    {
                        var subrangeNodeString = $"!DISubrange(count: {fat.dims[i]})";
                        var subrangeIdx        = AddDebugInfoNode(subrangeNodeString);
                        subranges.Add("!" + subrangeIdx.ToString());
                    }
                    var elementsIdx = AddDebugInfoNode($"!{{{string.Join(", ", subranges)}}}");
                    nodeString = $"!DICompositeType(tag: DW_TAG_array_type, baseType: !{GetDIType(fat.elementType)}, size: {SizeOfArrayType(fat)}, elements: !{elementsIdx})";
                }
                else if (ft is FrontendEnumType fet)
                {
                    var node           = (AST.EnumDeclaration)typeChecker.GetTypeRoot(fet);
                    var elementIndices = new List <int>(node.entries.Count);
                    for (int entryIdx = 0; entryIdx < node.entries.Count; ++entryIdx)
                    {
                        var entry             = node.entries[entryIdx];
                        var elementNodeString = $"!DIEnumerator(name: \"{entry.name}\", value: {entry.value})";
                        var elementIdx        = AddDebugInfoNode(elementNodeString);
                        elementIndices.Add(elementIdx);
                    }
                    var elementsIdx = AddDebugInfoNode($"!{{{string.Join(", ", elementIndices.Select(ei => $"!{ei}"))}}}");
                    nodeString = $"!DICompositeType(tag: DW_TAG_enumeration_type, name: \"{fet.name}\", file: !{GetDIFile(node)}, line: {node.token.Line}, baseType: !{GetDIType(fet.integerType)}, size: {8 * GetSizeOfFrontendType(fet.integerType)}, elements: !{elementsIdx})";
                }
                else if (ft is FrontendVectorType fvt)
                {
                    // TODO(pragma): Add a derived type with the vector name
                    var subrangeNodeString = $"!DISubrange(count: {fvt.length})";
                    var subrangeIdx        = AddDebugInfoNode(subrangeNodeString);
                    var elementsIdx        = AddDebugInfoNode($"!{{!{subrangeIdx}}}");
                    nodeString = $"!DICompositeType(tag: DW_TAG_array_type, baseType: !{GetDIType(fvt.elementType)}, size: {SizeOfVectorType(fvt)}, flags: DIFlagVector, elements: !{elementsIdx})";
                }


                Debug.Assert(nodeString != null);
                typeIdx = AddDebugInfoNode(nodeString);
                debugInfoTypeLookup.Add(ft, typeIdx);
            }
            return(typeIdx);
        }
Exemple #16
0
 public FrontendPointerType(FrontendType elementType)
 {
     this.elementType = elementType;
     name             = elementType + "*";
 }
Exemple #17
0
 public FrontendVectorType(FrontendType elementType, int length)
 {
     this.elementType = elementType;
     this.length      = length;
     name             = $"<{length} x {elementType}>";
 }
Exemple #18
0
 public static bool IntegersOrLateBind(FrontendType a, FrontendType b)
 {
     // TODO: resolve to same bit width
     return(IsIntegerOrLateBind(a) && IsIntegerOrLateBind(b));
 }
Exemple #19
0
        public static bool CompatibleAndLateBind(FrontendType a, FrontendType b)
        {
            var a_is_number = a is FrontendNumberType;
            var b_is_number = b is FrontendNumberType;

            if (a_is_number || b_is_number)
            {
                if (a_is_number && b_is_number)
                {
                    var an = a as FrontendNumberType;
                    var bn = b as FrontendNumberType;
                    an.others.Add(bn);
                    bn.others.Add(an);
                    if (an.floatType || bn.floatType)
                    {
                        an.floatType = true;
                        bn.floatType = true;
                    }

                    return(true);
                }

                if (a_is_number)
                {
                    if (IsIntegerType(b))
                    {
                        var an = a as FrontendNumberType;
                        if (an.floatType)
                        {
                            return(false);
                        }
                        else
                        {
                            an.Bind(b);
                            return(true);
                        }
                    }
                    else if (IsFloatType(b))
                    {
                        (a as FrontendNumberType).Bind(b);
                        return(true);
                    }
                    else
                    {
                        return(false);
                    }
                }
                if (b_is_number)
                {
                    if (IsIntegerType(a))
                    {
                        var bn = b as FrontendNumberType;
                        if (bn.floatType)
                        {
                            return(false);
                        }
                        else
                        {
                            bn.Bind(a);
                            return(true);
                        }
                    }
                    else if (IsFloatType(a))
                    {
                        (b as FrontendNumberType).Bind(a);
                        return(true);
                    }
                    else
                    {
                        return(false);
                    }
                }
            }
            if (a.Equals(b))
            {
                return(true);
            }
            else
            {
                return(false);
            }
        }
Exemple #20
0
 public static bool IsVoidType(FrontendType t)
 {
     return(t.Equals(void_));
 }
 public ParserExpectedArgumentType(FrontendType expected, FrontendType got, int idx, Token t)
     : base(string.Format("function argument {2} has type \"{0}\", but got type \"{1}\"", expected.ToString(), got.ToString(), idx), t)
 {
 }
Exemple #22
0
        public void Bind(FrontendType type)
        {
            HashSet <FrontendNumberType> visited = new HashSet <FrontendNumberType>();

            bind(type, visited);
        }
 public ParserExpectedType(FrontendType expected, FrontendType got, Token t)
     : base(string.Format("expected type \"{0}\", but got type \"{1}\"", expected.ToString(), got.ToString()), t)
 {
 }