static string FormatIl2CppGeneric(TypeSig type) { string result = ""; if (type.GetName().StartsWith("List")) { result = "Il2CppList<"; } else if (type.GetName().StartsWith("Dictionary")) { result = "Il2CppDictionary<"; } else { return("void*"); } List <string> args = new List <string>(); foreach (var arg in type.ToGenericInstSig().GenericArguments) { if (arg.IsGenericInstanceType) { args.Add(FormatIl2CppGeneric(arg)); } else { args.Add(Il2CppTypeToCppType(arg)); } } result += string.Join(", ", args.ToArray()); result += ">*"; return(result); }
public static IList <TypeSig> PossibleTypeSigs(TypeSig returnType, IList <TypeSig> typeGenerics, IList <TypeSig> methodGenerics) { IList <TypeSig> list = new List <TypeSig>(); // Ignore [], &, * when comparing against generic types // Otherwise, String[] Blah<String>(...) won't consider that the // return type might be T[]. Stack <String> modifiers; TypeSig returnTypeBase = SigUtil.ToBaseSig(returnType, out modifiers); if (returnTypeBase == null) { throw new Exception(String.Format("Given TypeSig is not a TypeDefOrRefSig: {0}", returnType)); } // Generic instance type if (returnTypeBase.IsGenericInstanceType) { var genericSig = returnTypeBase.ToGenericInstSig(); var combos = GenericUtils.CreateGenericParameterCombinations( genericSig.GenericArguments, typeGenerics, methodGenerics); foreach (var combo in combos) { list.Add(new GenericInstSig(genericSig.GenericType, combo)); } return(list); } else // Non-generic-instance type { list.Add(returnType); for (UInt16 g = 0; g < typeGenerics.Count; g++) { var gtype = typeGenerics[g]; if (returnTypeBase.FullName.Equals(gtype.FullName)) { list.Add(SigUtil.FromBaseSig(new GenericVar(g), modifiers)); } } for (UInt16 g = 0; g < methodGenerics.Count; g++) { var gtype = methodGenerics[g]; if (returnTypeBase.FullName.Equals(gtype.FullName)) { list.Add(SigUtil.FromBaseSig(new GenericMVar(g), modifiers)); } } return(list); } }
private TypeSig RemapGenericType(TypeSig reference) { var typeDef = reference.TryGetTypeDef(); if (typeDef != null) { if (reference.DefinitionAssembly != null && reference.DefinitionAssembly == Module.Assembly) { return(reference); } } var genericInstSig = reference.ToGenericInstSig(); if (genericInstSig != null) { return(RemapGenericInstSig(genericInstSig)); } throw new NotImplementedException(); }
public static HashSet <TypeDef> UsedTypes(this TypeSig typeSig) { var types = new HashSet <TypeDef>(); var td = typeSig.GetNonNestedTypeRefScope().ResolveTypeDef(); if (td != null) { types.Add(td); if (typeSig.IsGenericInstanceType) { var gi = typeSig.ToGenericInstSig(); foreach (var gp in gi.GenericArguments) { foreach (var t in gp.UsedTypes()) { types.Add(t); } } } } return(types); }
public static TypeDef ToTypeDef(this TypeSig type) { TypeDef typeDef = type.ToTypeDefOrRef().ResolveTypeDef(); if (typeDef != null) { return(typeDef); } if (type.IsArray) { typeDef = type.Next.ToTypeDefOrRef().ResolveTypeDef(); } if (typeDef != null) { return(typeDef); } if (type.IsGenericInstanceType) { typeDef = type.ToGenericInstSig().ToTypeDefOrRef().ResolveTypeDef(); } return(typeDef); }
public static string ParsedTypeSignatureStr(this TypeSig typeSig, bool useValueTypes = true, string context = null, bool typesOnly = false) { switch (typeSig.ElementType) { case ElementType.Object: return("DLL2SDK::mscorlib::System::Object"); case ElementType.String: return("DLL2SDK::mscorlib::System::String"); case ElementType.Void when useValueTypes: return("void"); case ElementType.Boolean when useValueTypes: return("bool"); case ElementType.Char when useValueTypes: return("wchar_t"); case ElementType.I1 when useValueTypes: return("int8_t"); case ElementType.U1 when useValueTypes: return("uint8_t"); case ElementType.I2 when useValueTypes: return("int16_t"); case ElementType.U2 when useValueTypes: return("uint16_t"); case ElementType.I4 when useValueTypes: return("int32_t"); case ElementType.U4 when useValueTypes: return("uint32_t"); case ElementType.I8 when useValueTypes: return("int64_t"); case ElementType.U8 when useValueTypes: return("uint64_t"); case ElementType.R4 when useValueTypes: return("float"); case ElementType.R8 when useValueTypes: return("double"); case ElementType.I when useValueTypes: return("intptr_t"); case ElementType.U when useValueTypes: return("uintptr_t"); } var underlying = typeSig.GetNonNestedTypeRefScope().ResolveTypeDef(); if (underlying?.IsEnum ?? false) { return(underlying.ParsedFullName()); } if (typeSig.IsArray || typeSig.IsSZArray) { return($"DLL2SDK::Array<{typeSig.Next.ParsedReferenceTypeDefinition(context: context)}>"); } if (typeSig.IsGenericParameter) { return(typeSig.ToGenericSig().GenericParam.Name.String.Parseable()); } var genericCtx = new List <string>(); if (typeSig.IsGenericInstanceType) { var gi = typeSig.ToGenericInstSig(); genericCtx = new List <string>(gi.GenericArguments.Count); foreach (var t in gi.GenericArguments) { genericCtx.Add(t.ParsedReferenceTypeDefinition(context: context)); } } var typeDef = typeSig.TryGetTypeDef(); if (typeDef?.HasGenericParameters ?? false) { var gi = typeDef.GenericParameters; genericCtx = new List <string>(gi.Count); foreach (var t in gi) { genericCtx.Add(t.Name.String.Parseable()); } } if (genericCtx.Count > 0) { var builder = new StringBuilder(); if (!typesOnly) { builder.Append(typeSig.ToTypeDefOrRef().ParsedFullName()); } if (context == null) { builder.Append("<"); builder.Append(string.Join(", ", genericCtx)); builder.Append(">"); } else { builder.Append(context); } return(builder.ToString()); } if (typeSig.IsByRef || typeSig.IsPointer) { return($"{typeSig.Next.ParsedTypeSignatureStr(context: context)}"); } return(typeSig.ToTypeDefOrRef().ParsedFullName()); }
public static void EscapeMethodTypeName(StringBuilder sb, TypeSig cntSig) { switch (cntSig.ElementType) { case ElementType.Void: sb.Append("void"); break; case ElementType.Boolean: case ElementType.Char: case ElementType.I1: case ElementType.U1: case ElementType.I2: case ElementType.U2: case ElementType.I4: case ElementType.U4: case ElementType.I8: case ElementType.U8: case ElementType.R4: case ElementType.R8: case ElementType.String: case ElementType.I: case ElementType.U: { switch (cntSig) { case TypeDefOrRefSig sig: sb.Append(EscapeTypeName(sig.TypeDefOrRef, hasGen: false, hasModuleName: false)); break; default: throw new NotSupportedException(); } } break; case ElementType.ValueType: case ElementType.Class: case ElementType.Object: { switch (cntSig) { case TypeDefOrRefSig sig: sb.Append(EscapeTypeName(sig.TypeDefOrRef, hasGen: false, hasModuleName: false)); break; default: throw new NotSupportedException(); } } break; case ElementType.SZArray: sb.Append("System_SZArray_1_"); EscapeTypeName(sb, cntSig.Next); break; case ElementType.Var: { var var = cntSig.ToGenericVar(); sb.Append(var.GetName()); } break; case ElementType.MVar: { var mvar = cntSig.ToGenericMVar(); sb.Append(mvar.GetName()); } break; case ElementType.GenericInst: { var sig = cntSig.ToGenericInstSig(); sb.Append(EscapeTypeName(sig.GenericType.TypeDefOrRef, hasGen: false, hasModuleName: false)); sb.Append("_"); for (int i = 0; i < sig.GenericArguments.Count; i++) { EscapeMethodTypeName(sb, sig.GenericArguments[i]); if (i != sig.GenericArguments.Count - 1) { sb.Append("_ "); } } } break; case ElementType.ByRef: sb.Append("ref_"); EscapeMethodTypeName(sb, cntSig.Next); break; case ElementType.Ptr: sb.Append("ptr_"); EscapeMethodTypeName(sb, cntSig.Next); break; case ElementType.Pinned: EscapeMethodTypeName(sb, cntSig.Next); break; case ElementType.CModReqd: EscapeMethodTypeName(sb, cntSig.Next); break; default: throw new NotSupportedException(); } }
public static void EscapeTypeName(StringBuilder sb, TypeSig cntSig, TypeDef declaringType = null, int hasGen = 0, IList <TypeSig> genArgs = null, bool cppBasicType = false) { switch (cntSig.ElementType) { case ElementType.Void: sb.Append("void"); break; case ElementType.Boolean: case ElementType.Char: case ElementType.I1: case ElementType.U1: case ElementType.I2: case ElementType.U2: case ElementType.I4: case ElementType.U4: case ElementType.I8: case ElementType.U8: case ElementType.R4: case ElementType.R8: case ElementType.String: case ElementType.I: case ElementType.U: { switch (cntSig) { case TypeDefOrRefSig sig: if (declaringType != null && sig.TypeDef == declaringType) { sb.Append(GetConstantTypeName(cntSig.ElementType)); } else { sb.Append(EscapeTypeName(sig.TypeDefOrRef, hasGen: hasGen-- > 0, genArgs: genArgs, cppBasicType: cppBasicType)); } break; default: throw new NotSupportedException(); } } break; case ElementType.ValueType: case ElementType.Class: case ElementType.Object: { switch (cntSig) { case TypeDefOrRefSig sig: if (sig.IsPrimitive && declaringType != null && sig.TypeDef == declaringType) { sb.Append(GetConstantTypeName(cntSig.ElementType)); } else { sb.Append(EscapeTypeName(sig.TypeDefOrRef, hasGen: hasGen-- > 0, genArgs: genArgs, cppBasicType: cppBasicType)); } break; default: throw new NotSupportedException(); } } break; case ElementType.SZArray: sb.Append("::System_Private_CoreLib::System::SZArray_1<"); EscapeTypeName(sb, cntSig.Next, declaringType, genArgs: genArgs, cppBasicType: true); sb.Append(">"); break; case ElementType.Var: { var var = cntSig.ToGenericVar(); if (genArgs != null) { var sig = genArgs.OfType <GenericSig>().FirstOrDefault(x => x.Number == var.Number); if (sig != null) { EscapeTypeName(sb, sig, cppBasicType: true); } else { EscapeTypeName(sb, genArgs[(int)var.Number], cppBasicType: true); } } else { if (cppBasicType) { sb.Append(var.GetName()); } else { sb.Append($"::natsu::to_clr_type_t<{var.GetName()}>"); } } } break; case ElementType.MVar: { var mvar = cntSig.ToGenericMVar(); if (genArgs != null) { EscapeTypeName(sb, genArgs[(int)mvar.Number], cppBasicType: true); } else { if (cppBasicType) { sb.Append(mvar.GetName()); } else { sb.Append($"::natsu::to_clr_type_t<{mvar.GetName()}>"); } } } break; case ElementType.GenericInst: { var sig = cntSig.ToGenericInstSig(); sb.Append(EscapeTypeName(sig.GenericType.TypeDefOrRef, hasGen: false, cppBasicType: cppBasicType)); sb.Append("<"); for (int i = 0; i < sig.GenericArguments.Count; i++) { EscapeTypeName(sb, sig.GenericArguments[i], null, genArgs: genArgs, cppBasicType: true); if (i != sig.GenericArguments.Count - 1) { sb.Append(", "); } } sb.Append(">"); } break; case ElementType.ByRef: sb.Append("::natsu::gc_ref<"); sb.Append(EscapeVariableTypeName(cntSig.Next, declaringType, hasGen, genArgs)); sb.Append(">"); break; case ElementType.Ptr: sb.Append("::natsu::gc_ptr<"); sb.Append(EscapeVariableTypeName(cntSig.Next, declaringType, hasGen, genArgs)); sb.Append(">"); break; case ElementType.Pinned: EscapeTypeName(sb, cntSig.Next, declaringType, hasGen, genArgs, cppBasicType: cppBasicType); break; case ElementType.CModReqd: { var modifier = ((ModifierSig)cntSig).Modifier; var modName = modifier.FullName; if (modName == "System.Runtime.InteropServices.InAttribute") { EscapeTypeName(sb, cntSig.Next, declaringType, hasGen, genArgs, cppBasicType: cppBasicType); } else if (modName == "System.Runtime.CompilerServices.IsVolatile") { sb.Append("::natsu::clr_volatile<"); EscapeTypeName(sb, cntSig.Next, declaringType, hasGen, genArgs, cppBasicType: cppBasicType); sb.Append(">"); } else { EscapeTypeName(sb, cntSig.Next, declaringType, hasGen, genArgs, cppBasicType: cppBasicType); } break; } default: throw new NotSupportedException(); } }
public static StackType GetStackType(TypeSig type, IList <TypeSig> genArgs = null) { StackTypeCode code; switch (type.ElementType) { case ElementType.Void: code = StackTypeCode.Void; break; case ElementType.Boolean: code = StackTypeCode.Int32; break; case ElementType.Char: code = StackTypeCode.Int32; break; case ElementType.I1: code = StackTypeCode.Int32; break; case ElementType.U1: code = StackTypeCode.Int32; break; case ElementType.I2: code = StackTypeCode.Int32; break; case ElementType.U2: code = StackTypeCode.Int32; break; case ElementType.I4: code = StackTypeCode.Int32; break; case ElementType.U4: code = StackTypeCode.Int32; break; case ElementType.I8: code = StackTypeCode.Int64; break; case ElementType.U8: code = StackTypeCode.Int64; break; case ElementType.R4: code = StackTypeCode.F; break; case ElementType.R8: code = StackTypeCode.F; break; case ElementType.String: code = StackTypeCode.O; break; case ElementType.Ptr: code = StackTypeCode.NativeInt; break; case ElementType.ByRef: code = StackTypeCode.Ref; break; case ElementType.ValueType: code = StackTypeCode.ValueType; break; case ElementType.Class: code = StackTypeCode.O; break; case ElementType.Array: code = StackTypeCode.O; break; case ElementType.TypedByRef: code = StackTypeCode.ValueType; break; case ElementType.I: code = StackTypeCode.NativeInt; break; case ElementType.U: code = StackTypeCode.NativeInt; break; case ElementType.R: code = StackTypeCode.F; break; case ElementType.Object: code = StackTypeCode.O; break; case ElementType.SZArray: code = StackTypeCode.O; break; case ElementType.Var: { var var = type.ToGenericVar(); if (genArgs != null) { var sig = genArgs.OfType <GenericSig>().FirstOrDefault(x => x.Number == var.Number); if (sig != null) { code = GetStackType(sig).Code; } else { code = GetStackType(genArgs[(int)var.Number]).Code; } } else { code = StackTypeCode.Runtime; } } break; case ElementType.MVar: { var mvar = type.ToGenericMVar(); if (genArgs != null) { code = GetStackType(genArgs[(int)mvar.Number]).Code; } else { code = StackTypeCode.Runtime; } } break; case ElementType.GenericInst: { var gen = type.ToGenericInstSig(); code = GetStackType(gen.GenericType, genArgs).Code; break; } case ElementType.CModReqd: case ElementType.CModOpt: case ElementType.Pinned: return(GetStackType(type.Next, genArgs)); default: throw new NotSupportedException(); } return(new StackType { Code = code, Name = EscapeVariableTypeName(type, genArgs: genArgs), TypeSig = type, GenArgs = genArgs }); }
public static void AddTexts(TypeSig type, IList <TextRun> target) { if (type.IsSZArray) { if (type.Next != null) { AddTexts(type.Next, target); target.Add(new TextRun("[]")); return; } } else if (type.IsArray) { if (type.Next != null) { AddTexts(type.Next, target); target.Add(new TextRun("[")); var arraySig = type.ToArraySig(); for (var i = 1; i < arraySig.Rank; i++) { target.Add(new TextRun(",")); } target.Add(new TextRun("]")); return; } } string text; string cssClass; var keyword = TypeSigAsKeyword(type); if (!string.IsNullOrEmpty(keyword)) { text = keyword; cssClass = "d-keyword"; } else { text = type.TypeName; // Remove generic parameter count // ex) List`1 => List var generic = text.LastIndexOf('`'); if (generic > 0) { text = text.Substring(0, generic); } switch (type.ElementType) { case ElementType.ValueType: cssClass = "d-valuetype"; break; case ElementType.Class: var classSig = type.ToClassSig(); if (classSig.IsTypeDef) { var typeDef = classSig.TypeDef; if (typeDef.IsInterface) { cssClass = "d-interface"; } else if (typeDef.IsSealed) { cssClass = "d-sealedtype"; } else { cssClass = "d-type"; } } else { cssClass = "d-type"; } break; case ElementType.GenericInst: var genericInstSig = type.ToGenericInstSig(); if (genericInstSig.GenericType.IsTypeDef) { var genericTypeSig = genericInstSig.GenericType.TypeDef.ToTypeSig(); AddTexts(genericTypeSig, target); } else { target.Add(new TextRun(text, "d-type")); } target.Add(new TextRun("<")); var _isFirst = true; foreach (var genericArgType in genericInstSig.GenericArguments) { if (_isFirst) { _isFirst = false; } else { target.Add(new TextRun(", ")); } AddTexts(genericArgType, target); } target.Add(new TextRun(">")); return; case ElementType.I: case ElementType.U: cssClass = "d-valuetype"; break; case ElementType.Var: cssClass = "d-typegenericparameter"; break; case ElementType.MVar: cssClass = "d-methodgenericparameter"; break; default: cssClass = string.Empty; break; } } target.Add(new TextRun(text, cssClass)); }