diff --git a/src/codeview/codeview.h b/src/codeview/codeview.h index 4075934c..a037bee2 100644 --- a/src/codeview/codeview.h +++ b/src/codeview/codeview.h @@ -969,7 +969,9 @@ struct CV_RecHeader //////////////////////////////// //~ rjf: CodeView Format "Sym" Types +// // (per-compilation-unit info, variables, procedures, etc.) +// typedef U8 CV_ProcFlags; enum @@ -1931,8 +1933,10 @@ struct CV_SymInlinees }; //////////////////////////////// -//~ CodeView Format "Leaf" Types +//~ rjf: CodeView Format "Leaf" Types +// // (type info) +// #define CV_LeafIDKindXList(X) \ X(FUNC_ID, 0x1601)\ @@ -1952,70 +1956,6 @@ typedef enum CV_LeafIDKindEnum } CV_LeafIDKindEnum; -#define CV_BasicTypeXList(X) \ -X(NOTYPE, 0x00)\ -X(ABS, 0x01)\ -X(SEGMENT, 0x02)\ -X(VOID, 0x03)\ -X(CURRENCY, 0x04)\ -X(NBASICSTR, 0x05)\ -X(FBASICSTR, 0x06)\ -X(NOTTRANS, 0x07)\ -X(HRESULT, 0x08)\ -X(CHAR, 0x10)\ -X(SHORT, 0x11)\ -X(LONG, 0x12)\ -X(QUAD, 0x13)\ -X(OCT, 0x14)\ -X(UCHAR, 0x20)\ -X(USHORT, 0x21)\ -X(ULONG, 0x22)\ -X(UQUAD, 0x23)\ -X(UOCT, 0x24)\ -X(BOOL8, 0x30)\ -X(BOOL16, 0x31)\ -X(BOOL32, 0x32)\ -X(BOOL64, 0x33)\ -X(FLOAT32, 0x40)\ -X(FLOAT64, 0x41)\ -X(FLOAT80, 0x42)\ -X(FLOAT128, 0x43)\ -X(FLOAT48, 0x44)\ -X(FLOAT32PP, 0x45)\ -X(FLOAT16, 0x46)\ -X(COMPLEX32, 0x50)\ -X(COMPLEX64, 0x51)\ -X(COMPLEX80, 0x52)\ -X(COMPLEX128, 0x53)\ -X(BIT, 0x60)\ -X(PASCHAR, 0x61)\ -X(BOOL32FF, 0x62)\ -X(INT8, 0x68)\ -X(UINT8, 0x69)\ -X(RCHAR, 0x70)\ -X(WCHAR, 0x71)\ -X(INT16, 0x72)\ -X(UINT16, 0x73)\ -X(INT32, 0x74)\ -X(UINT32, 0x75)\ -X(INT64, 0x76)\ -X(UINT64, 0x77)\ -X(INT128, 0x78)\ -X(UINT128, 0x79)\ -X(CHAR16, 0x7a)\ -X(CHAR32, 0x7b)\ -X(CHAR8, 0x7c)\ -X(PTR, 0xf0) - -typedef U8 CV_BasicType; -typedef enum CV_BasicTypeEnum -{ -#define X(N,c) CV_BasicType_##N = c, - CV_BasicTypeXList(X) -#undef X -} -CV_BasicTypeEnum; - #define CV_TypeId_Variadic 0 #define CV_BasicPointerKindXList(X) \ @@ -2061,22 +2001,21 @@ CV_MoComUDTKindEnum; typedef U16 CV_TypeProps; enum { - CV_TypeProp_Packed = (1 << 0), - CV_TypeProp_HasConstructorsDestructors = (1 << 1), - CV_TypeProp_OverloadedOperators = (1 << 2), - CV_TypeProp_IsNested = (1 << 3), - CV_TypeProp_ContainsNested = (1 << 4), - CV_TypeProp_OverloadedAssignment = (1 << 5), - CV_TypeProp_OverloadedCasting = (1 << 6), - CV_TypeProp_FwdRef = (1 << 7), - CV_TypeProp_Scoped = (1 << 8), - CV_TypeProp_HasUniqueName = (1 << 9), - CV_TypeProp_Sealed = (1 << 10), + CV_TypeProp_Packed = (1<<0), + CV_TypeProp_HasConstructorsDestructors = (1<<1), + CV_TypeProp_OverloadedOperators = (1<<2), + CV_TypeProp_IsNested = (1<<3), + CV_TypeProp_ContainsNested = (1<<4), + CV_TypeProp_OverloadedAssignment = (1<<5), + CV_TypeProp_OverloadedCasting = (1<<6), + CV_TypeProp_FwdRef = (1<<7), + CV_TypeProp_Scoped = (1<<8), + CV_TypeProp_HasUniqueName = (1<<9), + CV_TypeProp_Sealed = (1<<10), // HFA: 11,12 - CV_TypeProp_Intrinsic = (1 << 13), + CV_TypeProp_Intrinsic = (1<<13), // MOCOM: 14,15 }; - #define CV_TypeProps_ExtractHFA(f) (((f)>>11)&0x3) #define CV_TypeProps_ExtractMOCOM(f) (((f)>>14)&0x3) @@ -2128,11 +2067,11 @@ CV_MemberPointerKindEnum; typedef U32 CV_VirtualTableShape; typedef enum CV_VirtualTableShapeEnum { - CV_VirtualTableShape_Near, // 16 bit ptr - CV_VirtualTableShape_Far, // 16:16 bit ptr - CV_VirtualTableShape_Thin, // ??? - CV_VirtualTableShape_Outer, // address point displacment to outermost class entry[-1] - CV_VirtualTableShape_Meta, // far pointer to metaclass descriptor entry[-2] + CV_VirtualTableShape_Near, // 16 bit ptr + CV_VirtualTableShape_Far, // 16:16 bit ptr + CV_VirtualTableShape_Thin, // ??? + CV_VirtualTableShape_Outer, // address point displacment to outermost class entry[-1] + CV_VirtualTableShape_Meta, // far pointer to metaclass descriptor entry[-2] CV_VirtualTableShape_Near32, // 32 bit ptr CV_VirtualTableShape_Far32, // ??? } @@ -2165,11 +2104,11 @@ enum { // Access: 0,1 // MethodProp: [2:4] - CV_FieldAttrib_Pseudo = (1 << 5), - CV_FieldAttrib_NoInherit = (1 << 6), - CV_FieldAttrib_NoConstruct = (1 << 7), - CV_FieldAttrib_CompilerGenated = (1 << 8), - CV_FieldAttrib_Sealed = (1 << 9), + CV_FieldAttrib_Pseudo = (1<<5), + CV_FieldAttrib_NoInherit = (1<<6), + CV_FieldAttrib_NoConstruct = (1<<7), + CV_FieldAttrib_CompilerGenated = (1<<8), + CV_FieldAttrib_Sealed = (1<<9), }; #define CV_FieldAttribs_ExtractAccess(f) ((f)&0x3) #define CV_FieldAttribs_ExtractMethodProp(f) (((f)>>2)&0x7) @@ -2185,9 +2124,9 @@ CV_LabelKindEnum; typedef U8 CV_FunctionAttribs; enum { - CV_FunctionAttrib_CxxReturnUDT = (1 << 0), - CV_FunctionAttrib_Constructor = (1 << 1), - CV_FunctionAttrib_ConstructorVBase = (1 << 2), + CV_FunctionAttrib_CxxReturnUDT = (1<<0), + CV_FunctionAttrib_Constructor = (1<<1), + CV_FunctionAttrib_ConstructorVBase = (1<<2), }; typedef U8 CV_CallKind; diff --git a/src/codeview/codeview.mdesk b/src/codeview/codeview.mdesk index 5b57fd39..1c10ebfe 100644 --- a/src/codeview/codeview.mdesk +++ b/src/codeview/codeview.mdesk @@ -380,138 +380,214 @@ cv_string_from_sym_kind: `}`; } +//////////////////////////////// +//~ rjf: CV Basic Types + +@table(name val type_name) +CV_BasicTypeTable: +{ + {NOTYPE 0x00 "" } + {ABS 0x01 "" } + {SEGMENT 0x02 "" } + {VOID 0x03 "void" } + {CURRENCY 0x04 "" } + {NBASICSTR 0x05 "" } + {FBASICSTR 0x06 "" } + {NOTTRANS 0x07 "" } + {HRESULT 0x08 "HRESULT" } + {CHAR 0x10 "char" } + {SHORT 0x11 "S16" } + {LONG 0x12 "S32" } + {QUAD 0x13 "S64" } + {OCT 0x14 "S128" } + {UCHAR 0x20 "UCHAR" } + {USHORT 0x21 "U16" } + {ULONG 0x22 "U32" } + {UQUAD 0x23 "U64" } + {UOCT 0x24 "U128" } + {BOOL8 0x30 "B8" } + {BOOL16 0x31 "B16" } + {BOOL32 0x32 "B32" } + {BOOL64 0x33 "B64" } + {FLOAT32 0x40 "F32" } + {FLOAT64 0x41 "F64" } + {FLOAT80 0x42 "F80" } + {FLOAT128 0x43 "F128" } + {FLOAT48 0x44 "F48" } + {FLOAT32PP 0x45 "F32PP" } + {FLOAT16 0x46 "F16" } + {COMPLEX32 0x50 "ComplexF32" } + {COMPLEX64 0x51 "ComplexF64" } + {COMPLEX80 0x52 "ComplexF80" } + {COMPLEX128 0x53 "ComplexF128" } + {BIT 0x60 "" } + {PASCHAR 0x61 "" } + {BOOL32FF 0x62 "B32FF" } + {INT8 0x68 "S8" } + {UINT8 0x69 "U8" } + {RCHAR 0x70 "char" } + {WCHAR 0x71 "WCHAR" } + {INT16 0x72 "S16" } + {UINT16 0x73 "U16" } + {INT32 0x74 "S32" } + {UINT32 0x75 "U32" } + {INT64 0x76 "S64" } + {UINT64 0x77 "U64" } + {INT128 0x78 "S128" } + {UINT128 0x79 "U128" } + {CHAR16 0x7a "CHAR16" } + {CHAR32 0x7b "CHAR32" } + {CHAR8 0x7c "char" } + {PTR 0xf0 "PTR" } +} + +@enum(U8) CV_BasicType: +{ + @expand(CV_BasicTypeTable a) `$(a.name) = $(a.val)` +} + +@enum2string_switch(CV_BasicType) cv_string_from_basic_type: +{ + @expand(CV_BasicTypeTable a) `case CV_BasicType_$(a.name):{result = str8_lit("$(a.name)");}break` +} + +@enum2string_switch(CV_BasicType) cv_type_name_from_basic_type: +{ + @expand(CV_BasicTypeTable a) `case CV_BasicType_$(a.name):{result = str8_lit("$(a.type_name)");}break` +} + //////////////////////////////// //~ rjf: CV Leaf -@table(name val) +@table(name header_type_name val) CV_LeafKindTable: { - {MODIFIER_16t 0x0001} - {POINTER_16t 0x0002} - {ARRAY_16t 0x0003} - {CLASS_16t 0x0004} - {STRUCTURE_16t 0x0005} - {UNION_16t 0x0006} - {ENUM_16t 0x0007} - {PROCEDURE_16t 0x0008} - {MFUNCTION_16t 0x0009} - {VTSHAPE 0x000a} - {COBOL0_16t 0x000b} - {COBOL1 0x000c} - {BARRAY_16t 0x000d} - {LABEL 0x000e} - {NULL 0x000f} - {NOTTRAN 0x0010} - {DIMARRAY_16t 0x0011} - {VFTPATH_16t 0x0012} - {PRECOMP_16t 0x0013} - {ENDPRECOMP 0x0014} - {OEM_16t 0x0015} - {TYPESERVER_ST 0x0016} - {SKIP_16t 0x0200} - {ARGLIST_16t 0x0201} - {DEFARG_16t 0x0202} - {LIST 0x0203} - {FIELDLIST_16t 0x0204} - {DERIVED_16t 0x0205} - {BITFIELD_16t 0x0206} - {METHODLIST_16t 0x0207} - {DIMCONU_16t 0x0208} - {DIMCONLU_16t 0x0209} - {DIMVARU_16t 0x020a} - {DIMVARLU_16t 0x020b} - {REFSYM 0x020c} - {BCLASS_16t 0x0400} - {VBCLASS_16t 0x0401} - {IVBCLASS_16t 0x0402} - {ENUMERATE_ST 0x0403} - {FRIENDFCN_16t 0x0404} - {INDEX_16t 0x0405} - {MEMBER_16t 0x0406} - {STMEMBER_16t 0x0407} - {METHOD_16t 0x0408} - {NESTTYPE_16t 0x0409} - {VFUNCTAB_16t 0x040a} - {FRIENDCLS_16t 0x040b} - {ONEMETHOD_16t 0x040c} - {VFUNCOFF_16t 0x040d} - {TI16_MAX 0x1000} - {MODIFIER 0x1001} - {POINTER 0x1002} - {ARRAY_ST 0x1003} - {CLASS_ST 0x1004} - {STRUCTURE_ST 0x1005} - {UNION_ST 0x1006} - {ENUM_ST 0x1007} - {PROCEDURE 0x1008} - {MFUNCTION 0x1009} - {COBOL0 0x100a} - {BARRAY 0x100b} - {DIMARRAY_ST 0x100c} - {VFTPATH 0x100d} - {PRECOMP_ST 0x100e} - {OEM 0x100f} - {ALIAS_ST 0x1010} - {OEM2 0x1011} - {SKIP 0x1200} - {ARGLIST 0x1201} - {DEFARG_ST 0x1202} - {FIELDLIST 0x1203} - {DERIVED 0x1204} - {BITFIELD 0x1205} - {METHODLIST 0x1206} - {DIMCONU 0x1207} - {DIMCONLU 0x1208} - {DIMVARU 0x1209} - {DIMVARLU 0x120a} - {BCLASS 0x1400} - {VBCLASS 0x1401} - {IVBCLASS 0x1402} - {FRIENDFCN_ST 0x1403} - {INDEX 0x1404} - {MEMBER_ST 0x1405} - {STMEMBER_ST 0x1406} - {METHOD_ST 0x1407} - {NESTTYPE_ST 0x1408} - {VFUNCTAB 0x1409} - {FRIENDCLS 0x140a} - {ONEMETHOD_ST 0x140b} - {VFUNCOFF 0x140c} - {NESTTYPEEX_ST 0x140d} - {MEMBERMODIFY_ST 0x140e} - {MANAGED_ST 0x140f} - {ST_MAX 0x1500} - {TYPESERVER 0x1501} - {ENUMERATE 0x1502} - {ARRAY 0x1503} - {CLASS 0x1504} - {STRUCTURE 0x1505} - {UNION 0x1506} - {ENUM 0x1507} - {DIMARRAY 0x1508} - {PRECOMP 0x1509} - {ALIAS 0x150a} - {DEFARG 0x150b} - {FRIENDFCN 0x150c} - {MEMBER 0x150d} - {STMEMBER 0x150e} - {METHOD 0x150f} - {NESTTYPE 0x1510} - {ONEMETHOD 0x1511} - {NESTTYPEEX 0x1512} - {MEMBERMODIFY 0x1513} - {MANAGED 0x1514} - {TYPESERVER2 0x1515} - {STRIDED_ARRAY 0x1516} - {HLSL 0x1517} - {MODIFIER_EX 0x1518} - {INTERFACE 0x1519} - {BINTERFACE 0x151a} - {VECTOR 0x151b} - {MATRIX 0x151c} - {VFTABLE 0x151d} - {CLASS2 0x1608} - {STRUCT2 0x1609} + {MODIFIER_16t - 0x0001} + {POINTER_16t - 0x0002} + {ARRAY_16t - 0x0003} + {CLASS_16t - 0x0004} + {STRUCTURE_16t - 0x0005} + {UNION_16t - 0x0006} + {ENUM_16t - 0x0007} + {PROCEDURE_16t - 0x0008} + {MFUNCTION_16t - 0x0009} + {VTSHAPE VTShape 0x000a} + {COBOL0_16t - 0x000b} + {COBOL1 - 0x000c} + {BARRAY_16t - 0x000d} + {LABEL Label 0x000e} + {NULL - 0x000f} + {NOTTRAN - 0x0010} + {DIMARRAY_16t - 0x0011} + {VFTPATH_16t - 0x0012} + {PRECOMP_16t - 0x0013} + {ENDPRECOMP - 0x0014} + {OEM_16t - 0x0015} + {TYPESERVER_ST - 0x0016} + {SKIP_16t - 0x0200} + {ARGLIST_16t - 0x0201} + {DEFARG_16t - 0x0202} + {LIST - 0x0203} + {FIELDLIST_16t - 0x0204} + {DERIVED_16t - 0x0205} + {BITFIELD_16t - 0x0206} + {METHODLIST_16t - 0x0207} + {DIMCONU_16t - 0x0208} + {DIMCONLU_16t - 0x0209} + {DIMVARU_16t - 0x020a} + {DIMVARLU_16t - 0x020b} + {REFSYM - 0x020c} + {BCLASS_16t - 0x0400} + {VBCLASS_16t - 0x0401} + {IVBCLASS_16t - 0x0402} + {ENUMERATE_ST - 0x0403} + {FRIENDFCN_16t - 0x0404} + {INDEX_16t - 0x0405} + {MEMBER_16t - 0x0406} + {STMEMBER_16t - 0x0407} + {METHOD_16t - 0x0408} + {NESTTYPE_16t - 0x0409} + {VFUNCTAB_16t - 0x040a} + {FRIENDCLS_16t - 0x040b} + {ONEMETHOD_16t - 0x040c} + {VFUNCOFF_16t - 0x040d} + {TI16_MAX - 0x1000} + {MODIFIER Modifier 0x1001} + {POINTER Pointer 0x1002} + {ARRAY_ST - 0x1003} + {CLASS_ST - 0x1004} + {STRUCTURE_ST - 0x1005} + {UNION_ST - 0x1006} + {ENUM_ST - 0x1007} + {PROCEDURE Procedure 0x1008} + {MFUNCTION MFunction 0x1009} + {COBOL0 - 0x100a} + {BARRAY - 0x100b} + {DIMARRAY_ST - 0x100c} + {VFTPATH VFPath 0x100d} + {PRECOMP_ST - 0x100e} + {OEM - 0x100f} + {ALIAS_ST - 0x1010} + {OEM2 - 0x1011} + {SKIP Skip 0x1200} + {ARGLIST ArgList 0x1201} + {DEFARG_ST - 0x1202} + {FIELDLIST - 0x1203} + {DERIVED - 0x1204} + {BITFIELD BitField 0x1205} + {METHODLIST MethodListMember 0x1206} + {DIMCONU - 0x1207} + {DIMCONLU - 0x1208} + {DIMVARU - 0x1209} + {DIMVARLU - 0x120a} + {BCLASS BClass 0x1400} + {VBCLASS VBClass 0x1401} + {IVBCLASS - 0x1402} + {FRIENDFCN_ST - 0x1403} + {INDEX Index 0x1404} + {MEMBER_ST - 0x1405} + {STMEMBER_ST - 0x1406} + {METHOD_ST - 0x1407} + {NESTTYPE_ST - 0x1408} + {VFUNCTAB VFuncTab 0x1409} + {FRIENDCLS - 0x140a} + {ONEMETHOD_ST - 0x140b} + {VFUNCOFF VFuncOff 0x140c} + {NESTTYPEEX_ST - 0x140d} + {MEMBERMODIFY_ST - 0x140e} + {MANAGED_ST - 0x140f} + {ST_MAX - 0x1500} + {TYPESERVER TypeServer 0x1501} + {ENUMERATE Enumerate 0x1502} + {ARRAY Array 0x1503} + {CLASS Struct 0x1504} + {STRUCTURE Struct 0x1505} + {UNION Union 0x1506} + {ENUM Enum 0x1507} + {DIMARRAY - 0x1508} + {PRECOMP PreComp 0x1509} + {ALIAS Alias 0x150a} + {DEFARG - 0x150b} + {FRIENDFCN - 0x150c} + {MEMBER Member 0x150d} + {STMEMBER StMember 0x150e} + {METHOD Method 0x150f} + {NESTTYPE NestType 0x1510} + {ONEMETHOD OneMethod 0x1511} + {NESTTYPEEX NestTypeEx 0x1512} + {MEMBERMODIFY - 0x1513} + {MANAGED - 0x1514} + {TYPESERVER2 TypeServer2 0x1515} + {STRIDED_ARRAY - 0x1516} + {HLSL - 0x1517} + {MODIFIER_EX - 0x1518} + {INTERFACE Struct 0x1519} + {BINTERFACE - 0x151a} + {VECTOR - 0x151b} + {MATRIX - 0x151c} + {VFTABLE - 0x151d} + {CLASS2 Struct2 0x1608} + {STRUCT2 Struct2 0x1609} } @enum(U16) CV_LeafKind: @@ -524,3 +600,23 @@ cv_string_from_leaf_kind: { @expand(CV_LeafKindTable a) `case CV_LeafKind_$(a.name):{result = str8_lit("$(a.name)");}break`; } + +@gen(functions) +{ + `internal U64 cv_header_struct_size_from_leaf_kind(CV_LeafKind v);`; +} + +@gen(functions) @c_file +{ + `internal U64`; + `cv_header_struct_size_from_leaf_kind(CV_LeafKind v)`; + `{`; + `U64 result = 0;`; + `switch(v)`; + `{`; + `default:{}break;`; + @expand(CV_LeafKindTable a) `$(a.header_type_name != "-" -> "case CV_LeafKind_"..a.name..":{result = sizeof(CV_Leaf"..a.header_type_name..");}break;")`; + `}`; + `return result;`; + `}`; +} diff --git a/src/codeview/codeview_stringize.c b/src/codeview/codeview_stringize.c index 983b078e..9c1245ae 100644 --- a/src/codeview/codeview_stringize.c +++ b/src/codeview/codeview_stringize.c @@ -48,17 +48,6 @@ cv_stringize_lvar_addr_gap_list(Arena *arena, String8List *out, void *first, voi } } -internal String8 -cv_string_from_basic_type(CV_BasicType basic_type){ - String8 result = str8_lit("UNRECOGNIZED_BASIC_TYPE"); - switch (basic_type){ -#define X(N,c) case CV_BasicType_##N: result = str8_lit(#N); break; - CV_BasicTypeXList(X) -#undef X - } - return(result); -} - internal String8 cv_string_from_c13_sub_section_kind(CV_C13_SubSectionKind kind){ String8 result = str8_lit("UNRECOGNIZED_C13_SUB_SECTION_KIND"); diff --git a/src/codeview/generated/codeview.meta.c b/src/codeview/generated/codeview.meta.c index b65dc4fc..2aaef62e 100644 --- a/src/codeview/generated/codeview.meta.c +++ b/src/codeview/generated/codeview.meta.c @@ -312,6 +312,134 @@ case CV_SymKind_INLINEES:{result = str8_lit("INLINEES");}break; return result; } +internal String8 +cv_string_from_basic_type(CV_BasicType v) +{ +String8 result = str8_lit(""); +switch(v) +{ +default:{}break; +case CV_BasicType_NOTYPE:{result = str8_lit("NOTYPE");}break; +case CV_BasicType_ABS:{result = str8_lit("ABS");}break; +case CV_BasicType_SEGMENT:{result = str8_lit("SEGMENT");}break; +case CV_BasicType_VOID:{result = str8_lit("VOID");}break; +case CV_BasicType_CURRENCY:{result = str8_lit("CURRENCY");}break; +case CV_BasicType_NBASICSTR:{result = str8_lit("NBASICSTR");}break; +case CV_BasicType_FBASICSTR:{result = str8_lit("FBASICSTR");}break; +case CV_BasicType_NOTTRANS:{result = str8_lit("NOTTRANS");}break; +case CV_BasicType_HRESULT:{result = str8_lit("HRESULT");}break; +case CV_BasicType_CHAR:{result = str8_lit("CHAR");}break; +case CV_BasicType_SHORT:{result = str8_lit("SHORT");}break; +case CV_BasicType_LONG:{result = str8_lit("LONG");}break; +case CV_BasicType_QUAD:{result = str8_lit("QUAD");}break; +case CV_BasicType_OCT:{result = str8_lit("OCT");}break; +case CV_BasicType_UCHAR:{result = str8_lit("UCHAR");}break; +case CV_BasicType_USHORT:{result = str8_lit("USHORT");}break; +case CV_BasicType_ULONG:{result = str8_lit("ULONG");}break; +case CV_BasicType_UQUAD:{result = str8_lit("UQUAD");}break; +case CV_BasicType_UOCT:{result = str8_lit("UOCT");}break; +case CV_BasicType_BOOL8:{result = str8_lit("BOOL8");}break; +case CV_BasicType_BOOL16:{result = str8_lit("BOOL16");}break; +case CV_BasicType_BOOL32:{result = str8_lit("BOOL32");}break; +case CV_BasicType_BOOL64:{result = str8_lit("BOOL64");}break; +case CV_BasicType_FLOAT32:{result = str8_lit("FLOAT32");}break; +case CV_BasicType_FLOAT64:{result = str8_lit("FLOAT64");}break; +case CV_BasicType_FLOAT80:{result = str8_lit("FLOAT80");}break; +case CV_BasicType_FLOAT128:{result = str8_lit("FLOAT128");}break; +case CV_BasicType_FLOAT48:{result = str8_lit("FLOAT48");}break; +case CV_BasicType_FLOAT32PP:{result = str8_lit("FLOAT32PP");}break; +case CV_BasicType_FLOAT16:{result = str8_lit("FLOAT16");}break; +case CV_BasicType_COMPLEX32:{result = str8_lit("COMPLEX32");}break; +case CV_BasicType_COMPLEX64:{result = str8_lit("COMPLEX64");}break; +case CV_BasicType_COMPLEX80:{result = str8_lit("COMPLEX80");}break; +case CV_BasicType_COMPLEX128:{result = str8_lit("COMPLEX128");}break; +case CV_BasicType_BIT:{result = str8_lit("BIT");}break; +case CV_BasicType_PASCHAR:{result = str8_lit("PASCHAR");}break; +case CV_BasicType_BOOL32FF:{result = str8_lit("BOOL32FF");}break; +case CV_BasicType_INT8:{result = str8_lit("INT8");}break; +case CV_BasicType_UINT8:{result = str8_lit("UINT8");}break; +case CV_BasicType_RCHAR:{result = str8_lit("RCHAR");}break; +case CV_BasicType_WCHAR:{result = str8_lit("WCHAR");}break; +case CV_BasicType_INT16:{result = str8_lit("INT16");}break; +case CV_BasicType_UINT16:{result = str8_lit("UINT16");}break; +case CV_BasicType_INT32:{result = str8_lit("INT32");}break; +case CV_BasicType_UINT32:{result = str8_lit("UINT32");}break; +case CV_BasicType_INT64:{result = str8_lit("INT64");}break; +case CV_BasicType_UINT64:{result = str8_lit("UINT64");}break; +case CV_BasicType_INT128:{result = str8_lit("INT128");}break; +case CV_BasicType_UINT128:{result = str8_lit("UINT128");}break; +case CV_BasicType_CHAR16:{result = str8_lit("CHAR16");}break; +case CV_BasicType_CHAR32:{result = str8_lit("CHAR32");}break; +case CV_BasicType_CHAR8:{result = str8_lit("CHAR8");}break; +case CV_BasicType_PTR:{result = str8_lit("PTR");}break; +} +return result; +} + +internal String8 +cv_type_name_from_basic_type(CV_BasicType v) +{ +String8 result = str8_lit(""); +switch(v) +{ +default:{}break; +case CV_BasicType_NOTYPE:{result = str8_lit("");}break; +case CV_BasicType_ABS:{result = str8_lit("");}break; +case CV_BasicType_SEGMENT:{result = str8_lit("");}break; +case CV_BasicType_VOID:{result = str8_lit("void");}break; +case CV_BasicType_CURRENCY:{result = str8_lit("");}break; +case CV_BasicType_NBASICSTR:{result = str8_lit("");}break; +case CV_BasicType_FBASICSTR:{result = str8_lit("");}break; +case CV_BasicType_NOTTRANS:{result = str8_lit("");}break; +case CV_BasicType_HRESULT:{result = str8_lit("HRESULT");}break; +case CV_BasicType_CHAR:{result = str8_lit("char");}break; +case CV_BasicType_SHORT:{result = str8_lit("S16");}break; +case CV_BasicType_LONG:{result = str8_lit("S32");}break; +case CV_BasicType_QUAD:{result = str8_lit("S64");}break; +case CV_BasicType_OCT:{result = str8_lit("S128");}break; +case CV_BasicType_UCHAR:{result = str8_lit("UCHAR");}break; +case CV_BasicType_USHORT:{result = str8_lit("U16");}break; +case CV_BasicType_ULONG:{result = str8_lit("U32");}break; +case CV_BasicType_UQUAD:{result = str8_lit("U64");}break; +case CV_BasicType_UOCT:{result = str8_lit("U128");}break; +case CV_BasicType_BOOL8:{result = str8_lit("B8");}break; +case CV_BasicType_BOOL16:{result = str8_lit("B16");}break; +case CV_BasicType_BOOL32:{result = str8_lit("B32");}break; +case CV_BasicType_BOOL64:{result = str8_lit("B64");}break; +case CV_BasicType_FLOAT32:{result = str8_lit("F32");}break; +case CV_BasicType_FLOAT64:{result = str8_lit("F64");}break; +case CV_BasicType_FLOAT80:{result = str8_lit("F80");}break; +case CV_BasicType_FLOAT128:{result = str8_lit("F128");}break; +case CV_BasicType_FLOAT48:{result = str8_lit("F48");}break; +case CV_BasicType_FLOAT32PP:{result = str8_lit("F32PP");}break; +case CV_BasicType_FLOAT16:{result = str8_lit("F16");}break; +case CV_BasicType_COMPLEX32:{result = str8_lit("ComplexF32");}break; +case CV_BasicType_COMPLEX64:{result = str8_lit("ComplexF64");}break; +case CV_BasicType_COMPLEX80:{result = str8_lit("ComplexF80");}break; +case CV_BasicType_COMPLEX128:{result = str8_lit("ComplexF128");}break; +case CV_BasicType_BIT:{result = str8_lit("");}break; +case CV_BasicType_PASCHAR:{result = str8_lit("");}break; +case CV_BasicType_BOOL32FF:{result = str8_lit("B32FF");}break; +case CV_BasicType_INT8:{result = str8_lit("S8");}break; +case CV_BasicType_UINT8:{result = str8_lit("U8");}break; +case CV_BasicType_RCHAR:{result = str8_lit("char");}break; +case CV_BasicType_WCHAR:{result = str8_lit("WCHAR");}break; +case CV_BasicType_INT16:{result = str8_lit("S16");}break; +case CV_BasicType_UINT16:{result = str8_lit("U16");}break; +case CV_BasicType_INT32:{result = str8_lit("S32");}break; +case CV_BasicType_UINT32:{result = str8_lit("U32");}break; +case CV_BasicType_INT64:{result = str8_lit("S64");}break; +case CV_BasicType_UINT64:{result = str8_lit("U64");}break; +case CV_BasicType_INT128:{result = str8_lit("S128");}break; +case CV_BasicType_UINT128:{result = str8_lit("U128");}break; +case CV_BasicType_CHAR16:{result = str8_lit("CHAR16");}break; +case CV_BasicType_CHAR32:{result = str8_lit("CHAR32");}break; +case CV_BasicType_CHAR8:{result = str8_lit("char");}break; +case CV_BasicType_PTR:{result = str8_lit("PTR");}break; +} +return result; +} + internal String8 cv_string_from_leaf_kind(CV_LeafKind v) { @@ -528,6 +656,51 @@ case CV_SymKind_INLINEES:{result = sizeof(CV_SymInlinees);}break; } return result; } +internal U64 +cv_header_struct_size_from_leaf_kind(CV_LeafKind v) +{ +U64 result = 0; +switch(v) +{ +default:{}break; +case CV_LeafKind_VTSHAPE:{result = sizeof(CV_LeafVTShape);}break; +case CV_LeafKind_LABEL:{result = sizeof(CV_LeafLabel);}break; +case CV_LeafKind_MODIFIER:{result = sizeof(CV_LeafModifier);}break; +case CV_LeafKind_POINTER:{result = sizeof(CV_LeafPointer);}break; +case CV_LeafKind_PROCEDURE:{result = sizeof(CV_LeafProcedure);}break; +case CV_LeafKind_MFUNCTION:{result = sizeof(CV_LeafMFunction);}break; +case CV_LeafKind_VFTPATH:{result = sizeof(CV_LeafVFPath);}break; +case CV_LeafKind_SKIP:{result = sizeof(CV_LeafSkip);}break; +case CV_LeafKind_ARGLIST:{result = sizeof(CV_LeafArgList);}break; +case CV_LeafKind_BITFIELD:{result = sizeof(CV_LeafBitField);}break; +case CV_LeafKind_METHODLIST:{result = sizeof(CV_LeafMethodListMember);}break; +case CV_LeafKind_BCLASS:{result = sizeof(CV_LeafBClass);}break; +case CV_LeafKind_VBCLASS:{result = sizeof(CV_LeafVBClass);}break; +case CV_LeafKind_INDEX:{result = sizeof(CV_LeafIndex);}break; +case CV_LeafKind_VFUNCTAB:{result = sizeof(CV_LeafVFuncTab);}break; +case CV_LeafKind_VFUNCOFF:{result = sizeof(CV_LeafVFuncOff);}break; +case CV_LeafKind_TYPESERVER:{result = sizeof(CV_LeafTypeServer);}break; +case CV_LeafKind_ENUMERATE:{result = sizeof(CV_LeafEnumerate);}break; +case CV_LeafKind_ARRAY:{result = sizeof(CV_LeafArray);}break; +case CV_LeafKind_CLASS:{result = sizeof(CV_LeafStruct);}break; +case CV_LeafKind_STRUCTURE:{result = sizeof(CV_LeafStruct);}break; +case CV_LeafKind_UNION:{result = sizeof(CV_LeafUnion);}break; +case CV_LeafKind_ENUM:{result = sizeof(CV_LeafEnum);}break; +case CV_LeafKind_PRECOMP:{result = sizeof(CV_LeafPreComp);}break; +case CV_LeafKind_ALIAS:{result = sizeof(CV_LeafAlias);}break; +case CV_LeafKind_MEMBER:{result = sizeof(CV_LeafMember);}break; +case CV_LeafKind_STMEMBER:{result = sizeof(CV_LeafStMember);}break; +case CV_LeafKind_METHOD:{result = sizeof(CV_LeafMethod);}break; +case CV_LeafKind_NESTTYPE:{result = sizeof(CV_LeafNestType);}break; +case CV_LeafKind_ONEMETHOD:{result = sizeof(CV_LeafOneMethod);}break; +case CV_LeafKind_NESTTYPEEX:{result = sizeof(CV_LeafNestTypeEx);}break; +case CV_LeafKind_TYPESERVER2:{result = sizeof(CV_LeafTypeServer2);}break; +case CV_LeafKind_INTERFACE:{result = sizeof(CV_LeafStruct);}break; +case CV_LeafKind_CLASS2:{result = sizeof(CV_LeafStruct2);}break; +case CV_LeafKind_STRUCT2:{result = sizeof(CV_LeafStruct2);}break; +} +return result; +} C_LINKAGE_BEGIN C_LINKAGE_END diff --git a/src/codeview/generated/codeview.meta.h b/src/codeview/generated/codeview.meta.h index fe61870e..b30192a7 100644 --- a/src/codeview/generated/codeview.meta.h +++ b/src/codeview/generated/codeview.meta.h @@ -320,6 +320,64 @@ CV_SymKind_FASTLINK = 0x1167, CV_SymKind_INLINEES = 0x1168, } CV_SymKindEnum; +typedef U8 CV_BasicType; +typedef enum CV_BasicTypeEnum +{ +CV_BasicType_NOTYPE = 0x00, +CV_BasicType_ABS = 0x01, +CV_BasicType_SEGMENT = 0x02, +CV_BasicType_VOID = 0x03, +CV_BasicType_CURRENCY = 0x04, +CV_BasicType_NBASICSTR = 0x05, +CV_BasicType_FBASICSTR = 0x06, +CV_BasicType_NOTTRANS = 0x07, +CV_BasicType_HRESULT = 0x08, +CV_BasicType_CHAR = 0x10, +CV_BasicType_SHORT = 0x11, +CV_BasicType_LONG = 0x12, +CV_BasicType_QUAD = 0x13, +CV_BasicType_OCT = 0x14, +CV_BasicType_UCHAR = 0x20, +CV_BasicType_USHORT = 0x21, +CV_BasicType_ULONG = 0x22, +CV_BasicType_UQUAD = 0x23, +CV_BasicType_UOCT = 0x24, +CV_BasicType_BOOL8 = 0x30, +CV_BasicType_BOOL16 = 0x31, +CV_BasicType_BOOL32 = 0x32, +CV_BasicType_BOOL64 = 0x33, +CV_BasicType_FLOAT32 = 0x40, +CV_BasicType_FLOAT64 = 0x41, +CV_BasicType_FLOAT80 = 0x42, +CV_BasicType_FLOAT128 = 0x43, +CV_BasicType_FLOAT48 = 0x44, +CV_BasicType_FLOAT32PP = 0x45, +CV_BasicType_FLOAT16 = 0x46, +CV_BasicType_COMPLEX32 = 0x50, +CV_BasicType_COMPLEX64 = 0x51, +CV_BasicType_COMPLEX80 = 0x52, +CV_BasicType_COMPLEX128 = 0x53, +CV_BasicType_BIT = 0x60, +CV_BasicType_PASCHAR = 0x61, +CV_BasicType_BOOL32FF = 0x62, +CV_BasicType_INT8 = 0x68, +CV_BasicType_UINT8 = 0x69, +CV_BasicType_RCHAR = 0x70, +CV_BasicType_WCHAR = 0x71, +CV_BasicType_INT16 = 0x72, +CV_BasicType_UINT16 = 0x73, +CV_BasicType_INT32 = 0x74, +CV_BasicType_UINT32 = 0x75, +CV_BasicType_INT64 = 0x76, +CV_BasicType_UINT64 = 0x77, +CV_BasicType_INT128 = 0x78, +CV_BasicType_UINT128 = 0x79, +CV_BasicType_CHAR16 = 0x7a, +CV_BasicType_CHAR32 = 0x7b, +CV_BasicType_CHAR8 = 0x7c, +CV_BasicType_PTR = 0xf0, +} CV_BasicTypeEnum; + typedef U16 CV_LeafKind; typedef enum CV_LeafKindEnum { @@ -454,8 +512,11 @@ CV_LeafKind_STRUCT2 = 0x1609, internal String8 cv_string_from_numeric_kind(CV_NumericKind v); internal String8 cv_string_from_arch(CV_Arch v); internal String8 cv_string_from_sym_kind(CV_SymKind v); +internal String8 cv_string_from_basic_type(CV_BasicType v); +internal String8 cv_type_name_from_basic_type(CV_BasicType v); internal String8 cv_string_from_leaf_kind(CV_LeafKind v); internal U64 cv_header_struct_size_from_sym_kind(CV_SymKind v); +internal U64 cv_header_struct_size_from_leaf_kind(CV_LeafKind v); C_LINKAGE_BEGIN C_LINKAGE_END diff --git a/src/lib_raddbgi_make/raddbgi_make.c b/src/lib_raddbgi_make/raddbgi_make.c index cab11028..0a5c495d 100644 --- a/src/lib_raddbgi_make/raddbgi_make.c +++ b/src/lib_raddbgi_make/raddbgi_make.c @@ -4,8 +4,8 @@ //////////////////////////////// //~ rjf: API Implementation Helper Macros -#define rdim_require(root, b32, else_code, error_msg) do { if(!(b32)) {rdim_push_error((root), (error_msg)); else_code;} }while(0) -#define rdim_requiref(root, b32, else_code, fmt, ...) do { if(!(b32)) {rdim_push_errorf((root), (fmt), __VA_ARGS__); else_code;} }while(0) +#define rdim_require(root, b32, else_code, error_msg) do { if(!(b32)) {rdim_push_msg((root), (error_msg)); else_code;} }while(0) +#define rdim_requiref(root, b32, else_code, fmt, ...) do { if(!(b32)) {rdim_push_msgf((root), (fmt), __VA_ARGS__); else_code;} }while(0) //////////////////////////////// //~ rjf: Basic Helpers @@ -234,99 +234,6 @@ rdim_str8_list_join(RDIM_Arena *arena, RDIM_String8List *list, RDIM_String8 sep) return result; } -//- rjf: type lists - -RDI_PROC void -rdim_type_list_push(RDIM_Arena *arena, RDIM_TypeList *list, RDIM_Type *type) -{ - RDIM_TypeNode *node = rdim_push_array(arena, RDIM_TypeNode, 1); - RDIM_SLLQueuePush(list->first, list->last, node); - list->count += 1; - node->type = type; -} - -//- rjf: bytecode lists - -RDI_PROC void -rdim_bytecode_push_op(RDIM_Arena *arena, RDIM_EvalBytecode *bytecode, RDI_EvalOp op, RDI_U64 p) -{ - RDI_U8 ctrlbits = rdi_eval_opcode_ctrlbits[op]; - RDI_U32 p_size = RDI_DECODEN_FROM_CTRLBITS(ctrlbits); - - RDIM_EvalBytecodeOp *node = rdim_push_array(arena, RDIM_EvalBytecodeOp, 1); - node->op = op; - node->p_size = p_size; - node->p = p; - - RDIM_SLLQueuePush(bytecode->first_op, bytecode->last_op, node); - bytecode->op_count += 1; - bytecode->encoded_size += 1 + p_size; -} - -RDI_PROC void -rdim_bytecode_push_uconst(RDIM_Arena *arena, RDIM_EvalBytecode *bytecode, RDI_U64 x) -{ - if(x <= 0xFF) - { - rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU8, x); - } - else if(x <= 0xFFFF) - { - rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU16, x); - } - else if(x <= 0xFFFFFFFF) - { - rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU32, x); - } - else - { - rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU64, x); - } -} - -RDI_PROC void -rdim_bytecode_push_sconst(RDIM_Arena *arena, RDIM_EvalBytecode *bytecode, RDI_S64 x) -{ - if(-0x80 <= x && x <= 0x7F) - { - rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU8, (RDI_U64)x); - rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_TruncSigned, 8); - } - else if(-0x8000 <= x && x <= 0x7FFF) - { - rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU16, (RDI_U64)x); - rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_TruncSigned, 16); - } - else if(-0x80000000ll <= x && x <= 0x7FFFFFFFll) - { - rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU32, (RDI_U64)x); - rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_TruncSigned, 32); - } - else - { - rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU64, (RDI_U64)x); - } -} - -RDI_PROC void -rdim_bytecode_concat_in_place(RDIM_EvalBytecode *left_dst, RDIM_EvalBytecode *right_destroyed) -{ - if(right_destroyed->first_op != 0) - { - if(left_dst->first_op == 0) - { - rdim_memcpy_struct(left_dst, right_destroyed); - } - else - { - left_dst->last_op = right_destroyed->last_op; - left_dst->op_count += right_destroyed->op_count; - left_dst->encoded_size += right_destroyed->encoded_size; - } - rdim_memzero_struct(right_destroyed); - } -} - //- rjf: sortable range sorting RDI_PROC RDIM_SortKey* @@ -492,6 +399,17 @@ rdim_sort_key_array(RDIM_Arena *arena, RDIM_SortKey *keys, RDI_U64 count) //////////////////////////////// //~ rjf: Auxiliary Data Structure Functions +//- rjf: rng1u64 list + +RDI_PROC void +rdim_rng1u64_list_push(RDIM_Arena *arena, RDIM_Rng1U64List *list, RDIM_Rng1U64 r) +{ + RDIM_Rng1U64Node *n = rdim_push_array(arena, RDIM_Rng1U64Node, 1); + n->v = r; + RDIM_SLLQueuePush(list->first, list->last, n); + list->count += 1; +} + //- rjf: u64 -> ptr map RDI_PROC void @@ -590,6 +508,247 @@ rdim_str8toptr_map_insert(RDIM_Arena *arena, RDIM_Str8ToPtrMap *map, RDIM_String map->pair_count += 1; } +//////////////////////////////// +//~ rjf: Binary Section List Building + +RDI_PROC RDIM_BinarySection * +rdim_binary_section_list_push(RDIM_Arena *arena, RDIM_BinarySectionList *list) +{ + RDIM_BinarySectionNode *n = rdim_push_array(arena, RDIM_BinarySectionNode, 1); + RDIM_SLLQueuePush(list->first, list->last, n); + list->count += 1; + RDIM_BinarySection *result = &n->v; + return result; +} + +//////////////////////////////// +//~ rjf: Unit List Building + +RDI_PROC RDIM_Unit * +rdim_unit_chunk_list_push(RDIM_Arena *arena, RDIM_UnitChunkList *list) +{ + RDIM_UnitChunkNode *n = list->last; + if(n == 0 || n->count >= n->cap) + { + n = rdim_push_array(arena, RDIM_UnitChunkNode, 1); + n->cap = 512; + n->v = rdim_push_array_no_zero(arena, RDIM_Unit, n->cap); + RDIM_SLLQueuePush(list->first, list->last, n); + list->chunk_count += 1; + } + RDIM_Unit *unit = &n->v[n->count]; + n->count += 1; + list->total_count += 1; + return unit; +} + +RDI_PROC RDIM_LineSequence * +rdim_line_sequence_list_push(RDIM_Arena *arena, RDIM_LineSequenceList *list) +{ + RDIM_LineSequenceNode *n = rdim_push_array(arena, RDIM_LineSequenceNode, 1); + RDIM_SLLQueuePush(list->first, list->last, n); + list->count += 1; + return &n->v; +} + +RDI_PROC RDIM_UnitArray +rdim_unit_array_from_chunk_list(RDIM_Arena *arena, RDIM_UnitChunkList *list) +{ + RDIM_UnitArray array = {0}; + array.count = list->total_count; + array.v = rdim_push_array_no_zero(arena, RDIM_Unit, array.count); + U64 idx = 0; + for(RDIM_UnitChunkNode *n = list->first; n != 0; n = n->next) + { + rdim_memcpy(array.v+idx, n->v, sizeof(RDIM_Unit)*n->count); + idx += n->count; + } + return array; +} + +//////////////////////////////// +//~ rjf: Type Info Building + +RDI_PROC RDIM_Type * +rdim_type_chunk_list_push(RDIM_Arena *arena, RDIM_TypeChunkList *list, RDI_U64 cap) +{ + RDIM_TypeChunkNode *n = list->last; + if(n == 0 || n->count >= n->cap) + { + n = rdim_push_array(arena, RDIM_TypeChunkNode, 1); + n->cap = cap; + n->v = rdim_push_array_no_zero(arena, RDIM_Type, n->cap); + RDIM_SLLQueuePush(list->first, list->last, n); + list->chunk_count += 1; + } + RDIM_Type *result = &n->v[n->count]; + n->count += 1; + list->total_count += 1; + return result; +} + +RDI_PROC RDIM_UDT * +rdim_udt_chunk_list_push(RDIM_Arena *arena, RDIM_UDTChunkList *list, RDI_U64 cap) +{ + RDIM_UDTChunkNode *n = list->last; + if(n == 0 || n->count >= n->cap) + { + n = rdim_push_array(arena, RDIM_UDTChunkNode, 1); + n->cap = cap; + n->v = rdim_push_array_no_zero(arena, RDIM_UDT, n->cap); + RDIM_SLLQueuePush(list->first, list->last, n); + list->chunk_count += 1; + } + RDIM_UDT *result = &n->v[n->count]; + n->count += 1; + list->total_count += 1; + return result; +} + +RDI_PROC RDIM_UDTMember * +rdim_udt_push_member(RDIM_Arena *arena, RDIM_UDT *udt) +{ + RDIM_UDTMember *mem = rdim_push_array(arena, RDIM_UDTMember, 1); + RDIM_SLLQueuePush(udt->first_member, udt->last_member, mem); + udt->member_count += 1; + return mem; +} + +RDI_PROC RDIM_UDTEnumVal * +rdim_udt_push_enum_val(RDIM_Arena *arena, RDIM_UDT *udt) +{ + RDIM_UDTEnumVal *mem = rdim_push_array(arena, RDIM_UDTEnumVal, 1); + RDIM_SLLQueuePush(udt->first_enum_val, udt->last_enum_val, mem); + udt->enum_val_count += 1; + return mem; +} + +//////////////////////////////// +//~ rjf: Location Info Building + +RDI_PROC void +rdim_bytecode_push_op(RDIM_Arena *arena, RDIM_EvalBytecode *bytecode, RDI_EvalOp op, RDI_U64 p) +{ + RDI_U8 ctrlbits = rdi_eval_opcode_ctrlbits[op]; + RDI_U32 p_size = RDI_DECODEN_FROM_CTRLBITS(ctrlbits); + + RDIM_EvalBytecodeOp *node = rdim_push_array(arena, RDIM_EvalBytecodeOp, 1); + node->op = op; + node->p_size = p_size; + node->p = p; + + RDIM_SLLQueuePush(bytecode->first_op, bytecode->last_op, node); + bytecode->op_count += 1; + bytecode->encoded_size += 1 + p_size; +} + +RDI_PROC void +rdim_bytecode_push_uconst(RDIM_Arena *arena, RDIM_EvalBytecode *bytecode, RDI_U64 x) +{ + if(x <= 0xFF) + { + rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU8, x); + } + else if(x <= 0xFFFF) + { + rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU16, x); + } + else if(x <= 0xFFFFFFFF) + { + rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU32, x); + } + else + { + rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU64, x); + } +} + +RDI_PROC void +rdim_bytecode_push_sconst(RDIM_Arena *arena, RDIM_EvalBytecode *bytecode, RDI_S64 x) +{ + if(-0x80 <= x && x <= 0x7F) + { + rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU8, (RDI_U64)x); + rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_TruncSigned, 8); + } + else if(-0x8000 <= x && x <= 0x7FFF) + { + rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU16, (RDI_U64)x); + rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_TruncSigned, 16); + } + else if(-0x80000000ll <= x && x <= 0x7FFFFFFFll) + { + rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU32, (RDI_U64)x); + rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_TruncSigned, 32); + } + else + { + rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU64, (RDI_U64)x); + } +} + +RDI_PROC void +rdim_bytecode_concat_in_place(RDIM_EvalBytecode *left_dst, RDIM_EvalBytecode *right_destroyed) +{ + if(right_destroyed->first_op != 0) + { + if(left_dst->first_op == 0) + { + rdim_memcpy_struct(left_dst, right_destroyed); + } + else + { + left_dst->last_op = right_destroyed->last_op; + left_dst->op_count += right_destroyed->op_count; + left_dst->encoded_size += right_destroyed->encoded_size; + } + rdim_memzero_struct(right_destroyed); + } +} + +//////////////////////////////// +//~ rjf: Symbol Info Building + +RDI_PROC RDIM_Symbol * +rdim_symbol_chunk_list_push(RDIM_Arena *arena, RDIM_SymbolChunkList *list, RDI_U64 cap) +{ + RDIM_SymbolChunkNode *n = list->last; + if(n == 0 || n->count >= n->cap) + { + n = rdim_push_array(arena, RDIM_SymbolChunkNode, 1); + n->cap = cap; + n->v = rdim_push_array_no_zero(arena, RDIM_Symbol, n->cap); + RDIM_SLLQueuePush(list->first, list->last, n); + list->chunk_count += 1; + } + RDIM_Symbol *result = &n->v[n->count]; + n->count += 1; + list->total_count += 1; + return result; +} + +//////////////////////////////// +//~ rjf: Scope Info Building + +RDI_PROC RDIM_Scope * +rdim_scope_chunk_list_push(RDIM_Arena *arena, RDIM_ScopeChunkList *list, RDI_U64 cap) +{ + RDIM_ScopeChunkNode *n = list->last; + if(n == 0 || n->count >= n->cap) + { + n = rdim_push_array(arena, RDIM_ScopeChunkNode, 1); + n->cap = cap; + n->v = rdim_push_array_no_zero(arena, RDIM_Scope, n->cap); + RDIM_SLLQueuePush(list->first, list->last, n); + list->chunk_count += 1; + } + RDIM_Scope *result = &n->v[n->count]; + n->count += 1; + list->total_count += 1; + return result; +} + +#if 0 //////////////////////////////// //~ rjf: Loose Debug Info Construction (Anything -> Loose) Functions @@ -657,126 +816,28 @@ rdim_root_release(RDIM_Root *root) //- rjf: error accumulation RDI_PROC void -rdim_push_error(RDIM_Root *root, RDIM_String8 string) +rdim_push_msg(RDIM_Root *root, RDIM_String8 string) { - RDIM_Error *error = rdim_push_array(root->arena, RDIM_Error, 1); - SLLQueuePush(root->errors.first, root->errors.last, error); - root->errors.count += 1; - error->msg = string; + RDIM_Msg *msg = rdim_push_array(root->arena, RDIM_Msg, 1); + SLLQueuePush(root->msgs.first, root->msgs.last, msg); + root->msgs.count += 1; + msg->string = string; } RDI_PROC void -rdim_push_errorf(RDIM_Root *root, char *fmt, ...) +rdim_push_msgf(RDIM_Root *root, char *fmt, ...) { va_list args; va_start(args, fmt); RDIM_String8 str = rdim_str8fv(root->arena, fmt, args); - rdim_push_error(root, str); + rdim_push_msg(root, str); va_end(args); } -RDI_PROC RDIM_Error* -rdim_first_error_from_root(RDIM_Root *root) +RDI_PROC RDIM_Msg * +rdim_first_msg_from_root(RDIM_Root *root) { - return root->errors.first; -} - -//- rjf: top-level info specification - -RDI_PROC void -rdim_set_top_level_info(RDIM_Root *root, RDIM_TopLevelInfo *tli) -{ - rdim_requiref(root, !root->top_level_info_is_set, return, "Top level information set multiple times."); - rdim_memcpy_struct(&root->top_level_info, tli); - root->top_level_info_is_set = 1; -} - -//- rjf: binary section building - -RDI_PROC void -rdim_add_binary_section(RDIM_Root *root, RDIM_String8 name, RDI_BinarySectionFlags flags, RDI_U64 voff_first, RDI_U64 voff_opl, RDI_U64 foff_first, RDI_U64 foff_opl) -{ - RDIM_BinarySection *sec = rdim_push_array(root->arena, RDIM_BinarySection, 1); - SLLQueuePush(root->binary_section_first, root->binary_section_last, sec); - root->binary_section_count += 1; - sec->name = name; - sec->flags = flags; - sec->voff_first = voff_first; - sec->voff_opl = voff_opl; - sec->foff_first = foff_first; - sec->foff_opl = foff_opl; -} - -//- rjf: unit info building - -RDI_PROC RDIM_Unit* -rdim_unit_handle_from_user_id(RDIM_Root *root, RDI_U64 unit_user_id, RDI_U64 unit_user_id_hash) -{ - RDIM_U64ToPtrLookup lookup = {0}; - rdim_u64toptr_map_lookup(&root->unit_map, unit_user_id, unit_user_id_hash, &lookup); - RDIM_Unit *result = 0; - if(lookup.match != 0) - { - result = (RDIM_Unit*)lookup.match; - } - else - { - result = rdim_push_array(root->arena, RDIM_Unit, 1); - result->idx = root->unit_count; - RDIM_SLLQueuePush_N(root->unit_first, root->unit_last, result, next_order); - root->unit_count += 1; - rdim_u64toptr_map_insert(root->arena, &root->unit_map, unit_user_id, unit_user_id, &lookup, result); - } - return result; -} - -RDI_PROC void -rdim_unit_set_info(RDIM_Root *root, RDIM_Unit *unit, RDIM_UnitInfo *info) -{ - rdim_requiref(root, !unit->info_is_set, return, "Unit information set multiple times."); - unit->info_is_set = 1; - unit->unit_name = rdim_str8_copy(root->arena, info->unit_name); - unit->compiler_name = rdim_str8_copy(root->arena, info->compiler_name); - unit->source_file = rdim_str8_copy(root->arena, info->source_file); - unit->object_file = rdim_str8_copy(root->arena, info->object_file); - unit->archive_file = rdim_str8_copy(root->arena, info->archive_file); - unit->build_path = rdim_str8_copy(root->arena, info->build_path); - unit->language = info->language; -} - -RDI_PROC void -rdim_unit_add_line_sequence(RDIM_Root *root, RDIM_Unit *unit, RDIM_LineSequence *line_sequence) -{ - RDIM_LineSequenceNode *node = rdim_push_array(root->arena, RDIM_LineSequenceNode, 1); - SLLQueuePush(unit->line_seq_first, unit->line_seq_last, node); - unit->line_seq_count += 1; - - node->line_seq.file_name = rdim_str8_copy(root->arena, line_sequence->file_name); - - node->line_seq.voffs = rdim_push_array(root->arena, RDI_U64, line_sequence->line_count + 1); - rdim_memcpy(node->line_seq.voffs, line_sequence->voffs, sizeof(RDI_U64)*(line_sequence->line_count + 1)); - - node->line_seq.line_nums = rdim_push_array(root->arena, RDI_U32, line_sequence->line_count); - rdim_memcpy(node->line_seq.line_nums, line_sequence->line_nums, sizeof(RDI_U32)*line_sequence->line_count); - - if(line_sequence->col_nums != 0) - { - node->line_seq.col_nums = rdim_push_array(root->arena, RDI_U16, line_sequence->line_count); - rdim_memcpy(node->line_seq.col_nums, line_sequence->col_nums, sizeof(RDI_U16)*line_sequence->line_count); - } - - node->line_seq.line_count = line_sequence->line_count; -} - -RDI_PROC void -rdim_unit_vmap_add_range(RDIM_Root *root, RDIM_Unit *unit, RDI_U64 first, RDI_U64 opl) -{ - RDIM_UnitVMapRange *node = rdim_push_array(root->arena, RDIM_UnitVMapRange, 1); - SLLQueuePush(root->unit_vmap_range_first, root->unit_vmap_range_last, node); - root->unit_vmap_range_count += 1; - node->unit = unit; - node->first = first; - node->opl = opl; + return root->msgs.first; } //- rjf: type info lookups/reservations @@ -3671,3 +3732,4 @@ rdim_bake_file(RDIM_Arena *arena, RDIM_Root *root, RDIM_String8List *out) rdim_bake_ctx_release(bctx); } +#endif diff --git a/src/lib_raddbgi_make/raddbgi_make.h b/src/lib_raddbgi_make/raddbgi_make.h index 3e20d559..cf611926 100644 --- a/src/lib_raddbgi_make/raddbgi_make.h +++ b/src/lib_raddbgi_make/raddbgi_make.h @@ -280,26 +280,32 @@ RDIM_CheckNil(nil,p) ? \ #define rdim_noop ((void)0) //////////////////////////////// -//~ rjf: Error Types +//~ rjf: Auxiliary Data Structure Types -typedef struct RDIM_Error RDIM_Error; -struct RDIM_Error +//- rjf: 1-dimensional U64 ranges + +typedef struct RDIM_Rng1U64 RDIM_Rng1U64; +struct RDIM_Rng1U64 { - RDIM_Error *next; - RDIM_String8 msg; + RDI_U64 min; + RDI_U64 max; }; -typedef struct RDIM_ErrorList RDIM_ErrorList; -struct RDIM_ErrorList +typedef struct RDIM_Rng1U64Node RDIM_Rng1U64Node; +struct RDIM_Rng1U64Node { - RDIM_Error *first; - RDIM_Error *last; + RDIM_Rng1U64Node *next; + RDIM_Rng1U64 v; +}; + +typedef struct RDIM_Rng1U64List RDIM_Rng1U64List; +struct RDIM_Rng1U64List +{ + RDIM_Rng1U64Node *first; + RDIM_Rng1U64Node *last; RDI_U64 count; }; -//////////////////////////////// -//~ rjf: Auxiliary Data Structure Types - //- rjf: u64 -> pointer map typedef struct RDIM_U64ToPtrNode RDIM_U64ToPtrNode; @@ -365,13 +371,42 @@ struct RDIM_OrderedRange RDI_U64 opl; }; +//////////////////////////////// +//~ rjf: Error/Warning/Note Message Types + +typedef struct RDIM_Msg RDIM_Msg; +struct RDIM_Msg +{ + RDIM_Msg *next; + RDIM_String8 string; +}; + +typedef struct RDIM_MsgList RDIM_MsgList; +struct RDIM_MsgList +{ + RDIM_Msg *first; + RDIM_Msg *last; + RDI_U64 count; +}; + +//////////////////////////////// +//~ rjf: Top-Level Debug Info Types + +typedef struct RDIM_TopLevelInfo RDIM_TopLevelInfo; +struct RDIM_TopLevelInfo +{ + RDI_Arch arch; + RDIM_String8 exe_name; + RDI_U64 exe_hash; + RDI_U64 voff_max; +}; + //////////////////////////////// //~ rjf: Binary Section Types typedef struct RDIM_BinarySection RDIM_BinarySection; struct RDIM_BinarySection { - RDIM_BinarySection *next; RDIM_String8 name; RDI_BinarySectionFlags flags; RDI_U64 voff_first; @@ -380,6 +415,21 @@ struct RDIM_BinarySection RDI_U64 foff_opl; }; +typedef struct RDIM_BinarySectionNode RDIM_BinarySectionNode; +struct RDIM_BinarySectionNode +{ + RDIM_BinarySectionNode *next; + RDIM_BinarySection v; +}; + +typedef struct RDIM_BinarySectionList RDIM_BinarySectionList; +struct RDIM_BinarySectionList +{ + RDIM_BinarySectionNode *first; + RDIM_BinarySectionNode *last; + RDI_U64 count; +}; + //////////////////////////////// //~ rjf: Per-Compilation-Unit Info Types @@ -397,27 +447,20 @@ typedef struct RDIM_LineSequenceNode RDIM_LineSequenceNode; struct RDIM_LineSequenceNode { RDIM_LineSequenceNode *next; - RDIM_LineSequence line_seq; + RDIM_LineSequence v; }; -typedef struct RDIM_UnitInfo RDIM_UnitInfo; -struct RDIM_UnitInfo +typedef struct RDIM_LineSequenceList RDIM_LineSequenceList; +struct RDIM_LineSequenceList { - RDIM_String8 unit_name; - RDIM_String8 compiler_name; - RDIM_String8 source_file; - RDIM_String8 object_file; - RDIM_String8 archive_file; - RDIM_String8 build_path; - RDI_Language language; + RDIM_LineSequenceNode *first; + RDIM_LineSequenceNode *last; + RDI_U64 count; }; typedef struct RDIM_Unit RDIM_Unit; struct RDIM_Unit { - RDIM_Unit *next_order; - RDI_U32 idx; - RDI_S32 info_is_set; RDIM_String8 unit_name; RDIM_String8 compiler_name; RDIM_String8 source_file; @@ -425,61 +468,42 @@ struct RDIM_Unit RDIM_String8 archive_file; RDIM_String8 build_path; RDI_Language language; - RDIM_LineSequenceNode *line_seq_first; - RDIM_LineSequenceNode *line_seq_last; - RDI_U64 line_seq_count; + RDIM_LineSequenceList line_sequences; + RDIM_Rng1U64List voff_ranges; }; -typedef struct RDIM_UnitVMapRange RDIM_UnitVMapRange; -struct RDIM_UnitVMapRange +typedef struct RDIM_UnitChunkNode RDIM_UnitChunkNode; +struct RDIM_UnitChunkNode { - RDIM_UnitVMapRange *next; - RDIM_Unit *unit; - RDI_U64 first; - RDI_U64 opl; + RDIM_UnitChunkNode *next; + RDIM_Unit *v; + RDI_U64 count; + RDI_U64 cap; +}; + +typedef struct RDIM_UnitChunkList RDIM_UnitChunkList; +struct RDIM_UnitChunkList +{ + RDIM_UnitChunkNode *first; + RDIM_UnitChunkNode *last; + RDI_U64 chunk_count; + RDI_U64 total_count; +}; + +typedef struct RDIM_UnitArray RDIM_UnitArray; +struct RDIM_UnitArray +{ + RDIM_Unit *v; + RDI_U64 count; }; //////////////////////////////// -//~ rjf: Type Info Types - -typedef RDI_U8 RDIM_TypeConstructKind; -enum -{ - RDIM_TypeConstructKind_Basic, - RDIM_TypeConstructKind_Modifier, - RDIM_TypeConstructKind_Bitfield, - RDIM_TypeConstructKind_Pointer, - RDIM_TypeConstructKind_Array, - RDIM_TypeConstructKind_Procedure, - RDIM_TypeConstructKind_Method, -}; - -typedef struct RDIM_Reservation RDIM_Reservation; - -typedef struct RDIM_TypeMember RDIM_TypeMember; -struct RDIM_TypeMember -{ - RDIM_TypeMember *next; - RDI_MemberKind kind; - RDIM_String8 name; - struct RDIM_Type *type; - RDI_U32 off; -}; - -typedef struct RDIM_TypeEnumVal RDIM_TypeEnumVal; -struct RDIM_TypeEnumVal -{ - RDIM_TypeEnumVal *next; - RDIM_String8 name; - RDI_U64 val; -}; +//~ rjf: Type System Node Types typedef struct RDIM_Type RDIM_Type; struct RDIM_Type { - RDIM_Type *next_order; RDI_TypeKind kind; - RDI_U32 idx; RDI_U32 byte_size; RDI_U32 flags; RDI_U32 off; @@ -487,133 +511,86 @@ struct RDIM_Type RDIM_String8 name; RDIM_Type *direct_type; RDIM_Type **param_types; - struct RDIM_TypeUDT *udt; + struct RDIM_UDT *udt; }; -typedef struct RDIM_TypeUDT RDIM_TypeUDT; -struct RDIM_TypeUDT +typedef struct RDIM_TypeChunkNode RDIM_TypeChunkNode; +struct RDIM_TypeChunkNode +{ + RDIM_TypeChunkNode *next; + RDIM_Type *v; + RDI_U64 count; + RDI_U64 cap; +}; + +typedef struct RDIM_TypeChunkList RDIM_TypeChunkList; +struct RDIM_TypeChunkList +{ + RDIM_TypeChunkNode *first; + RDIM_TypeChunkNode *last; + RDI_U64 chunk_count; + RDI_U64 total_count; +}; + +typedef struct RDIM_TypeArray RDIM_TypeArray; +struct RDIM_TypeArray +{ + RDIM_Type *v; + RDI_U64 count; +}; + +//////////////////////////////// +//~ rjf: User-Defined-Type Info Types + +typedef struct RDIM_UDTMember RDIM_UDTMember; +struct RDIM_UDTMember +{ + RDIM_UDTMember *next; + RDI_MemberKind kind; + RDIM_String8 name; + RDIM_Type *type; + RDI_U32 off; +}; + +typedef struct RDIM_UDTEnumVal RDIM_UDTEnumVal; +struct RDIM_UDTEnumVal +{ + RDIM_UDTEnumVal *next; + RDIM_String8 name; + RDI_U64 val; +}; + +typedef struct RDIM_UDT RDIM_UDT; +struct RDIM_UDT { - RDIM_TypeUDT *next_order; - RDI_U32 idx; RDIM_Type *self_type; - RDIM_TypeMember *first_member; - RDIM_TypeMember *last_member; + RDIM_UDTMember *first_member; + RDIM_UDTMember *last_member; RDI_U64 member_count; - RDIM_TypeEnumVal *first_enum_val; - RDIM_TypeEnumVal *last_enum_val; + RDIM_UDTEnumVal *first_enum_val; + RDIM_UDTEnumVal *last_enum_val; RDI_U64 enum_val_count; RDIM_String8 source_path; RDI_U32 line; RDI_U32 col; }; -typedef struct RDIM_TypeNode RDIM_TypeNode; -struct RDIM_TypeNode +typedef struct RDIM_UDTChunkNode RDIM_UDTChunkNode; +struct RDIM_UDTChunkNode { - RDIM_TypeNode *next; - RDIM_Type *type; -}; - -typedef struct RDIM_TypeList RDIM_TypeList; -struct RDIM_TypeList -{ - RDIM_TypeNode *first; - RDIM_TypeNode *last; + RDIM_UDTChunkNode *next; + RDIM_UDT *v; RDI_U64 count; + RDI_U64 cap; }; -//////////////////////////////// -//~ rjf: Symbol Info Types - -typedef enum RDIM_SymbolKind +typedef struct RDIM_UDTChunkList RDIM_UDTChunkList; +struct RDIM_UDTChunkList { - RDIM_SymbolKind_NULL, - RDIM_SymbolKind_GlobalVariable, - RDIM_SymbolKind_ThreadVariable, - RDIM_SymbolKind_Procedure, - RDIM_SymbolKind_COUNT -} -RDIM_SymbolKind; - -typedef struct RDIM_SymbolInfo RDIM_SymbolInfo; -struct RDIM_SymbolInfo -{ - RDIM_SymbolKind kind; - RDIM_String8 name; - RDIM_String8 link_name; - RDIM_Type *type; - RDI_S32 is_extern; - RDI_U64 offset; - // TODO(allen): should this actually be "container scope"? - struct RDIM_Symbol *container_symbol; - RDIM_Type *container_type; - struct RDIM_Scope *root_scope; -}; - -typedef struct RDIM_Symbol RDIM_Symbol; -struct RDIM_Symbol -{ - RDIM_Symbol *next_order; - RDI_U32 idx; - RDIM_SymbolKind kind; - RDIM_String8 name; - RDIM_String8 link_name; - RDIM_Type *type; - RDI_S32 is_extern; - RDI_S8 offset_is_set; - RDI_U64 offset; - RDIM_Symbol *container_symbol; - RDIM_Type *container_type; - struct RDIM_Scope *root_scope; -}; - -//////////////////////////////// -//~ rjf: Scope Info Types - -typedef struct RDIM_LocalInfo RDIM_LocalInfo; -struct RDIM_LocalInfo -{ - RDI_LocalKind kind; - struct RDIM_Scope *scope; - RDIM_String8 name; - RDIM_Type *type; -}; - -typedef struct RDIM_Local RDIM_Local; -struct RDIM_Local -{ - RDIM_Local *next; - RDI_LocalKind kind; - RDIM_String8 name; - RDIM_Type *type; - struct RDIM_LocationSet *locset; -}; - -typedef struct RDIM_VOffRange RDIM_VOffRange; -struct RDIM_VOffRange -{ - RDIM_VOffRange *next; - RDI_U64 voff_first; - RDI_U64 voff_opl; -}; - -typedef struct RDIM_Scope RDIM_Scope; -struct RDIM_Scope -{ - RDIM_Scope *next_order; - RDIM_Symbol *symbol; - RDIM_Scope *parent_scope; - RDIM_Scope *first_child; - RDIM_Scope *last_child; - RDIM_Scope *next_sibling; - RDI_U64 voff_base; - RDIM_VOffRange *first_range; - RDIM_VOffRange *last_range; - RDI_U32 range_count; - RDI_U32 idx; - RDIM_Local *first_local; - RDIM_Local *last_local; - RDI_U32 local_count; + RDIM_UDTChunkNode *first; + RDIM_UDTChunkNode *last; + RDI_U64 chunk_count; + RDI_U64 total_count; }; //////////////////////////////// @@ -663,6 +640,97 @@ struct RDIM_LocationSet RDI_U64 location_case_count; }; +//////////////////////////////// +//~ rjf: Symbol Info Types + +typedef enum RDIM_SymbolKind +{ + RDIM_SymbolKind_NULL, + RDIM_SymbolKind_GlobalVariable, + RDIM_SymbolKind_ThreadVariable, + RDIM_SymbolKind_Procedure, + RDIM_SymbolKind_COUNT +} +RDIM_SymbolKind; + +typedef struct RDIM_Symbol RDIM_Symbol; +struct RDIM_Symbol +{ + RDIM_SymbolKind kind; + RDI_S32 is_extern; + RDIM_String8 name; + RDIM_String8 link_name; + RDIM_Type *type; + RDI_U64 offset; + RDIM_Symbol *container_symbol; + RDIM_Type *container_type; + struct RDIM_Scope *root_scope; +}; + +typedef struct RDIM_SymbolChunkNode RDIM_SymbolChunkNode; +struct RDIM_SymbolChunkNode +{ + RDIM_SymbolChunkNode *next; + RDIM_Symbol *v; + RDI_U64 count; + RDI_U64 cap; +}; + +typedef struct RDIM_SymbolChunkList RDIM_SymbolChunkList; +struct RDIM_SymbolChunkList +{ + RDIM_SymbolChunkNode *first; + RDIM_SymbolChunkNode *last; + RDI_U64 chunk_count; + RDI_U64 total_count; +}; + +//////////////////////////////// +//~ rjf: Scope Info Types + +typedef struct RDIM_Local RDIM_Local; +struct RDIM_Local +{ + RDIM_Local *next; + RDI_LocalKind kind; + RDIM_String8 name; + RDIM_Type *type; + RDIM_LocationSet *locset; +}; + +typedef struct RDIM_Scope RDIM_Scope; +struct RDIM_Scope +{ + RDIM_Symbol *symbol; + RDIM_Scope *parent_scope; + RDIM_Scope *first_child; + RDIM_Scope *last_child; + RDIM_Scope *next_sibling; + RDI_U64 voff_base; + RDIM_Rng1U64List voff_ranges; + RDIM_Local *first_local; + RDIM_Local *last_local; + RDI_U32 local_count; +}; + +typedef struct RDIM_ScopeChunkNode RDIM_ScopeChunkNode; +struct RDIM_ScopeChunkNode +{ + RDIM_ScopeChunkNode *next; + RDIM_Scope *v; + RDI_U64 count; + RDI_U64 cap; +}; + +typedef struct RDIM_ScopeChunkList RDIM_ScopeChunkList; +struct RDIM_ScopeChunkList +{ + RDIM_ScopeChunkNode *first; + RDIM_ScopeChunkNode *last; + RDI_U64 chunk_count; + RDI_U64 total_count; +}; + //////////////////////////////// //~ rjf: Name Map Types @@ -695,18 +763,6 @@ struct RDIM_NameMap RDI_U64 name_count; }; -//////////////////////////////// -//~ rjf: Top-Level Debug Info Types - -typedef struct RDIM_TopLevelInfo RDIM_TopLevelInfo; -struct RDIM_TopLevelInfo -{ - RDI_Arch architecture; - RDIM_String8 exe_name; - RDI_U64 exe_hash; - RDI_U64 voff_max; -}; - //////////////////////////////// //~ rjf: Root Construction Bundle Types @@ -726,7 +782,7 @@ typedef struct RDIM_Root RDIM_Root; struct RDIM_Root { RDIM_Arena *arena; - RDIM_ErrorList errors; + RDIM_MsgList msgs; //////// Contextual Information @@ -734,38 +790,6 @@ struct RDIM_Root //////// Info Declared By User - // top level info - RDI_S32 top_level_info_is_set; - RDIM_TopLevelInfo top_level_info; - - // binary layout - RDIM_BinarySection *binary_section_first; - RDIM_BinarySection *binary_section_last; - RDI_U64 binary_section_count; - - // compilation units - RDIM_Unit *unit_first; - RDIM_Unit *unit_last; - RDI_U64 unit_count; - - RDIM_UnitVMapRange *unit_vmap_range_first; - RDIM_UnitVMapRange *unit_vmap_range_last; - RDI_U64 unit_vmap_range_count; - - // types - RDIM_Type *first_type; - RDIM_Type *last_type; - RDI_U64 type_count; - - RDIM_Type *nil_type; - RDIM_Type *variadic_type; - - RDIM_Type handled_nil_type; - - RDIM_TypeUDT *first_udt; - RDIM_TypeUDT *last_udt; - RDI_U64 type_udt_count; - RDI_U64 total_member_count; RDI_U64 total_enum_val_count; @@ -1136,21 +1160,15 @@ RDI_PROC RDI_S32 rdim_str8_match(RDIM_String8 a, RDIM_String8 b, RDIM_StringMatc RDI_PROC void rdim_str8_list_push(RDIM_Arena *arena, RDIM_String8List *list, RDIM_String8 string); RDI_PROC RDIM_String8 rdim_str8_list_join(RDIM_Arena *arena, RDIM_String8List *list, RDIM_String8 sep); -//- rjf: type lists -RDI_PROC void rdim_type_list_push(RDIM_Arena *arena, RDIM_TypeList *list, RDIM_Type *type); - -//- rjf: bytecode lists -RDI_PROC void rdim_bytecode_push_op(RDIM_Arena *arena, RDIM_EvalBytecode *bytecode, RDI_EvalOp op, RDI_U64 p); -RDI_PROC void rdim_bytecode_push_uconst(RDIM_Arena *arena, RDIM_EvalBytecode *bytecode, RDI_U64 x); -RDI_PROC void rdim_bytecode_push_sconst(RDIM_Arena *arena, RDIM_EvalBytecode *bytecode, RDI_S64 x); -RDI_PROC void rdim_bytecode_concat_in_place(RDIM_EvalBytecode *left_dst, RDIM_EvalBytecode *right_destroyed); - //- rjf: sortable range sorting RDI_PROC RDIM_SortKey* rdim_sort_key_array(RDIM_Arena *arena, RDIM_SortKey *keys, RDI_U64 count); //////////////////////////////// //~ rjf: Auxiliary Data Structure Functions +//- rjf: rng1u64 list +RDI_PROC void rdim_rng1u64_list_push(RDIM_Arena *arena, RDIM_Rng1U64List *list, RDIM_Rng1U64 r); + //- rjf: u64 -> ptr map RDI_PROC void rdim_u64toptr_map_init(RDIM_Arena *arena, RDIM_U64ToPtrMap *map, RDI_U64 bucket_count); RDI_PROC void rdim_u64toptr_map_lookup(RDIM_U64ToPtrMap *map, RDI_U64 key, RDI_U64 hash, RDIM_U64ToPtrLookup *lookup_out); @@ -1161,6 +1179,46 @@ RDI_PROC void rdim_str8toptr_map_init(RDIM_Arena *arena, RDIM_Str8ToPtrMap *map, RDI_PROC void*rdim_str8toptr_map_lookup(RDIM_Str8ToPtrMap *map, RDIM_String8 key, RDI_U64 hash); RDI_PROC void rdim_str8toptr_map_insert(RDIM_Arena *arena, RDIM_Str8ToPtrMap *map, RDIM_String8 key, RDI_U64 hash, void *ptr); +//////////////////////////////// +//~ rjf: Binary Section Info Building + +RDI_PROC RDIM_BinarySection *rdim_binary_section_list_push(RDIM_Arena *arena, RDIM_BinarySectionList *list); + +//////////////////////////////// +//~ rjf: Unit Info Building + +RDI_PROC RDIM_Unit *rdim_unit_chunk_list_push(RDIM_Arena *arena, RDIM_UnitChunkList *list); +RDI_PROC RDIM_LineSequence *rdim_line_sequence_list_push(RDIM_Arena *arena, RDIM_LineSequenceList *list); +RDI_PROC RDIM_UnitArray rdim_unit_array_from_chunk_list(RDIM_Arena *arena, RDIM_UnitChunkList *list); + +//////////////////////////////// +//~ rjf: Type Info & UDT Building + +RDI_PROC RDIM_Type *rdim_type_chunk_list_push(RDIM_Arena *arena, RDIM_TypeChunkList *list, RDI_U64 cap); +RDI_PROC RDIM_UDT *rdim_udt_chunk_list_push(RDIM_Arena *arena, RDIM_UDTChunkList *list, RDI_U64 cap); +RDI_PROC RDIM_UDTMember *rdim_udt_push_member(RDIM_Arena *arena, RDIM_UDT *udt); +RDI_PROC RDIM_UDTEnumVal *rdim_udt_push_enum_val(RDIM_Arena *arena, RDIM_UDT *udt); + +//////////////////////////////// +//~ rjf: Location Info Building + +RDI_PROC void rdim_bytecode_push_op(RDIM_Arena *arena, RDIM_EvalBytecode *bytecode, RDI_EvalOp op, RDI_U64 p); +RDI_PROC void rdim_bytecode_push_uconst(RDIM_Arena *arena, RDIM_EvalBytecode *bytecode, RDI_U64 x); +RDI_PROC void rdim_bytecode_push_sconst(RDIM_Arena *arena, RDIM_EvalBytecode *bytecode, RDI_S64 x); +RDI_PROC void rdim_bytecode_concat_in_place(RDIM_EvalBytecode *left_dst, RDIM_EvalBytecode *right_destroyed); + +//////////////////////////////// +//~ rjf: Symbol Info Building + +RDI_PROC RDIM_Symbol *rdim_symbol_chunk_list_push(RDIM_Arena *arena, RDIM_SymbolChunkList *list, RDI_U64 cap); + +//////////////////////////////// +//~ rjf: Scope Info Building + +RDI_PROC RDIM_Scope *rdim_scope_chunk_list_push(RDIM_Arena *arena, RDIM_ScopeChunkList *list, RDI_U64 cap); + + +#if 0 //////////////////////////////// //~ rjf: Loose Debug Info Construction (Anything -> Loose) Functions @@ -1169,24 +1227,9 @@ RDI_PROC RDIM_Root* rdim_root_alloc(RDIM_RootParams *params); RDI_PROC void rdim_root_release(RDIM_Root *root); //- rjf: error accumulation -RDI_PROC void rdim_push_error(RDIM_Root *root, RDIM_String8 string); -RDI_PROC void rdim_push_errorf(RDIM_Root *root, char *fmt, ...); -RDI_PROC RDIM_Error* rdim_first_error_from_root(RDIM_Root *root); - -//- rjf: top-level info specification -RDI_PROC void rdim_set_top_level_info(RDIM_Root *root, RDIM_TopLevelInfo *tli); - -//- rjf: binary section building -RDI_PROC void rdim_add_binary_section(RDIM_Root *root, - RDIM_String8 name, RDI_BinarySectionFlags flags, - RDI_U64 voff_first, RDI_U64 voff_opl, RDI_U64 foff_first, - RDI_U64 foff_opl); - -//- rjf: unit info building -RDI_PROC RDIM_Unit* rdim_unit_handle_from_user_id(RDIM_Root *root, RDI_U64 unit_user_id, RDI_U64 unit_user_id_hash); -RDI_PROC void rdim_unit_set_info(RDIM_Root *root, RDIM_Unit *unit, RDIM_UnitInfo *info); -RDI_PROC void rdim_unit_add_line_sequence(RDIM_Root *root, RDIM_Unit *unit, RDIM_LineSequence *line_sequence); -RDI_PROC void rdim_unit_vmap_add_range(RDIM_Root *root, RDIM_Unit *unit, RDI_U64 first, RDI_U64 opl); +RDI_PROC void rdim_push_msg(RDIM_Root *root, RDIM_String8 string); +RDI_PROC void rdim_push_msgf(RDIM_Root *root, char *fmt, ...); +RDI_PROC RDIM_Msg* rdim_first_msg_from_root(RDIM_Root *root); //- rjf: type info lookups/reservations RDI_PROC RDIM_Type* rdim_type_from_id(RDIM_Root *root, RDI_U64 type_user_id, RDI_U64 type_user_id_hash); @@ -1309,5 +1352,6 @@ RDI_PROC RDIM_NameMapBaked* rdim_name_map_bake(RDIM_Arena *arena, RDIM_Root *roo //- rjf: top-level baking entry point RDI_PROC void rdim_bake_file(RDIM_Arena *arena, RDIM_Root *root, RDIM_String8List *out); +#endif #endif // RDI_MAKE_H diff --git a/src/raddbgi_from_pdb/raddbgi_from_pdb.c b/src/raddbgi_from_pdb/raddbgi_from_pdb.c index 94d9dcd8..0b2f23a1 100644 --- a/src/raddbgi_from_pdb/raddbgi_from_pdb.c +++ b/src/raddbgi_from_pdb/raddbgi_from_pdb.c @@ -298,6 +298,84 @@ rdi_language_from_cv_language(CV_Language cv_language) return(result); } +internal RDI_TypeKind +rdi_type_kind_from_cv_basic_type(CV_BasicType basic_type) +{ + RDI_TypeKind result = RDI_TypeKind_NULL; + switch(basic_type) + { + case CV_BasicType_VOID: {result = RDI_TypeKind_Void;}break; + case CV_BasicType_HRESULT: {result = RDI_TypeKind_Handle;}break; + + case CV_BasicType_RCHAR: + case CV_BasicType_CHAR: + case CV_BasicType_CHAR8: + {result = RDI_TypeKind_Char8;}break; + + case CV_BasicType_UCHAR: {result = RDI_TypeKind_UChar8;}break; + case CV_BasicType_WCHAR: {result = RDI_TypeKind_UChar16;}break; + case CV_BasicType_CHAR16: {result = RDI_TypeKind_Char16;}break; + case CV_BasicType_CHAR32: {result = RDI_TypeKind_Char32;}break; + + case CV_BasicType_BOOL8: + case CV_BasicType_INT8: + {result = RDI_TypeKind_S8;}break; + + case CV_BasicType_BOOL16: + case CV_BasicType_INT16: + case CV_BasicType_SHORT: + {result = RDI_TypeKind_S16;}break; + + case CV_BasicType_BOOL32: + case CV_BasicType_INT32: + case CV_BasicType_LONG: + {result = RDI_TypeKind_S32;}break; + + case CV_BasicType_BOOL64: + case CV_BasicType_INT64: + case CV_BasicType_QUAD: + {result = RDI_TypeKind_S64;}break; + + case CV_BasicType_INT128: + case CV_BasicType_OCT: + {result = RDI_TypeKind_S128;}break; + + case CV_BasicType_UINT8: {result = RDI_TypeKind_U8;}break; + + case CV_BasicType_UINT16: + case CV_BasicType_USHORT: + {result = RDI_TypeKind_U16;}break; + + case CV_BasicType_UINT32: + case CV_BasicType_ULONG: + {result = RDI_TypeKind_U32;}break; + + case CV_BasicType_UINT64: + case CV_BasicType_UQUAD: + {result = RDI_TypeKind_U64;}break; + + case CV_BasicType_UINT128: + case CV_BasicType_UOCT: + {result = RDI_TypeKind_U128;}break; + + case CV_BasicType_FLOAT16:{result = RDI_TypeKind_F16;}break; + case CV_BasicType_FLOAT32:{result = RDI_TypeKind_F32;}break; + case CV_BasicType_FLOAT32PP:{result = RDI_TypeKind_F32PP;}break; + case CV_BasicType_FLOAT48:{result = RDI_TypeKind_F48;}break; + case CV_BasicType_FLOAT64:{result = RDI_TypeKind_F64;}break; + case CV_BasicType_FLOAT80:{result = RDI_TypeKind_F80;}break; + case CV_BasicType_FLOAT128:{result = RDI_TypeKind_F128;}break; + case CV_BasicType_COMPLEX32:{result = RDI_TypeKind_ComplexF32;}break; + case CV_BasicType_COMPLEX64:{result = RDI_TypeKind_ComplexF64;}break; + case CV_BasicType_COMPLEX80:{result = RDI_TypeKind_ComplexF80;}break; + case CV_BasicType_COMPLEX128:{result = RDI_TypeKind_ComplexF128;}break; + case CV_BasicType_PTR:{result = RDI_TypeKind_Handle;}break; + } + return result; +} + +#if 0 + //////////////////////////////// //~ rjf: Conversion Implementation Helpers @@ -362,7 +440,7 @@ p2r_u32_from_numeric(P2R_Ctx *ctx, CV_NumericParsed *num) U32 n_u32 = (U32)n_u64; if(n_u64 > 0xFFFFFFFF) { - rdim_push_errorf(ctx->root, "constant too large"); + rdim_push_msgf(ctx->root, "constant too large"); n_u32 = 0; } return(n_u32); @@ -1053,8 +1131,8 @@ p2r_type_equip_members(P2R_Ctx *ctx, RDIM_Type *owner_type, CV_TypeId field_ityp default: { String8 kind_str = cv_string_from_leaf_kind(field_kind); - rdim_push_errorf(ctx->root, "unhandled/invalid case: equip_members -> %.*s", - str8_varg(kind_str)); + rdim_push_msgf(ctx->root, "unhandled/invalid case: equip_members -> %.*s", + str8_varg(kind_str)); }break; } @@ -1188,8 +1266,8 @@ p2r_type_equip_enumerates(P2R_Ctx *ctx, RDIM_Type *owner_type, CV_TypeId field_i default: { String8 kind_str = cv_string_from_leaf_kind(field_kind); - rdim_push_errorf(ctx->root, "unhandled/invalid case: equip_enumerates -> %.*s", - str8_varg(kind_str)); + rdim_push_msgf(ctx->root, "unhandled/invalid case: equip_enumerates -> %.*s", + str8_varg(kind_str)); }break; } @@ -1932,8 +2010,8 @@ p2r_type_cons_leaf_record(P2R_Ctx *ctx, CV_TypeId itype) default: { String8 kind_str = cv_string_from_leaf_kind(range->hdr.kind); - rdim_push_errorf(ctx->root, "pdbconv: unhandled leaf case %.*s (0x%x)", - str8_varg(kind_str), range->hdr.kind); + rdim_push_msgf(ctx->root, "pdbconv: unhandled leaf case %.*s (0x%x)", + str8_varg(kind_str), range->hdr.kind); }break; } } @@ -1949,7 +2027,7 @@ p2r_type_resolve_and_check(P2R_Ctx *ctx, CV_TypeId itype) RDIM_Type *result = p2r_type_resolve_itype(ctx, itype); if(rdim_type_is_unhandled_nil(ctx->root, result)) { - rdim_push_errorf(ctx->root, "pdbconv: could not resolve itype (itype = %u)", itype); + rdim_push_msgf(ctx->root, "pdbconv: could not resolve itype (itype = %u)", itype); } return(result); } @@ -3193,90 +3271,86 @@ p2r_link_name_find(P2R_LinkNameMap *map, U64 voff) return(result); } +#endif + //////////////////////////////// -//~ Conversion Path +//~ rjf: Top-Level Conversion Entry Point internal P2R_Out * p2r_convert(Arena *arena, P2R_Params *params) { + Temp scratch = scratch_begin(&arena, 1); P2R_Out *out = push_array(arena, P2R_Out, 1); out->good_parse = 1; - // will we try to parse an input file? - B32 try_parse_input = (params->errors.node_count == 0); - -#define PARSE_CHECK_ERROR(p,fmt,...) do{ if((p) == 0){\ -out->good_parse = 0;\ -str8_list_pushf(arena, &out->errors, fmt, __VA_ARGS__);\ -} }while(0) - - // parse msf file + ////////////////////////////////////////////////////////////// + //- rjf: parse MSF structure + // MSF_Parsed *msf = 0; - if(try_parse_input) ProfScope("parse msf") + if(params->errors.node_count == 0) ProfScope("parse MSF structure") { msf = msf_parsed_from_data(arena, params->input_pdb_data); - PARSE_CHECK_ERROR(msf, "MSF"); } - // parse pdb info + ////////////////////////////////////////////////////////////// + //- rjf: parse PDB auth_guid & named streams table + // PDB_NamedStreamTable *named_streams = 0; COFF_Guid auth_guid = {0}; - if(msf != 0) ProfScope("parse pdb info") + if(msf != 0) ProfScope("parse PDB auth_guid & named streams table") { Temp scratch = scratch_begin(&arena, 1); - String8 info_data = msf_data_from_stream(msf, PDB_FixedStream_PdbInfo); PDB_Info *info = pdb_info_from_data(scratch.arena, info_data); named_streams = pdb_named_stream_table_from_info(arena, info); MemoryCopyStruct(&auth_guid, &info->auth_guid); - scratch_end(scratch); - - PARSE_CHECK_ERROR(named_streams, "named streams from pdb info"); } - // parse strtbl + ////////////////////////////////////////////////////////////// + //- rjf: parse PDB strtbl + // PDB_Strtbl *strtbl = 0; - if(named_streams != 0) ProfScope("parse strtbl") + if(named_streams != 0) ProfScope("parse PDB strtbl") { MSF_StreamNumber strtbl_sn = named_streams->sn[PDB_NamedStream_STRTABLE]; String8 strtbl_data = msf_data_from_stream(msf, strtbl_sn); strtbl = pdb_strtbl_from_data(arena, strtbl_data); - - PARSE_CHECK_ERROR(strtbl, "string table"); } - // parse dbi + ////////////////////////////////////////////////////////////// + //- rjf: parse dbi + // PDB_DbiParsed *dbi = 0; if(msf != 0) ProfScope("parse dbi") { String8 dbi_data = msf_data_from_stream(msf, PDB_FixedStream_Dbi); dbi = pdb_dbi_from_data(arena, dbi_data); - - PARSE_CHECK_ERROR(dbi, "DBI"); } - // parse tpi + ////////////////////////////////////////////////////////////// + //- rjf: parse tpi + // PDB_TpiParsed *tpi = 0; if(msf != 0) ProfScope("parse tpi") { String8 tpi_data = msf_data_from_stream(msf, PDB_FixedStream_Tpi); tpi = pdb_tpi_from_data(arena, tpi_data); - - PARSE_CHECK_ERROR(tpi, "TPI"); } - // parse ipi + ////////////////////////////////////////////////////////////// + //- rjf: parse ipi + // PDB_TpiParsed *ipi = 0; if(msf != 0) ProfScope("parse ipi") { String8 ipi_data = msf_data_from_stream(msf, PDB_FixedStream_Ipi); ipi = pdb_tpi_from_data(arena, ipi_data); - - PARSE_CHECK_ERROR(ipi, "IPI"); } - // parse coff sections + ////////////////////////////////////////////////////////////// + //- rjf: parse coff sections + // PDB_CoffSectionArray *coff_sections = 0; U64 coff_section_count = 0; if(dbi != 0) ProfScope("parse coff sections") @@ -3285,85 +3359,84 @@ str8_list_pushf(arena, &out->errors, fmt, __VA_ARGS__);\ String8 section_data = msf_data_from_stream(msf, section_stream); coff_sections = pdb_coff_section_array_from_data(arena, section_data); coff_section_count = coff_sections->count; - - PARSE_CHECK_ERROR(coff_sections, "coff sections"); } - // parse gsi + ////////////////////////////////////////////////////////////// + //- rjf: parse gsi + // PDB_GsiParsed *gsi = 0; if(dbi != 0) ProfScope("parse gsi") { String8 gsi_data = msf_data_from_stream(msf, dbi->gsi_sn); gsi = pdb_gsi_from_data(arena, gsi_data); - - PARSE_CHECK_ERROR(gsi, "GSI"); } - // parse psi + ////////////////////////////////////////////////////////////// + //- rjf: parse psi + // PDB_GsiParsed *psi_gsi_part = 0; if(dbi != 0) ProfScope("parse psi") { String8 psi_data = msf_data_from_stream(msf, dbi->psi_sn); - String8 psi_data_gsi_part = str8_range(psi_data.str + sizeof(PDB_PsiHeader), - psi_data.str + psi_data.size); + String8 psi_data_gsi_part = str8_range(psi_data.str + sizeof(PDB_PsiHeader), psi_data.str + psi_data.size); psi_gsi_part = pdb_gsi_from_data(arena, psi_data_gsi_part); - - PARSE_CHECK_ERROR(psi_gsi_part, "PSI"); } - // parse tpi hash + ////////////////////////////////////////////////////////////// + //- rjf: parse tpi hash + // PDB_TpiHashParsed *tpi_hash = 0; if(tpi != 0) ProfScope("parse tpi hash") { String8 hash_data = msf_data_from_stream(msf, tpi->hash_sn); String8 aux_data = msf_data_from_stream(msf, tpi->hash_sn_aux); tpi_hash = pdb_tpi_hash_from_data(arena, strtbl, tpi, hash_data, aux_data); - - PARSE_CHECK_ERROR(tpi_hash, "TPI hash table"); } - // parse tpi leaves + ////////////////////////////////////////////////////////////// + //- rjf: parse tpi leaves + // CV_LeafParsed *tpi_leaf = 0; if(tpi != 0) ProfScope("parse tpi leaves") { String8 leaf_data = pdb_leaf_data_from_tpi(tpi); tpi_leaf = cv_leaf_from_data(arena, leaf_data, tpi->itype_first); - - PARSE_CHECK_ERROR(tpi_leaf, "TPI leaf data"); } - // parse ipi hash + ////////////////////////////////////////////////////////////// + //- rjf: parse ipi hash + // PDB_TpiHashParsed *ipi_hash = 0; if(ipi != 0) ProfScope("parse ipi hash") { String8 hash_data = msf_data_from_stream(msf, ipi->hash_sn); String8 aux_data = msf_data_from_stream(msf, ipi->hash_sn_aux); ipi_hash = pdb_tpi_hash_from_data(arena, strtbl, ipi, hash_data, aux_data); - - PARSE_CHECK_ERROR(ipi_hash, "IPI hash table"); } - // parse ipi leaves + ////////////////////////////////////////////////////////////// + //- rjf: parse ipi leaves + // CV_LeafParsed *ipi_leaf = 0; if(ipi != 0) ProfScope("parse ipi leaves") { String8 leaf_data = pdb_leaf_data_from_tpi(ipi); ipi_leaf = cv_leaf_from_data(arena, leaf_data, ipi->itype_first); - - PARSE_CHECK_ERROR(ipi_leaf, "IPI leaf data"); } - // parse sym + ////////////////////////////////////////////////////////////// + //- rjf: parse sym + // CV_SymParsed *sym = 0; if(dbi != 0) ProfScope("parse sym") { String8 sym_data = msf_data_from_stream(msf, dbi->sym_sn); sym = cv_sym_from_data(arena, sym_data, 4); - - PARSE_CHECK_ERROR(sym, "public SYM data"); } - // parse compilation units + ////////////////////////////////////////////////////////////// + //- rjf: parse compilation units + // PDB_CompUnitArray *comp_units = 0; U64 comp_unit_count = 0; if(dbi != 0) ProfScope("parse compilation units") @@ -3371,42 +3444,37 @@ str8_list_pushf(arena, &out->errors, fmt, __VA_ARGS__);\ String8 mod_info_data = pdb_data_from_dbi_range(dbi, PDB_DbiRange_ModuleInfo); comp_units = pdb_comp_unit_array_from_data(arena, mod_info_data); comp_unit_count = comp_units->count; - - PARSE_CHECK_ERROR(comp_units, "module info"); } - // parse dbi's section contributions + ////////////////////////////////////////////////////////////// + //- rjf: parse dbi's section contributions + // PDB_CompUnitContributionArray *comp_unit_contributions = 0; U64 comp_unit_contribution_count = 0; if(dbi != 0 && coff_sections != 0) ProfScope("parse dbi section contributions") { String8 section_contribution_data = pdb_data_from_dbi_range(dbi, PDB_DbiRange_SecCon); - comp_unit_contributions = - pdb_comp_unit_contribution_array_from_data(arena, section_contribution_data, coff_sections); + comp_unit_contributions = pdb_comp_unit_contribution_array_from_data(arena, section_contribution_data, coff_sections); comp_unit_contribution_count = comp_unit_contributions->count; - - PARSE_CHECK_ERROR(comp_unit_contributions, "module contributions"); } - // parse syms for each compilation unit + ////////////////////////////////////////////////////////////// + //- rjf: parse syms for each compilation unit + // CV_SymParsed **sym_for_unit = push_array(arena, CV_SymParsed*, comp_unit_count); if(comp_units != 0) ProfScope("parse symbols") { PDB_CompUnit **unit_ptr = comp_units->units; for(U64 i = 0; i < comp_unit_count; i += 1, unit_ptr += 1) { - CV_SymParsed *unit_sym = 0; - { - String8 sym_data = pdb_data_from_unit_range(msf, *unit_ptr, PDB_DbiCompUnitRange_Symbols); - unit_sym = cv_sym_from_data(arena, sym_data, 4); - } - PARSE_CHECK_ERROR(unit_sym, "module (i=%llu) SYM data", i); - - sym_for_unit[i] = unit_sym; + String8 sym_data = pdb_data_from_unit_range(msf, *unit_ptr, PDB_DbiCompUnitRange_Symbols); + sym_for_unit[i] = cv_sym_from_data(arena, sym_data, 4); } } - // parse c13 for each compilation unit + ////////////////////////////////////////////////////////////// + //- rjf: parse c13 for each compilation unit + // CV_C13Parsed **c13_for_unit = push_array(arena, CV_C13Parsed*, comp_unit_count); if(comp_units != 0) ProfScope("parse c13s") { @@ -3418,81 +3486,1462 @@ str8_list_pushf(arena, &out->errors, fmt, __VA_ARGS__);\ String8 c13_data = pdb_data_from_unit_range(msf, *unit_ptr, PDB_DbiCompUnitRange_C13); unit_c13 = cv_c13_from_data(arena, c13_data, strtbl, coff_sections); } - PARSE_CHECK_ERROR(unit_c13, "module (i=%llu) C13 line info", i); - c13_for_unit[i] = unit_c13; } } - // parsing error - if(try_parse_input && !out->good_parse && - !params->hide_errors.parsing) - { - str8_list_pushf(arena, &out->errors, "error(parsing): '%S' as a PDB\n", params->input_pdb_name); - } - - // exe hash + ////////////////////////////////////////////////////////////// + //- rjf: hash exe + // U64 exe_hash = 0; - if(out->good_parse && params->input_exe_data.size > 0) ProfScope("hash exe") + if(params->input_exe_data.size > 0) ProfScope("hash exe") { exe_hash = rdi_hash(params->input_exe_data.str, params->input_exe_data.size); } - // output generation - P2R_Ctx *p2r_ctx = 0; - if(params->output_name.size > 0) + ////////////////////////////////////////////////////////////// + //- rjf: calculate EXE's max voff + // + U64 exe_voff_max = 0; + { + COFF_SectionHeader *coff_sec_ptr = coff_sections->sections; + COFF_SectionHeader *coff_ptr_opl = coff_sec_ptr + coff_section_count; + for(;coff_sec_ptr < coff_ptr_opl; coff_sec_ptr += 1) + { + U64 sec_voff_max = coff_sec_ptr->voff + coff_sec_ptr->vsize; + exe_voff_max = Max(exe_voff_max, sec_voff_max); + } + } + + ////////////////////////////////////////////////////////////// + //- rjf: determine architecture + // + RDI_Arch arch = RDI_Arch_NULL; + U64 arch_addr_size = 0; { - - // determine arch - RDI_Arch architecture = RDI_Arch_NULL; // TODO(rjf): in some cases, the first compilation unit has a zero // architecture, as it's sometimes used as a "nil" unit. this causes bugs // in later stages of conversion - particularly, this was detected via // busted location info. so i've converted this to a scan-until-we-find-an- - // architecture. however, this is still fundamentally insufficient, because - // Nick has informed me that x86 units can be linked with x64 units, - // meaning the appropriate architecture at any point in time is not a top- - // level concept, and is rather dependent on to which compilation unit - // particular symbols belong. so in the future, to support that (odd) case, - // we'll need to not only have this be a top-level "contextual" piece of - // info, but to use the appropriate compilation unit's architecture when - // possible. - // + // architecture. however, this may still be fundamentally insufficient, + // because Nick has informed me that x86 units can be linked with x64 + // units, meaning the appropriate architecture at any point in time is not + // a top-level concept, and is rather dependent on to which compilation + // unit particular symbols belong. so in the future, to support that (odd) + // case, we'll need to not only have this be a top-level "contextual" piece + // of info, but to use the appropriate compilation unit's architecture when + // possible. assuming, of course, that we care about supporting that case. for(U64 comp_unit_idx = 0; comp_unit_idx < comp_unit_count; comp_unit_idx += 1) { if(sym_for_unit[comp_unit_idx] != 0) { - architecture = rdi_arch_from_cv_arch(sym_for_unit[comp_unit_idx]->info.arch); - if(architecture != 0) + arch = rdi_arch_from_cv_arch(sym_for_unit[comp_unit_idx]->info.arch); + if(arch != RDI_Arch_NULL) { break; } } } - U64 addr_size = rdi_addr_size_from_arch(architecture); - - - // predict symbol counts - U64 symbol_count_prediction = 0; + arch_addr_size = rdi_addr_size_from_arch(arch); + } + + ////////////////////////////////////////////////////////////// + //- rjf: produce top-level-info + // + RDIM_TopLevelInfo top_level_info = {0}; + { + top_level_info.arch = arch; + top_level_info.exe_name = params->input_exe_name; + top_level_info.exe_hash = exe_hash; + top_level_info.voff_max = exe_voff_max; + } + + ////////////////////////////////////////////////////////////// + //- rjf: build binary sections list + // + RDIM_BinarySectionList binary_sections = {0}; + ProfScope("build binary section list") + { + COFF_SectionHeader *coff_ptr = coff_sections->sections; + COFF_SectionHeader *coff_opl = coff_ptr + coff_section_count; + for(;coff_ptr < coff_opl; coff_ptr += 1) { - U64 rec_range_count = 0; - if(sym != 0) + char *name_first = (char*)coff_ptr->name; + char *name_opl = name_first + sizeof(coff_ptr->name); + RDIM_BinarySection *sec = rdim_binary_section_list_push(arena, &binary_sections); + sec->name = str8_cstring_capped(name_first, name_opl); + sec->flags = rdi_binary_section_flags_from_coff_section_flags(coff_ptr->flags); + sec->voff_first = coff_ptr->voff; + sec->voff_opl = coff_ptr->voff+coff_ptr->vsize; + sec->foff_first = coff_ptr->foff; + sec->foff_opl = coff_ptr->foff+coff_ptr->fsize; + } + } + + ////////////////////////////////////////////////////////////// + //- rjf: build unit array + // + RDIM_UnitArray units = {0}; + ProfScope("build unit array") + { + //- rjf: allocate + units.count = comp_unit_count; + units.v = push_array(arena, RDIM_Unit, units.count); + + //- rjf: pass 1: fill basic per-unit info & line info + for(U64 comp_unit_idx = 0; comp_unit_idx < comp_unit_count; comp_unit_idx += 1) + { + PDB_CompUnit *pdb_unit = comp_units->units[comp_unit_idx]; + CV_SymParsed *pdb_unit_sym = sym_for_unit[comp_unit_idx]; + CV_C13Parsed *pdb_unit_c13 = c13_for_unit[comp_unit_idx]; + + //- rjf: produce unit name + String8 unit_name = pdb_unit->obj_name; + if(unit_name.size != 0) { - rec_range_count += sym->sym_ranges.count; + String8 unit_name_past_last_slash = str8_skip_last_slash(unit_name); + if(unit_name_past_last_slash.size != 0) + { + unit_name = unit_name_past_last_slash; + } } - for(U64 i = 0; i < comp_unit_count; i += 1) + + //- rjf: produce obj name + String8 obj_name = pdb_unit->obj_name; + if(str8_match(obj_name, str8_lit("* Linker *"), 0) || + str8_match(obj_name, str8_lit("Import:"), StringMatchFlag_RightSideSloppy)) { - CV_SymParsed *unit_sym = sym_for_unit[i]; - rec_range_count += unit_sym->sym_ranges.count; + MemoryZeroStruct(&obj_name); } - symbol_count_prediction = rec_range_count/8; - if(symbol_count_prediction < 128) + + //- rjf: fill basic output unit info + RDIM_Unit *dst_unit = &units.v[comp_unit_idx]; + dst_unit->unit_name = unit_name; + dst_unit->compiler_name = pdb_unit_sym->info.compiler_name; + dst_unit->object_file = obj_name; + dst_unit->archive_file = pdb_unit->group_name; + dst_unit->language = rdi_language_from_cv_language(sym->info.language); + + //- rjf: fill unit line info + for(CV_C13SubSectionNode *node = pdb_unit_c13->first_sub_section; + node != 0; + node = node->next) { - symbol_count_prediction = 128; + if(node->kind == CV_C13_SubSectionKind_Lines) + { + for(CV_C13LinesParsedNode *lines_n = node->lines_first; + lines_n != 0; + lines_n = lines_n->next) + { + CV_C13LinesParsed *lines = &lines_n->v; + RDIM_LineSequence *seq = rdim_line_sequence_list_push(arena, &dst_unit->line_sequences); + seq->file_name = lines->file_name; + seq->voffs = lines->voffs; + seq->line_nums = lines->line_nums; + seq->col_nums = lines->col_nums; + seq->line_count = lines->line_count; + } + } } } + //- rjf: pass 2: build per-unit voff ranges from comp unit contributions table + PDB_CompUnitContribution *contrib_ptr = comp_unit_contributions->contributions; + PDB_CompUnitContribution *contrib_opl = contrib_ptr + comp_unit_contribution_count; + for(;contrib_ptr < contrib_opl; contrib_ptr += 1) + { + if(contrib_ptr->mod < comp_unit_count) + { + RDIM_Unit *unit = &units.v[contrib_ptr->mod]; + RDIM_Rng1U64 range = {contrib_ptr->voff_first, contrib_ptr->voff_opl}; + rdim_rng1u64_list_push(arena, &unit->voff_ranges, range); + } + } + } + + ////////////////////////////// + //- rjf: predict symbol count + // + U64 symbol_count_prediction = 0; + ProfScope("predict symbol count") + { + U64 rec_range_count = 0; + if(sym != 0) + { + rec_range_count += sym->sym_ranges.count; + } + for(U64 i = 0; i < comp_unit_count; i += 1) + { + CV_SymParsed *unit_sym = sym_for_unit[i]; + rec_range_count += unit_sym->sym_ranges.count; + } + symbol_count_prediction = rec_range_count/8; + if(symbol_count_prediction < 128) + { + symbol_count_prediction = 128; + } + } + + ////////////////////////////////////////////////////////////// + //- rjf: types pass 0: produce type forward resolution map + // + U64 type_fwd_map_count = 0; + CV_TypeId *type_fwd_map = 0; + ProfScope("types pass 0: produce type forward resolution map") + { + CV_TypeId itype_first = tpi_leaf->itype_first; + CV_TypeId itype_opl = tpi_leaf->itype_opl; + type_fwd_map_count = (U64)(itype_opl-itype_first); + type_fwd_map = push_array(arena, CV_TypeId, type_fwd_map_count); + for(CV_TypeId itype = itype_first; itype < itype_opl; itype += 1) + { + //- rjf: determine if this itype resolves to another + CV_TypeId itype_fwd = 0; + CV_RecRange *range = &tpi_leaf->leaf_ranges.ranges[itype-itype_first]; + CV_LeafKind kind = range->hdr.kind; + U64 header_struct_size = cv_header_struct_size_from_leaf_kind(kind); + if(range->off+range->hdr.size <= tpi_leaf->data.size && + range->off+2+header_struct_size <= tpi_leaf->data.size && + range->hdr.size >= 2) + { + U8 *itype_leaf_first = tpi_leaf->data.str + range->off+2; + U8 *itype_leaf_opl = itype_leaf_first + range->hdr.size-2; + switch(kind) + { + default:{}break; + + //- rjf: CLASS/STRUCTURE + case CV_LeafKind_CLASS: + case CV_LeafKind_STRUCTURE: + { + // rjf: unpack leaf + CV_LeafStruct *lf_struct = (CV_LeafStruct *)itype_leaf_first; + U8 *numeric_ptr = (U8 *)(lf_struct + 1); + CV_NumericParsed size = cv_numeric_from_data_range(numeric_ptr, itype_leaf_opl); + U8 *name_ptr = numeric_ptr + size.encoded_size; + String8 name = str8_cstring_capped(name_ptr, itype_leaf_opl); + U8 *unique_name_ptr = name_ptr + name.size + 1; + String8 unique_name = str8_cstring_capped(unique_name_ptr, itype_leaf_opl); + + // rjf: has fwd ref flag -> lookup itype that this itype resolves to + if(lf_struct->props & CV_TypeProp_FwdRef) + { + B32 do_unique_name_lookup = (((lf_struct->props & CV_TypeProp_Scoped) != 0) && + ((lf_struct->props & CV_TypeProp_HasUniqueName) != 0)); + itype_fwd = pdb_tpi_first_itype_from_name(tpi_hash, tpi_leaf, do_unique_name_lookup?unique_name:name, do_unique_name_lookup); + } + }break; + + //- rjf: CLASS2/STRUCT2 + case CV_LeafKind_CLASS2: + case CV_LeafKind_STRUCT2: + { + // rjf: unpack leaf + CV_LeafStruct2 *lf_struct = (CV_LeafStruct2 *)itype_leaf_first; + U8 *numeric_ptr = (U8 *)(lf_struct + 1); + CV_NumericParsed size = cv_numeric_from_data_range(numeric_ptr, itype_leaf_opl); + U8 *name_ptr = (U8 *)numeric_ptr + size.encoded_size; + String8 name = str8_cstring_capped(name_ptr, itype_leaf_opl); + U8 *unique_name_ptr = name_ptr + name.size + 1; + String8 unique_name = str8_cstring_capped(unique_name_ptr, itype_leaf_opl); + + // rjf: has fwd ref flag -> lookup itype that this itype resolves to + if(lf_struct->props & CV_TypeProp_FwdRef) + { + B32 do_unique_name_lookup = (((lf_struct->props & CV_TypeProp_Scoped) != 0) && + ((lf_struct->props & CV_TypeProp_HasUniqueName) != 0)); + itype_fwd = pdb_tpi_first_itype_from_name(tpi_hash, tpi_leaf, do_unique_name_lookup?unique_name:name, do_unique_name_lookup); + } + }break; + + //- rjf: UNION + case CV_LeafKind_UNION: + { + // rjf: unpack leaf + CV_LeafUnion *lf_union = (CV_LeafUnion *)itype_leaf_first; + U8 *numeric_ptr = (U8 *)(lf_union + 1); + CV_NumericParsed size = cv_numeric_from_data_range(numeric_ptr, itype_leaf_opl); + U8 *name_ptr = numeric_ptr + size.encoded_size; + String8 name = str8_cstring_capped(name_ptr, itype_leaf_opl); + U8 *unique_name_ptr = name_ptr + name.size + 1; + String8 unique_name = str8_cstring_capped(unique_name_ptr, itype_leaf_opl); + + // rjf: has fwd ref flag -> lookup itype that this itype resolves tos + if(lf_union->props & CV_TypeProp_FwdRef) + { + B32 do_unique_name_lookup = (((lf_union->props & CV_TypeProp_Scoped) != 0) && + ((lf_union->props & CV_TypeProp_HasUniqueName) != 0)); + itype_fwd = pdb_tpi_first_itype_from_name(tpi_hash, tpi_leaf, do_unique_name_lookup?unique_name:name, do_unique_name_lookup); + } + }break; + + //- rjf: ENUM + case CV_LeafKind_ENUM: + { + // rjf: unpack leaf + CV_LeafEnum *lf_enum = (CV_LeafEnum*)itype_leaf_first; + U8 *name_ptr = (U8 *)(lf_enum + 1); + String8 name = str8_cstring_capped(name_ptr, itype_leaf_opl); + U8 *unique_name_ptr = name_ptr + name.size + 1; + String8 unique_name = str8_cstring_capped(unique_name_ptr, itype_leaf_opl); + + // rjf: has fwd ref flag -> lookup itype that this itype resolves to + if(lf_enum->props & CV_TypeProp_FwdRef) + { + B32 do_unique_name_lookup = (((lf_enum->props & CV_TypeProp_Scoped) != 0) && + ((lf_enum->props & CV_TypeProp_HasUniqueName) != 0)); + itype_fwd = pdb_tpi_first_itype_from_name(tpi_hash, tpi_leaf, do_unique_name_lookup?unique_name:name, do_unique_name_lookup); + } + }break; + } + } + + //- rjf: if the forwarded itype is nonzero & in TPI range -> save to map + if(itype_fwd != 0 && itype_first <= itype_fwd && itype_fwd < itype_opl) + { + type_fwd_map[itype-itype_first] = itype_fwd; + } + } + } + + ////////////////////////////////////////////////////////////// + //- rjf: types pass 1: construct all root/stub types from TPI + // + // this does NOT gather the following information, which is done by + // subsequent passes, as they all require full resolution of all itypes first + // (to allow for early itypes to reference later itypes): + // + // - function/method type parameters + // - modifier byte sizes + // - bitfield direct type byte sizes + // - struct/class/union members + // - array counts + // - direct type forward resolution + // + typedef struct P2R_TypeIdRevisitTask P2R_TypeIdRevisitTask; + struct P2R_TypeIdRevisitTask + { + P2R_TypeIdRevisitTask *next; + RDIM_Type *base_type; + CV_TypeId field_itype; + CV_TypeId this_itype; + }; + P2R_TypeIdRevisitTask *first_itype_revisit_task = 0; + P2R_TypeIdRevisitTask *last_itype_revisit_task = 0; + RDIM_TypeArray itype_types = {0}; // root type for per-TPI-itype + RDIM_TypeChunkList extra_types = {0}; // extra supplementary types we build, which do not have any itypes + ProfScope("types pass 1: construct all root/stub types from TPI") + { + RDI_U64 extra_types_chunk_cap = 1024; + CV_TypeId itype_first = tpi_leaf->itype_first; + CV_TypeId itype_opl = tpi_leaf->itype_opl; + itype_types.count = (U64)(itype_opl-itype_first); + itype_types.v = push_array(arena, RDIM_Type, itype_types.count); +#define p2r_type_ptr_from_itype(itype) ((itype_first <= (itype) && (itype) < itype_opl) ? (&itype_types.v[(type_fwd_map[(itype)-itype_first] ? type_fwd_map[(itype)-itype_first] : (itype))-itype_first]) : 0) + for(CV_TypeId itype = itype_first; itype < itype_opl; itype += 1) + { + RDIM_Type *dst_type = &itype_types.v[itype-itype_first]; + B32 itype_is_basic = (itype < 0x1000); + + ////////////////////////// + //- rjf: build basic type + // + if(itype_is_basic) + { + // rjf: unpack itype + CV_BasicPointerKind cv_basic_ptr_kind = CV_BasicPointerKindFromTypeId(itype); + CV_BasicType cv_basic_type_code = CV_BasicTypeFromTypeId(itype); + + // rjf: get basic type slot, fill if unfilled + RDIM_Type *basic_type = &itype_types.v[cv_basic_type_code-itype_first]; + if(basic_type->kind == RDI_TypeKind_NULL) + { + RDI_TypeKind type_kind = rdi_type_kind_from_cv_basic_type(cv_basic_type_code); + U32 byte_size = rdi_size_from_basic_type_kind(type_kind); + if(byte_size == 0xffffffff) + { + byte_size = arch_addr_size; + } + basic_type->kind = type_kind; + basic_type->name = cv_type_name_from_basic_type(cv_basic_type_code); + basic_type->byte_size = byte_size; + } + + // rjf: nonzero ptr kind -> form ptr type to basic tpye + if(cv_basic_ptr_kind != 0) + { + dst_type->kind = RDI_TypeKind_Ptr; + dst_type->byte_size = arch_addr_size; + dst_type->direct_type = basic_type; + } + } + + ////////////////////////// + //- rjf: build non-basic type + // + if(!itype_is_basic) + { + CV_RecRange *range = &tpi_leaf->leaf_ranges.ranges[itype-itype_first]; + CV_LeafKind kind = range->hdr.kind; + U64 header_struct_size = cv_header_struct_size_from_leaf_kind(kind); + if(range->off+range->hdr.size <= tpi_leaf->data.size && + range->off+2+header_struct_size <= tpi_leaf->data.size && + range->hdr.size >= 2) + { + U8 *itype_leaf_first = tpi_leaf->data.str + range->off+2; + U8 *itype_leaf_opl = itype_leaf_first + range->hdr.size-2; + switch(kind) + { + //- rjf: MODIFIER + case CV_LeafKind_MODIFIER: + { + // rjf: unpack leaf + CV_LeafModifier *modifier = (CV_LeafModifier *)itype_leaf_first; + + // rjf: cv -> rdi flags + RDI_TypeModifierFlags flags = 0; + if(modifier->flags & CV_ModifierFlag_Const) {flags |= RDI_TypeModifierFlag_Const;} + if(modifier->flags & CV_ModifierFlag_Volatile) {flags |= RDI_TypeModifierFlag_Volatile;} + + // rjf: fill type + dst_type->kind = RDI_TypeKind_Modifier; + dst_type->flags = flags; + dst_type->direct_type = p2r_type_ptr_from_itype(modifier->itype); + }break; + + //- rjf: POINTER + case CV_LeafKind_POINTER: + { + // TODO(rjf): if ptr_mode in {PtrMem, PtrMethod} then output a member pointer instead + + // rjf: unpack leaf + CV_LeafPointer *pointer = (CV_LeafPointer *)itype_leaf_first; + RDIM_Type *direct_type = p2r_type_ptr_from_itype(pointer->itype); + CV_PointerKind ptr_kind = CV_PointerAttribs_ExtractKind(pointer->attribs); + CV_PointerMode ptr_mode = CV_PointerAttribs_ExtractMode(pointer->attribs); + U32 ptr_size = CV_PointerAttribs_ExtractSize(pointer->attribs); + + // rjf: cv -> rdi modifier flags + RDI_TypeModifierFlags modifier_flags = 0; + if(pointer->attribs & CV_PointerAttrib_Const) {modifier_flags |= RDI_TypeModifierFlag_Const;} + if(pointer->attribs & CV_PointerAttrib_Volatile) {modifier_flags |= RDI_TypeModifierFlag_Volatile;} + + // rjf: cv info -> rdi pointer type kind + RDI_TypeKind type_kind = RDI_TypeKind_Ptr; + { + if(pointer->attribs & CV_PointerAttrib_LRef) + { + type_kind = RDI_TypeKind_LRef; + } + else if(pointer->attribs & CV_PointerAttrib_RRef) + { + type_kind = RDI_TypeKind_RRef; + } + if(ptr_mode == CV_PointerMode_LRef) + { + type_kind = RDI_TypeKind_LRef; + } + else if(ptr_mode == CV_PointerMode_RRef) + { + type_kind = RDI_TypeKind_RRef; + } + } + + // rjf: fill type + if(modifier_flags != 0) + { + RDIM_Type *pointer_type = rdim_type_chunk_list_push(arena, &extra_types, extra_types_chunk_cap); + dst_type->kind = RDI_TypeKind_Modifier; + dst_type->flags = modifier_flags; + dst_type->direct_type = pointer_type; + pointer_type->kind = type_kind; + pointer_type->byte_size = arch_addr_size; + pointer_type->direct_type = direct_type; + } + else + { + dst_type->kind = type_kind; + dst_type->byte_size = arch_addr_size; + dst_type->direct_type = direct_type; + } + + // rjf: push revisit task for full byte size of modifier type + if(modifier_flags != 0) + { + P2R_TypeIdRevisitTask *t = push_array(scratch.arena, P2R_TypeIdRevisitTask, 1); + SLLQueuePush(first_itype_revisit_task, last_itype_revisit_task, t); + t->base_type = dst_type; + } + }break; + + //- rjf: PROCEDURE + case CV_LeafKind_PROCEDURE: + { + // TODO(rjf): handle call_kind & attribs + + // rjf: unpack leaf + CV_LeafProcedure *procedure = (CV_LeafProcedure *)itype_leaf_first; + RDIM_Type *ret_type = p2r_type_ptr_from_itype(procedure->ret_itype); + + // rjf: fill type + dst_type->kind = RDI_TypeKind_Function; + dst_type->byte_size = arch_addr_size; + dst_type->count = procedure->arg_count; + dst_type->direct_type = ret_type; + + // rjf: push revisit task for parameters + P2R_TypeIdRevisitTask *t = push_array(scratch.arena, P2R_TypeIdRevisitTask, 1); + SLLQueuePush(first_itype_revisit_task, last_itype_revisit_task, t); + t->base_type = dst_type; + t->field_itype = procedure->arg_itype; + }break; + + //- rjf: MFUNCTION + case CV_LeafKind_MFUNCTION: + { + // TODO(rjf): handle call_kind & attribs + // TODO(rjf): preserve "this_adjust" + + // rjf: unpack leaf + CV_LeafMFunction *mfunction = (CV_LeafMFunction *)itype_leaf_first; + RDIM_Type *ret_type = p2r_type_ptr_from_itype(mfunction->ret_itype); + + // rjf: fill type + dst_type->kind = (mfunction->this_itype != 0) ? RDI_TypeKind_Method : RDI_TypeKind_Function; + dst_type->byte_size = arch_addr_size; + dst_type->count = mfunction->arg_count; + dst_type->direct_type = ret_type; + + // rjf: push revisit task for parameters/this + P2R_TypeIdRevisitTask *t = push_array(scratch.arena, P2R_TypeIdRevisitTask, 1); + SLLQueuePush(first_itype_revisit_task, last_itype_revisit_task, t); + t->base_type = dst_type; + t->field_itype = mfunction->arg_itype; + t->this_itype = mfunction->this_itype; + }break; + + //- rjf: BITFIELD + case CV_LeafKind_BITFIELD: + { + // rjf: unpack leaf + CV_LeafBitField *bit_field = (CV_LeafBitField *)itype_leaf_first; + RDIM_Type *direct_type = p2r_type_ptr_from_itype(bit_field->itype); + + // rjf: fill type + dst_type->kind = RDI_TypeKind_Bitfield; + dst_type->off = bit_field->pos; + dst_type->count = bit_field->len; + dst_type->direct_type = direct_type; + + // rjf: push revisit task for byte size + P2R_TypeIdRevisitTask *t = push_array(scratch.arena, P2R_TypeIdRevisitTask, 1); + SLLQueuePush(first_itype_revisit_task, last_itype_revisit_task, t); + t->base_type = dst_type; + }break; + + //- rjf: ARRAY + case CV_LeafKind_ARRAY: + { + // rjf: unpack leaf + CV_LeafArray *array = (CV_LeafArray *)itype_leaf_first; + RDIM_Type *direct_type = p2r_type_ptr_from_itype(array->entry_itype); + U8 *numeric_ptr = (U8*)(array + 1); + CV_NumericParsed array_count = cv_numeric_from_data_range(numeric_ptr, itype_leaf_opl); + U64 full_size = cv_u64_from_numeric(&array_count); + + // rjf: fill type + dst_type->kind = RDI_TypeKind_Array; + dst_type->direct_type = direct_type; + dst_type->byte_size = full_size; + + // rjf: push revisit task for full count + P2R_TypeIdRevisitTask *t = push_array(scratch.arena, P2R_TypeIdRevisitTask, 1); + SLLQueuePush(first_itype_revisit_task, last_itype_revisit_task, t); + t->base_type = dst_type; + }break; + + //- rjf: CLASS/STRUCTURE + case CV_LeafKind_CLASS: + case CV_LeafKind_STRUCTURE: + { + // TODO(rjf): handle props + + // rjf: unpack leaf + CV_LeafStruct *lf_struct = (CV_LeafStruct *)itype_leaf_first; + U8 *numeric_ptr = (U8*)(lf_struct + 1); + CV_NumericParsed size = cv_numeric_from_data_range(numeric_ptr, itype_leaf_opl); + U64 size_u64 = cv_u64_from_numeric(&size); + U8 *name_ptr = numeric_ptr + size.encoded_size; + String8 name = str8_cstring_capped(name_ptr, itype_leaf_opl); + + // rjf: fill type + if(lf_struct->props & CV_TypeProp_FwdRef) + { + dst_type->kind = (kind == CV_LeafKind_CLASS ? RDI_TypeKind_IncompleteClass : RDI_TypeKind_IncompleteStruct); + dst_type->name = name; + } + else + { + dst_type->kind = (kind == CV_LeafKind_CLASS ? RDI_TypeKind_Class : RDI_TypeKind_Struct); + dst_type->byte_size = (U32)size_u64; + dst_type->name = name; + } + + // rjf: push revisit task for members + if(!(lf_struct->props & CV_TypeProp_FwdRef)) + { + P2R_TypeIdRevisitTask *t = push_array(scratch.arena, P2R_TypeIdRevisitTask, 1); + SLLQueuePush(first_itype_revisit_task, last_itype_revisit_task, t); + t->base_type = dst_type; + t->field_itype = lf_struct->field_itype; + } + }break; + + //- rjf: CLASS2/STRUCT2 + case CV_LeafKind_CLASS2: + case CV_LeafKind_STRUCT2: + { + // TODO(rjf): handle props + + // rjf: unpack leaf + CV_LeafStruct2 *lf_struct = (CV_LeafStruct2 *)itype_leaf_first; + U8 *numeric_ptr = (U8*)(lf_struct + 1); + CV_NumericParsed size = cv_numeric_from_data_range(numeric_ptr, itype_leaf_opl); + U64 size_u64 = cv_u64_from_numeric(&size); + U8 *name_ptr = numeric_ptr + size.encoded_size; + String8 name = str8_cstring_capped(name_ptr, itype_leaf_opl); + + // rjf: fill type + if(lf_struct->props & CV_TypeProp_FwdRef) + { + dst_type->kind = (kind == CV_LeafKind_CLASS2 ? RDI_TypeKind_IncompleteClass : RDI_TypeKind_IncompleteStruct); + dst_type->name = name; + } + else + { + dst_type->kind = (kind == CV_LeafKind_CLASS2 ? RDI_TypeKind_Class : RDI_TypeKind_Struct); + dst_type->byte_size = (U32)size_u64; + dst_type->name = name; + } + + // rjf: push revisit task for members + if(!(lf_struct->props & CV_TypeProp_FwdRef)) + { + P2R_TypeIdRevisitTask *t = push_array(scratch.arena, P2R_TypeIdRevisitTask, 1); + SLLQueuePush(first_itype_revisit_task, last_itype_revisit_task, t); + t->base_type = dst_type; + t->field_itype = lf_struct->field_itype; + } + }break; + + //- rjf: UNION + case CV_LeafKind_UNION: + { + // TODO(rjf): handle props + + // rjf: unpack leaf + CV_LeafUnion *lf_union = (CV_LeafUnion *)itype_leaf_first; + U8 *numeric_ptr = (U8*)(lf_union + 1); + CV_NumericParsed size = cv_numeric_from_data_range(numeric_ptr, itype_leaf_opl); + U64 size_u64 = cv_u64_from_numeric(&size); + U8 *name_ptr = numeric_ptr + size.encoded_size; + String8 name = str8_cstring_capped(name_ptr, itype_leaf_opl); + + // rjf: fill type + if(lf_union->props & CV_TypeProp_FwdRef) + { + dst_type->kind = RDI_TypeKind_IncompleteUnion; + dst_type->name = name; + } + else + { + dst_type->kind = RDI_TypeKind_Union; + dst_type->byte_size = (U32)size_u64; + dst_type->name = name; + } + + // rjf: push revisit task for members + if(!(lf_union->props & CV_TypeProp_FwdRef)) + { + P2R_TypeIdRevisitTask *t = push_array(scratch.arena, P2R_TypeIdRevisitTask, 1); + SLLQueuePush(first_itype_revisit_task, last_itype_revisit_task, t); + t->base_type = dst_type; + t->field_itype = lf_union->field_itype; + } + }break; + + //- rjf: ENUM + case CV_LeafKind_ENUM: + { + // TODO(rjf): handle props + + // rjf: unpack leaf + CV_LeafEnum *lf_enum = (CV_LeafEnum *)itype_leaf_first; + RDIM_Type *direct_type = p2r_type_ptr_from_itype(lf_enum->base_itype); + U8 *name_ptr = (U8 *)(lf_enum + 1); + String8 name = str8_cstring_capped(name_ptr, itype_leaf_opl); + + // rjf: fill type + if(lf_enum->props & CV_TypeProp_FwdRef) + { + dst_type->kind = RDI_TypeKind_IncompleteEnum; + dst_type->name = name; + } + else + { + dst_type->kind = RDI_TypeKind_Enum; + dst_type->direct_type = direct_type; + dst_type->name = name; + } + + // rjf: push revisit task for enumerates/size + if(!(lf_enum->props & CV_TypeProp_FwdRef)) + { + P2R_TypeIdRevisitTask *t = push_array(scratch.arena, P2R_TypeIdRevisitTask, 1); + SLLQueuePush(first_itype_revisit_task, last_itype_revisit_task, t); + t->base_type = dst_type; + t->field_itype = lf_enum->field_itype; + } + }break; + } + } + } + } +#undef p2r_type_ptr_from_itype + } + + ////////////////////////////////////////////////////////////// + //- rjf: types pass 2: attach cross-itype-relationship data to all types, build UDTs + // + // given the root/stub types for all itypes, this pass takes care of the + // following extra pieces of per-type information: + // + // - function/method type parameters + // - modifier byte sizes + // - bitfield direct type byte sizes + // - struct/class/union members + // - array counts + // - direct type forward resolution + // + RDIM_UDTChunkList udts = {0}; + ProfScope("types pass 2: attach cross-itype-relationship data to all types, build UDTs") + { + RDI_U64 udts_chunk_cap = 1024; + CV_TypeId itype_first = tpi_leaf->itype_first; + CV_TypeId itype_opl = tpi_leaf->itype_opl; +#define p2r_type_ptr_from_itype(itype) ((itype_first <= (itype) && (itype) < itype_opl) ? (&itype_types.v[(type_fwd_map[(itype)-itype_first] ? type_fwd_map[(itype)-itype_first] : (itype))-itype_first]) : 0) + for(P2R_TypeIdRevisitTask *task = first_itype_revisit_task; task != 0; task = task->next) + { + RDIM_Type *dst_type = task->base_type; + switch(dst_type->kind) + { + default:{}break; + + //////////////////////// + //- rjf: bitfields/modifiers -> calculate byte size + // + case RDI_TypeKind_Bitfield: + case RDI_TypeKind_Modifier: + if(dst_type->direct_type != 0) + { + dst_type->byte_size = dst_type->direct_type->byte_size; + }break; + + //////////////////////// + //- rjf: functions -> equip parameters + // + case RDI_TypeKind_Function: + { + // rjf: unpack arglist range + CV_RecRange *range = &tpi_leaf->leaf_ranges.ranges[task->field_itype-itype_first]; + if(range->hdr.kind != CV_LeafKind_ARGLIST || + range->hdr.size<2 || + range->off + range->hdr.size > tpi_leaf->data.size) + { + break; + } + U8 *arglist_first = tpi_leaf->data.str + range->off + 2; + U8 *arglist_opl = arglist_first+range->hdr.size-2; + if(arglist_first + sizeof(CV_LeafArgList) > arglist_opl) + { + break; + } + + // rjf: unpack arglist info + CV_LeafArgList *arglist = (CV_LeafArgList*)arglist_first; + CV_TypeId *arglist_itypes_base = (CV_TypeId *)(arglist+1); + U32 arglist_itypes_count = arglist->count; + + // rjf: build param type array + RDIM_Type **params = push_array(arena, RDIM_Type *, arglist_itypes_count); + for(U32 idx = 0; idx < arglist_itypes_count; idx += 1) + { + params[idx] = p2r_type_ptr_from_itype(arglist_itypes_base[idx]); + } + + // rjf: fill dst type + dst_type->count = arglist_itypes_count; + dst_type->param_types = params; + }break; + + //////////////////////// + //- rjf: methods -> equip this ptr + parameters + // + case RDI_TypeKind_Method: + { + // rjf: unpack arglist range + CV_RecRange *range = &tpi_leaf->leaf_ranges.ranges[task->field_itype-itype_first]; + if(range->hdr.kind != CV_LeafKind_ARGLIST || + range->hdr.size<2 || + range->off + range->hdr.size > tpi_leaf->data.size) + { + break; + } + U8 *arglist_first = tpi_leaf->data.str + range->off + 2; + U8 *arglist_opl = arglist_first+range->hdr.size-2; + if(arglist_first + sizeof(CV_LeafArgList) > arglist_opl) + { + break; + } + + // rjf: unpack arglist info + CV_LeafArgList *arglist = (CV_LeafArgList*)arglist_first; + CV_TypeId *arglist_itypes_base = (CV_TypeId *)(arglist+1); + U32 arglist_itypes_count = arglist->count; + + // rjf: build param type array + RDIM_Type **params = push_array(arena, RDIM_Type *, arglist_itypes_count+1); + for(U32 idx = 0; idx < arglist_itypes_count; idx += 1) + { + params[idx+1] = p2r_type_ptr_from_itype(arglist_itypes_base[idx]); + } + params[0] = p2r_type_ptr_from_itype(task->this_itype); + + // rjf: fill dst type + dst_type->count = arglist_itypes_count+1; + dst_type->param_types = params; + }break; + + //////////////////////// + //- rjf: arrays -> calculate array count based on direct type size + // + case RDI_TypeKind_Array: + if(dst_type->direct_type != 0) + { + dst_type->count = dst_type->byte_size/dst_type->direct_type->byte_size; + }break; + + //////////////////////// + //- rjf: structs/unions/classes -> equip members + // + case RDI_TypeKind_Struct: + case RDI_TypeKind_Union: + case RDI_TypeKind_Class: + { + //- rjf: grab UDT info + RDIM_UDT *dst_udt = dst_type->udt; + if(dst_udt == 0) + { + dst_udt = dst_type->udt = rdim_udt_chunk_list_push(arena, &udts, udts_chunk_cap); + dst_udt->self_type = dst_type; + } + + //- rjf: gather all fields + typedef struct FieldListTask FieldListTask; + struct FieldListTask + { + FieldListTask *next; + CV_TypeId itype; + }; + FieldListTask start_fl_task = {0, task->field_itype}; + FieldListTask *fl_todo_stack = &start_fl_task; + FieldListTask *fl_done_stack = 0; + for(;fl_todo_stack != 0;) + { + //- rjf: take & unpack task + FieldListTask *fl_task = fl_todo_stack; + SLLStackPop(fl_todo_stack); + SLLStackPush(fl_done_stack, fl_task); + CV_TypeId field_list_itype = fl_task->itype; + + //- rjf: skip bad itypes + if(field_list_itype < itype_first || itype_opl <= field_list_itype) + { + continue; + } + + //- rjf: field list itype -> range + CV_RecRange *range = &tpi_leaf->leaf_ranges.ranges[field_list_itype-itype_first]; + + //- rjf: skip bad headers + if(range->off+range->hdr.size > tpi_leaf->data.size || + range->hdr.size < 2 || + range->hdr.kind != CV_LeafKind_FIELDLIST) + { + continue; + } + + //- rjf: loop over all fields + { + U8 *field_list_first = tpi_leaf->data.str+range->off+2; + U8 *field_list_opl = field_list_first+range->hdr.size-2; + for(U8 *read_ptr = field_list_first, *next_read_ptr = field_list_opl; + read_ptr < field_list_opl; + read_ptr = next_read_ptr) + { + // rjf: unpack field + CV_LeafKind field_kind = *(CV_LeafKind *)read_ptr; + U64 field_leaf_header_size = cv_header_struct_size_from_leaf_kind(field_kind); + U8 *field_leaf_first = read_ptr+2; + U8 *field_leaf_opl = field_leaf_first+field_leaf_header_size; + next_read_ptr = field_leaf_opl; + + // rjf: skip out-of-bounds fields + if(field_leaf_opl > field_list_opl) + { + continue; + } + + // rjf: process field + switch(field_kind) + { + //- rjf: unhandled/invalid cases + default: + { + // TODO(rjf): log + }break; + + //- rjf: INDEX + case CV_LeafKind_INDEX: + { + // rjf: unpack leaf + CV_LeafIndex *lf = (CV_LeafIndex *)field_leaf_first; + CV_TypeId new_itype = lf->itype; + + // rjf: determine if index itype is new + B32 is_new = 1; + for(FieldListTask *t = fl_done_stack; t != 0; t = t->next) + { + if(t->itype == new_itype) + { + is_new = 0; + break; + } + } + + // rjf: if new -> push task to follow new itype + if(is_new) + { + FieldListTask *new_task = push_array(scratch.arena, FieldListTask, 1); + SLLStackPush(fl_todo_stack, new_task); + new_task->itype = new_itype; + } + }break; + + //- rjf: MEMBER + case CV_LeafKind_MEMBER: + { + // TODO(rjf): log on bad offset + + // rjf: unpack leaf + CV_LeafMember *lf = (CV_LeafMember *)field_leaf_first; + U8 *offset_ptr = (U8 *)(lf+1); + CV_NumericParsed offset = cv_numeric_from_data_range(offset_ptr, field_leaf_opl); + U64 offset64 = cv_u64_from_numeric(&offset); + U8 *name_ptr = offset_ptr + offset.encoded_size; + String8 name = str8_cstring_capped(name_ptr, field_leaf_opl); + + // rjf: bump next read pointer past variable length parts + next_read_ptr = name.str+name.size+1; + + // rjf: emit member + RDIM_UDTMember *mem = rdim_udt_push_member(arena, dst_udt); + mem->kind = RDI_MemberKind_DataField; + mem->name = name; + mem->type = p2r_type_ptr_from_itype(lf->itype); + mem->off = (U32)offset64; + }break; + + //- rjf: STMEMBER + case CV_LeafKind_STMEMBER: + { + // TODO(rjf): handle attribs + + // rjf: unpack leaf + CV_LeafStMember *lf = (CV_LeafStMember *)field_leaf_first; + U8 *name_ptr = (U8 *)(lf+1); + String8 name = str8_cstring_capped(name_ptr, field_leaf_opl); + + // rjf: bump next read pointer past variable length parts + next_read_ptr = name.str+name.size+1; + + // rjf: emit member + RDIM_UDTMember *mem = rdim_udt_push_member(arena, dst_udt); + mem->kind = RDI_MemberKind_StaticData; + mem->name = name; + mem->type = p2r_type_ptr_from_itype(lf->itype); + }break; + + //- rjf: METHOD + case CV_LeafKind_METHOD: + { + // rjf: unpack leaf + CV_LeafMethod *lf = (CV_LeafMethod *)field_leaf_first; + U8 *name_ptr = (U8 *)(lf+1); + String8 name = str8_cstring_capped(name_ptr, field_leaf_opl); + + // rjf: bump next read pointer past variable length parts + next_read_ptr = name.str+name.size+1; + + //- rjf: method list itype -> range + CV_RecRange *method_list_range = &tpi_leaf->leaf_ranges.ranges[lf->list_itype-itype_first]; + + //- rjf: skip bad method lists + if(method_list_range->off+method_list_range->hdr.size > tpi_leaf->data.size || + method_list_range->hdr.size < 2 || + method_list_range->hdr.kind != CV_LeafKind_METHODLIST) + { + break; + } + + //- rjf: loop through all methods & emit members + U8 *method_list_first = tpi_leaf->data.str + method_list_range->off + 2; + U8 *method_list_opl = method_list_first + method_list_range->hdr.size-2; + for(U8 *method_read_ptr = method_list_first, *next_method_read_ptr = method_list_opl; + method_read_ptr < method_list_opl; + method_read_ptr = next_method_read_ptr) + { + CV_LeafMethodListMember *method = (CV_LeafMethodListMember*)method_read_ptr; + CV_MethodProp prop = CV_FieldAttribs_ExtractMethodProp(method->attribs); + RDIM_Type *method_type = p2r_type_ptr_from_itype(method->itype); + next_method_read_ptr = (U8 *)(method+1); + + // TODO(allen): PROBLEM + // We only get offsets for virtual functions (the "vbaseoff") from + // "Intro" and "PureIntro". In C++ inheritance, when we have a chain + // of inheritance (let's just talk single inheritance for now) the + // first class in the chain that introduces a new virtual function + // has this "Intro" method. If a later class in the chain redefines + // the virtual function it only has a "Virtual" method which does + // not update the offset. There is a "Virtual" and "PureVirtual" + // variant of "Virtual". The "Pure" in either case means there + // is no concrete procedure. When there is no "Pure" the method + // should have a corresponding procedure symbol id. + // + // The issue is we will want to mark all of our virtual methods as + // virtual and give them an offset, but that means we have to do + // some extra figuring to propogate offsets from "Intro" methods + // to "Virtual" methods in inheritance trees. That is - IF we want + // to start preserving the offsets of virtuals. There is room in + // the method struct to make this work, but for now I've just + // decided to drop this information. It is not urgently useful to + // us and greatly complicates matters. + + // rjf: read vbaseoff + U32 vbaseoff = 0; + if(prop == CV_MethodProp_Intro || prop == CV_MethodProp_PureIntro) + { + if(next_method_read_ptr+4 <= method_list_opl) + { + vbaseoff = *(U32 *)next_method_read_ptr; + } + next_method_read_ptr += 4; + } + + // rjf: emit method + switch(prop) + { + default: + { + RDIM_UDTMember *mem = rdim_udt_push_member(arena, dst_udt); + mem->kind = RDI_MemberKind_Method; + mem->name = name; + mem->type = method_type; + }break; + case CV_MethodProp_Static: + { + RDIM_UDTMember *mem = rdim_udt_push_member(arena, dst_udt); + mem->kind = RDI_MemberKind_StaticMethod; + mem->name = name; + mem->type = method_type; + }break; + case CV_MethodProp_Virtual: + case CV_MethodProp_PureVirtual: + case CV_MethodProp_Intro: + case CV_MethodProp_PureIntro: + { + RDIM_UDTMember *mem = rdim_udt_push_member(arena, dst_udt); + mem->kind = RDI_MemberKind_VirtualMethod; + mem->name = name; + mem->type = method_type; + }break; + } + } + + }break; + + //- rjf: ONEMETHOD + case CV_LeafKind_ONEMETHOD: + { + // TODO(rjf): handle attribs + + // rjf: unpack leaf + CV_LeafOneMethod *lf = (CV_LeafOneMethod *)field_leaf_first; + CV_MethodProp prop = CV_FieldAttribs_ExtractMethodProp(lf->attribs); + U8 *vbaseoff_ptr = (U8 *)(lf+1); + U8 *vbaseoff_opl_ptr = vbaseoff_ptr; + U32 vbaseoff = 0; + if(prop == CV_MethodProp_Intro || prop == CV_MethodProp_PureIntro) + { + vbaseoff = *(U32 *)(vbaseoff_ptr); + vbaseoff_opl_ptr += sizeof(U32); + } + U8 *name_ptr = vbaseoff_opl_ptr; + String8 name = str8_cstring_capped(name_ptr, field_leaf_opl); + RDIM_Type *method_type = p2r_type_ptr_from_itype(lf->itype); + + // rjf: bump next read pointer past variable length parts + next_read_ptr = name.str+name.size+1; + + // rjf: emit method + switch(prop) + { + default: + { + RDIM_UDTMember *mem = rdim_udt_push_member(arena, dst_udt); + mem->kind = RDI_MemberKind_Method; + mem->name = name; + mem->type = method_type; + }break; + + case CV_MethodProp_Static: + { + RDIM_UDTMember *mem = rdim_udt_push_member(arena, dst_udt); + mem->kind = RDI_MemberKind_StaticMethod; + mem->name = name; + mem->type = method_type; + }break; + + case CV_MethodProp_Virtual: + case CV_MethodProp_PureVirtual: + case CV_MethodProp_Intro: + case CV_MethodProp_PureIntro: + { + RDIM_UDTMember *mem = rdim_udt_push_member(arena, dst_udt); + mem->kind = RDI_MemberKind_VirtualMethod; + mem->name = name; + mem->type = method_type; + }break; + } + }break; + + //- rjf: NESTTYPE + case CV_LeafKind_NESTTYPE: + { + // rjf: unpack leaf + CV_LeafNestType *lf = (CV_LeafNestType *)field_leaf_first; + U8 *name_ptr = (U8 *)(lf+1); + String8 name = str8_cstring_capped(name_ptr, field_leaf_opl); + + // rjf: bump next read pointer past variable length parts + next_read_ptr = name.str+name.size+1; + + // rjf: emit member + RDIM_UDTMember *mem = rdim_udt_push_member(arena, dst_udt); + mem->kind = RDI_MemberKind_NestedType; + mem->name = name; + mem->type = p2r_type_ptr_from_itype(lf->itype); + }break; + + //- rjf: NESTTYPEEX + case CV_LeafKind_NESTTYPEEX: + { + // TODO(rjf): handle attribs + + // rjf: unpack leaf + CV_LeafNestTypeEx *lf = (CV_LeafNestTypeEx *)field_leaf_first; + U8 *name_ptr = (U8 *)(lf+1); + String8 name = str8_cstring_capped(name_ptr, field_leaf_opl); + + // rjf: bump next read pointer past variable length parts + next_read_ptr = name.str+name.size+1; + + // rjf: emit member + RDIM_UDTMember *mem = rdim_udt_push_member(arena, dst_udt); + mem->kind = RDI_MemberKind_NestedType; + mem->name = name; + mem->type = p2r_type_ptr_from_itype(lf->itype); + }break; + + //- rjf: BCLASS + case CV_LeafKind_BCLASS: + { + // TODO(rjf): log on bad offset + + // rjf: unpack leaf + CV_LeafBClass *lf = (CV_LeafBClass *)field_leaf_first; + U8 *offset_ptr = (U8 *)(lf+1); + CV_NumericParsed offset = cv_numeric_from_data_range(offset_ptr, field_leaf_opl); + U64 offset64 = cv_u64_from_numeric(&offset); + + // rjf: bump next read pointer past variable length parts + next_read_ptr = offset_ptr+offset.encoded_size; + + // rjf: emit member + RDIM_UDTMember *mem = rdim_udt_push_member(arena, dst_udt); + mem->kind = RDI_MemberKind_Base; + mem->type = p2r_type_ptr_from_itype(lf->itype); + mem->off = (U32)offset64; + }break; + + //- rjf: VBCLASS/IVBCLASS + case CV_LeafKind_VBCLASS: + case CV_LeafKind_IVBCLASS: + { + // TODO(rjf): log on bad offsets + // TODO(rjf): handle attribs + // TODO(rjf): offsets? + + // rjf: unpack leaf + CV_LeafVBClass *lf = (CV_LeafVBClass *)field_leaf_first; + U8 *num1_ptr = (U8 *)(lf+1); + CV_NumericParsed num1 = cv_numeric_from_data_range(num1_ptr, field_leaf_opl); + U8 *num2_ptr = num1_ptr + num1.encoded_size; + CV_NumericParsed num2 = cv_numeric_from_data_range(num2_ptr, field_leaf_opl); + + // rjf: emit member + RDIM_UDTMember *mem = rdim_udt_push_member(arena, dst_udt); + mem->kind = RDI_MemberKind_VirtualBase; + mem->type = p2r_type_ptr_from_itype(lf->itype); + }break; + + //- rjf: VFUNCTAB + case CV_LeafKind_VFUNCTAB: + { + CV_LeafVFuncTab *lf = (CV_LeafVFuncTab *)field_leaf_first; + // NOTE(rjf): currently no-op this case + (void)lf; + }break; + } + + // rjf: align-up next field + next_read_ptr = (U8 *)AlignPow2((U64)next_read_ptr, 4); + } + } + } + }break; + + //////////////////////// + //- rjf: enums -> equip enumerates + // + case RDI_TypeKind_Enum: + { + //- rjf: grab UDT info + RDIM_UDT *dst_udt = dst_type->udt; + if(dst_udt == 0) + { + dst_udt = dst_type->udt = rdim_udt_chunk_list_push(arena, &udts, udts_chunk_cap); + dst_udt->self_type = dst_type; + } + + //- rjf: gather all fields + typedef struct FieldListTask FieldListTask; + struct FieldListTask + { + FieldListTask *next; + CV_TypeId itype; + }; + FieldListTask start_fl_task = {0, task->field_itype}; + FieldListTask *fl_todo_stack = &start_fl_task; + FieldListTask *fl_done_stack = 0; + for(;fl_todo_stack != 0;) + { + //- rjf: take & unpack task + FieldListTask *fl_task = fl_todo_stack; + SLLStackPop(fl_todo_stack); + SLLStackPush(fl_done_stack, fl_task); + CV_TypeId field_list_itype = fl_task->itype; + + //- rjf: skip bad itypes + if(field_list_itype < itype_first || itype_opl <= field_list_itype) + { + continue; + } + + //- rjf: field list itype -> range + CV_RecRange *range = &tpi_leaf->leaf_ranges.ranges[field_list_itype-itype_first]; + + //- rjf: skip bad headers + if(range->off+range->hdr.size > tpi_leaf->data.size || + range->hdr.size < 2 || + range->hdr.kind != CV_LeafKind_FIELDLIST) + { + continue; + } + + //- rjf: loop over all fields + { + U8 *field_list_first = tpi_leaf->data.str+range->off+2; + U8 *field_list_opl = field_list_first+range->hdr.size-2; + for(U8 *read_ptr = field_list_first, *next_read_ptr = field_list_opl; + read_ptr < field_list_opl; + read_ptr = next_read_ptr) + { + // rjf: unpack field + CV_LeafKind field_kind = *(CV_LeafKind *)read_ptr; + U64 field_leaf_header_size = cv_header_struct_size_from_leaf_kind(field_kind); + U8 *field_leaf_first = read_ptr+2; + U8 *field_leaf_opl = field_leaf_first+field_leaf_header_size; + next_read_ptr = field_leaf_opl; + + // rjf: skip out-of-bounds fields + if(field_leaf_opl > field_list_opl) + { + continue; + } + + // rjf: process field + switch(field_kind) + { + //- rjf: unhandled/invalid cases + default: + { + // TODO(rjf): log + }break; + + //- rjf: INDEX + case CV_LeafKind_INDEX: + { + // rjf: unpack leaf + CV_LeafIndex *lf = (CV_LeafIndex *)field_leaf_first; + CV_TypeId new_itype = lf->itype; + + // rjf: determine if index itype is new + B32 is_new = 1; + for(FieldListTask *t = fl_done_stack; t != 0; t = t->next) + { + if(t->itype == new_itype) + { + is_new = 0; + break; + } + } + + // rjf: if new -> push task to follow new itype + if(is_new) + { + FieldListTask *new_task = push_array(scratch.arena, FieldListTask, 1); + SLLStackPush(fl_todo_stack, new_task); + new_task->itype = new_itype; + } + }break; + + //- rjf: ENUMERATE + case CV_LeafKind_ENUMERATE: + { + // TODO(rjf): attribs + + // rjf: unpack leaf + CV_LeafEnumerate *lf = (CV_LeafEnumerate *)field_leaf_first; + U8 *val_ptr = (U8 *)(lf+1); + CV_NumericParsed val = cv_numeric_from_data_range(val_ptr, field_leaf_opl); + U64 val64 = cv_u64_from_numeric(&val); + U8 *name_ptr = val_ptr + val.encoded_size; + String8 name = str8_cstring_capped(name_ptr, field_leaf_opl); + + // rjf: bump next read pointer past variable length parts + next_read_ptr = name.str+name.size+1; + + // rjf: emit member + RDIM_UDTEnumVal *enum_val = rdim_udt_push_enum_val(arena, dst_udt); + enum_val->name = name; + enum_val->val = val64; + }break; + } + + // rjf: align-up next field + next_read_ptr = (U8 *)AlignPow2((U64)next_read_ptr, 4); + } + } + } + }break; + } + } +#undef p2r_type_ptr_from_itype + } + + ////////////////////////////////////////////////////////////// + //- rjf: produce link name map + // + P2R_LinkNameMap link_name_map = {0}; + ProfScope("produce link name map") + { + link_name_map.buckets_count = symbol_count_prediction; + link_name_map.buckets = push_array(arena, P2R_LinkNameNode *, link_name_map.buckets_count); + CV_RecRange *rec_ranges_first = sym->sym_ranges.ranges; + CV_RecRange *rec_ranges_opl = rec_ranges_first + sym->sym_ranges.count; + for(CV_RecRange *rec_range = rec_ranges_first; + rec_range < rec_ranges_opl; + rec_range += 1) + { + //- rjf: unpack symbol range info + CV_SymKind kind = rec_range->hdr.kind; + U64 header_struct_size = cv_header_struct_size_from_sym_kind(kind); + U8 *sym_first = sym->data.str + rec_range->off + 2; + U8 *sym_opl = sym_first + rec_range->hdr.size; + + //- rjf: skip bad ranges + if(sym_opl > sym->data.str + sym->data.size || sym_first + header_struct_size > sym->data.str + sym->data.size) + { + continue; + } + + //- rjf: consume symbol + switch(kind) + { + default:{}break; + case CV_SymKind_PUB32: + { + // rjf: unpack sym + CV_SymPub32 *pub32 = (CV_SymPub32 *)sym_first; + String8 name = str8_cstring_capped(pub32+1, sym_opl); + COFF_SectionHeader *section = (0 < pub32->sec && pub32->sec <= coff_sections->count) ? &coff_sections->sections[pub32->sec-1] : 0; + U64 voff = 0; + if(section != 0) + { + voff = section->voff + pub32->off; + } + + // rjf: commit to link name map + U64 hash = (voff >> 3) ^ ((7 & voff) << 6); + U64 bucket_idx = hash%link_name_map.buckets_count; + P2R_LinkNameNode *node = push_array(arena, P2R_LinkNameNode, 1); + SLLStackPush(link_name_map.buckets[bucket_idx], node); + node->voff = voff; + node->name = name; + link_name_map.link_name_count += 1; + link_name_map.bucket_collision_count += (node->next != 0); + }break; + } + } + } + + ////////////////////////////////////////////////////////////// + //- rjf: produce all symbols for all units + // + ProfScope("produce all symbols for all units") + { + } + + + //~ TODO(rjf): OLD vvvvvvvvvvvvvvvvvvv +#if 0 + + // output generation + P2R_Ctx *p2r_ctx = 0; + if(params->output_name.size > 0) + { // setup root RDIM_RootParams root_params = {0}; root_params.addr_size = addr_size; @@ -3673,11 +5122,11 @@ str8_list_pushf(arena, &out->errors, fmt, __VA_ARGS__);\ // conversion errors if(!params->hide_errors.converting) { - for(RDIM_Error *error = rdim_first_error_from_root(root); - error != 0; - error = error->next) + for(RDIM_Msg *msg = rdim_first_msg_from_root(root); + msg != 0; + msg = msg->next) { - str8_list_push(arena, &out->errors, error->msg); + str8_list_push(arena, &out->errors, msg->string); } } } @@ -3916,5 +5365,8 @@ str8_list_pushf(arena, &out->errors, fmt, __VA_ARGS__);\ out->dump = dump; } +#endif + + scratch_end(scratch); return out; } diff --git a/src/raddbgi_from_pdb/raddbgi_from_pdb.h b/src/raddbgi_from_pdb/raddbgi_from_pdb.h index 42f382fa..308b5118 100644 --- a/src/raddbgi_from_pdb/raddbgi_from_pdb.h +++ b/src/raddbgi_from_pdb/raddbgi_from_pdb.h @@ -222,6 +222,9 @@ internal RDI_BinarySectionFlags rdi_binary_section_flags_from_coff_section_flags internal RDI_Arch rdi_arch_from_cv_arch(CV_Arch arch); internal RDI_RegisterCode rdi_reg_code_from_cv_reg_code(RDI_Arch arch, CV_Reg reg_code); internal RDI_Language rdi_language_from_cv_language(CV_Language language); +internal RDI_TypeKind rdi_type_kind_from_cv_basic_type(CV_BasicType basic_type); + +#if 0 //////////////////////////////// //~ rjf: Conversion Implementation Helpers @@ -327,6 +330,8 @@ internal void p2r_link_name_save(Arena *arena, P2R_LinkNameMap *map, U64 voff, String8 name); internal String8 p2r_link_name_find(P2R_LinkNameMap *map, U64 voff); +#endif + //////////////////////////////// //~ rjf: Top-Level Conversion Entry Point