public void AddField(string name, FrontendType type) { fields.Add(new Field { name = name, type = type }); calcTypeName(); }
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(); }
public FrontendNumberType(bool floatLiteral) { name = "$$__number__$$"; others = new List <FrontendNumberType>(); boundType = null; this.floatType = floatLiteral; }
public static bool IsFloatType(FrontendType t) { bool result = false; result |= t.Equals(f32); result |= t.Equals(f64); return(result); }
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}]"; }
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); }
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); }
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 + "]"; } }
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); } } }
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); }
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); }
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) { }
// 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); }
public FrontendPointerType(FrontendType elementType) { this.elementType = elementType; name = elementType + "*"; }
public FrontendVectorType(FrontendType elementType, int length) { this.elementType = elementType; this.length = length; name = $"<{length} x {elementType}>"; }
public static bool IntegersOrLateBind(FrontendType a, FrontendType b) { // TODO: resolve to same bit width return(IsIntegerOrLateBind(a) && IsIntegerOrLateBind(b)); }
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); } }
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) { }
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) { }