<s> for ( const auto & FuncSec : FuncInfoTable ) { FuncLen += <STR_LIT> ; FuncLen += FuncSec . second . size ( ) * <STR_LIT> ; } for ( const auto & LineSec : LineInfoTable ) { LineLen += <STR_LIT> ; LineLen += LineSec . second . size ( ) * <STR_LIT> ; } for ( const auto & FieldRelocSec : FieldRelocTable ) { FieldRelocLen += <STR_LIT> ; FieldRelocLen += FieldRelocSec . second . size ( ) * <STR_LIT> ; } if ( FieldRelocLen ) FieldRelocLen += <NUM_LIT> ; OS . emitIntValue ( <NUM_LIT> , <NUM_LIT> ) ; OS . emitIntValue ( FuncLen , <NUM_LIT> ) ; OS . emitIntValue ( FuncLen , <NUM_LIT> ) ; OS . emitIntValue ( LineLen , <NUM_LIT> ) ; OS . emitIntValue ( FuncLen + LineLen , <NUM_LIT> ) ; OS . emitIntValue ( FieldRelocLen , <NUM_LIT> ) ; OS . AddComment ( <STR_LIT> ) ; OS . emitIntValue ( <STR_LIT> , <NUM_LIT> ) ; for ( const auto & FuncSec : FuncInfoTable ) { OS . AddComment ( <STR_LIT> + std :: to_string ( FuncSec . first ) ) ;

OS . emitIntValue ( FuncSec . first , <NUM_LIT> ) ;


<s> MCContext & Ctx = OS . getContext ( ) ; OS . SwitchSection ( Ctx . getELFSection ( <STR_LIT> , ELF :: SHT_PROGBITS , <NUM_LIT> ) ) ; emitCommonHeader ( ) ; OS . emitIntValue ( <STR_LIT> , <NUM_LIT> ) ; uint32_t TypeLen = <NUM_LIT> , StrLen ; for ( const auto & TypeEntry : TypeEntries ) TypeLen += TypeEntry -> getSize ( ) ; StrLen = StringTable . getSize ( ) ; OS . emitIntValue ( <NUM_LIT> , <NUM_LIT> ) ;

OS . emitIntValue ( TypeLen , <NUM_LIT> ) ;


<s> OS . emitIntValue ( TypeLen , <NUM_LIT> ) ; OS . emitIntValue ( TypeLen , <NUM_LIT> ) ; OS . emitIntValue ( StrLen , <NUM_LIT> ) ; for ( const auto & TypeEntry : TypeEntries ) TypeEntry -> emitType ( OS ) ; uint32_t StringOffset = <NUM_LIT> ; for ( const auto & S : StringTable . getTable ( ) ) { OS . AddComment ( <STR_LIT> + std :: to_string ( StringOffset ) ) ;


<s> OS . AddComment ( <STR_LIT> + Twine :: utohexstr ( <STR_LIT> ) ) ; OS . emitIntValue ( <STR_LIT> , <NUM_LIT> ) ;


<s> OS . emitIntValue ( <STR_LIT> , <NUM_LIT> ) ; OS . emitIntValue ( <NUM_LIT> , <NUM_LIT> ) ;


<s> Asm -> emitLabelReference ( std :: get < <NUM_LIT> > ( V ) , <NUM_LIT> ) ; OS . emitIntValue ( std :: get < <NUM_LIT> > ( V ) , <NUM_LIT> ) ;


<s> } if ( MI -> getOpcode ( ) == <STR_LIT> ) { processReloc ( MI -> getOperand ( <NUM_LIT> ) ) ; } else if ( MI -> getOpcode ( ) == <STR_LIT> || MI -> getOpcode ( ) == <STR_LIT> || MI -> getOpcode ( ) == <STR_LIT> ) { processReloc ( MI -> getOperand ( <NUM_LIT> ) ) ; } else if ( MI -> getOpcode ( ) == <STR_LIT> ) { const MachineOperand & MO = MI -> getOperand ( <NUM_LIT> ) ; if ( MO . isGlobal ( ) ) { processFuncPrototypes ( dyn_cast < Function > ( MO . getGlobal ( ) ) ) ; } } if ( ! CurMI ) return ; const DebugLoc & DL = MI -> getDebugLoc ( ) ; if ( ! DL || PrevInstLoc == DL ) { if ( LineInfoGenerated == false ) { auto * S = MI -> getMF ( ) -> getFunction ( ) . getSubprogram ( ) ; MCSymbol * FuncLabel = Asm -> getFunctionBegin ( ) ; constructLineInfo ( S , FuncLabel , S -> getLine ( ) , <NUM_LIT> ) ; LineInfoGenerated = true ; } return ; } MCSymbol * LineSym = OS . getContext ( ) . createTempSymbol ( ) ; OS . emitLabel ( LineSym ) ;

auto SP = DL . get ( ) -> getScope ( ) -> getSubprogram ( ) ;


<s> if ( MO . isGlobal ( ) ) { const GlobalValue * GVal = MO . getGlobal ( ) ; auto * GVar = dyn_cast < GlobalVariable > ( GVal ) ; if ( GVar ) { int64_t Imm ; uint32_t Reloc ; if ( GVar -> hasAttribute ( <STR_LIT> ) || GVar -> hasAttribute ( <STR_LIT> ) ) { Imm = PatchImms [ GVar ] . first ; Reloc = PatchImms [ GVar ] . second ; } else { return false ; } if ( Reloc == <STR_LIT> || Reloc == <STR_LIT> ) OutMI . setOpcode ( <STR_LIT> ) ; else OutMI . setOpcode ( <STR_LIT> ) ; OutMI . addOperand ( MCOperand :: createReg ( MI -> getOperand ( <NUM_LIT> ) . getReg ( ) ) ) ; OutMI . addOperand ( MCOperand :: createImm ( Imm ) ) ; return true ; } } } else if ( MI -> getOpcode ( ) == <STR_LIT> || MI -> getOpcode ( ) == <STR_LIT> || MI -> getOpcode ( ) == <STR_LIT> ) { const MachineOperand & MO = MI -> getOperand ( <NUM_LIT> ) ; if ( MO . isGlobal ( ) ) { const GlobalValue * GVal = MO . getGlobal ( ) ; auto * GVar = dyn_cast < GlobalVariable > ( GVal ) ; if ( GVar && GVar -> hasAttribute ( <STR_LIT> ) ) { uint32_t Imm = PatchImms [ GVar ] . first ; OutMI . setOpcode ( MI -> getOperand ( <NUM_LIT> ) . getImm ( ) ) ; if ( MI -> getOperand ( <NUM_LIT> ) . isImm ( ) ) OutMI . addOperand ( MCOperand :: createImm ( MI -> getOperand ( <NUM_LIT> ) . getImm ( ) ) ) ;

else OutMI . addOperand ( MCOperand :: createReg ( MI -> getOperand ( <NUM_LIT> ) . getReg ( ) ) ) ;


<s> Imm = PatchImms [ GVar ] . first ; Reloc = PatchImms [ GVar ] . second ; } else { return false ; } if ( Reloc == <STR_LIT> || Reloc == <STR_LIT> ) OutMI . setOpcode ( <STR_LIT> ) ; else OutMI . setOpcode ( <STR_LIT> ) ; OutMI . addOperand ( MCOperand :: createReg ( MI -> getOperand ( <NUM_LIT> ) . getReg ( ) ) ) ; OutMI . addOperand ( MCOperand :: createImm ( Imm ) ) ; return true ; } } } else if ( MI -> getOpcode ( ) == <STR_LIT> || MI -> getOpcode ( ) == <STR_LIT> || MI -> getOpcode ( ) == <STR_LIT> ) { const MachineOperand & MO = MI -> getOperand ( <NUM_LIT> ) ; if ( MO . isGlobal ( ) ) { const GlobalValue * GVal = MO . getGlobal ( ) ; auto * GVar = dyn_cast < GlobalVariable > ( GVal ) ; if ( GVar && GVar -> hasAttribute ( <STR_LIT> ) ) { uint32_t Imm = PatchImms [ GVar ] . first ; OutMI . setOpcode ( MI -> getOperand ( <NUM_LIT> ) . getImm ( ) ) ; if ( MI -> getOperand ( <NUM_LIT> ) . isImm ( ) ) OutMI . addOperand ( MCOperand :: createImm ( MI -> getOperand ( <NUM_LIT> ) . getImm ( ) ) ) ; else OutMI . addOperand ( MCOperand :: createReg ( MI -> getOperand ( <NUM_LIT> ) . getReg ( ) ) ) ; OutMI . addOperand ( MCOperand :: createReg ( MI -> getOperand ( <NUM_LIT> ) . getReg ( ) ) ) ;


<s> DataSecEntries [ std :: string ( SecName ) ] = std :: make_unique < BTFKindDataSec > ( Asm , std :: string ( SecName ) ) ; } } SmallVector < DIGlobalVariableExpression * , <NUM_LIT> > GVs ; Global . getDebugInfo ( GVs ) ; if ( GVs . size ( ) == <NUM_LIT> ) continue ; uint32_t GVTypeId = <NUM_LIT> ; for ( auto * GVE : GVs ) { if ( SecName . startswith ( <STR_LIT> ) ) visitMapDefType ( GVE -> getVariable ( ) -> getType ( ) , GVTypeId ) ; else visitTypeEntry ( GVE -> getVariable ( ) -> getType ( ) , GVTypeId , false , false ) ; break ; } auto Linkage = Global . getLinkage ( ) ; if ( Linkage != GlobalValue :: InternalLinkage && Linkage != GlobalValue :: ExternalLinkage && Linkage != GlobalValue :: WeakAnyLinkage && Linkage != GlobalValue :: ExternalWeakLinkage ) continue ; uint32_t GVarInfo ; if ( Linkage == GlobalValue :: InternalLinkage ) { GVarInfo = <STR_LIT> ; } else if ( Global . hasInitializer ( ) ) { GVarInfo = <STR_LIT> ; } else { GVarInfo = <STR_LIT> ; }

auto VarEntry = std :: make_unique < BTFKindVar > ( Global . getName ( ) , GVTypeId , GVarInfo ) ;


<s> BTFTypeTag :: BTFTypeTag ( uint32_t BaseTypeId , int ComponentIdx , StringRef Tag ) : Tag ( Tag ) { Kind = <STR_LIT> ; BTFType . Info = Kind << <NUM_LIT> ; BTFType . Type = BaseTypeId ;


<s> const MDNode * MD = cast < MDNode > ( Annotation ) ; const MDString * Name = cast < MDString > ( MD -> getOperand ( <NUM_LIT> ) ) ; if ( ! Name -> getString ( ) . equals ( <STR_LIT> ) ) continue ; const MDString * Value = cast < MDString > ( MD -> getOperand ( <NUM_LIT> ) ) ; auto TypeEntry = std :: make_unique < BTFTypeTag > ( BaseTypeId , ComponentIdx , Value -> getString ( ) ) ;


<s> StringRef SecName ; if ( Global . hasSection ( ) ) { SecName = Global . getSection ( ) ; } else { if ( Global . isConstant ( ) ) SecName = <STR_LIT> ; else SecName = Global . getInitializer ( ) -> isZeroValue ( ) ? <STR_LIT> : <STR_LIT> ; } if ( ProcessingMapDef != SecName . startswith ( <STR_LIT> ) ) continue ; SmallVector < DIGlobalVariableExpression * , <NUM_LIT> > GVs ; Global . getDebugInfo ( GVs ) ; if ( GVs . size ( ) == <NUM_LIT> ) continue ; uint32_t GVTypeId = <NUM_LIT> ; for ( auto * GVE : GVs ) { if ( SecName . startswith ( <STR_LIT> ) ) visitMapDefType ( GVE -> getVariable ( ) -> getType ( ) , GVTypeId ) ; else visitTypeEntry ( GVE -> getVariable ( ) -> getType ( ) , GVTypeId , false , false ) ; break ;


<s> if ( ! Annotations ) return ; for ( const Metadata * Annotation : Annotations -> operands ( ) ) { const MDNode * MD = cast < MDNode > ( Annotation ) ; const MDString * Name = cast < MDString > ( MD -> getOperand ( <NUM_LIT> ) ) ; if ( ! Name -> getString ( ) . equals ( <STR_LIT> ) ) continue ; const MDString * Value = cast < MDString > ( MD -> getOperand ( <NUM_LIT> ) ) ; auto TypeEntry = std :: make_unique < BTFTypeDeclTag > ( BaseTypeId , ComponentIdx , Value -> getString ( ) ) ; addType ( std :: move ( TypeEntry ) ) ; }


<s> if ( ! Name -> getString ( ) . equals ( <STR_LIT> ) ) continue ; const MDString * Value = cast < MDString > ( MD -> getOperand ( <NUM_LIT> ) ) ; auto TypeEntry = std :: make_unique < BTFTypeDeclTag > ( BaseTypeId , ComponentIdx , Value -> getString ( ) ) ;


<s> auto FuncTypeEntry = llvm :: make_unique < BTFTypeFunc > ( SP -> getName ( ) , ProtoTypeId ) ; uint32_t FuncTypeId = addType ( std :: move ( FuncTypeEntry ) ) ; MCSymbol * FuncLabel = Asm -> getFunctionBegin ( ) ; BTFFuncInfo FuncInfo ; FuncInfo . Label = FuncLabel ; FuncInfo . TypeId = FuncTypeId ; if ( FuncLabel -> isInSection ( ) ) { MCSection & Section = FuncLabel -> getSection ( ) ; const MCSectionELF * SectionELF = dyn_cast < MCSectionELF > ( & Section ) ; assert ( SectionELF && <STR_LIT> ) ; SecNameOff = addString ( SectionELF -> getSectionName ( ) ) ; } else { SecNameOff = addString ( <STR_LIT> ) ; } FuncInfoTable [ SecNameOff ] . push_back ( FuncInfo ) ;


<s> OS . EmitIntValue ( <STR_LIT> , <NUM_LIT> ) ; uint32_t FuncLen = <NUM_LIT> , LineLen = <NUM_LIT> ; for ( const auto & FuncSec : FuncInfoTable ) { FuncLen += <STR_LIT> ; FuncLen += FuncSec . second . size ( ) * <STR_LIT> ; } for ( const auto & LineSec : LineInfoTable ) { LineLen += <STR_LIT> ; LineLen += LineSec . second . size ( ) * <STR_LIT> ; } OS . EmitIntValue ( <NUM_LIT> , <NUM_LIT> ) ; OS . EmitIntValue ( FuncLen , <NUM_LIT> ) ; OS . EmitIntValue ( FuncLen , <NUM_LIT> ) ; OS . EmitIntValue ( LineLen , <NUM_LIT> ) ; OS . AddComment ( <STR_LIT> ) ; OS . EmitIntValue ( <STR_LIT> , <NUM_LIT> ) ; for ( const auto & FuncSec : FuncInfoTable ) { OS . AddComment ( <STR_LIT> + std :: to_string ( FuncSec . first ) ) ; OS . EmitIntValue ( FuncSec . first , <NUM_LIT> ) ; OS . EmitIntValue ( FuncSec . second . size ( ) , <NUM_LIT> ) ; for ( const auto & FuncInfo : FuncSec . second ) { Asm -> EmitLabelReference ( FuncInfo . Label , <NUM_LIT> ) ; OS . EmitIntValue ( FuncInfo . TypeId , <NUM_LIT> ) ; } } OS . AddComment ( <STR_LIT> ) ; OS . EmitIntValue ( <STR_LIT> , <NUM_LIT> ) ; for ( const auto & LineSec : LineInfoTable ) {

OS . AddComment ( <STR_LIT> + std :: to_string ( LineSec . first ) ) ;


for ( const auto & TypeEntry : TypeEntries ) TypeEntry -> completeType ( * this ) ;


<s> void BTFDebug :: endModule ( ) { processGlobals ( ) ; for ( const auto & TypeEntry : TypeEntries ) TypeEntry -> completeType ( * this ) ;


<s> auto Linkage = Global . getLinkage ( ) ; if ( Linkage != GlobalValue :: InternalLinkage && ( Linkage != GlobalValue :: ExternalLinkage || ! Global . hasSection ( ) ) ) continue ; uint32_t GVarInfo = Linkage == GlobalValue :: ExternalLinkage ? <STR_LIT> : <STR_LIT> ; auto VarEntry = llvm :: make_unique < BTFKindVar > ( Global . getName ( ) , GVTypeId , GVarInfo ) ; uint32_t VarId = addType ( std :: move ( VarEntry ) ) ; std :: string SecName ; if ( Global . hasSection ( ) ) { SecName = Global . getSection ( ) . str ( ) ; } else { if ( Global . isConstant ( ) ) SecName += <STR_LIT> ;

else SecName += Global . getInitializer ( ) -> isZeroValue ( ) ? <STR_LIT> : <STR_LIT> ;


<s> uint32_t Encoding = BTy -> getEncoding ( ) ; if ( Encoding != dwarf :: DW_ATE_boolean && Encoding != dwarf :: DW_ATE_signed && Encoding != dwarf :: DW_ATE_signed_char && Encoding != dwarf :: DW_ATE_unsigned && Encoding != dwarf :: DW_ATE_unsigned_char ) return ;

auto TypeEntry = llvm :: make_unique < BTFTypeInt > ( Encoding , BTy -> getSizeInBits ( ) , BTy -> getOffsetInBits ( ) , BTy -> getName ( ) ) ;


<s> void BTFDebug :: visitBasicType ( const DIBasicType * BTy , uint32_t & TypeId ) { uint32_t Encoding = BTy -> getEncoding ( ) ;

if ( Encoding != dwarf :: DW_ATE_boolean && Encoding != dwarf :: DW_ATE_signed && Encoding != dwarf :: DW_ATE_signed_char && Encoding != dwarf :: DW_ATE_unsigned && Encoding != dwarf :: DW_ATE_unsigned_char ) return ;


<s> auto TypeEntry = llvm :: make_unique < BTFTypeDerived > ( DTy , Tag ) ; TypeId = addType ( std :: move ( TypeEntry ) , DTy ) ; } else if ( Tag != dwarf :: DW_TAG_member ) { return ; }


<s> if ( Tag == dwarf :: DW_TAG_pointer_type || Tag == dwarf :: DW_TAG_typedef || Tag == dwarf :: DW_TAG_const_type || Tag == dwarf :: DW_TAG_volatile_type || Tag == dwarf :: DW_TAG_restrict_type ) { auto TypeEntry = llvm :: make_unique < BTFTypeDerived > ( DTy , Tag ) ;

TypeId = addType ( std :: move ( TypeEntry ) , DTy ) ;


<s> auto TypeEntry = llvm :: make_unique < BTFTypeEnum > ( CTy , VLen ) ;

TypeId = addType ( std :: move ( TypeEntry ) , CTy ) ;


<s> DINodeArray Elements = CTy -> getElements ( ) ; uint32_t VLen = Elements . size ( ) ; if ( VLen > <STR_LIT> ) return ;

auto TypeEntry = llvm :: make_unique < BTFTypeEnum > ( CTy , VLen ) ;


<s> auto TypeEntry = llvm :: make_unique < BTFTypeFwd > ( CTy -> getName ( ) , IsUnion ) ;


<s> if ( VLen > <STR_LIT> ) return ; auto TypeEntry = llvm :: make_unique < BTFTypeFuncProto > ( STy , VLen , FuncArgNames ) ; if ( ForSubprog ) TypeId = addType ( std :: move ( TypeEntry ) ) ;

else TypeId = addType ( std :: move ( TypeEntry ) , STy ) ;


<s> void BTFDebug :: visitTypeEntry ( const DIType * Ty ) { uint32_t TypeId ;


<s> if ( OffsetRelocLen ) OffsetRelocLen += <NUM_LIT> ; if ( ExternRelocLen ) ExternRelocLen += <NUM_LIT> ; OS . EmitIntValue ( <NUM_LIT> , <NUM_LIT> ) ; OS . EmitIntValue ( FuncLen , <NUM_LIT> ) ; OS . EmitIntValue ( FuncLen , <NUM_LIT> ) ; OS . EmitIntValue ( LineLen , <NUM_LIT> ) ; OS . EmitIntValue ( FuncLen + LineLen , <NUM_LIT> ) ; OS . EmitIntValue ( OffsetRelocLen , <NUM_LIT> ) ; OS . EmitIntValue ( FuncLen + LineLen + OffsetRelocLen , <NUM_LIT> ) ; OS . EmitIntValue ( ExternRelocLen , <NUM_LIT> ) ; OS . AddComment ( <STR_LIT> ) ; OS . EmitIntValue ( <STR_LIT> , <NUM_LIT> ) ; for ( const auto & FuncSec : FuncInfoTable ) { OS . AddComment ( <STR_LIT> + std :: to_string ( FuncSec . first ) ) ; OS . EmitIntValue ( FuncSec . first , <NUM_LIT> ) ; OS . EmitIntValue ( FuncSec . second . size ( ) , <NUM_LIT> ) ; for ( const auto & FuncInfo : FuncSec . second ) { Asm -> EmitLabelReference ( FuncInfo . Label , <NUM_LIT> ) ; OS . EmitIntValue ( FuncInfo . TypeId , <NUM_LIT> ) ; } } OS . AddComment ( <STR_LIT> ) ; OS . EmitIntValue ( <STR_LIT> , <NUM_LIT> ) ; for ( const auto & LineSec : LineInfoTable ) { OS . AddComment ( <STR_LIT> + std :: to_string ( LineSec . first ) ) ; OS . EmitIntValue ( LineSec . first , <NUM_LIT> ) ;

OS . EmitIntValue ( LineSec . second . size ( ) , <NUM_LIT> ) ;


<s> BTFOffsetReloc OffsetReloc ; OffsetReloc . Label = ORSym ; OffsetReloc . OffsetNameOff = addString ( IndexPattern ) ; OffsetReloc . TypeID = RootId ; AccessOffsets [ AccessPattern . str ( ) ] = std :: stoi ( OffsetStr ) ;

OffsetRelocTable [ SecNameOff ] . push_back ( OffsetReloc ) ;


<s> bool BTFDebug :: InstLower ( const MachineInstr * MI , MCInst & OutMI ) { if ( MI -> getOpcode ( ) == <STR_LIT> ) { const MachineOperand & MO = MI -> getOperand ( <NUM_LIT> ) ; if ( MO . isGlobal ( ) ) { const GlobalValue * GVal = MO . getGlobal ( ) ; auto * GVar = dyn_cast < GlobalVariable > ( GVal ) ; if ( GVar && GVar -> hasAttribute ( <STR_LIT> ) ) { MDNode * MDN = GVar -> getMetadata ( LLVMContext :: MD_preserve_access_index ) ; DIType * Ty = dyn_cast < DIType > ( MDN ) ; std :: string TypeName = Ty -> getName ( ) ;

int64_t Imm = AccessOffsets [ GVar -> getName ( ) . str ( ) ] ;


<s> DIType * Ty = dyn_cast < DIType > ( MDN ) ; generateOffsetReloc ( MI , ORSym , Ty , GVar -> getName ( ) ) ; } else if ( GVar && ! GVar -> hasInitializer ( ) && GVar -> hasExternalLinkage ( ) && GVar -> getSection ( ) == <STR_LIT> ) { MCSymbol * ORSym = OS . getContext ( ) . createTempSymbol ( ) ; OS . EmitLabel ( ORSym ) ;


<s> auto TypeEntry = std :: make_unique < BTFTypeArray > ( ElemTypeId , <NUM_LIT> ) ; ElemTypeId = addType ( std :: move ( TypeEntry ) , CTy ) ; } else { DINodeArray Elements = CTy -> getElements ( ) ; for ( int I = Elements . size ( ) - <NUM_LIT> ; I >= <NUM_LIT> ; -- I ) { if ( auto * Element = dyn_cast_or_null < DINode > ( Elements [ I ] ) ) if ( Element -> getTag ( ) == dwarf :: DW_TAG_subrange_type ) { const DISubrange * SR = cast < DISubrange > ( Element ) ;

auto * CI = SR -> getCount ( ) . dyn_cast < ConstantInt * > ( ) ;


<s> for ( int I = Elements . size ( ) - <NUM_LIT> ; I >= <NUM_LIT> ; -- I ) { if ( auto * Element = dyn_cast_or_null < DINode > ( Elements [ I ] ) ) if ( Element -> getTag ( ) == dwarf :: DW_TAG_subrange_type ) { const DISubrange * SR = cast < DISubrange > ( Element ) ; auto * CI = SR -> getCount ( ) . dyn_cast < ConstantInt * > ( ) ; int64_t Count = CI -> getSExtValue ( ) ; auto TypeEntry = std :: make_unique < BTFTypeArray > ( ElemTypeId , Count ) ; if ( I == <NUM_LIT> ) ElemTypeId = addType ( std :: move ( TypeEntry ) , CTy ) ; else ElemTypeId = addType ( std :: move ( TypeEntry ) ) ; ElemSize = ElemSize * Count ; } } } TypeId = ElemTypeId ; if ( ! ArrayIndexTypeId ) { auto TypeEntry = std :: make_unique < BTFTypeInt > ( dwarf :: DW_ATE_unsigned , <NUM_LIT> , <NUM_LIT> , <STR_LIT> ) ; ArrayIndexTypeId = addType ( std :: move ( TypeEntry ) ) ; }


<s> visitSubroutineType ( SP -> getType ( ) , true , FuncArgNames , ProtoTypeId ) ; auto FuncTypeEntry = llvm :: make_unique < BTFTypeFunc > ( SP -> getName ( ) , ProtoTypeId ) ; uint32_t FuncTypeId = addType ( std :: move ( FuncTypeEntry ) ) ; for ( const auto & TypeEntry : TypeEntries ) TypeEntry -> completeType ( * this ) ; MCSymbol * FuncLabel = Asm -> getFunctionBegin ( ) ; BTFFuncInfo FuncInfo ; FuncInfo . Label = FuncLabel ; FuncInfo . TypeId = FuncTypeId ; if ( FuncLabel -> isInSection ( ) ) {

MCSection & Section = FuncLabel -> getSection ( ) ;


<s> } std :: unordered_map < uint32_t , StringRef > FuncArgNames ; for ( const DINode * DN : SP -> getRetainedNodes ( ) ) { if ( const auto * DV = dyn_cast < DILocalVariable > ( DN ) ) { uint32_t Arg = DV -> getArg ( ) ; if ( Arg ) { visitTypeEntry ( DV -> getType ( ) ) ; FuncArgNames [ Arg ] = DV -> getName ( ) ; } } } uint32_t ProtoTypeId ; visitSubroutineType ( SP -> getType ( ) , true , FuncArgNames , ProtoTypeId ) ; auto FuncTypeEntry = llvm :: make_unique < BTFTypeFunc > ( SP -> getName ( ) , ProtoTypeId ) ; uint32_t FuncTypeId = addType ( std :: move ( FuncTypeEntry ) ) ; for ( const auto & TypeEntry : TypeEntries ) TypeEntry -> completeType ( * this ) ; MCSymbol * FuncLabel = Asm -> getFunctionBegin ( ) ; BTFFuncInfo FuncInfo ; FuncInfo . Label = FuncLabel ; FuncInfo . TypeId = FuncTypeId ;


<s> BTFType . NameOff = <NUM_LIT> ; BTFType . Info = Kind << <NUM_LIT> ; BTFType . Size = <NUM_LIT> ; ArrayInfo . ElemType = ElemTypeId ; ArrayInfo . Nelems = NumElems ;


<s> const auto * DDTy = cast < DIDerivedType > ( Element ) ; BTFMember . NameOff = BDebug . addString ( DDTy -> getName ( ) ) ; if ( HasBitField ) { uint8_t BitFieldSize = DDTy -> isBitField ( ) ? DDTy -> getSizeInBits ( ) : <NUM_LIT> ; BTFMember . Offset = BitFieldSize << <NUM_LIT> | DDTy -> getOffsetInBits ( ) ; } else { BTFMember . Offset = DDTy -> getOffsetInBits ( ) ;


<s> struct <STR_LIT> BTFMember ; const auto * DDTy = cast < DIDerivedType > ( Element ) ; BTFMember . NameOff = BDebug . addString ( DDTy -> getName ( ) ) ; if ( HasBitField ) { uint8_t BitFieldSize = DDTy -> isBitField ( ) ? DDTy -> getSizeInBits ( ) : <NUM_LIT> ; BTFMember . Offset = BitFieldSize << <NUM_LIT> | DDTy -> getOffsetInBits ( ) ; } else { BTFMember . Offset = DDTy -> getOffsetInBits ( ) ; } BTFMember . Type = BDebug . getTypeId ( DDTy -> getBaseType ( ) ) ; Members . push_back ( BTFMember ) ; }


<s> } } if ( StructTypeId == <NUM_LIT> ) { auto FwdTypeEntry = llvm :: make_unique < BTFTypeFwd > ( TypeName , IsUnion ) ; StructTypeId = addType ( std :: move ( FwdTypeEntry ) ) ; } for ( auto & DType : Fixup . second . second ) { DType -> setPointeeType ( StructTypeId ) ; } } for ( const auto & TypeEntry : TypeEntries ) TypeEntry -> completeType ( * this ) ; emitBTFSection ( ) ;


<s> ElementTypeId = ArrayInfo . ElemType ; LocOffset = Loc * ElemSize ;


<s> void BTFTypeArray :: getLocInfo ( uint32_t Loc , uint32_t & LocOffset , uint32_t & ElementTypeId ) {


<s> MemberType = Members [ Loc ] . Type ; MemberOffset = HasBitField ? Members [ Loc ] . Offset & <NUM_LIT> : Members [ Loc ] . Offset ;


<s> std :: string TypeName = Ty -> getName ( ) ; int64_t Imm = AccessOffsets [ TypeName + <STR_LIT> + GVar -> getName ( ) . str ( ) ] ; OutMI . setOpcode ( <STR_LIT> ) ; OutMI . addOperand ( MCOperand :: createReg ( MI -> getOperand ( <NUM_LIT> ) . getReg ( ) ) ) ; OutMI . addOperand ( MCOperand :: createImm ( Imm ) ) ; return true ; } else if ( GVar && ! GVar -> hasInitializer ( ) && GVar -> hasExternalLinkage ( ) && GVar -> getSection ( ) == <STR_LIT> ) { const IntegerType * IntTy = dyn_cast < IntegerType > ( GVar -> getValueType ( ) ) ; assert ( IntTy ) ; if ( IntTy -> getBitWidth ( ) == <NUM_LIT> ) OutMI . setOpcode ( <STR_LIT> ) ; else OutMI . setOpcode ( <STR_LIT> ) ; OutMI . addOperand ( MCOperand :: createReg ( MI -> getOperand ( <NUM_LIT> ) . getReg ( ) ) ) ; OutMI . addOperand ( MCOperand :: createImm ( <NUM_LIT> ) ) ;


<s> if ( SecName . startswith ( <STR_LIT> ) ) visitMapDefType ( GVE -> getVariable ( ) -> getType ( ) , GVTypeId ) ; else visitTypeEntry ( GVE -> getVariable ( ) -> getType ( ) , GVTypeId , false , false ) ; break ; } auto Linkage = Global . getLinkage ( ) ; if ( Linkage != GlobalValue :: InternalLinkage && ( Linkage != GlobalValue :: ExternalLinkage || ! Global . hasSection ( ) ) ) continue ; uint32_t GVarInfo = Linkage == GlobalValue :: ExternalLinkage ? <STR_LIT> : <STR_LIT> ;

auto VarEntry = llvm :: make_unique < BTFKindVar > ( Global . getName ( ) , GVTypeId , GVarInfo ) ;


<s> uint32_t GVarInfo = Linkage == GlobalValue :: ExternalLinkage ? <STR_LIT> : <STR_LIT> ; auto VarEntry = llvm :: make_unique < BTFKindVar > ( Global . getName ( ) , GVTypeId , GVarInfo ) ; uint32_t VarId = addType ( std :: move ( VarEntry ) ) ; if ( DataSecEntries . find ( SecName ) == DataSecEntries . end ( ) ) { DataSecEntries [ SecName ] = llvm :: make_unique < BTFKindDataSec > ( Asm , SecName ) ; } const DataLayout & DL = Global . getParent ( ) -> getDataLayout ( ) ; uint32_t Size = DL . getTypeAllocSize ( Global . getType ( ) -> getElementType ( ) ) ; DataSecEntries [ SecName ] -> addVar ( VarId , Asm -> getSymbol ( & Global ) , Size ) ; }


<s> } for ( const auto & ArrayType : ArrayTypes ) { if ( ArrayType -> getId ( ) == TypeId ) { * PrevArrayType = ArrayType ;


<s> auto TypeEntry = llvm :: make_unique < BTFTypeArray > ( ElemTypeId , <NUM_LIT> , <NUM_LIT> ) ; ArrayTypes . push_back ( TypeEntry . get ( ) ) ; ElemTypeId = addType ( std :: move ( TypeEntry ) , CTy ) ; } else { DINodeArray Elements = CTy -> getElements ( ) ; for ( int I = Elements . size ( ) - <NUM_LIT> ; I >= <NUM_LIT> ; -- I ) { if ( auto * Element = dyn_cast_or_null < DINode > ( Elements [ I ] ) ) if ( Element -> getTag ( ) == dwarf :: DW_TAG_subrange_type ) { const DISubrange * SR = cast < DISubrange > ( Element ) ;


<s> auto CTag = CTy -> getTag ( ) ; if ( ( CTag == dwarf :: DW_TAG_structure_type || CTag == dwarf :: DW_TAG_union_type ) && ! CTy -> isForwardDecl ( ) ) { auto TypeEntry = llvm :: make_unique < BTFTypeDerived > ( DTy , Tag , true ) ; auto & Fixup = FixupDerivedTypes [ CTy -> getName ( ) ] ; Fixup . first = CTag == dwarf :: DW_TAG_union_type ; Fixup . second . push_back ( TypeEntry . get ( ) ) ; TypeId = addType ( std :: move ( TypeEntry ) , DTy ) ; return ; } } } } if ( Tag == dwarf :: DW_TAG_pointer_type || Tag == dwarf :: DW_TAG_typedef || Tag == dwarf :: DW_TAG_const_type || Tag == dwarf :: DW_TAG_volatile_type || Tag == dwarf :: DW_TAG_restrict_type ) { auto TypeEntry = llvm :: make_unique < BTFTypeDerived > ( DTy , Tag , false ) ; TypeId = addType ( std :: move ( TypeEntry ) , DTy ) ; } else if ( Tag != dwarf :: DW_TAG_member ) { return ; } uint32_t TempTypeId = <NUM_LIT> ;

if ( Tag == dwarf :: DW_TAG_member ) visitTypeEntry ( DTy -> getBaseType ( ) , TempTypeId , true , false ) ;


<s> HasBitField = true ; break ; } } auto TypeEntry = llvm :: make_unique < BTFTypeStruct > ( CTy , true , HasBitField , Elements . size ( ) ) ; StructTypes . push_back ( TypeEntry . get ( ) ) ; TypeId = addType ( std :: move ( TypeEntry ) , CTy ) ; for ( const auto * Element : Elements ) { const auto * MemberType = cast < DIDerivedType > ( Element ) ; visitTypeEntry ( MemberType -> getBaseType ( ) ) ; }


<s> void BTFDebug :: visitMapDefType ( const DIType * Ty , uint32_t & TypeId ) { if ( ! Ty || DIToIdMap . find ( Ty ) != DIToIdMap . end ( ) ) { TypeId = DIToIdMap [ Ty ] ; return ; } const auto * CTy = dyn_cast < DICompositeType > ( Ty ) ; if ( ! CTy ) return ; auto Tag = CTy -> getTag ( ) ; if ( Tag != dwarf :: DW_TAG_structure_type || CTy -> isForwardDecl ( ) ) return ; const DINodeArray Elements = CTy -> getElements ( ) ; bool HasBitField = false ; for ( const auto * Element : Elements ) { auto E = cast < DIDerivedType > ( Element ) ; if ( E -> isBitField ( ) ) { HasBitField = true ; break ; } } auto TypeEntry = llvm :: make_unique < BTFTypeStruct > ( CTy , true , HasBitField , Elements . size ( ) ) ; StructTypes . push_back ( TypeEntry . get ( ) ) ; TypeId = addType ( std :: move ( TypeEntry ) , CTy ) ; for ( const auto * Element : Elements ) { const auto * MemberType = cast < DIDerivedType > ( Element ) ; visitTypeEntry ( MemberType -> getBaseType ( ) ) ;


<s> const DINodeArray Elements = CTy -> getElements ( ) ; uint32_t VLen = Elements . size ( ) ; if ( VLen > <STR_LIT> ) return ; bool HasBitField = false ; for ( const auto * Element : Elements ) { auto E = cast < DIDerivedType > ( Element ) ; if ( E -> isBitField ( ) ) { HasBitField = true ; break ; } } auto TypeEntry = llvm :: make_unique < BTFTypeStruct > ( CTy , IsStruct , HasBitField , VLen ) ; StructTypes . push_back ( TypeEntry . get ( ) ) ;


<s> void BTFDebug :: visitSubroutineType ( const DISubroutineType * STy , bool ForSubprog , const std :: unordered_map < uint32_t , StringRef > & FuncArgNames , uint32_t & TypeId ) { DITypeRefArray Elements = STy -> getTypeArray ( ) ; uint32_t VLen = Elements . size ( ) - <NUM_LIT> ; if ( VLen > <STR_LIT> ) return ; auto TypeEntry = llvm :: make_unique < BTFTypeFuncProto > ( STy , VLen , FuncArgNames ) ; if ( ForSubprog ) TypeId = addType ( std :: move ( TypeEntry ) ) ; else TypeId = addType ( std :: move ( TypeEntry ) , STy ) ;


<s> if ( ForSubprog ) TypeId = addType ( std :: move ( TypeEntry ) ) ; else TypeId = addType ( std :: move ( TypeEntry ) , STy ) ; for ( const auto Element : Elements ) { visitTypeEntry ( Element ) ;


<s> auto * Unit = SP -> getUnit ( ) ; if ( Unit -> getEmissionKind ( ) == DICompileUnit :: NoDebug ) { SkipInstruction = true ; return ; } SkipInstruction = false ; std :: unordered_map < uint32_t , StringRef > FuncArgNames ; for ( const DINode * DN : SP -> getRetainedNodes ( ) ) { if ( const auto * DV = dyn_cast < DILocalVariable > ( DN ) ) { uint32_t Arg = DV -> getArg ( ) ; if ( Arg ) { visitTypeEntry ( DV -> getType ( ) ) ; FuncArgNames [ Arg ] = DV -> getName ( ) ; } } } uint32_t ProtoTypeId ; visitSubroutineType ( SP -> getType ( ) , true , FuncArgNames , ProtoTypeId ) ; auto FuncTypeEntry = llvm :: make_unique < BTFTypeFunc > ( SP -> getName ( ) , ProtoTypeId ) ;

uint32_t FuncTypeId = addType ( std :: move ( FuncTypeEntry ) ) ;


<s> BTFType . Type = RetType ? BDebug . getTypeId ( RetType ) : <NUM_LIT> ; BTFType . NameOff = <NUM_LIT> ;

for ( unsigned I = <NUM_LIT> , N = Elements . size ( ) ; I < N ; ++ I ) {


<s> if ( ! Global . hasInitializer ( ) && Global . hasExternalLinkage ( ) ) continue ; SmallVector < DIGlobalVariableExpression * , <NUM_LIT> > GVs ; Global . getDebugInfo ( GVs ) ; uint32_t GVTypeId = <NUM_LIT> ; for ( auto * GVE : GVs ) { visitTypeEntry ( GVE -> getVariable ( ) -> getType ( ) , GVTypeId ) ; break ; } auto Linkage = Global . getLinkage ( ) ; if ( Linkage != GlobalValue :: InternalLinkage && ( Linkage != GlobalValue :: ExternalLinkage || ! Global . hasSection ( ) ) ) continue ; uint32_t GVarInfo = Linkage == GlobalValue :: ExternalLinkage ? <STR_LIT> : <STR_LIT> ; auto VarEntry = llvm :: make_unique < BTFKindVar > ( Global . getName ( ) , GVTypeId , GVarInfo ) ; uint32_t VarId = addType ( std :: move ( VarEntry ) ) ; std :: string SecName ; if ( Global . hasSection ( ) ) { SecName = Global . getSection ( ) . str ( ) ; } else { if ( Global . isConstant ( ) ) SecName += <STR_LIT> ; else SecName += Global . getInitializer ( ) -> isZeroValue ( ) ? <STR_LIT> : <STR_LIT> ; } if ( DataSecEntries . find ( SecName ) == DataSecEntries . end ( ) ) { DataSecEntries [ SecName ] = llvm :: make_unique < BTFKindDataSec > ( Asm , SecName ) ;


<s> const Module * M = MMI -> getModule ( ) ; for ( const GlobalVariable & Global : M -> globals ( ) ) { if ( ! Global . hasInitializer ( ) && Global . hasExternalLinkage ( ) ) continue ; SmallVector < DIGlobalVariableExpression * , <NUM_LIT> > GVs ; Global . getDebugInfo ( GVs ) ; uint32_t GVTypeId = <NUM_LIT> ; for ( auto * GVE : GVs ) { visitTypeEntry ( GVE -> getVariable ( ) -> getType ( ) , GVTypeId ) ; break ; } auto Linkage = Global . getLinkage ( ) ; if ( Linkage != GlobalValue :: InternalLinkage && ( Linkage != GlobalValue :: ExternalLinkage || ! Global . hasSection ( ) ) ) continue ; uint32_t GVarInfo = Linkage == GlobalValue :: ExternalLinkage ? <STR_LIT> : <STR_LIT> ; auto VarEntry = llvm :: make_unique < BTFKindVar > ( Global . getName ( ) , GVTypeId , GVarInfo ) ; uint32_t VarId = addType ( std :: move ( VarEntry ) ) ; std :: string SecName ; if ( Global . hasSection ( ) ) { SecName = Global . getSection ( ) . str ( ) ; } else { if ( Global . isConstant ( ) ) SecName += <STR_LIT> ; else SecName += Global . getInitializer ( ) -> isZeroValue ( ) ? <STR_LIT> : <STR_LIT> ; } if ( DataSecEntries . find ( SecName ) == DataSecEntries . end ( ) ) { DataSecEntries [ SecName ] = llvm :: make_unique < BTFKindDataSec > ( Asm , SecName ) ;


<s> if ( auto * Element = dyn_cast_or_null < DINode > ( Elements [ I ] ) ) if ( Element -> getTag ( ) == dwarf :: DW_TAG_subrange_type ) { const DISubrange * SR = cast < DISubrange > ( Element ) ; auto * CI = SR -> getCount ( ) . dyn_cast < ConstantInt * > ( ) ; int64_t Count = CI -> getSExtValue ( ) ; auto TypeEntry = llvm :: make_unique < BTFTypeArray > ( ElemTypeId , Count ) ; if ( I == <NUM_LIT> ) ElemTypeId = addType ( std :: move ( TypeEntry ) , CTy ) ; else ElemTypeId = addType ( std :: move ( TypeEntry ) ) ;


<s> ElemTypeId = addType ( std :: move ( TypeEntry ) , CTy ) ; } else { DINodeArray Elements = CTy -> getElements ( ) ; for ( int I = Elements . size ( ) - <NUM_LIT> ; I >= <NUM_LIT> ; -- I ) { if ( auto * Element = dyn_cast_or_null < DINode > ( Elements [ I ] ) ) if ( Element -> getTag ( ) == dwarf :: DW_TAG_subrange_type ) { const DISubrange * SR = cast < DISubrange > ( Element ) ; auto * CI = SR -> getCount ( ) . dyn_cast < ConstantInt * > ( ) ; int64_t Count = CI -> getSExtValue ( ) ; auto TypeEntry = llvm :: make_unique < BTFTypeArray > ( ElemTypeId , Count ) ; if ( I == <NUM_LIT> ) ElemTypeId = addType ( std :: move ( TypeEntry ) , CTy ) ; else ElemTypeId = addType ( std :: move ( TypeEntry ) ) ; } } } TypeId = ElemTypeId ;


<s> void BTFDebug :: visitDerivedType ( const DIDerivedType * DTy , uint32_t & TypeId ) { unsigned Tag = DTy -> getTag ( ) ; if ( Tag == dwarf :: DW_TAG_pointer_type || Tag == dwarf :: DW_TAG_typedef || Tag == dwarf :: DW_TAG_const_type || Tag == dwarf :: DW_TAG_volatile_type || Tag == dwarf :: DW_TAG_restrict_type ) { auto TypeEntry = llvm :: make_unique < BTFTypeDerived > ( DTy , Tag ) ; TypeId = addType ( std :: move ( TypeEntry ) , DTy ) ; } else if ( Tag != dwarf :: DW_TAG_member ) { return ; }


<s> return ; } } } } if ( Tag == dwarf :: DW_TAG_pointer_type ) { SmallVector < const MDString * , <NUM_LIT> > MDStrs ; DINodeArray Annots = DTy -> getAnnotations ( ) ; if ( Annots ) { for ( const Metadata * Annotations : Annots -> operands ( ) ) { const MDNode * MD = cast < MDNode > ( Annotations ) ; const MDString * Name = cast < MDString > ( MD -> getOperand ( <NUM_LIT> ) ) ; if ( ! Name -> getString ( ) . equals ( <STR_LIT> ) ) continue ; MDStrs . push_back ( cast < MDString > ( MD -> getOperand ( <NUM_LIT> ) ) ) ; } } if ( MDStrs . size ( ) > <NUM_LIT> ) { auto TypeEntry = std :: make_unique < BTFTypeTypeTag > ( DTy , MDStrs [ <NUM_LIT> ] -> getString ( ) ) ; unsigned TmpTypeId = addType ( std :: move ( TypeEntry ) ) ; for ( unsigned I = <NUM_LIT> ; I < MDStrs . size ( ) ; I ++ ) { const MDString * Value = MDStrs [ I ] ; TypeEntry = std :: make_unique < BTFTypeTypeTag > ( TmpTypeId , Value -> getString ( ) ) ; TmpTypeId = addType ( std :: move ( TypeEntry ) ) ; } auto TypeDEntry = std :: make_unique < BTFTypeDerived > ( TmpTypeId , Tag , DTy -> getName ( ) ) ; TypeId = addType ( std :: move ( TypeDEntry ) , DTy ) ; } else {

auto TypeEntry = std :: make_unique < BTFTypeDerived > ( DTy , Tag , false ) ;


<s> } auto Linkage = Global . getLinkage ( ) ; if ( Linkage != GlobalValue :: InternalLinkage && Linkage != GlobalValue :: ExternalLinkage ) continue ; uint32_t GVarInfo = Linkage == GlobalValue :: ExternalLinkage ? <STR_LIT> : <STR_LIT> ; auto VarEntry = std :: make_unique < BTFKindVar > ( Global . getName ( ) , GVTypeId , GVarInfo ) ; uint32_t VarId = addType ( std :: move ( VarEntry ) ) ; if ( DataSecEntries . find ( SecName ) == DataSecEntries . end ( ) ) { DataSecEntries [ SecName ] = std :: make_unique < BTFKindDataSec > ( Asm , SecName ) ; } const DataLayout & DL = Global . getParent ( ) -> getDataLayout ( ) ; uint32_t Size = DL . getTypeAllocSize ( Global . getType ( ) -> getElementType ( ) ) ; DataSecEntries [ SecName ] -> addVar ( VarId , Asm -> getSymbol ( & Global ) , Size ) ; }


<s> BTFTypeArray :: BTFTypeArray ( const DIType * Ty , uint32_t ElemTypeId , uint32_t ElemSize , uint32_t NumElems ) : ElemTyNoQual ( Ty ) , ElemSize ( ElemSize ) { Kind = <STR_LIT> ; BTFType . NameOff = <NUM_LIT> ; BTFType . Info = Kind << <NUM_LIT> ; BTFType . Size = <NUM_LIT> ;


<s> Kind = <STR_LIT> ; BTFType . NameOff = <NUM_LIT> ; BTFType . Info = Kind << <NUM_LIT> ; BTFType . Size = <NUM_LIT> ; ArrayInfo . ElemType = ElemTypeId ; ArrayInfo . Nelems = NumElems ;


<s> IsCompleted = true ; BTFType . NameOff = BDebug . addString ( STy -> getName ( ) ) ; const DINodeArray Elements = STy -> getElements ( ) ; for ( const auto * Element : Elements ) { struct <STR_LIT> BTFMember ; const auto * DDTy = cast < DIDerivedType > ( Element ) ; BTFMember . NameOff = BDebug . addString ( DDTy -> getName ( ) ) ; if ( HasBitField ) { uint8_t BitFieldSize = DDTy -> isBitField ( ) ? DDTy -> getSizeInBits ( ) : <NUM_LIT> ; BTFMember . Offset = BitFieldSize << <NUM_LIT> | DDTy -> getOffsetInBits ( ) ; } else { BTFMember . Offset = DDTy -> getOffsetInBits ( ) ; } const auto * BaseTy = DDTy -> getBaseType ( ) ; BTFMember . Type = BDebug . getTypeId ( BaseTy ) ; MemberTypeNoQual . push_back ( BDebug . getTypeId ( stripQualifiers ( BaseTy ) ) ) ; Members . push_back ( BTFMember ) ;


<s> FirstAccess = false ; } else if ( PrevStructType ) { uint32_t MemberOffset , MemberTypeId ; PrevStructType -> getMemberInfo ( Loc , MemberOffset , MemberTypeId ) ; Offset += MemberOffset >> <NUM_LIT> ; PrevStructType = nullptr ; setTypeFromId ( MemberTypeId , & PrevStructType , & PrevArrayType ) ; } else if ( PrevArrayType ) { uint32_t LocOffset , ElementTypeId ; PrevArrayType -> getLocInfo ( Loc , LocOffset , ElementTypeId ) ; Offset += LocOffset ; PrevArrayType = nullptr ; setTypeFromId ( ElementTypeId , & PrevStructType , & PrevArrayType ) ; } else { llvm_unreachable ( <STR_LIT> ) ; } Start = End + <NUM_LIT> ; End = Start ; } } AccessOffsets [ AccessPattern . str ( ) ] = Offset ;


<s> unsigned RootId = populateStructType ( RootTy ) ; setTypeFromId ( RootId , & PrevStructType , & PrevArrayType ) ; unsigned RootTySize = PrevStructType -> getStructSize ( ) ; StringRef IndexPattern = AccessPattern . substr ( AccessPattern . find_first_of ( ':' ) + <NUM_LIT> ) ; BTFOffsetReloc OffsetReloc ; OffsetReloc . Label = ORSym ; OffsetReloc . OffsetNameOff = addString ( IndexPattern . drop_back ( ) ) ; OffsetReloc . TypeID = RootId ; uint32_t Start = <NUM_LIT> , End = <NUM_LIT> , Offset = <NUM_LIT> ; bool FirstAccess = true ; for ( auto C : IndexPattern ) { if ( C != ':' ) { End ++ ; } else { std :: string SubStr = IndexPattern . substr ( Start , End - Start ) ; int Loc = std :: stoi ( SubStr ) ; if ( FirstAccess ) { Offset = Loc * RootTySize ; FirstAccess = false ; } else if ( PrevStructType ) { uint32_t MemberOffset , MemberTypeId ; PrevStructType -> getMemberInfo ( Loc , MemberOffset , MemberTypeId ) ; Offset += MemberOffset >> <NUM_LIT> ; PrevStructType = nullptr ; setTypeFromId ( MemberTypeId , & PrevStructType , & PrevArrayType ) ; } else if ( PrevArrayType ) { uint32_t LocOffset , ElementTypeId ; PrevArrayType -> getLocInfo ( Loc , LocOffset , ElementTypeId ) ; Offset += LocOffset ; PrevArrayType = nullptr ; setTypeFromId ( ElementTypeId , & PrevStructType , & PrevArrayType ) ; } else { llvm_unreachable ( <STR_LIT> ) ; } Start = End + <NUM_LIT> ; End = Start ; }


<s> ElementTypeId = ElemTypeNoQual ; LocOffset = Loc * ElemSize ;


<s> void BTFTypeStruct :: getMemberInfo ( uint32_t Loc , uint32_t & MemberOffset , uint32_t & MemberType ) { MemberType = MemberTypeNoQual [ Loc ] ; MemberOffset = HasBitField ? Members [ Loc ] . Offset & <NUM_LIT> : Members [ Loc ] . Offset ;


if ( Tag != dwarf :: DW_TAG_typedef && Tag != dwarf :: DW_TAG_const_type && Tag != dwarf :: DW_TAG_volatile_type && Tag != dwarf :: DW_TAG_restrict_type ) break ;


<s> uint32_t ElemTypeId , ElemSize ; const DIType * ElemType = CTy -> getBaseType ( ) ; visitTypeEntry ( ElemType , ElemTypeId , false , false ) ; ElemType = stripQualifiers ( ElemType ) ; ElemSize = ElemType -> getSizeInBits ( ) >> <NUM_LIT> ; if ( ! CTy -> getSizeInBits ( ) ) { auto TypeEntry = llvm :: make_unique < BTFTypeArray > ( ElemType , ElemTypeId , <NUM_LIT> , <NUM_LIT> ) ; ArrayTypes . push_back ( TypeEntry . get ( ) ) ; ElemTypeId = addType ( std :: move ( TypeEntry ) , CTy ) ; } else { DINodeArray Elements = CTy -> getElements ( ) ; for ( int I = Elements . size ( ) - <NUM_LIT> ; I >= <NUM_LIT> ; -- I ) { if ( auto * Element = dyn_cast_or_null < DINode > ( Elements [ I ] ) ) if ( Element -> getTag ( ) == dwarf :: DW_TAG_subrange_type ) { const DISubrange * SR = cast < DISubrange > ( Element ) ; auto * CI = SR -> getCount ( ) . dyn_cast < ConstantInt * > ( ) ; int64_t Count = CI -> getSExtValue ( ) ; const DIType * ArrayElemTy = ( I == <NUM_LIT> ) ? ElemType : nullptr ; auto TypeEntry = llvm :: make_unique < BTFTypeArray > ( ArrayElemTy , ElemTypeId , ElemSize , Count ) ; ArrayTypes . push_back ( TypeEntry . get ( ) ) ; if ( I == <NUM_LIT> ) ElemTypeId = addType ( std :: move ( TypeEntry ) , CTy ) ; else ElemTypeId = addType ( std :: move ( TypeEntry ) ) ; ElemSize = ElemSize * Count ; } } } TypeId = ElemTypeId ; if ( ! ArrayIndexTypeId ) { auto TypeEntry = llvm :: make_unique < BTFTypeInt > ( dwarf :: DW_ATE_unsigned , <NUM_LIT> , <NUM_LIT> , <STR_LIT> ) ; ArrayIndexTypeId = addType ( std :: move ( TypeEntry ) ) ; }


<s> void addDataSecEntry ( uint32_t Id , const MCSymbol * Sym , uint32_t Size ) { Vars . push_back ( std :: make_tuple ( Id , Sym , Size ) ) ;


<s> size_t addString ( StringRef S ) { return StringTable . addString ( S ) ;


<s> BTFStringTable ( ) : Size ( <NUM_LIT> ) {


<s> BTFTypeBase ( ) : IsCompleted ( false ) {


<s> virtual void completeType ( BTFDebug & BDebug ) {


<s> uint32_t getSize ( ) { return Size ;


<s> std :: vector < std :: string > & getTable ( ) {


<s> uint32_t getTypeId ( const DIType * Ty ) {


assert ( DIToIdMap . find ( Ty ) != DIToIdMap . end ( ) && <STR_LIT> ) ;


<s> return ( NumBits + <NUM_LIT> ) >> <NUM_LIT> ;


<s> void setId ( uint32_t Id ) { this -> Id = Id ;


<s> void setSymbolSize ( const MCSymbol * Symbol , uint64_t Size ) override {