"********** Abstract Member Accesses **********\n"

runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass .


runOnModule - Virtual method overriden by subclasses to process the module being operated on .


<s> Instruction * BPFCoreSharedInfo :: insertPassThrough ( Module * M , BasicBlock * BB , Instruction * Input , Instruction * Before ) { Function * Fn = Intrinsic :: getDeclaration ( M , Intrinsic :: bpf_passthrough , { Input -> getType ( ) , Input -> getType ( ) } ) ; Constant * SeqNumVal = ConstantInt :: get ( Type :: getInt32Ty ( BB -> getContext ( ) ) , BPFCoreSharedInfo :: SeqNum ++ ) ; auto * NewInst = CallInst :: Create ( Fn , { SeqNumVal , Input } ) ; BB -> getInstList ( ) . insert ( Before -> getIterator ( ) , NewInst ) ; return NewInst ; } </s>

Insert a bpf passthrough builtin function .

BPF BPFCoreSharedInfo::insertPassThrough Intrinsic::getDeclaration Intrinsic::bpf_passthrough BPFCoreSharedInfo::SeqNum


<s> PreservedAnalyses BPFAbstractMemberAccessPass :: run ( Function & F , FunctionAnalysisManager & AM ) { return BPFAbstractMemberAccess ( TM ) . run ( F ) ? PreservedAnalyses :: none ( ) : PreservedAnalyses :: all ( ) ; } </s>

Run the analysis pass over a function and produce a dominator tree .


<s> bool runOnFunction ( Function & F ) override { return BPFAbstractMemberAccess ( TM ) . run ( F ) ; } </s>


<s> uint64_t BPFAbstractMemberAccess :: getConstant ( const Value * IndexValue ) { const ConstantInt * CV = dyn_cast < ConstantInt > ( IndexValue ) ; assert ( CV ) ; return CV -> getValue ( ) . getZExtValue ( ) ; } </s>

Return the large constant at the given index .


<s>
StringRef
getPassName
(
)
const
override
{
return
"BPF Abstract Member Access"
;
}
</s>

getPassName - Return a nice clean name for a pass .


<s> bool BPFAdjustOptImpl :: run ( ) { for ( Function & F : * M ) for ( auto & BB : F ) { adjustBasicBlock ( BB ) ; for ( auto & I : BB ) adjustInst ( I ) ; } return insertPassThrough ( ) ; } </s>


<s> bool BPFAdjustOpt :: insertPassThrough ( ) { for ( auto & Info : PassThroughs ) { auto * CI = BPFCoreSharedInfo :: insertPassThrough ( Mod , Info . UsedInst -> getParent ( ) , Info . Input , Info . UsedInst ) ; Info . UsedInst -> setOperand ( Info . OpIdx , CI ) ; } return ! PassThroughs . empty ( ) ; } </s>


<s> bool BPFAdjustOpt :: runOnModule ( Module & M ) { Mod = & M ; for ( Function & F : M ) for ( auto & BB : F ) { adjustBasicBlock ( BB ) ; for ( auto & I : BB ) adjustInst ( I ) ; } return insertPassThrough ( ) ; } </s>


<s> bool BPFAdjustOptImpl :: insertPassThrough ( ) { for ( auto & Info : PassThroughs ) { auto * CI = BPFCoreSharedInfo :: insertPassThrough ( M , Info . UsedInst -> getParent ( ) , Info . Input , Info . UsedInst ) ; Info . UsedInst -> setOperand ( Info . OpIdx , CI ) ; } return ! PassThroughs . empty ( ) ; } </s>


<s> PreservedAnalyses BPFAdjustOptPass :: run ( Module & M , ModuleAnalysisManager & AM ) { return BPFAdjustOptImpl ( & M ) . run ( ) ? PreservedAnalyses :: none ( ) : PreservedAnalyses :: all ( ) ; } </s>


<s> bool BPFAdjustOpt :: runOnModule ( Module & M ) { return BPFAdjustOptImpl ( & M ) . run ( ) ; } </s>


<s>
void
BPFAsmBackend
::
applyFixup
(
const
MCAssembler
&
Asm
,
const
MCFixup
&
Fixup
,
const
MCValue
&
Target
,
MutableArrayRef
<
char
>
Data
,
uint64_t
Value
,
bool
IsResolved
,
const
MCSubtargetInfo
*
STI
)
const
{
if
(
Fixup
.
getKind
(
)
==
FK_SecRel_8
)
{
assert
(
Value
<=
UINT32_MAX
)
;
support
::
endian
::
write
<
uint32_t
>
(
&
Data
[
Fixup
.
getOffset
(
)
+
4
]
,
static_cast
<
uint32_t
>
(
Value
)
,
Endian
)
;
}
else
if
(
Fixup
.
getKind
(
)
==
FK_Data_4
)
{
support
::
endian
::
write
<
uint32_t
>
(
&
Data
[
Fixup
.
getOffset
(
)
]
,
Value
,
Endian
)
;
}
else
if
(
Fixup
.
getKind
(
)
==
FK_Data_8
)
{
support
::
endian
::
write
<
uint64_t
>
(
&
Data
[
Fixup
.
getOffset
(
)
]
,
Value
,
Endian
)
;
}
else
if
(
Fixup
.
getKind
(
)
==
FK_PCRel_4
)
{
Value
=
(
uint32_t
)
(
(
Value
8
)
/
8
)
;
if
(
Endian
==
support
::
little
)
{
Data
[
Fixup
.
getOffset
(
)
+
1
]
=
0x10
;
support
::
endian
::
write32le
(
&
Data
[
Fixup
.
getOffset
(
)
+
4
]
,
Value
)
;
}
else
{
Data
[
Fixup
.
getOffset
(
)
+
1
]
=
0x1
;
support
::
endian
::
write32be
(
&
Data
[
Fixup
.
getOffset
(
)
+
4
]
,
Value
)
;
}
}
else
{
assert
(
Fixup
.
getKind
(
)
==
FK_PCRel_2
)
;
int64_t
ByteOff
=
(
int64_t
)
Value
8
;
if
(
ByteOff
>
INT16_MAX
*
8
||
ByteOff
<
INT16_MIN
*
8
)
report_fatal_error
(
"Branch target out of insn range"
)
;
Value
=
(
uint16_t
)
(
(
Value
8
)
/
8
)
;
support
::
endian
::
write
<
uint16_t
>
(
&
Data
[
Fixup
.
getOffset
(
)
+
2
]
,
Value
,
Endian
)
;
}
}
</s>

Apply the Value for given Fixup into the provided data fragment , at the offset specified by the fixup and following the fixup kind as appropriate .


<s> bool fixupNeedsRelaxation ( const MCFixup & Fixup , uint64_t Value , const MCRelaxableFragment * DF , const MCAsmLayout & Layout ) const override { return false ; } </s>

Simple predicate for targets where ! Resolved implies requiring relaxation .


<s> unsigned getNumFixupKinds ( ) const override { return 1 ; } </s>

Get the number of target specific fixup kinds .


<s> bool BPFAsmBackend :: writeNopData ( raw_ostream & OS , uint64_t Count , const MCSubtargetInfo * STI ) const { if ( ( Count % 8 ) != 0 ) return false ; for ( uint64_t i = 0 ; i < Count ; i += 8 ) support :: endian :: write < uint64_t > ( OS , 0x15000000 , Endian ) ; return true ; } </s>

Write an ( optimal ) nop sequence of Count bytes to the given output .


<s> void BPFAsmBackend :: applyFixup ( const MCFixup & Fixup , char * Data , unsigned DataSize , uint64_t Value , bool IsPCRel ) const { if ( Fixup . getKind ( ) == FK_SecRel_4 || Fixup . getKind ( ) == FK_SecRel_8 ) { assert ( Value == 0 ) ; } else if ( Fixup . getKind ( ) == FK_Data_4 || Fixup . getKind ( ) == FK_Data_8 ) { unsigned Size = Fixup . getKind ( ) == FK_Data_4 ? 4 : 8 ; for ( unsigned i = 0 ; i != Size ; ++ i ) { unsigned Idx = IsLittleEndian ? i : Size - i ; Data [ Fixup . getOffset ( ) + Idx ] = uint8_t ( Value >> ( i * 8 ) ) ; } } else { assert ( Fixup . getKind ( ) == FK_PCRel_2 ) ; Value = ( uint16_t ) ( ( Value - 8 ) / 8 ) ; if ( IsLittleEndian ) { Data [ Fixup . getOffset ( ) + 2 ] = Value & 0xFF ; Data [ Fixup . getOffset ( ) + 3 ] = Value >> 8 ; } else { Data [ Fixup . getOffset ( ) + 2 ] = Value >> 8 ; Data [ Fixup . getOffset ( ) + 3 ] = Value & 0xFF ; } } } </s>


<s> void BPFAsmBackend :: applyFixup ( const MCFixup & Fixup , char * Data , unsigned DataSize , uint64_t Value , bool IsPCRel ) const { if ( Fixup . getKind ( ) == FK_SecRel_4 || Fixup . getKind ( ) == FK_SecRel_8 ) { assert ( Value == 0 ) ; return ; } assert ( Fixup . getKind ( ) == FK_PCRel_2 ) ; * ( uint16_t * ) & Data [ Fixup . getOffset ( ) + 2 ] = ( uint16_t ) ( ( Value - 8 ) / 8 ) ; } </s>


<s> MCObjectWriter * BPFAsmBackend :: createObjectWriter ( raw_ostream & OS ) const { return createBPFELFObjectWriter ( OS , 0 ) ; } </s>

Create a new MCObjectWriter instance for use by the assembler backend to emit the final object file .


<s> bool BPFAsmBackend :: writeNopData ( uint64_t Count , MCObjectWriter * OW ) const { if ( ( Count % 8 ) != 0 ) return false ; for ( uint64_t i = 0 ; i < Count ; i += 8 ) OW -> Write64 ( 0x15000000 ) ; return true ; } </s>


<s> void BPFAsmBackend :: applyFixup ( const MCAssembler & Asm , const MCFixup & Fixup , const MCValue & Target , MutableArrayRef < char > Data , uint64_t Value , bool IsResolved , const MCSubtargetInfo * STI ) const { if ( Fixup . getKind ( ) == FK_SecRel_4 || Fixup . getKind ( ) == FK_SecRel_8 ) { assert ( Value == 0 ) ; } else if ( Fixup . getKind ( ) == FK_Data_4 ) { support :: endian :: write < uint32_t > ( & Data [ Fixup . getOffset ( ) ] , Value , Endian ) ; } else if ( Fixup . getKind ( ) == FK_Data_8 ) { support :: endian :: write < uint64_t > ( & Data [ Fixup . getOffset ( ) ] , Value , Endian ) ; } else if ( Fixup . getKind ( ) == FK_PCRel_4 ) { Value = ( uint32_t ) ( ( Value - 8 ) / 8 ) ; if ( Endian == support :: little ) { Data [ Fixup . getOffset ( ) + 1 ] = 0x10 ; support :: endian :: write32le ( & Data [ Fixup . getOffset ( ) + 4 ] , Value ) ; } else { Data [ Fixup . getOffset ( ) + 1 ] = 0x1 ; support :: endian :: write32be ( & Data [ Fixup . getOffset ( ) + 4 ] , Value ) ; } } else { assert ( Fixup . getKind ( ) == FK_PCRel_2 ) ; Value = ( uint16_t ) ( ( Value - 8 ) / 8 ) ; support :: endian :: write < uint16_t > ( & Data [ Fixup . getOffset ( ) + 2 ] , Value , Endian ) ; } } </s>


<s> bool mayNeedRelaxation ( const MCInst & Inst , const MCSubtargetInfo & STI ) const override { return false ; } </s>

Check whether the given instruction may need relaxation .


<s> bool BPFAsmBackend :: writeNopData ( raw_ostream & OS , uint64_t Count ) const { if ( ( Count % 8 ) != 0 ) return false ; for ( uint64_t i = 0 ; i < Count ; i += 8 ) support :: endian :: write < uint64_t > ( OS , 0x15000000 , Endian ) ; return true ; } </s>


<s> void BPFAsmBackend :: applyFixup ( const MCAssembler & Asm , const MCFixup & Fixup , const MCValue & Target , MutableArrayRef < char > Data , uint64_t Value , bool IsResolved , const MCSubtargetInfo * STI ) const { if ( Fixup . getKind ( ) == FK_SecRel_4 || Fixup . getKind ( ) == FK_SecRel_8 ) { assert ( Value <= UINT32_MAX ) ; support :: endian :: write < uint32_t > ( & Data [ Fixup . getOffset ( ) + 4 ] , static_cast < uint32_t > ( Value ) , Endian ) ; } else if ( Fixup . getKind ( ) == FK_Data_4 ) { support :: endian :: write < uint32_t > ( & Data [ Fixup . getOffset ( ) ] , Value , Endian ) ; } else if ( Fixup . getKind ( ) == FK_Data_8 ) { support :: endian :: write < uint64_t > ( & Data [ Fixup . getOffset ( ) ] , Value , Endian ) ; } else if ( Fixup . getKind ( ) == FK_PCRel_4 ) { Value = ( uint32_t ) ( ( Value - 8 ) / 8 ) ; if ( Endian == support :: little ) { Data [ Fixup . getOffset ( ) + 1 ] = 0x10 ; support :: endian :: write32le ( & Data [ Fixup . getOffset ( ) + 4 ] , Value ) ; } else { Data [ Fixup . getOffset ( ) + 1 ] = 0x1 ; support :: endian :: write32be ( & Data [ Fixup . getOffset ( ) + 4 ] , Value ) ; } } else { assert ( Fixup . getKind ( ) == FK_PCRel_2 ) ; Value = ( uint16_t ) ( ( Value - 8 ) / 8 ) ; support :: endian :: write < uint16_t > ( & Data [ Fixup . getOffset ( ) + 2 ] , Value , Endian ) ; } } </s>


"Unsupported relocation: try to compile with -O2 or above, "


<s> void BPFAsmBackend :: applyFixup ( const MCAssembler & Asm , const MCFixup & Fixup , const MCValue & Target , MutableArrayRef < char > Data , uint64_t Value , bool IsResolved ) const { if ( Fixup . getKind ( ) == FK_SecRel_4 || Fixup . getKind ( ) == FK_SecRel_8 ) { assert ( Value == 0 ) ; } else if ( Fixup . getKind ( ) == FK_Data_4 || Fixup . getKind ( ) == FK_Data_8 ) { unsigned Size = Fixup . getKind ( ) == FK_Data_4 ? 4 : 8 ; for ( unsigned i = 0 ; i != Size ; ++ i ) { unsigned Idx = IsLittleEndian ? i : Size - i - 1 ; Data [ Fixup . getOffset ( ) + Idx ] = uint8_t ( Value >> ( i * 8 ) ) ; } } else if ( Fixup . getKind ( ) == FK_PCRel_4 ) { Value = ( uint32_t ) ( ( Value - 8 ) / 8 ) ; if ( IsLittleEndian ) { Data [ Fixup . getOffset ( ) + 1 ] = 0x10 ; support :: endian :: write32le ( & Data [ Fixup . getOffset ( ) + 4 ] , Value ) ; } else { Data [ Fixup . getOffset ( ) + 1 ] = 0x1 ; support :: endian :: write32be ( & Data [ Fixup . getOffset ( ) + 4 ] , Value ) ; } } else { assert ( Fixup . getKind ( ) == FK_PCRel_2 ) ; Value = ( uint16_t ) ( ( Value - 8 ) / 8 ) ; if ( IsLittleEndian ) { Data [ Fixup . getOffset ( ) + 2 ] = Value & 0xFF ; Data [ Fixup . getOffset ( ) + 3 ] = Value >> 8 ; } else { Data [ Fixup . getOffset ( ) + 2 ] = Value >> 8 ; Data [ Fixup . getOffset ( ) + 3 ] = Value & 0xFF ; } } } </s>


<s> std :: unique_ptr < MCObjectWriter > BPFAsmBackend :: createObjectWriter ( raw_pwrite_stream & OS ) const { return createBPFELFObjectWriter ( OS , 0 , IsLittleEndian ) ; } </s>


<s> void BPFAsmBackend :: applyFixup ( const MCAssembler & Asm , const MCFixup & Fixup , const MCValue & Target , MutableArrayRef < char > Data , uint64_t Value , bool IsResolved ) const { if ( Fixup . getKind ( ) == FK_SecRel_4 || Fixup . getKind ( ) == FK_SecRel_8 ) { assert ( Value == 0 ) ; } else if ( Fixup . getKind ( ) == FK_Data_4 || Fixup . getKind ( ) == FK_Data_8 ) { unsigned Size = Fixup . getKind ( ) == FK_Data_4 ? 4 : 8 ; for ( unsigned i = 0 ; i != Size ; ++ i ) { unsigned Idx = IsLittleEndian ? i : Size - i - 1 ; Data [ Fixup . getOffset ( ) + Idx ] = uint8_t ( Value >> ( i * 8 ) ) ; } } else { assert ( Fixup . getKind ( ) == FK_PCRel_2 ) ; Value = ( uint16_t ) ( ( Value - 8 ) / 8 ) ; if ( IsLittleEndian ) { Data [ Fixup . getOffset ( ) + 2 ] = Value & 0xFF ; Data [ Fixup . getOffset ( ) + 3 ] = Value >> 8 ; } else { Data [ Fixup . getOffset ( ) + 2 ] = Value >> 8 ; Data [ Fixup . getOffset ( ) + 3 ] = Value & 0xFF ; } } } </s>


<s> void BPFAsmBackend :: applyFixup ( const MCFixup & Fixup , MutableArrayRef < char > Data , uint64_t Value , bool IsPCRel , MCContext & Ctx ) const { if ( Fixup . getKind ( ) == FK_SecRel_4 || Fixup . getKind ( ) == FK_SecRel_8 ) { assert ( Value == 0 ) ; } else if ( Fixup . getKind ( ) == FK_Data_4 || Fixup . getKind ( ) == FK_Data_8 ) { unsigned Size = Fixup . getKind ( ) == FK_Data_4 ? 4 : 8 ; for ( unsigned i = 0 ; i != Size ; ++ i ) { unsigned Idx = IsLittleEndian ? i : Size - i - 1 ; Data [ Fixup . getOffset ( ) + Idx ] = uint8_t ( Value >> ( i * 8 ) ) ; } } else { assert ( Fixup . getKind ( ) == FK_PCRel_2 ) ; Value = ( uint16_t ) ( ( Value - 8 ) / 8 ) ; if ( IsLittleEndian ) { Data [ Fixup . getOffset ( ) + 2 ] = Value & 0xFF ; Data [ Fixup . getOffset ( ) + 3 ] = Value >> 8 ; } else { Data [ Fixup . getOffset ( ) + 2 ] = Value >> 8 ; Data [ Fixup . getOffset ( ) + 3 ] = Value & 0xFF ; } } } </s>


<s> void relaxInstruction ( const MCInst & Inst , const MCSubtargetInfo & STI , MCInst & Res ) const override { } </s>

Relax the instruction in the given fragment to the next wider instruction .


<s> void BPFAsmBackend :: applyFixup ( const MCFixup & Fixup , char * Data , unsigned DataSize , uint64_t Value , bool IsPCRel , MCContext & Ctx ) const { if ( Fixup . getKind ( ) == FK_SecRel_4 || Fixup . getKind ( ) == FK_SecRel_8 ) { assert ( Value == 0 ) ; } else if ( Fixup . getKind ( ) == FK_Data_4 || Fixup . getKind ( ) == FK_Data_8 ) { unsigned Size = Fixup . getKind ( ) == FK_Data_4 ? 4 : 8 ; for ( unsigned i = 0 ; i != Size ; ++ i ) { unsigned Idx = IsLittleEndian ? i : Size - i ; Data [ Fixup . getOffset ( ) + Idx ] = uint8_t ( Value >> ( i * 8 ) ) ; } } else { assert ( Fixup . getKind ( ) == FK_PCRel_2 ) ; Value = ( uint16_t ) ( ( Value - 8 ) / 8 ) ; if ( IsLittleEndian ) { Data [ Fixup . getOffset ( ) + 2 ] = Value & 0xFF ; Data [ Fixup . getOffset ( ) + 3 ] = Value >> 8 ; } else { Data [ Fixup . getOffset ( ) + 2 ] = Value >> 8 ; Data [ Fixup . getOffset ( ) + 3 ] = Value & 0xFF ; } } } </s>


<s> void BPFAsmBackend :: applyFixup ( const MCAssembler & Asm , const MCFixup & Fixup , const MCValue & Target , MutableArrayRef < char > Data , uint64_t Value , bool IsResolved , const MCSubtargetInfo * STI ) const { if ( Fixup . getKind ( ) == FK_SecRel_8 ) { assert ( Value <= UINT32_MAX ) ; support :: endian :: write < uint32_t > ( & Data [ Fixup . getOffset ( ) + 4 ] , static_cast < uint32_t > ( Value ) , Endian ) ; } else if ( Fixup . getKind ( ) == FK_Data_4 ) { support :: endian :: write < uint32_t > ( & Data [ Fixup . getOffset ( ) ] , Value , Endian ) ; } else if ( Fixup . getKind ( ) == FK_Data_8 ) { support :: endian :: write < uint64_t > ( & Data [ Fixup . getOffset ( ) ] , Value , Endian ) ; } else if ( Fixup . getKind ( ) == FK_PCRel_4 ) { Value = ( uint32_t ) ( ( Value - 8 ) / 8 ) ; if ( Endian == support :: little ) { Data [ Fixup . getOffset ( ) + 1 ] = 0x10 ; support :: endian :: write32le ( & Data [ Fixup . getOffset ( ) + 4 ] , Value ) ; } else { Data [ Fixup . getOffset ( ) + 1 ] = 0x1 ; support :: endian :: write32be ( & Data [ Fixup . getOffset ( ) + 4 ] , Value ) ; } } else { assert ( Fixup . getKind ( ) == FK_PCRel_2 ) ; Value = ( uint16_t ) ( ( Value - 8 ) / 8 ) ; support :: endian :: write < uint16_t > ( & Data [ Fixup . getOffset ( ) + 2 ] , Value , Endian ) ; } } </s>


<s>
void
BPFAsmBackend
::
applyFixup
(
const
MCFixup
&
Fixup
,
char
*
Data
,
unsigned
DataSize
,
uint64_t
Value
)
const
{
if
(
0
)
errs
(
)
<<
"<MCFixup"
<<
" Offset:"
<<
Fixup
.
getOffset
(
)
<<
" Value:"
<<
*
(
Fixup
.
getValue
(
)
)
<<
" Kind:"
<<
Fixup
.
getKind
(
)
<<
" val "
<<
Value
<<
">\n"
;
if
(
Fixup
.
getKind
(
)
==
FK_SecRel_4
||
Fixup
.
getKind
(
)
==
FK_SecRel_8
)
{
assert
(
Value
==
0
)
;
return
;
}
assert
(
Fixup
.
getKind
(
)
==
FK_PCRel_2
)
;
*
(
uint16_t
*
)
&
Data
[
Fixup
.
getOffset
(
)
+
2
]
=
(
uint16_t
)
(
(
Value
8
)
/
8
)
;
}
</s>


<s> bool fixupNeedsRelaxation ( const MCFixup & Fixup , uint64_t Value , const MCInstFragment * DF , const MCAsmLayout & Layout ) const { return false ; } </s>


<s> unsigned getNumFixupKinds ( ) const { return 1 ; } </s>


<s> bool mayNeedRelaxation ( const MCInst & Inst ) const { return false ; } </s>


<s> void relaxInstruction ( const MCInst & Inst , MCInst & Res ) const { } </s>


<s> MCObjectWriter * BPFAsmBackend :: createObjectWriter ( raw_pwrite_stream & OS ) const { return createBPFELFObjectWriter ( OS , 0 ) ; } </s>


<s> void BPFAsmBackend :: applyFixup ( const MCFixup & Fixup , char * Data , unsigned DataSize , uint64_t Value , bool IsPCRel , MCContext & Ctx ) const { if ( Fixup . getKind ( ) == FK_SecRel_4 || Fixup . getKind ( ) == FK_SecRel_8 ) { assert ( Value == 0 ) ; } else if ( Fixup . getKind ( ) == FK_Data_4 || Fixup . getKind ( ) == FK_Data_8 ) { unsigned Size = Fixup . getKind ( ) == FK_Data_4 ? 4 : 8 ; for ( unsigned i = 0 ; i != Size ; ++ i ) { unsigned Idx = IsLittleEndian ? i : Size - i - 1 ; Data [ Fixup . getOffset ( ) + Idx ] = uint8_t ( Value >> ( i * 8 ) ) ; } } else { assert ( Fixup . getKind ( ) == FK_PCRel_2 ) ; Value = ( uint16_t ) ( ( Value - 8 ) / 8 ) ; if ( IsLittleEndian ) { Data [ Fixup . getOffset ( ) + 2 ] = Value & 0xFF ; Data [ Fixup . getOffset ( ) + 3 ] = Value >> 8 ; } else { Data [ Fixup . getOffset ( ) + 2 ] = Value >> 8 ; Data [ Fixup . getOffset ( ) + 3 ] = Value & 0xFF ; } } } </s>


<s> void BPFAsmBackend :: applyFixup ( const MCAssembler & Asm , const MCFixup & Fixup , const MCValue & Target , MutableArrayRef < char > Data , uint64_t Value , bool IsPCRel ) const { if ( Fixup . getKind ( ) == FK_SecRel_4 || Fixup . getKind ( ) == FK_SecRel_8 ) { assert ( Value == 0 ) ; } else if ( Fixup . getKind ( ) == FK_Data_4 || Fixup . getKind ( ) == FK_Data_8 ) { unsigned Size = Fixup . getKind ( ) == FK_Data_4 ? 4 : 8 ; for ( unsigned i = 0 ; i != Size ; ++ i ) { unsigned Idx = IsLittleEndian ? i : Size - i - 1 ; Data [ Fixup . getOffset ( ) + Idx ] = uint8_t ( Value >> ( i * 8 ) ) ; } } else { assert ( Fixup . getKind ( ) == FK_PCRel_2 ) ; Value = ( uint16_t ) ( ( Value - 8 ) / 8 ) ; if ( IsLittleEndian ) { Data [ Fixup . getOffset ( ) + 2 ] = Value & 0xFF ; Data [ Fixup . getOffset ( ) + 3 ] = Value >> 8 ; } else { Data [ Fixup . getOffset ( ) + 2 ] = Value >> 8 ; Data [ Fixup . getOffset ( ) + 3 ] = Value & 0xFF ; } } } </s>


<s> void BPFAsmBackend :: applyFixup ( const MCAssembler & Asm , const MCFixup & Fixup , const MCValue & Target , MutableArrayRef < char > Data , uint64_t Value , bool IsResolved ) const { if ( Fixup . getKind ( ) == FK_SecRel_4 || Fixup . getKind ( ) == FK_SecRel_8 ) { assert ( Value == 0 ) ; } else if ( Fixup . getKind ( ) == FK_Data_4 ) { support :: endian :: write < uint32_t > ( & Data [ Fixup . getOffset ( ) ] , Value , Endian ) ; } else if ( Fixup . getKind ( ) == FK_Data_8 ) { support :: endian :: write < uint64_t > ( & Data [ Fixup . getOffset ( ) ] , Value , Endian ) ; } else if ( Fixup . getKind ( ) == FK_PCRel_4 ) { Value = ( uint32_t ) ( ( Value - 8 ) / 8 ) ; if ( Endian == support :: little ) { Data [ Fixup . getOffset ( ) + 1 ] = 0x10 ; support :: endian :: write32le ( & Data [ Fixup . getOffset ( ) + 4 ] , Value ) ; } else { Data [ Fixup . getOffset ( ) + 1 ] = 0x1 ; support :: endian :: write32be ( & Data [ Fixup . getOffset ( ) + 4 ] , Value ) ; } } else { assert ( Fixup . getKind ( ) == FK_PCRel_2 ) ; Value = ( uint16_t ) ( ( Value - 8 ) / 8 ) ; support :: endian :: write < uint16_t > ( & Data [ Fixup . getOffset ( ) + 2 ] , Value , Endian ) ; } } </s>


<s> void BPFAsmBackend :: applyFixup ( const MCFixup & Fixup , char * Data , unsigned DataSize , uint64_t Value , bool IsPCRel ) const { if ( Fixup . getKind ( ) == FK_SecRel_4 || Fixup . getKind ( ) == FK_SecRel_8 ) { assert ( Value == 0 ) ; return ; } assert ( Fixup . getKind ( ) == FK_PCRel_2 ) ; Value = ( uint16_t ) ( ( Value - 8 ) / 8 ) ; if ( IsLittleEndian ) { Data [ Fixup . getOffset ( ) + 2 ] = Value & 0xFF ; Data [ Fixup . getOffset ( ) + 3 ] = Value >> 8 ; } else { Data [ Fixup . getOffset ( ) + 2 ] = Value >> 8 ; Data [ Fixup . getOffset ( ) + 3 ] = Value & 0xFF ; } } </s>


<s> MCObjectWriter * BPFAsmBackend :: createObjectWriter ( raw_pwrite_stream & OS ) const { return createBPFELFObjectWriter ( OS , 0 , IsLittleEndian ) ; } </s>


<s> bool mayNeedRelaxation ( const MCInst & Inst ) const override { return false ; } </s>


<s> void relaxInstruction ( const MCInst & Inst , MCInst & Res ) const override { } </s>


<s> bool BPFAsmBackend :: writeNopData ( uint64_t Count , MCObjectWriter * OW ) const { if ( ( Count % 8 ) != 0 ) return false ; for ( uint64_t i = 0 ; i < Count ; i += 8 ) OW -> write64 ( 0x15000000 ) ; return true ; } </s>


<s>
bool
BPFAsmParser
::
ParseInstruction
(
ParseInstructionInfo
&
Info
,
StringRef
Name
,
SMLoc
NameLoc
,
OperandVector
&
Operands
)
{
unsigned
RegNo
=
MatchRegisterName
(
Name
)
;
if
(
RegNo
!=
0
)
{
SMLoc
E
=
SMLoc
::
getFromPointer
(
NameLoc
.
getPointer
(
)
1
)
;
Operands
.
push_back
(
BPFOperand
::
createReg
(
RegNo
,
NameLoc
,
E
)
)
;
}
else
if
(
BPFOperand
::
isValidIdAtStart
(
Name
)
)
Operands
.
push_back
(
BPFOperand
::
createToken
(
Name
,
NameLoc
)
)
;
else
return
true
;
while
(
!
getLexer
(
)
.
is
(
AsmToken
::
EndOfStatement
)
)
{
if
(
parseOperandAsOperator
(
Operands
)
==
MatchOperand_Success
)
continue
;
if
(
parseRegister
(
Operands
)
==
MatchOperand_Success
)
continue
;
if
(
parseImmediate
(
Operands
)
!=
MatchOperand_Success
)
return
true
;
}
if
(
getLexer
(
)
.
isNot
(
AsmToken
::
EndOfStatement
)
)
{
SMLoc
Loc
=
getLexer
(
)
.
getLoc
(
)
;
getParser
(
)
.
eatToEndOfStatement
(
)
;
return
Error
(
Loc
,
"unexpected token"
)
;
}
getParser
(
)
.
Lex
(
)
;
return
false
;
}
</s>

ParseInstruction - Parse one assembly instruction .

BPF
BPF
0
1
BPFOperand::createReg
BPFOperand::isValidIdAtStart
BPFOperand::createToken
"unexpected token"


"instruction use requires an option to be enabled"

MatchAndEmitInstruction - Recognize a series of operands of a parsed instruction as an actual MCInst and emit it to the specified MCStreamer .


<s> OperandMatchResultTy BPFAsmParser :: tryParseRegister ( unsigned & RegNo , SMLoc & StartLoc , SMLoc & EndLoc ) { const AsmToken & Tok = getParser ( ) . getTok ( ) ; StartLoc = Tok . getLoc ( ) ; EndLoc = Tok . getEndLoc ( ) ; RegNo = 0 ; StringRef Name = getLexer ( ) . getTok ( ) . getIdentifier ( ) ; if ( ! MatchRegisterName ( Name ) ) { getParser ( ) . Lex ( ) ; return MatchOperand_Success ; } return MatchOperand_NoMatch ; } </s>

tryParseRegister - parse one register if possible


<s>
void
addExpr
(
MCInst
&
Inst
,
const
MCExpr
*
Expr
)
const
{
assert
(
Expr
&&
"Expr shouldn't be null!"
)
;
if
(
auto
*
CE
=
dyn_cast
<
MCConstantExpr
>
(
Expr
)
)
Inst
.
addOperand
(
MCOperand
::
createImm
(
CE
->
getValue
(
)
)
)
;
else
Inst
.
addOperand
(
MCOperand
::
createExpr
(
Expr
)
)
;
}
</s>


<s> SMLoc getEndLoc ( ) const override { return EndLoc ; } </s>

getEndLoc - Get the location of the last token of this operand .


<s> SMLoc getLoc ( ) const { return getParser ( ) . getTok ( ) . getLoc ( ) ; } </s>

Get the source location of the point where the field was defined .


<s>
unsigned
getReg
(
)
const
override
{
assert
(
Kind
==
Register
&&
"Invalid type access!"
)
;
return
Reg
.
RegNum
;
}
</s>

Returns the register associated with this edge .


<s> SMLoc getStartLoc ( ) const override { return StartLoc ; } </s>

getStartLoc - Get the location of the first token of this operand .


<s> bool isImm ( ) const override { return Kind == Immediate ; } </s>


<s> bool isMem ( ) const override { return false ; } </s>


<s> bool isReg ( ) const override { return Kind == Register ; } </s>


<s> bool isToken ( ) const override { return Kind == Token ; } </s>


<s> bool BPFAsmParser :: ParseDirective ( AsmToken DirectiveID ) { return true ; } </s>

ParseDirective - Parse a target specific assembler directive This method is deprecated , use 'parseDirective ' instead .


<s>
bool
BPFAsmParser
::
ParseInstruction
(
ParseInstructionInfo
&
Info
,
StringRef
Name
,
SMLoc
NameLoc
,
OperandVector
&
Operands
)
{
unsigned
RegNo
=
MatchRegisterName
(
Name
)
;
if
(
RegNo
!=
0
)
{
SMLoc
E
=
SMLoc
::
getFromPointer
(
NameLoc
.
getPointer
(
)
1
)
;
Operands
.
push_back
(
BPFOperand
::
createReg
(
RegNo
,
NameLoc
,
E
)
)
;
}
else
if
(
BPFOperand
::
isValidIdAtStart
(
Name
)
)
Operands
.
push_back
(
BPFOperand
::
createToken
(
Name
,
NameLoc
)
)
;
else
return
Error
(
NameLoc
,
"invalid register/token name"
)
;
while
(
!
getLexer
(
)
.
is
(
AsmToken
::
EndOfStatement
)
)
{
if
(
parseOperandAsOperator
(
Operands
)
==
MatchOperand_Success
)
continue
;
if
(
parseRegister
(
Operands
)
==
MatchOperand_Success
)
continue
;
if
(
parseImmediate
(
Operands
)
!=
MatchOperand_Success
)
{
SMLoc
Loc
=
getLexer
(
)
.
getLoc
(
)
;
return
Error
(
Loc
,
"unexpected token"
)
;
}
}
if
(
getLexer
(
)
.
isNot
(
AsmToken
::
EndOfStatement
)
)
{
SMLoc
Loc
=
getLexer
(
)
.
getLoc
(
)
;
getParser
(
)
.
eatToEndOfStatement
(
)
;
return
Error
(
Loc
,
"unexpected token"
)
;
}
getParser
(
)
.
Lex
(
)
;
return
false
;
}
</s>

BPF
BPF
0
1
BPFOperand::createReg
BPFOperand::isValidIdAtStart
BPFOperand::createToken
"invalid register/token name"
"unexpected token"
"unexpected token"


<s>
void
print
(
raw_ostream
&
OS
)
const
override
{
switch
(
Kind
)
{
case
Immediate
:
OS
<<
*
getImm
(
)
;
break
;
case
Register
:
OS
<<
"<register x"
;
OS
<<
getReg
(
)
<<
">"
;
break
;
case
Token
:
OS
<<
"'"
<<
getToken
(
)
<<
"'"
;
break
;
}
}
</s>

print - Print a debug representation of the operand to the given stream .


<s> void BPFAsmPrinter :: EmitInstruction ( const MachineInstr * MI ) { BPFMCInstLower MCInstLowering ( OutContext , * this ) ; MCInst TmpInst ; MCInstLowering . Lower ( MI , TmpInst ) ; EmitToStreamer ( * OutStreamer , TmpInst ) ; } </s>

EmitInstruction - This callback is invoked when an instruction is emitted , to advance the hazard state .


<s>
const
char
*
getPassName
(
)
const
override
{
return
"BPF Assembly Printer"
;
}
</s>

getPassName - Return a nice clean name for a pass .


"Unexpected base pointer for inline asm memory operand."

"Unexpected offset for inline asm memory operand."

Print the specified operand of MI , an INLINEASM instruction , using the specified assembler variant as an address .


<s> bool BPFAsmPrinter :: PrintAsmOperand ( const MachineInstr * MI , unsigned OpNo , unsigned , const char * ExtraCode , raw_ostream & O ) { if ( ExtraCode && ExtraCode [ 0 ] ) return true ; printOperand ( MI , OpNo , O ) ; return false ; } </s>

PrintAsmOperand - Print out an operand for an inline asm expression .


<s>
bool
BPFAsmPrinter
::
doInitialization
(
Module
&
M
)
{
AsmPrinter
::
doInitialization
(
M
)
;
if
(
MAI
->
doesSupportDebugInformation
(
)
&&
!
M
.
debug_compile_units
(
)
.
empty
(
)
)
{
BTF
=
new
BTFDebug
(
this
)
;
Handlers
.
push_back
(
HandlerInfo
(
std
::
unique_ptr
<
BTFDebug
>
(
BTF
)
,
"emit"
,
"Debug Info Emission"
,
"BTF"
,
"BTF Emission"
)
)
;
}
return
false
;
}
</s>

Set up the AsmPrinter when we are working on a new module .

BPF
BPF
"emit"
"Debug Info Emission"
"BTF"
"BTF Emission"


<s> void BPFAsmPrinter :: EmitInstruction ( const MachineInstr * MI ) { MCInst TmpInst ; if ( ! BTF || ! BTF -> InstLower ( MI , TmpInst ) ) { BPFMCInstLower MCInstLowering ( OutContext , * this ) ; MCInstLowering . Lower ( MI , TmpInst ) ; } EmitToStreamer ( * OutStreamer , TmpInst ) ; } </s>


<s> bool BPFAsmPrinter :: PrintAsmOperand ( const MachineInstr * MI , unsigned OpNo , const char * ExtraCode , raw_ostream & O ) { if ( ExtraCode && ExtraCode [ 0 ] ) return AsmPrinter :: PrintAsmOperand ( MI , OpNo , ExtraCode , O ) ; printOperand ( MI , OpNo , O ) ; return false ; } </s>


<s>
bool
BPFAsmPrinter
::
doInitialization
(
Module
&
M
)
{
AsmPrinter
::
doInitialization
(
M
)
;
if
(
MAI
->
doesSupportDebugInformation
(
)
&&
!
empty
(
M
.
debug_compile_units
(
)
)
)
{
Handlers
.
emplace_back
(
llvm
::
make_unique
<
BTFDebug
>
(
this
)
,
"emit"
,
"Debug Info Emission"
,
"BTF"
,
"BTF Emission"
)
;
}
return
false
;
}
</s>


<s> void BPFAsmPrinter :: EmitInstruction ( const MachineInstr * MI ) { MachineBasicBlock :: const_instr_iterator I = MI ; MachineBasicBlock :: const_instr_iterator E = MI -> getParent ( ) -> instr_end ( ) ; do { customEmitInstruction ( I ++ ) ; } while ( ( I != E ) && I -> isInsideBundle ( ) ) ; } </s>


<s>
virtual
const
char
*
getPassName
(
)
const
{
return
"BPF Assembly Printer"
;
}
</s>


<s> void BPFAsmPrinter :: emitInstruction ( const MachineInstr * MI ) { MCInst TmpInst ; if ( ! BTF || ! BTF -> InstLower ( MI , TmpInst ) ) { BPFMCInstLower MCInstLowering ( OutContext , * this ) ; MCInstLowering . Lower ( MI , TmpInst ) ; } EmitToStreamer ( * OutStreamer , TmpInst ) ; } </s>

Targets should implement this to emit instructions .


<s>
StringRef
getPassName
(
)
const
override
{
return
"BPF Assembly Printer"
;
}
</s>


<s>
bool
BPFAsmPrinter
::
doInitialization
(
Module
&
M
)
{
AsmPrinter
::
doInitialization
(
M
)
;
if
(
MAI
->
doesSupportDebugInformation
(
)
&&
!
M
.
debug_compile_units
(
)
.
empty
(
)
)
{
Handlers
.
emplace_back
(
llvm
::
make_unique
<
BTFDebug
>
(
this
)
,
"emit"
,
"Debug Info Emission"
,
"BTF"
,
"BTF Emission"
)
;
}
return
false
;
}
</s>


<s>
bool
BPFAsmPrinter
::
doInitialization
(
Module
&
M
)
{
AsmPrinter
::
doInitialization
(
M
)
;
if
(
MAI
->
doesSupportDebugInformation
(
)
&&
!
empty
(
M
.
debug_compile_units
(
)
)
)
{
BTF
=
new
BTFDebug
(
this
)
;
Handlers
.
push_back
(
HandlerInfo
(
std
::
unique_ptr
<
BTFDebug
>
(
BTF
)
,
"emit"
,
"Debug Info Emission"
,
"BTF"
,
"BTF Emission"
)
)
;
}
return
false
;
}
</s>


<s>
bool
BPFAsmPrinter
::
doInitialization
(
Module
&
M
)
{
AsmPrinter
::
doInitialization
(
M
)
;
if
(
MAI
->
doesSupportDebugInformation
(
)
)
{
Handlers
.
push_back
(
HandlerInfo
(
new
BTFDebug
(
this
)
,
"emit"
,
"Debug Info Emission"
,
"BTF"
,
"BTF Emission"
)
)
;
}
return
false
;
}
</s>


<s> void BPFAsmPrinter :: EmitInstruction ( const MachineInstr * MI ) { BPFMCInstLower MCInstLowering ( OutContext , * this ) ; MCInst TmpInst ; MCInstLowering . Lower ( MI , TmpInst ) ; EmitToStreamer ( OutStreamer , TmpInst ) ; } </s>


<s> bool BPFCheckAndAdjustIR :: runOnModule ( Module & M ) { checkIR ( M ) ; return adjustIR ( M ) ; } </s>

runOnModule - Virtual method overriden by subclasses to process the module being operated on .


<s> DecodeStatus BPFDisassembler :: getInstruction ( MCInst & Instr , uint64_t & Size , ArrayRef < uint8_t > Bytes , uint64_t Address , raw_ostream & CStream ) const { bool IsLittleEndian = getContext ( ) . getAsmInfo ( ) -> isLittleEndian ( ) ; uint64_t Insn , Hi ; DecodeStatus Result ; Result = readInstruction64 ( Bytes , Address , Size , Insn , IsLittleEndian ) ; if ( Result == MCDisassembler :: Fail ) return MCDisassembler :: Fail ; uint8_t InstClass = getInstClass ( Insn ) ; uint8_t InstMode = getInstMode ( Insn ) ; if ( ( InstClass == BPF_LDX || InstClass == BPF_STX ) && getInstSize ( Insn ) != BPF_DW && ( InstMode == BPF_MEM || InstMode == BPF_XADD ) && STI . getFeatureBits ( ) [ BPF :: ALU32 ] ) Result = decodeInstruction ( DecoderTableBPFALU3264 , Instr , Insn , Address , this , STI ) ; else Result = decodeInstruction ( DecoderTableBPF64 , Instr , Insn , Address , this , STI ) ; if ( Result == MCDisassembler :: Fail ) return MCDisassembler :: Fail ; switch ( Instr . getOpcode ( ) ) { case BPF :: LD_imm64 : case BPF :: LD_pseudo : { if ( Bytes . size ( ) < 16 ) { Size = 0 ; return MCDisassembler :: Fail ; } Size = 16 ; if ( IsLittleEndian ) Hi = ( Bytes [ 12 ] << 0 ) | ( Bytes [ 13 ] << 8 ) | ( Bytes [ 14 ] << 16 ) | ( Bytes [ 15 ] << 24 ) ; else Hi = ( Bytes [ 12 ] << 24 ) | ( Bytes [ 13 ] << 16 ) | ( Bytes [ 14 ] << 8 ) | ( Bytes [ 15 ] << 0 ) ; auto & Op = Instr . getOperand ( 1 ) ; Op . setImm ( Make_64 ( Hi , Op . getImm ( ) ) ) ; break ; } case BPF :: LD_ABS_B : case BPF :: LD_ABS_H : case BPF :: LD_ABS_W : case BPF :: LD_IND_B : case BPF :: LD_IND_H : case BPF :: LD_IND_W : { auto Op = Instr . getOperand ( 0 ) ; Instr . clear ( ) ; Instr . addOperand ( MCOperand :: createReg ( BPF :: R6 ) ) ; Instr . addOperand ( Op ) ; break ; } } return Result ; } </s>

Returns the disassembly of a single instruction .


<s> DecodeStatus BPFDisassembler :: getInstruction ( MCInst & Instr , uint64_t & Size , ArrayRef < uint8_t > Bytes , uint64_t Address , raw_ostream & VStream , raw_ostream & CStream ) const { uint64_t Insn ; DecodeStatus Result ; Result = readInstruction64 ( Bytes , Address , Size , Insn ) ; if ( Result == MCDisassembler :: Fail ) return MCDisassembler :: Fail ; Result = decodeInstruction ( DecoderTableBPF64 , Instr , Insn , Address , this , STI ) ; if ( Result == MCDisassembler :: Fail ) return MCDisassembler :: Fail ; switch ( Instr . getOpcode ( ) ) { case BPF :: LD_imm64 : { if ( Bytes . size ( ) < 16 ) { Size = 0 ; return MCDisassembler :: Fail ; } Size = 16 ; uint64_t Hi = ( Bytes [ 12 ] << 0 ) | ( Bytes [ 13 ] << 8 ) | ( Bytes [ 14 ] << 16 ) | ( Bytes [ 15 ] << 24 ) ; auto & Op = Instr . getOperand ( 1 ) ; Op . setImm ( Make_64 ( Hi , Op . getImm ( ) ) ) ; break ; } case BPF :: LD_ABS_B : case BPF :: LD_ABS_H : case BPF :: LD_ABS_W : case BPF :: LD_IND_B : case BPF :: LD_IND_H : case BPF :: LD_IND_W : { auto Op = Instr . getOperand ( 0 ) ; Instr . clear ( ) ; Instr . addOperand ( MCOperand :: createReg ( BPF :: R6 ) ) ; Instr . addOperand ( Op ) ; break ; } } return Result ; } </s>


<s> DecodeStatus BPFDisassembler :: getInstruction ( MCInst & Instr , uint64_t & Size , ArrayRef < uint8_t > Bytes , uint64_t Address , raw_ostream & CStream ) const { bool IsLittleEndian = getContext ( ) . getAsmInfo ( ) -> isLittleEndian ( ) ; uint64_t Insn , Hi ; DecodeStatus Result ; Result = readInstruction64 ( Bytes , Address , Size , Insn , IsLittleEndian ) ; if ( Result == MCDisassembler :: Fail ) return MCDisassembler :: Fail ; uint8_t InstClass = getInstClass ( Insn ) ; uint8_t InstMode = getInstMode ( Insn ) ; if ( ( InstClass == BPF_LDX || InstClass == BPF_STX ) && getInstSize ( Insn ) != BPF_DW && ( InstMode == BPF_MEM || InstMode == BPF_ATOMIC ) && STI . getFeatureBits ( ) [ BPF :: ALU32 ] ) Result = decodeInstruction ( DecoderTableBPFALU3264 , Instr , Insn , Address , this , STI ) ; else Result = decodeInstruction ( DecoderTableBPF64 , Instr , Insn , Address , this , STI ) ; if ( Result == MCDisassembler :: Fail ) return MCDisassembler :: Fail ; switch ( Instr . getOpcode ( ) ) { case BPF :: LD_imm64 : case BPF :: LD_pseudo : { if ( Bytes . size ( ) < 16 ) { Size = 0 ; return MCDisassembler :: Fail ; } Size = 16 ; if ( IsLittleEndian ) Hi = ( Bytes [ 12 ] << 0 ) | ( Bytes [ 13 ] << 8 ) | ( Bytes [ 14 ] << 16 ) | ( Bytes [ 15 ] << 24 ) ; else Hi = ( Bytes [ 12 ] << 24 ) | ( Bytes [ 13 ] << 16 ) | ( Bytes [ 14 ] << 8 ) | ( Bytes [ 15 ] << 0 ) ; auto & Op = Instr . getOperand ( 1 ) ; Op . setImm ( Make_64 ( Hi , Op . getImm ( ) ) ) ; break ; } case BPF :: LD_ABS_B : case BPF :: LD_ABS_H : case BPF :: LD_ABS_W : case BPF :: LD_IND_B : case BPF :: LD_IND_H : case BPF :: LD_IND_W : { auto Op = Instr . getOperand ( 0 ) ; Instr . clear ( ) ; Instr . addOperand ( MCOperand :: createReg ( BPF :: R6 ) ) ; Instr . addOperand ( Op ) ; break ; } } return Result ; } </s>


<s> DecodeStatus BPFDisassembler :: getInstruction ( MCInst & Instr , uint64_t & Size , ArrayRef < uint8_t > Bytes , uint64_t Address , raw_ostream & VStream , raw_ostream & CStream ) const { bool IsLittleEndian = getContext ( ) . getAsmInfo ( ) -> isLittleEndian ( ) ; uint64_t Insn , Hi ; DecodeStatus Result ; Result = readInstruction64 ( Bytes , Address , Size , Insn , IsLittleEndian ) ; if ( Result == MCDisassembler :: Fail ) return MCDisassembler :: Fail ; uint8_t InstClass = getInstClass ( Insn ) ; uint8_t InstMode = getInstMode ( Insn ) ; if ( ( InstClass == BPF_LDX || InstClass == BPF_STX ) && getInstSize ( Insn ) != BPF_DW && ( InstMode == BPF_MEM || InstMode == BPF_XADD ) && STI . getFeatureBits ( ) [ BPF :: ALU32 ] ) Result = decodeInstruction ( DecoderTableBPFALU3264 , Instr , Insn , Address , this , STI ) ; else Result = decodeInstruction ( DecoderTableBPF64 , Instr , Insn , Address , this , STI ) ; if ( Result == MCDisassembler :: Fail ) return MCDisassembler :: Fail ; switch ( Instr . getOpcode ( ) ) { case BPF :: LD_imm64 : case BPF :: LD_pseudo : { if ( Bytes . size ( ) < 16 ) { Size = 0 ; return MCDisassembler :: Fail ; } Size = 16 ; if ( IsLittleEndian ) Hi = ( Bytes [ 12 ] << 0 ) | ( Bytes [ 13 ] << 8 ) | ( Bytes [ 14 ] << 16 ) | ( Bytes [ 15 ] << 24 ) ; else Hi = ( Bytes [ 12 ] << 24 ) | ( Bytes [ 13 ] << 16 ) | ( Bytes [ 14 ] << 8 ) | ( Bytes [ 15 ] << 0 ) ; auto & Op = Instr . getOperand ( 1 ) ; Op . setImm ( Make_64 ( Hi , Op . getImm ( ) ) ) ; break ; } case BPF :: LD_ABS_B : case BPF :: LD_ABS_H : case BPF :: LD_ABS_W : case BPF :: LD_IND_B : case BPF :: LD_IND_H : case BPF :: LD_IND_W : { auto Op = Instr . getOperand ( 0 ) ; Instr . clear ( ) ; Instr . addOperand ( MCOperand :: createReg ( BPF :: R6 ) ) ; Instr . addOperand ( Op ) ; break ; } } return Result ; } </s>


<s> DecodeStatus BPFDisassembler :: getInstruction ( MCInst & Instr , uint64_t & Size , ArrayRef < uint8_t > Bytes , uint64_t Address , raw_ostream & VStream , raw_ostream & CStream ) const { bool IsLittleEndian = getContext ( ) . getAsmInfo ( ) -> isLittleEndian ( ) ; uint64_t Insn , Hi ; DecodeStatus Result ; Result = readInstruction64 ( Bytes , Address , Size , Insn , IsLittleEndian ) ; if ( Result == MCDisassembler :: Fail ) return MCDisassembler :: Fail ; Result = decodeInstruction ( DecoderTableBPF64 , Instr , Insn , Address , this , STI ) ; if ( Result == MCDisassembler :: Fail ) return MCDisassembler :: Fail ; switch ( Instr . getOpcode ( ) ) { case BPF :: LD_imm64 : case BPF :: LD_pseudo : { if ( Bytes . size ( ) < 16 ) { Size = 0 ; return MCDisassembler :: Fail ; } Size = 16 ; if ( IsLittleEndian ) Hi = ( Bytes [ 12 ] << 0 ) | ( Bytes [ 13 ] << 8 ) | ( Bytes [ 14 ] << 16 ) | ( Bytes [ 15 ] << 24 ) ; else Hi = ( Bytes [ 12 ] << 24 ) | ( Bytes [ 13 ] << 16 ) | ( Bytes [ 14 ] << 8 ) | ( Bytes [ 15 ] << 0 ) ; auto & Op = Instr . getOperand ( 1 ) ; Op . setImm ( Make_64 ( Hi , Op . getImm ( ) ) ) ; break ; } case BPF :: LD_ABS_B : case BPF :: LD_ABS_H : case BPF :: LD_ABS_W : case BPF :: LD_IND_B : case BPF :: LD_IND_H : case BPF :: LD_IND_W : { auto Op = Instr . getOperand ( 0 ) ; Instr . clear ( ) ; Instr . addOperand ( MCOperand :: createReg ( BPF :: R6 ) ) ; Instr . addOperand ( Op ) ; break ; } } return Result ; } </s>


<s> DecodeStatus BPFDisassembler :: getInstruction ( MCInst & Instr , uint64_t & Size , ArrayRef < uint8_t > Bytes , uint64_t Address , raw_ostream & VStream , raw_ostream & CStream ) const { bool IsLittleEndian = getContext ( ) . getAsmInfo ( ) -> isLittleEndian ( ) ; uint64_t Insn , Hi ; DecodeStatus Result ; Result = readInstruction64 ( Bytes , Address , Size , Insn , IsLittleEndian ) ; if ( Result == MCDisassembler :: Fail ) return MCDisassembler :: Fail ; Result = decodeInstruction ( DecoderTableBPF64 , Instr , Insn , Address , this , STI ) ; if ( Result == MCDisassembler :: Fail ) return MCDisassembler :: Fail ; switch ( Instr . getOpcode ( ) ) { case BPF :: LD_imm64 : { if ( Bytes . size ( ) < 16 ) { Size = 0 ; return MCDisassembler :: Fail ; } Size = 16 ; if ( IsLittleEndian ) Hi = ( Bytes [ 12 ] << 0 ) | ( Bytes [ 13 ] << 8 ) | ( Bytes [ 14 ] << 16 ) | ( Bytes [ 15 ] << 24 ) ; else Hi = ( Bytes [ 12 ] << 24 ) | ( Bytes [ 13 ] << 16 ) | ( Bytes [ 14 ] << 8 ) | ( Bytes [ 15 ] << 0 ) ; auto & Op = Instr . getOperand ( 1 ) ; Op . setImm ( Make_64 ( Hi , Op . getImm ( ) ) ) ; break ; } case BPF :: LD_ABS_B : case BPF :: LD_ABS_H : case BPF :: LD_ABS_W : case BPF :: LD_IND_B : case BPF :: LD_IND_H : case BPF :: LD_IND_W : { auto Op = Instr . getOperand ( 0 ) ; Instr . clear ( ) ; Instr . addOperand ( MCOperand :: createReg ( BPF :: R6 ) ) ; Instr . addOperand ( Op ) ; break ; } } return Result ; } </s>


<s> DecodeStatus BPFDisassembler :: getInstruction ( MCInst & Instr , uint64_t & Size , ArrayRef < uint8_t > Bytes , uint64_t Address , raw_ostream & VStream , raw_ostream & CStream ) const { bool IsLittleEndian = getContext ( ) . getAsmInfo ( ) -> isLittleEndian ( ) ; uint64_t Insn , Hi ; DecodeStatus Result ; Result = readInstruction64 ( Bytes , Address , Size , Insn , IsLittleEndian ) ; if ( Result == MCDisassembler :: Fail ) return MCDisassembler :: Fail ; uint8_t InstClass = getInstClass ( Insn ) ; if ( ( InstClass == BPF_LDX || InstClass == BPF_STX ) && getInstSize ( Insn ) != BPF_DW && getInstMode ( Insn ) == BPF_MEM && STI . getFeatureBits ( ) [ BPF :: ALU32 ] ) Result = decodeInstruction ( DecoderTableBPFALU3264 , Instr , Insn , Address , this , STI ) ; else Result = decodeInstruction ( DecoderTableBPF64 , Instr , Insn , Address , this , STI ) ; if ( Result == MCDisassembler :: Fail ) return MCDisassembler :: Fail ; switch ( Instr . getOpcode ( ) ) { case BPF :: LD_imm64 : case BPF :: LD_pseudo : { if ( Bytes . size ( ) < 16 ) { Size = 0 ; return MCDisassembler :: Fail ; } Size = 16 ; if ( IsLittleEndian ) Hi = ( Bytes [ 12 ] << 0 ) | ( Bytes [ 13 ] << 8 ) | ( Bytes [ 14 ] << 16 ) | ( Bytes [ 15 ] << 24 ) ; else Hi = ( Bytes [ 12 ] << 24 ) | ( Bytes [ 13 ] << 16 ) | ( Bytes [ 14 ] << 8 ) | ( Bytes [ 15 ] << 0 ) ; auto & Op = Instr . getOperand ( 1 ) ; Op . setImm ( Make_64 ( Hi , Op . getImm ( ) ) ) ; break ; } case BPF :: LD_ABS_B : case BPF :: LD_ABS_H : case BPF :: LD_ABS_W : case BPF :: LD_IND_B : case BPF :: LD_IND_H : case BPF :: LD_IND_W : { auto Op = Instr . getOperand ( 0 ) ; Instr . clear ( ) ; Instr . addOperand ( MCOperand :: createReg ( BPF :: R6 ) ) ; Instr . addOperand ( Op ) ; break ; } } return Result ; } </s>


<s> void eliminateCallFramePseudoInstr ( MachineFunction & MF , MachineBasicBlock & MBB , MachineBasicBlock :: iterator MI ) const { MBB . erase ( MI ) ; } </s>

This method is called during prolog/epilog code insertion to eliminate call frame setup and destroy pseudo instructions ( but only if the Target is using them ) .


<s> void eliminateCallFramePseudoInstr ( MachineFunction & MF , MachineBasicBlock & MBB , MachineBasicBlock :: iterator MI ) const override { MBB . erase ( MI ) ; } </s>


<s> void BPFFrameLowering :: emitPrologue ( MachineFunction & MF ) const { } </s>

emitProlog/emitEpilog - These methods insert prolog and epilog code into the function .


<s> void BPFFrameLowering :: emitEpilogue ( MachineFunction & MF , MachineBasicBlock & MBB ) const { } </s>


<s> void BPFFrameLowering :: determineCalleeSaves ( MachineFunction & MF , BitVector & SavedRegs , RegScavenger * RS ) const { TargetFrameLowering :: determineCalleeSaves ( MF , SavedRegs , RS ) ; SavedRegs . reset ( BPF :: R6 ) ; SavedRegs . reset ( BPF :: R7 ) ; SavedRegs . reset ( BPF :: R8 ) ; SavedRegs . reset ( BPF :: R9 ) ; } </s>

This method determines which of the registers reported by TargetRegisterInfo : :getCalleeSavedRegs ( ) should actually get saved .


<s> MachineBasicBlock :: iterator eliminateCallFramePseudoInstr ( MachineFunction & MF , MachineBasicBlock & MBB , MachineBasicBlock :: iterator MI ) const override { return MBB . erase ( MI ) ; } </s>


<s> void BPFFrameLowering :: emitPrologue ( MachineFunction & MF , MachineBasicBlock & MBB ) const { } </s>


<s> bool BPFFrameLowering :: hasFP ( const MachineFunction & MF ) const { return true ; } </s>

hasFP - Return true if the specified function should have a dedicated frame pointer register .


<s> void BPFInstPrinter :: printInst ( const MCInst * MI , uint64_t Address , StringRef Annot , const MCSubtargetInfo & STI , raw_ostream & O ) { printInstruction ( MI , Address , O ) ; printAnnotation ( O , Annot ) ; } </s>

Print the specified MCInst to the specified raw_ostream .


<s> void BPFInstPrinter :: printInst ( const MCInst * MI , raw_ostream & O , StringRef Annot ) { printInstruction ( MI , O ) ; printAnnotation ( O , Annot ) ; } </s>


<s> void BPFInstPrinter :: printInst ( const MCInst * MI , raw_ostream & O , StringRef Annot , const MCSubtargetInfo & STI ) { printInstruction ( MI , O ) ; printAnnotation ( O , Annot ) ; } </s>


<s> bool BPFInstrInfo :: analyzeBranch ( MachineBasicBlock & MBB , MachineBasicBlock * & TBB , MachineBasicBlock * & FBB , SmallVectorImpl < MachineOperand > & Cond , bool AllowModify ) const { MachineBasicBlock :: iterator I = MBB . end ( ) ; while ( I != MBB . begin ( ) ) { -- I ; if ( I -> isDebugValue ( ) ) continue ; if ( ! isUnpredicatedTerminator ( * I ) ) break ; if ( ! I -> isBranch ( ) ) return true ; if ( I -> getOpcode ( ) == BPF :: JMP ) { if ( ! AllowModify ) { TBB = I -> getOperand ( 0 ) . getMBB ( ) ; continue ; } while ( std :: next ( I ) != MBB . end ( ) ) std :: next ( I ) -> eraseFromParent ( ) ; Cond . clear ( ) ; FBB = nullptr ; if ( MBB . isLayoutSuccessor ( I -> getOperand ( 0 ) . getMBB ( ) ) ) { TBB = nullptr ; I -> eraseFromParent ( ) ; I = MBB . end ( ) ; continue ; } TBB = I -> getOperand ( 0 ) . getMBB ( ) ; continue ; } return true ; } return false ; } </s>

analyzeBranch - Analyze the branching code at the end of MBB , returning true if it can not be understood ( e.g .


"insertBranch must not be told to insert a fallthrough"

"Unconditional branch with multiple successors!"

Insert branch code into the end of the specified MachineBasicBlock .


<s>
unsigned
BPFInstrInfo
::
removeBranch
(
MachineBasicBlock
&
MBB
,
int
*
BytesRemoved
)
const
{
assert
(
!
BytesRemoved
&&
"code size not handled"
)
;
MachineBasicBlock
::
iterator
I
=
MBB
.
end
(
)
;
unsigned
Count
=
0
;
while
(
I
!=
MBB
.
begin
(
)
)
{
I
;
if
(
I
->
isDebugValue
(
)
)
continue
;
if
(
I
->
getOpcode
(
)
!=
BPF
::
JMP
)
break
;
I
->
eraseFromParent
(
)
;
I
=
MBB
.
end
(
)
;
++
Count
;
}
return
Count
;
}
</s>

Remove the branching code at the end of the specific MBB .

BPF
BPF
"code size not handled"
0
BPF::JMP


<s> bool BPFInstrInfo :: analyzeBranch ( MachineBasicBlock & MBB , MachineBasicBlock * & TBB , MachineBasicBlock * & FBB , SmallVectorImpl < MachineOperand > & Cond , bool AllowModify ) const { MachineBasicBlock :: iterator I = MBB . end ( ) ; while ( I != MBB . begin ( ) ) { -- I ; if ( I -> isDebugInstr ( ) ) continue ; if ( ! isUnpredicatedTerminator ( * I ) ) break ; if ( ! I -> isBranch ( ) ) return true ; if ( I -> getOpcode ( ) == BPF :: JMP ) { if ( ! AllowModify ) { TBB = I -> getOperand ( 0 ) . getMBB ( ) ; continue ; } while ( std :: next ( I ) != MBB . end ( ) ) std :: next ( I ) -> eraseFromParent ( ) ; Cond . clear ( ) ; FBB = nullptr ; if ( MBB . isLayoutSuccessor ( I -> getOperand ( 0 ) . getMBB ( ) ) ) { TBB = nullptr ; I -> eraseFromParent ( ) ; I = MBB . end ( ) ; continue ; } TBB = I -> getOperand ( 0 ) . getMBB ( ) ; continue ; } return true ; } return false ; } </s>


<s>
void
BPFInstrInfo
::
copyPhysReg
(
MachineBasicBlock
&
MBB
,
MachineBasicBlock
::
iterator
I
,
const
DebugLoc
&
DL
,
unsigned
DestReg
,
unsigned
SrcReg
,
bool
KillSrc
)
const
{
if
(
BPF
::
GPRRegClass
.
contains
(
DestReg
,
SrcReg
)
)
BuildMI
(
MBB
,
I
,
DL
,
get
(
BPF
::
MOV_rr
)
,
DestReg
)
.
addReg
(
SrcReg
,
getKillRegState
(
KillSrc
)
)
;
else
if
(
BPF
::
GPR32RegClass
.
contains
(
DestReg
,
SrcReg
)
)
BuildMI
(
MBB
,
I
,
DL
,
get
(
BPF
::
MOV_rr_32
)
,
DestReg
)
.
addReg
(
SrcReg
,
getKillRegState
(
KillSrc
)
)
;
else
llvm_unreachable
(
"Impossible reg-to-reg copy"
)
;
}
</s>


<s> virtual const BPFRegisterInfo & getRegisterInfo ( ) const { return RI ; } </s>

getRegisterInfo - TargetInstrInfo is a superset of MRegister info .


"Can't load this register from stack slot"

Load the specified register of the given register class from the specified stack frame index .


<s>
unsigned
BPFInstrInfo
::
removeBranch
(
MachineBasicBlock
&
MBB
,
int
*
BytesRemoved
)
const
{
assert
(
!
BytesRemoved
&&
"code size not handled"
)
;
MachineBasicBlock
::
iterator
I
=
MBB
.
end
(
)
;
unsigned
Count
=
0
;
while
(
I
!=
MBB
.
begin
(
)
)
{
I
;
if
(
I
->
isDebugInstr
(
)
)
continue
;
if
(
I
->
getOpcode
(
)
!=
BPF
::
JMP
)
break
;
I
->
eraseFromParent
(
)
;
I
=
MBB
.
end
(
)
;
++
Count
;
}
return
Count
;
}
</s>


"Can't store this register to stack slot"

Store the specified register of the given register class to the specified stack frame index .


<s>
void
BPFInstrInfo
::
copyPhysReg
(
MachineBasicBlock
&
MBB
,
MachineBasicBlock
::
iterator
I
,
const
DebugLoc
&
DL
,
MCRegister
DestReg
,
MCRegister
SrcReg
,
bool
KillSrc
)
const
{
if
(
BPF
::
GPRRegClass
.
contains
(
DestReg
,
SrcReg
)
)
BuildMI
(
MBB
,
I
,
DL
,
get
(
BPF
::
MOV_rr
)
,
DestReg
)
.
addReg
(
SrcReg
,
getKillRegState
(
KillSrc
)
)
;
else
if
(
BPF
::
GPR32RegClass
.
contains
(
DestReg
,
SrcReg
)
)
BuildMI
(
MBB
,
I
,
DL
,
get
(
BPF
::
MOV_rr_32
)
,
DestReg
)
.
addReg
(
SrcReg
,
getKillRegState
(
KillSrc
)
)
;
else
llvm_unreachable
(
"Impossible reg-to-reg copy"
)
;
}
</s>


<s> bool BPFInstrInfo :: expandPostRAPseudo ( MachineInstr & MI ) const { if ( MI . getOpcode ( ) == BPF :: MEMCPY ) { expandMEMCPY ( MI ) ; return true ; } return false ; } </s>

This function is called for all pseudo instructions that remain after register allocation .


<s>
void
BPFInstrInfo
::
copyPhysReg
(
MachineBasicBlock
&
MBB
,
MachineBasicBlock
::
iterator
I
,
DebugLoc
DL
,
unsigned
DestReg
,
unsigned
SrcReg
,
bool
KillSrc
)
const
{
if
(
BPF
::
GPRRegClass
.
contains
(
DestReg
,
SrcReg
)
)
BuildMI
(
MBB
,
I
,
DL
,
get
(
BPF
::
MOV_rr
)
,
DestReg
)
.
addReg
(
SrcReg
,
getKillRegState
(
KillSrc
)
)
;
else
llvm_unreachable
(
"Impossible reg-to-reg copy"
)
;
}
</s>

BPF
BPF
BPF::GPRRegClass
BPF::MOV_rr
"Impossible reg-to-reg copy"


<s> bool BPFInstrInfo :: analyzeBranch ( MachineBasicBlock & MBB , MachineBasicBlock * & TBB , MachineBasicBlock * & FBB , SmallVectorImpl < MachineOperand > & Cond , bool AllowModify ) const { MachineBasicBlock :: iterator I = MBB . end ( ) ; while ( I != MBB . begin ( ) ) { -- I ; if ( I -> isDebugValue ( ) ) continue ; if ( ! isUnpredicatedTerminator ( * I ) ) break ; if ( ! I -> isBranch ( ) ) return true ; if ( I -> getOpcode ( ) == BPF :: JMP ) { if ( ! AllowModify ) { TBB = I -> getOperand ( 0 ) . getMBB ( ) ; continue ; } while ( std :: next ( I ) != MBB . end ( ) ) std :: next ( I ) -> eraseFromParent ( ) ; Cond . clear ( ) ; FBB = 0 ; if ( MBB . isLayoutSuccessor ( I -> getOperand ( 0 ) . getMBB ( ) ) ) { TBB = 0 ; I -> eraseFromParent ( ) ; I = MBB . end ( ) ; continue ; } TBB = I -> getOperand ( 0 ) . getMBB ( ) ; continue ; } return true ; } return false ; } </s>


<s>
void
BPFInstrInfo
::
copyPhysReg
(
MachineBasicBlock
&
MBB
,
MachineBasicBlock
::
iterator
I
,
const
DebugLoc
&
DL
,
unsigned
DestReg
,
unsigned
SrcReg
,
bool
KillSrc
)
const
{
if
(
BPF
::
GPRRegClass
.
contains
(
DestReg
,
SrcReg
)
)
BuildMI
(
MBB
,
I
,
DL
,
get
(
BPF
::
MOV_rr
)
,
DestReg
)
.
addReg
(
SrcReg
,
getKillRegState
(
KillSrc
)
)
;
else
llvm_unreachable
(
"Impossible reg-to-reg copy"
)
;
}
</s>


<s> const BPFRegisterInfo & getRegisterInfo ( ) const { return RI ; } </s>


<s> PreservedAnalyses BPFIRPeepholePass :: run ( Function & F , FunctionAnalysisManager & AM ) { return BPFIRPeepholeImpl ( F ) ? PreservedAnalyses :: none ( ) : PreservedAnalyses :: all ( ) ; } </s>

Run the analysis pass over a function and produce a dominator tree .


<s> bool BPFIRPeephole :: runOnFunction ( Function & F ) { return BPFIRPeepholeImpl ( F ) ; } </s>

runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass .


<s> void BPFDAGToDAGISel :: PreprocessISelDAG ( ) { for ( SelectionDAG :: allnodes_iterator I = CurDAG -> allnodes_begin ( ) , E = CurDAG -> allnodes_end ( ) ; I != E ; ) { SDNode * Node = & * I ++ ; unsigned Opcode = Node -> getOpcode ( ) ; if ( Opcode == ISD :: LOAD ) PreprocessLoad ( Node , I ) ; else if ( Opcode == ISD :: AND ) PreprocessTrunc ( Node , I ) ; } } </s>

PreprocessISelDAG - This hook allows targets to hack on the graph before instruction selection starts .


<s> bool runOnMachineFunction ( MachineFunction & MF ) override { Subtarget = & MF . getSubtarget < BPFSubtarget > ( ) ; return SelectionDAGISel :: runOnMachineFunction ( MF ) ; } </s>

runOnMachineFunction - Emit the function body .


<s>
void
BPFDAGToDAGISel
::
Select
(
SDNode
*
Node
)
{
unsigned
Opcode
=
Node
->
getOpcode
(
)
;
if
(
Node
->
isMachineOpcode
(
)
)
{
LLVM_DEBUG
(
dbgs
(
)
<<
"== "
;
Node
->
dump
(
CurDAG
)
;
dbgs
(
)
<<
'\n'
)
;
return
;
}
switch
(
Opcode
)
{
default
:
break
;
case
ISD
::
SDIV
:
{
DebugLoc
Empty
;
const
DebugLoc
&
DL
=
Node
->
getDebugLoc
(
)
;
if
(
DL
!=
Empty
)
errs
(
)
<<
"Error at line "
<<
DL
.
getLine
(
)
<<
": "
;
else
errs
(
)
<<
"Error: "
;
errs
(
)
<<
"Unsupport signed division for DAG: "
;
Node
->
print
(
errs
(
)
,
CurDAG
)
;
errs
(
)
<<
"Please convert to unsigned div/mod.\n"
;
break
;
}
case
ISD
::
INTRINSIC_W_CHAIN
:
{
unsigned
IntNo
=
cast
<
ConstantSDNode
>
(
Node
->
getOperand
(
1
)
)
->
getZExtValue
(
)
;
switch
(
IntNo
)
{
case
Intrinsic
::
bpf_load_byte
:
case
Intrinsic
::
bpf_load_half
:
case
Intrinsic
::
bpf_load_word
:
{
SDLoc
DL
(
Node
)
;
SDValue
Chain
=
Node
->
getOperand
(
0
)
;
SDValue
N1
=
Node
->
getOperand
(
1
)
;
SDValue
Skb
=
Node
->
getOperand
(
2
)
;
SDValue
N3
=
Node
->
getOperand
(
3
)
;
SDValue
R6Reg
=
CurDAG
->
getRegister
(
BPF
::
R6
,
MVT
::
i64
)
;
Chain
=
CurDAG
->
getCopyToReg
(
Chain
,
DL
,
R6Reg
,
Skb
,
SDValue
(
)
)
;
Node
=
CurDAG
->
UpdateNodeOperands
(
Node
,
Chain
,
N1
,
R6Reg
,
N3
)
;
break
;
}
}
break
;
}
case
ISD
::
FrameIndex
:
{
int
FI
=
cast
<
FrameIndexSDNode
>
(
Node
)
->
getIndex
(
)
;
EVT
VT
=
Node
->
getValueType
(
0
)
;
SDValue
TFI
=
CurDAG
->
getTargetFrameIndex
(
FI
,
VT
)
;
unsigned
Opc
=
BPF
::
MOV_rr
;
if
(
Node
->
hasOneUse
(
)
)
{
CurDAG
->
SelectNodeTo
(
Node
,
Opc
,
VT
,
TFI
)
;
return
;
}
ReplaceNode
(
Node
,
CurDAG
->
getMachineNode
(
Opc
,
SDLoc
(
Node
)
,
VT
,
TFI
)
)
;
return
;
}
}
SelectCode
(
Node
)
;
}
</s>

Main hook for targets to transform nodes into machine nodes .


<s>
void
BPFDAGToDAGISel
::
Select
(
SDNode
*
Node
)
{
unsigned
Opcode
=
Node
->
getOpcode
(
)
;
if
(
Node
->
isMachineOpcode
(
)
)
{
DEBUG
(
dbgs
(
)
<<
"== "
;
Node
->
dump
(
CurDAG
)
;
dbgs
(
)
<<
'\n'
)
;
return
;
}
switch
(
Opcode
)
{
default
:
break
;
case
ISD
::
SDIV
:
{
DebugLoc
Empty
;
const
DebugLoc
&
DL
=
Node
->
getDebugLoc
(
)
;
if
(
DL
!=
Empty
)
errs
(
)
<<
"Error at line "
<<
DL
.
getLine
(
)
<<
": "
;
else
errs
(
)
<<
"Error: "
;
errs
(
)
<<
"Unsupport signed division for DAG: "
;
Node
->
print
(
errs
(
)
,
CurDAG
)
;
errs
(
)
<<
"Please convert to unsigned div/mod.\n"
;
break
;
}
case
ISD
::
INTRINSIC_W_CHAIN
:
{
unsigned
IntNo
=
cast
<
ConstantSDNode
>
(
Node
->
getOperand
(
1
)
)
->
getZExtValue
(
)
;
switch
(
IntNo
)
{
case
Intrinsic
::
bpf_load_byte
:
case
Intrinsic
::
bpf_load_half
:
case
Intrinsic
::
bpf_load_word
:
{
SDLoc
DL
(
Node
)
;
SDValue
Chain
=
Node
->
getOperand
(
0
)
;
SDValue
N1
=
Node
->
getOperand
(
1
)
;
SDValue
Skb
=
Node
->
getOperand
(
2
)
;
SDValue
N3
=
Node
->
getOperand
(
3
)
;
SDValue
R6Reg
=
CurDAG
->
getRegister
(
BPF
::
R6
,
MVT
::
i64
)
;
Chain
=
CurDAG
->
getCopyToReg
(
Chain
,
DL
,
R6Reg
,
Skb
,
SDValue
(
)
)
;
Node
=
CurDAG
->
UpdateNodeOperands
(
Node
,
Chain
,
N1
,
R6Reg
,
N3
)
;
break
;
}
}
break
;
}
case
ISD
::
FrameIndex
:
{
int
FI
=
cast
<
FrameIndexSDNode
>
(
Node
)
->
getIndex
(
)
;
EVT
VT
=
Node
->
getValueType
(
0
)
;
SDValue
TFI
=
CurDAG
->
getTargetFrameIndex
(
FI
,
VT
)
;
unsigned
Opc
=
BPF
::
MOV_rr
;
if
(
Node
->
hasOneUse
(
)
)
{
CurDAG
->
SelectNodeTo
(
Node
,
Opc
,
VT
,
TFI
)
;
return
;
}
ReplaceNode
(
Node
,
CurDAG
->
getMachineNode
(
Opc
,
SDLoc
(
Node
)
,
VT
,
TFI
)
)
;
return
;
}
}
SelectCode
(
Node
)
;
}
</s>


<s>
void
BPFDAGToDAGISel
::
Select
(
SDNode
*
Node
)
{
unsigned
Opcode
=
Node
->
getOpcode
(
)
;
DEBUG
(
dbgs
(
)
<<
"Selecting: "
;
Node
->
dump
(
CurDAG
)
;
dbgs
(
)
<<
'\n'
)
;
if
(
Node
->
isMachineOpcode
(
)
)
{
DEBUG
(
dbgs
(
)
<<
"== "
;
Node
->
dump
(
CurDAG
)
;
dbgs
(
)
<<
'\n'
)
;
return
;
}
switch
(
Opcode
)
{
default
:
break
;
case
ISD
::
SDIV
:
{
DebugLoc
Empty
;
const
DebugLoc
&
DL
=
Node
->
getDebugLoc
(
)
;
if
(
DL
!=
Empty
)
errs
(
)
<<
"Error at line "
<<
DL
.
getLine
(
)
<<
": "
;
else
errs
(
)
<<
"Error: "
;
errs
(
)
<<
"Unsupport signed division for DAG: "
;
Node
->
print
(
errs
(
)
,
CurDAG
)
;
errs
(
)
<<
"Please convert to unsigned div/mod.\n"
;
break
;
}
case
ISD
::
INTRINSIC_W_CHAIN
:
{
unsigned
IntNo
=
cast
<
ConstantSDNode
>
(
Node
->
getOperand
(
1
)
)
->
getZExtValue
(
)
;
switch
(
IntNo
)
{
case
Intrinsic
::
bpf_load_byte
:
case
Intrinsic
::
bpf_load_half
:
case
Intrinsic
::
bpf_load_word
:
{
SDLoc
DL
(
Node
)
;
SDValue
Chain
=
Node
->
getOperand
(
0
)
;
SDValue
N1
=
Node
->
getOperand
(
1
)
;
SDValue
Skb
=
Node
->
getOperand
(
2
)
;
SDValue
N3
=
Node
->
getOperand
(
3
)
;
SDValue
R6Reg
=
CurDAG
->
getRegister
(
BPF
::
R6
,
MVT
::
i64
)
;
Chain
=
CurDAG
->
getCopyToReg
(
Chain
,
DL
,
R6Reg
,
Skb
,
SDValue
(
)
)
;
Node
=
CurDAG
->
UpdateNodeOperands
(
Node
,
Chain
,
N1
,
R6Reg
,
N3
)
;
break
;
}
}
break
;
}
case
ISD
::
FrameIndex
:
{
int
FI
=
cast
<
FrameIndexSDNode
>
(
Node
)
->
getIndex
(
)
;
EVT
VT
=
Node
->
getValueType
(
0
)
;
SDValue
TFI
=
CurDAG
->
getTargetFrameIndex
(
FI
,
VT
)
;
unsigned
Opc
=
BPF
::
MOV_rr
;
if
(
Node
->
hasOneUse
(
)
)
{
CurDAG
->
SelectNodeTo
(
Node
,
Opc
,
VT
,
TFI
)
;
return
;
}
ReplaceNode
(
Node
,
CurDAG
->
getMachineNode
(
Opc
,
SDLoc
(
Node
)
,
VT
,
TFI
)
)
;
return
;
}
}
SelectCode
(
Node
)
;
}
</s>


<s> void BPFDAGToDAGISel :: PreprocessISelDAG ( ) { if ( ! curr_func_ ) { curr_func_ = FuncInfo -> Fn ; } else if ( curr_func_ != FuncInfo -> Fn ) { load_to_vreg_ . clear ( ) ; curr_func_ = FuncInfo -> Fn ; } for ( SelectionDAG :: allnodes_iterator I = CurDAG -> allnodes_begin ( ) , E = CurDAG -> allnodes_end ( ) ; I != E ; ) { SDNode * Node = & * I ++ ; unsigned Opcode = Node -> getOpcode ( ) ; if ( Opcode == ISD :: LOAD ) PreprocessLoad ( Node , I ) ; else if ( Opcode == ISD :: CopyToReg ) PreprocessCopyToReg ( Node ) ; else if ( Opcode == ISD :: AND ) PreprocessTrunc ( Node , I ) ; } } </s>

BPF BPF ISD::LOAD ISD::CopyToReg ISD::AND


<s> bool BPFDAGToDAGISel :: SelectInlineAsmMemoryOperand ( const SDValue & Op , unsigned ConstraintCode , std :: vector < SDValue > & OutOps ) { SDValue Op0 , Op1 ; switch ( ConstraintCode ) { default : return true ; case InlineAsm :: Constraint_m : if ( ! SelectAddr ( Op , Op0 , Op1 ) ) return true ; break ; } SDLoc DL ( Op ) ; SDValue AluOp = CurDAG -> getTargetConstant ( ISD :: ADD , DL , MVT :: i32 ) ; ; OutOps . push_back ( Op0 ) ; OutOps . push_back ( Op1 ) ; OutOps . push_back ( AluOp ) ; return false ; } </s>

SelectInlineAsmMemoryOperand - Select the specified address as a target addressing mode , according to the specified constraint .


<s> void BPFDAGToDAGISel :: PreprocessISelDAG ( ) { for ( SelectionDAG :: allnodes_iterator I = CurDAG -> allnodes_begin ( ) , E = CurDAG -> allnodes_end ( ) ; I != E ; ) { SDNode * Node = & * I ++ ; unsigned Opcode = Node -> getOpcode ( ) ; if ( Opcode == ISD :: LOAD ) PreprocessLoad ( Node , I ) ; else if ( Opcode == ISD :: CopyToReg ) PreprocessCopyToReg ( Node ) ; else if ( Opcode == ISD :: AND ) PreprocessTrunc ( Node , I ) ; } } </s>


"BPF DAG->DAG Pattern Instruction Selection"

getPassName - Return a nice clean name for a pass .


<s>
SDNode
*
BPFDAGToDAGISel
::
Select
(
SDNode
*
Node
)
{
unsigned
Opcode
=
Node
->
getOpcode
(
)
;
DEBUG
(
dbgs
(
)
<<
"Selecting: "
;
Node
->
dump
(
CurDAG
)
;
dbgs
(
)
<<
'\n'
)
;
if
(
Node
->
isMachineOpcode
(
)
)
{
DEBUG
(
dbgs
(
)
<<
"== "
;
Node
->
dump
(
CurDAG
)
;
dbgs
(
)
<<
'\n'
)
;
return
;
}
switch
(
Opcode
)
{
default
:
break
;
case
ISD
::
INTRINSIC_W_CHAIN
:
{
unsigned
IntNo
=
cast
<
ConstantSDNode
>
(
Node
->
getOperand
(
1
)
)
->
getZExtValue
(
)
;
switch
(
IntNo
)
{
case
Intrinsic
::
bpf_load_byte
:
case
Intrinsic
::
bpf_load_half
:
case
Intrinsic
::
bpf_load_word
:
{
SDLoc
DL
(
Node
)
;
SDValue
Chain
=
Node
->
getOperand
(
0
)
;
SDValue
N1
=
Node
->
getOperand
(
1
)
;
SDValue
Skb
=
Node
->
getOperand
(
2
)
;
SDValue
N3
=
Node
->
getOperand
(
3
)
;
SDValue
R6Reg
=
CurDAG
->
getRegister
(
BPF
::
R6
,
MVT
::
i64
)
;
Chain
=
CurDAG
->
getCopyToReg
(
Chain
,
DL
,
R6Reg
,
Skb
,
SDValue
(
)
)
;
Node
=
CurDAG
->
UpdateNodeOperands
(
Node
,
Chain
,
N1
,
R6Reg
,
N3
)
;
break
;
}
}
break
;
}
case
ISD
::
FrameIndex
:
{
int
FI
=
cast
<
FrameIndexSDNode
>
(
Node
)
->
getIndex
(
)
;
EVT
VT
=
Node
->
getValueType
(
0
)
;
SDValue
TFI
=
CurDAG
->
getTargetFrameIndex
(
FI
,
VT
)
;
unsigned
Opc
=
BPF
::
MOV_rr
;
if
(
Node
->
hasOneUse
(
)
)
return
CurDAG
->
SelectNodeTo
(
Node
,
Opc
,
VT
,
TFI
)
;
return
CurDAG
->
getMachineNode
(
Opc
,
SDLoc
(
Node
)
,
VT
,
TFI
)
;
}
}
SDNode
*
ResNode
=
SelectCode
(
Node
)
;
DEBUG
(
dbgs
(
)
<<
"=> "
;
if
(
ResNode
==
nullptr
||
ResNode
==
Node
)
Node
->
dump
(
CurDAG
)
;
else
ResNode
->
dump
(
CurDAG
)
;
dbgs
(
)
<<
'\n'
)
;
return
ResNode
;
}
</s>


<s>
void
BPFDAGToDAGISel
::
Select
(
SDNode
*
Node
)
{
unsigned
Opcode
=
Node
->
getOpcode
(
)
;
DEBUG
(
dbgs
(
)
<<
"Selecting: "
;
Node
->
dump
(
CurDAG
)
;
dbgs
(
)
<<
'\n'
)
;
if
(
Node
->
isMachineOpcode
(
)
)
{
DEBUG
(
dbgs
(
)
<<
"== "
;
Node
->
dump
(
CurDAG
)
;
dbgs
(
)
<<
'\n'
)
;
return
;
}
switch
(
Opcode
)
{
default
:
break
;
case
ISD
::
SDIV
:
{
DebugLoc
Empty
;
const
DebugLoc
&
DL
=
Node
->
getDebugLoc
(
)
;
if
(
DL
!=
Empty
)
errs
(
)
<<
"Error at line "
<<
DL
.
getLine
(
)
<<
": "
;
else
errs
(
)
<<
"Error: "
;
errs
(
)
<<
"Unsupport signed division for DAG: "
;
Node
->
dump
(
CurDAG
)
;
errs
(
)
<<
"Please convert to unsigned div/mod.\n"
;
break
;
}
case
ISD
::
INTRINSIC_W_CHAIN
:
{
unsigned
IntNo
=
cast
<
ConstantSDNode
>
(
Node
->
getOperand
(
1
)
)
->
getZExtValue
(
)
;
switch
(
IntNo
)
{
case
Intrinsic
::
bpf_load_byte
:
case
Intrinsic
::
bpf_load_half
:
case
Intrinsic
::
bpf_load_word
:
{
SDLoc
DL
(
Node
)
;
SDValue
Chain
=
Node
->
getOperand
(
0
)
;
SDValue
N1
=
Node
->
getOperand
(
1
)
;
SDValue
Skb
=
Node
->
getOperand
(
2
)
;
SDValue
N3
=
Node
->
getOperand
(
3
)
;
SDValue
R6Reg
=
CurDAG
->
getRegister
(
BPF
::
R6
,
MVT
::
i64
)
;
Chain
=
CurDAG
->
getCopyToReg
(
Chain
,
DL
,
R6Reg
,
Skb
,
SDValue
(
)
)
;
Node
=
CurDAG
->
UpdateNodeOperands
(
Node
,
Chain
,
N1
,
R6Reg
,
N3
)
;
break
;
}
}
break
;
}
case
ISD
::
FrameIndex
:
{
int
FI
=
cast
<
FrameIndexSDNode
>
(
Node
)
->
getIndex
(
)
;
EVT
VT
=
Node
->
getValueType
(
0
)
;
SDValue
TFI
=
CurDAG
->
getTargetFrameIndex
(
FI
,
VT
)
;
unsigned
Opc
=
BPF
::
MOV_rr
;
if
(
Node
->
hasOneUse
(
)
)
{
CurDAG
->
SelectNodeTo
(
Node
,
Opc
,
VT
,
TFI
)
;
return
;
}
ReplaceNode
(
Node
,
CurDAG
->
getMachineNode
(
Opc
,
SDLoc
(
Node
)
,
VT
,
TFI
)
)
;
return
;
}
}
SelectCode
(
Node
)
;
}
</s>


<s>
SDNode
*
BPFDAGToDAGISel
::
Select
(
SDNode
*
Node
)
{
unsigned
Opcode
=
Node
->
getOpcode
(
)
;
DEBUG
(
dbgs
(
)
<<
"Selecting: "
;
Node
->
dump
(
CurDAG
)
;
dbgs
(
)
<<
'\n'
)
;
if
(
Node
->
isMachineOpcode
(
)
)
{
DEBUG
(
dbgs
(
)
<<
"== "
;
Node
->
dump
(
CurDAG
)
;
dbgs
(
)
<<
'\n'
)
;
return
;
}
switch
(
Opcode
)
{
default
:
break
;
case
ISD
::
UNDEF
:
{
errs
(
)
<<
"BUG: "
;
Node
->
dump
(
CurDAG
)
;
errs
(
)
<<
'\n'
;
report_fatal_error
(
"shouldn't see UNDEF during Select"
)
;
break
;
}
case
ISD
::
INTRINSIC_W_CHAIN
:
{
unsigned
IntNo
=
cast
<
ConstantSDNode
>
(
Node
->
getOperand
(
1
)
)
->
getZExtValue
(
)
;
switch
(
IntNo
)
{
case
Intrinsic
::
bpf_load_byte
:
case
Intrinsic
::
bpf_load_half
:
case
Intrinsic
::
bpf_load_word
:
{
SDLoc
DL
(
Node
)
;
SDValue
Chain
=
Node
->
getOperand
(
0
)
;
SDValue
N1
=
Node
->
getOperand
(
1
)
;
SDValue
Skb
=
Node
->
getOperand
(
2
)
;
SDValue
N3
=
Node
->
getOperand
(
3
)
;
SDValue
R6Reg
=
CurDAG
->
getRegister
(
BPF
::
R6
,
MVT
::
i64
)
;
Chain
=
CurDAG
->
getCopyToReg
(
Chain
,
DL
,
R6Reg
,
Skb
,
SDValue
(
)
)
;
Node
=
CurDAG
->
UpdateNodeOperands
(
Node
,
Chain
,
N1
,
R6Reg
,
N3
)
;
break
;
}
}
break
;
}
case
ISD
::
FrameIndex
:
{
int
FI
=
cast
<
FrameIndexSDNode
>
(
Node
)
->
getIndex
(
)
;
EVT
VT
=
Node
->
getValueType
(
0
)
;
SDValue
TFI
=
CurDAG
->
getTargetFrameIndex
(
FI
,
VT
)
;
unsigned
Opc
=
BPF
::
MOV_rr
;
if
(
Node
->
hasOneUse
(
)
)
return
CurDAG
->
SelectNodeTo
(
Node
,
Opc
,
VT
,
TFI
)
;
return
CurDAG
->
getMachineNode
(
Opc
,
SDLoc
(
Node
)
,
VT
,
TFI
)
;
}
}
SDNode
*
ResNode
=
SelectCode
(
Node
)
;
DEBUG
(
dbgs
(
)
<<
"=> "
;
if
(
ResNode
==
nullptr
||
ResNode
==
Node
)
Node
->
dump
(
CurDAG
)
;
else
ResNode
->
dump
(
CurDAG
)
;
dbgs
(
)
<<
'\n'
)
;
return
ResNode
;
}
</s>


<s> const BPFInstrInfo * getInstrInfo ( ) { return getTargetMachine ( ) . getInstrInfo ( ) ; } </s>


<s> const BPFTargetMachine & getTargetMachine ( ) { return static_cast < const BPFTargetMachine & > ( TM ) ; } </s>

Return the target machine ( if available ) .


<s>
SDNode
*
BPFDAGToDAGISel
::
Select
(
SDNode
*
Node
)
{
unsigned
Opcode
=
Node
->
getOpcode
(
)
;
DEBUG
(
errs
(
)
<<
"Selecting: "
;
Node
->
dump
(
CurDAG
)
;
errs
(
)
<<
"\n"
)
;
if
(
Node
->
isMachineOpcode
(
)
)
{
DEBUG
(
errs
(
)
<<
"== "
;
Node
->
dump
(
CurDAG
)
;
errs
(
)
<<
"\n"
)
;
return
;
}
switch
(
Opcode
)
{
default
:
break
;
case
ISD
::
FrameIndex
:
{
int
FI
=
dyn_cast
<
FrameIndexSDNode
>
(
Node
)
->
getIndex
(
)
;
EVT
VT
=
Node
->
getValueType
(
0
)
;
SDValue
TFI
=
CurDAG
->
getTargetFrameIndex
(
FI
,
VT
)
;
unsigned
Opc
=
BPF
::
MOV_rr
;
if
(
Node
->
hasOneUse
(
)
)
return
CurDAG
->
SelectNodeTo
(
Node
,
Opc
,
VT
,
TFI
)
;
return
CurDAG
->
getMachineNode
(
Opc
,
SDLoc
(
Node
)
,
VT
,
TFI
)
;
return
CurDAG
->
getMachineNode
(
Opc
,
Node
->
getDebugLoc
(
)
,
VT
,
TFI
)
;
}
}
SDNode
*
ResNode
=
SelectCode
(
Node
)
;
DEBUG
(
errs
(
)
<<
"=> "
)
;
if
(
ResNode
==
||
ResNode
==
Node
)
DEBUG
(
Node
->
dump
(
CurDAG
)
)
;
else
DEBUG
(
ResNode
->
dump
(
CurDAG
)
)
;
DEBUG
(
errs
(
)
<<
"\n"
)
;
return
ResNode
;
}
</s>

BPF
BPF
"Selecting: "
"\n"
"== "
"\n"
ISD::FrameIndex
0
BPF::MOV_rr
"=> "
"\n"


<s>
SDNode
*
BPFDAGToDAGISel
::
Select
(
SDNode
*
Node
)
{
unsigned
Opcode
=
Node
->
getOpcode
(
)
;
DEBUG
(
dbgs
(
)
<<
"Selecting: "
;
Node
->
dump
(
CurDAG
)
;
dbgs
(
)
<<
'\n'
)
;
if
(
Node
->
isMachineOpcode
(
)
)
{
DEBUG
(
dbgs
(
)
<<
"== "
;
Node
->
dump
(
CurDAG
)
;
dbgs
(
)
<<
'\n'
)
;
return
;
}
switch
(
Opcode
)
{
default
:
break
;
case
ISD
::
UNDEF
:
{
errs
(
)
<<
"BUG: "
;
Node
->
dump
(
CurDAG
)
;
errs
(
)
<<
'\n'
;
report_fatal_error
(
"shouldn't see UNDEF during Select"
)
;
break
;
}
case
ISD
::
INTRINSIC_W_CHAIN
:
{
unsigned
IntNo
=
cast
<
ConstantSDNode
>
(
Node
->
getOperand
(
1
)
)
->
getZExtValue
(
)
;
switch
(
IntNo
)
{
case
Intrinsic
::
bpf_load_byte
:
case
Intrinsic
::
bpf_load_half
:
case
Intrinsic
::
bpf_load_word
:
{
SDLoc
DL
(
Node
)
;
SDValue
Chain
=
Node
->
getOperand
(
0
)
;
SDValue
N1
=
Node
->
getOperand
(
1
)
;
SDValue
Skb
=
Node
->
getOperand
(
2
)
;
SDValue
N3
=
Node
->
getOperand
(
3
)
;
SDValue
R6Reg
=
CurDAG
->
getRegister
(
BPF
::
R6
,
MVT
::
i64
)
;
Chain
=
CurDAG
->
getCopyToReg
(
Chain
,
DL
,
R6Reg
,
Skb
,
SDValue
(
)
)
;
Node
=
CurDAG
->
UpdateNodeOperands
(
Node
,
Chain
,
N1
,
R6Reg
,
N3
)
;
break
;
}
}
break
;
}
case
ISD
::
FrameIndex
:
{
int
FI
=
dyn_cast
<
FrameIndexSDNode
>
(
Node
)
->
getIndex
(
)
;
EVT
VT
=
Node
->
getValueType
(
0
)
;
SDValue
TFI
=
CurDAG
->
getTargetFrameIndex
(
FI
,
VT
)
;
unsigned
Opc
=
BPF
::
MOV_rr
;
if
(
Node
->
hasOneUse
(
)
)
return
CurDAG
->
SelectNodeTo
(
Node
,
Opc
,
VT
,
TFI
)
;
return
CurDAG
->
getMachineNode
(
Opc
,
SDLoc
(
Node
)
,
VT
,
TFI
)
;
}
}
SDNode
*
ResNode
=
SelectCode
(
Node
)
;
DEBUG
(
dbgs
(
)
<<
"=> "
;
if
(
ResNode
==
nullptr
||
ResNode
==
Node
)
Node
->
dump
(
CurDAG
)
;
else
ResNode
->
dump
(
CurDAG
)
;
dbgs
(
)
<<
'\n'
)
;
return
ResNode
;
}
</s>


<s> static bool classof ( const DiagnosticInfo * DI ) { return DI -> getKind ( ) == getKindID ( ) ; } </s>

Methods for support type inquiry through isa , cast , and dyn_cast :


<s> DiagnosticInfoUnsupported ( SDLoc DLoc , const Function & Fn , const Twine & Desc , SDValue Value ) : DiagnosticInfo ( getKindID ( ) , DS_Error ) , DLoc ( DLoc . getDebugLoc ( ) ) , Description ( Desc ) , Fn ( Fn ) , Value ( Value ) { } </s>

Fn is the function where the diagnostic is being emitted .


<s> EVT getOptimalMemOpType ( uint64_t Size , unsigned DstAlign , unsigned SrcAlign , bool IsMemset , bool ZeroMemset , bool MemcpyStrSrc , MachineFunction & MF ) const override { return Size >= 8 ? MVT :: i64 : MVT :: i32 ; } </s>

It returns EVT : :Other if the type should be determined using generic target-independent logic .


<s> const char * BPFTargetLowering :: getTargetNodeName ( unsigned Opcode ) const { switch ( ( BPFISD :: NodeType ) Opcode ) { case BPFISD :: FIRST_NUMBER : break ; case BPFISD :: RET_FLAG : return "BPFISD::RET_FLAG" ; case BPFISD :: CALL : return "BPFISD::CALL" ; case BPFISD :: SELECT_CC : return "BPFISD::SELECT_CC" ; case BPFISD :: BR_CC : return "BPFISD::BR_CC" ; case BPFISD :: Wrapper : return "BPFISD::Wrapper" ; } return nullptr ; } </s>

getTargetNodeName - This method returns the name of a target specific


<s>
SDValue
BPFTargetLowering
::
LowerCallResult
(
SDValue
Chain
,
SDValue
InFlag
,
CallingConv
::
ID
CallConv
,
bool
IsVarArg
,
const
SmallVectorImpl
<
ISD
::
InputArg
>
&
Ins
,
SDLoc
DL
,
SelectionDAG
&
DAG
,
SmallVectorImpl
<
SDValue
>
&
InVals
)
const
{
MachineFunction
&
MF
=
DAG
.
getMachineFunction
(
)
;
SmallVector
<
CCValAssign
,
16
>
RVLocs
;
CCState
CCInfo
(
CallConv
,
IsVarArg
,
MF
,
RVLocs
,
*
DAG
.
getContext
(
)
)
;
if
(
Ins
.
size
(
)
>=
2
)
{
DiagnosticInfoUnsupported
Err
(
DL
,
*
MF
.
getFunction
(
)
,
"only small returns supported"
,
SDValue
(
)
)
;
DAG
.
getContext
(
)
->
diagnose
(
Err
)
;
}
CCInfo
.
AnalyzeCallResult
(
Ins
,
RetCC_BPF64
)
;
for
(
auto
&
Val
:
RVLocs
)
{
Chain
=
DAG
.
getCopyFromReg
(
Chain
,
DL
,
Val
.
getLocReg
(
)
,
Val
.
getValVT
(
)
,
InFlag
)
.
getValue
(
1
)
;
InFlag
=
Chain
.
getValue
(
2
)
;
InVals
.
push_back
(
Chain
.
getValue
(
0
)
)
;
}
return
Chain
;
}
</s>

LowerCallResult - Lower the result values of an ISD : :CALL into the appropriate copies out of appropriate physical registers .


"LowerFormalArguments Unhandled argument type: "

"functions with VarArgs or StructRet are not supported"

This hook must be implemented to lower the incoming ( formal ) arguments , described by the Ins array , into the specified DAG .


<s>
SDValue
BPFTargetLowering
::
LowerOperation
(
SDValue
Op
,
SelectionDAG
&
DAG
)
const
{
switch
(
Op
.
getOpcode
(
)
)
{
case
ISD
::
BR_CC
:
return
LowerBR_CC
(
Op
,
DAG
)
;
case
ISD
::
GlobalAddress
:
return
LowerGlobalAddress
(
Op
,
DAG
)
;
case
ISD
::
SELECT_CC
:
return
LowerSELECT_CC
(
Op
,
DAG
)
;
default
:
llvm_unreachable
(
"unimplemented operand"
)
;
}
}
</s>

LowerOperation - Provide custom lowering hooks for some operations .

BPF
BPF
ISD::BR_CC
ISD::GlobalAddress
ISD::SELECT_CC
"unimplemented operand"


<s>
SDValue
BPFTargetLowering
::
LowerReturn
(
SDValue
Chain
,
CallingConv
::
ID
CallConv
,
bool
IsVarArg
,
const
SmallVectorImpl
<
ISD
::
OutputArg
>
&
Outs
,
const
SmallVectorImpl
<
SDValue
>
&
OutVals
,
SDLoc
DL
,
SelectionDAG
&
DAG
)
const
{
SmallVector
<
CCValAssign
,
16
>
RVLocs
;
MachineFunction
&
MF
=
DAG
.
getMachineFunction
(
)
;
CCState
CCInfo
(
CallConv
,
IsVarArg
,
MF
,
RVLocs
,
*
DAG
.
getContext
(
)
)
;
if
(
MF
.
getFunction
(
)
->
getReturnType
(
)
->
isAggregateType
(
)
)
{
DiagnosticInfoUnsupported
Err
(
DL
,
*
MF
.
getFunction
(
)
,
"only integer returns supported"
,
SDValue
(
)
)
;
DAG
.
getContext
(
)
->
diagnose
(
Err
)
;
}
CCInfo
.
AnalyzeReturn
(
Outs
,
RetCC_BPF64
)
;
SDValue
Flag
;
SmallVector
<
SDValue
,
4
>
RetOps
(
1
,
Chain
)
;
for
(
unsigned
i
=
0
;
i
!=
RVLocs
.
size
(
)
;
++
i
)
{
CCValAssign
&
VA
=
RVLocs
[
i
]
;
assert
(
VA
.
isRegLoc
(
)
&&
"Can only return in registers!"
)
;
Chain
=
DAG
.
getCopyToReg
(
Chain
,
DL
,
VA
.
getLocReg
(
)
,
OutVals
[
i
]
,
Flag
)
;
Flag
=
Chain
.
getValue
(
1
)
;
RetOps
.
push_back
(
DAG
.
getRegister
(
VA
.
getLocReg
(
)
,
VA
.
getLocVT
(
)
)
)
;
}
unsigned
Opc
=
BPFISD
::
RET_FLAG
;
RetOps
[
0
]
=
Chain
;
if
(
Flag
.
getNode
(
)
)
RetOps
.
push_back
(
Flag
)
;
return
DAG
.
getNode
(
Opc
,
DL
,
MVT
::
Other
,
RetOps
)
;
}
</s>

This hook must be implemented to lower outgoing return values , described by the Outs array , into the specified DAG .


<s>
void
print
(
DiagnosticPrinter
&
DP
)
const
override
{
std
::
string
Str
;
raw_string_ostream
OS
(
Str
)
;
if
(
DLoc
)
{
auto
DIL
=
DLoc
.
get
(
)
;
StringRef
Filename
=
DIL
->
getFilename
(
)
;
unsigned
Line
=
DIL
->
getLine
(
)
;
unsigned
Column
=
DIL
->
getColumn
(
)
;
OS
<<
Filename
<<
':'
<<
Line
<<
':'
<<
Column
<<
' '
;
}
OS
<<
"in function "
<<
Fn
.
getName
(
)
<<
' '
<<
*
Fn
.
getFunctionType
(
)
<<
'\n'
<<
Description
;
if
(
Value
)
Value
->
print
(
OS
)
;
OS
<<
'\n'
;
OS
.
flush
(
)
;
DP
<<
Str
;
}
</s>

print - Print a debug representation of the operand to the given stream .


<s> bool shouldConvertConstantLoadToIntImm ( const APInt & Imm , Type * Ty ) const override { return true ; } </s>

Returns true if it is beneficial to convert a load of a constant to just the constant itself .


<s> EVT getOptimalMemOpType ( const MemOp & Op , const AttributeList & FuncAttributes ) const override { return Op . size ( ) >= 8 ? MVT :: i64 : MVT :: i32 ; } </s>


<s> bool isIntDivCheap ( EVT VT , AttributeList Attr ) const override { return true ; } </s>

Return true if integer divide is usually cheaper than a sequence of several shifts , adds , and multiplies for this target .


<s>
SDValue
BPFTargetLowering
::
LowerCallResult
(
SDValue
Chain
,
SDValue
InFlag
,
CallingConv
::
ID
CallConv
,
bool
IsVarArg
,
const
SmallVectorImpl
<
ISD
::
InputArg
>
&
Ins
,
const
SDLoc
&
DL
,
SelectionDAG
&
DAG
,
SmallVectorImpl
<
SDValue
>
&
InVals
)
const
{
MachineFunction
&
MF
=
DAG
.
getMachineFunction
(
)
;
SmallVector
<
CCValAssign
,
16
>
RVLocs
;
CCState
CCInfo
(
CallConv
,
IsVarArg
,
MF
,
RVLocs
,
*
DAG
.
getContext
(
)
)
;
if
(
Ins
.
size
(
)
>=
2
)
{
fail
(
DL
,
DAG
,
"only small returns supported"
)
;
for
(
unsigned
i
=
0
,
e
=
Ins
.
size
(
)
;
i
!=
e
;
++
i
)
InVals
.
push_back
(
DAG
.
getConstant
(
0
,
DL
,
Ins
[
i
]
.
VT
)
)
;
return
DAG
.
getCopyFromReg
(
Chain
,
DL
,
1
,
Ins
[
0
]
.
VT
,
InFlag
)
.
getValue
(
1
)
;
}
CCInfo
.
AnalyzeCallResult
(
Ins
,
RetCC_BPF64
)
;
for
(
auto
&
Val
:
RVLocs
)
{
Chain
=
DAG
.
getCopyFromReg
(
Chain
,
DL
,
Val
.
getLocReg
(
)
,
Val
.
getValVT
(
)
,
InFlag
)
.
getValue
(
1
)
;
InFlag
=
Chain
.
getValue
(
2
)
;
InVals
.
push_back
(
Chain
.
getValue
(
0
)
)
;
}
return
Chain
;
}
</s>


<s>
SDValue
BPFTargetLowering
::
LowerReturn
(
SDValue
Chain
,
CallingConv
::
ID
CallConv
,
bool
IsVarArg
,
const
SmallVectorImpl
<
ISD
::
OutputArg
>
&
Outs
,
const
SmallVectorImpl
<
SDValue
>
&
OutVals
,
const
SDLoc
&
DL
,
SelectionDAG
&
DAG
)
const
{
unsigned
Opc
=
BPFISD
::
RET_FLAG
;
SmallVector
<
CCValAssign
,
16
>
RVLocs
;
MachineFunction
&
MF
=
DAG
.
getMachineFunction
(
)
;
CCState
CCInfo
(
CallConv
,
IsVarArg
,
MF
,
RVLocs
,
*
DAG
.
getContext
(
)
)
;
if
(
MF
.
getFunction
(
)
->
getReturnType
(
)
->
isAggregateType
(
)
)
{
fail
(
DL
,
DAG
,
"only integer returns supported"
)
;
return
DAG
.
getNode
(
Opc
,
DL
,
MVT
::
Other
,
Chain
)
;
}
CCInfo
.
AnalyzeReturn
(
Outs
,
RetCC_BPF64
)
;
SDValue
Flag
;
SmallVector
<
SDValue
,
4
>
RetOps
(
1
,
Chain
)
;
for
(
unsigned
i
=
0
;
i
!=
RVLocs
.
size
(
)
;
++
i
)
{
CCValAssign
&
VA
=
RVLocs
[
i
]
;
assert
(
VA
.
isRegLoc
(
)
&&
"Can only return in registers!"
)
;
Chain
=
DAG
.
getCopyToReg
(
Chain
,
DL
,
VA
.
getLocReg
(
)
,
OutVals
[
i
]
,
Flag
)
;
Flag
=
Chain
.
getValue
(
1
)
;
RetOps
.
push_back
(
DAG
.
getRegister
(
VA
.
getLocReg
(
)
,
VA
.
getLocVT
(
)
)
)
;
}
RetOps
[
0
]
=
Chain
;
if
(
Flag
.
getNode
(
)
)
RetOps
.
push_back
(
Flag
)
;
return
DAG
.
getNode
(
Opc
,
DL
,
MVT
::
Other
,
RetOps
)
;
}
</s>


<s> bool shouldReduceLoadWidth ( SDNode * Load , ISD :: LoadExtType ExtTy , EVT NewVT ) const override { return false ; } </s>

Return true if we believe it is correct and profitable to reduce the load node to a smaller type .


<s> const char * BPFTargetLowering :: getTargetNodeName ( unsigned Opcode ) const { switch ( Opcode ) { default : return NULL ; case BPFISD :: RET_FLAG : return "BPFISD::RET_FLAG" ; case BPFISD :: CALL : return "BPFISD::CALL" ; case BPFISD :: SELECT_CC : return "BPFISD::SELECT_CC" ; case BPFISD :: BR_CC : return "BPFISD::BR_CC" ; case BPFISD :: Wrapper : return "BPFISD::Wrapper" ; } } </s>


<s>
void
print
(
DiagnosticPrinter
&
DP
)
const
override
{
std
::
string
Str
;
raw_string_ostream
OS
(
Str
)
;
if
(
DLoc
.
isUnknown
(
)
==
false
)
{
DILocation
DIL
(
DLoc
.
getAsMDNode
(
Fn
.
getContext
(
)
)
)
;
StringRef
Filename
=
DIL
.
getFilename
(
)
;
unsigned
Line
=
DIL
.
getLineNumber
(
)
;
unsigned
Column
=
DIL
.
getColumnNumber
(
)
;
OS
<<
Filename
<<
':'
<<
Line
<<
':'
<<
Column
<<
' '
;
}
OS
<<
"in function "
<<
Fn
.
getName
(
)
<<
' '
<<
*
Fn
.
getFunctionType
(
)
<<
'\n'
<<
Description
;
if
(
Value
)
Value
->
print
(
OS
)
;
OS
<<
'\n'
;
OS
.
flush
(
)
;
DP
<<
Str
;
}
</s>


<s>
void
print
(
DiagnosticPrinter
&
DP
)
const
override
{
std
::
string
Str
;
raw_string_ostream
OS
(
Str
)
;
if
(
DLoc
)
{
DILocation
DIL
(
DLoc
.
getAsMDNode
(
)
)
;
StringRef
Filename
=
DIL
.
getFilename
(
)
;
unsigned
Line
=
DIL
.
getLineNumber
(
)
;
unsigned
Column
=
DIL
.
getColumnNumber
(
)
;
OS
<<
Filename
<<
':'
<<
Line
<<
':'
<<
Column
<<
' '
;
}
OS
<<
"in function "
<<
Fn
.
getName
(
)
<<
' '
<<
*
Fn
.
getFunctionType
(
)
<<
'\n'
<<
Description
;
if
(
Value
)
Value
->
print
(
OS
)
;
OS
<<
'\n'
;
OS
.
flush
(
)
;
DP
<<
Str
;
}
</s>


<s>
SDValue
BPFTargetLowering
::
LowerReturn
(
SDValue
Chain
,
CallingConv
::
ID
CallConv
,
bool
IsVarArg
,
const
SmallVectorImpl
<
ISD
::
OutputArg
>
&
Outs
,
const
SmallVectorImpl
<
SDValue
>
&
OutVals
,
const
SDLoc
&
DL
,
SelectionDAG
&
DAG
)
const
{
unsigned
Opc
=
BPFISD
::
RET_FLAG
;
SmallVector
<
CCValAssign
,
16
>
RVLocs
;
MachineFunction
&
MF
=
DAG
.
getMachineFunction
(
)
;
CCState
CCInfo
(
CallConv
,
IsVarArg
,
MF
,
RVLocs
,
*
DAG
.
getContext
(
)
)
;
if
(
MF
.
getFunction
(
)
.
getReturnType
(
)
->
isAggregateType
(
)
)
{
fail
(
DL
,
DAG
,
"only integer returns supported"
)
;
return
DAG
.
getNode
(
Opc
,
DL
,
MVT
::
Other
,
Chain
)
;
}
CCInfo
.
AnalyzeReturn
(
Outs
,
RetCC_BPF64
)
;
SDValue
Flag
;
SmallVector
<
SDValue
,
4
>
RetOps
(
1
,
Chain
)
;
for
(
unsigned
i
=
0
;
i
!=
RVLocs
.
size
(
)
;
++
i
)
{
CCValAssign
&
VA
=
RVLocs
[
i
]
;
assert
(
VA
.
isRegLoc
(
)
&&
"Can only return in registers!"
)
;
Chain
=
DAG
.
getCopyToReg
(
Chain
,
DL
,
VA
.
getLocReg
(
)
,
OutVals
[
i
]
,
Flag
)
;
Flag
=
Chain
.
getValue
(
1
)
;
RetOps
.
push_back
(
DAG
.
getRegister
(
VA
.
getLocReg
(
)
,
VA
.
getLocVT
(
)
)
)
;
}
RetOps
[
0
]
=
Chain
;
if
(
Flag
.
getNode
(
)
)
RetOps
.
push_back
(
Flag
)
;
return
DAG
.
getNode
(
Opc
,
DL
,
MVT
::
Other
,
RetOps
)
;
}
</s>


<s> BPFTargetLowering :: ConstraintType BPFTargetLowering :: getConstraintType ( StringRef Constraint ) const { if ( Constraint . size ( ) == 1 ) { switch ( Constraint [ 0 ] ) { default : break ; case 'w' : return C_RegisterClass ; } } return TargetLowering :: getConstraintType ( Constraint ) ; } </s>

Given a constraint letter , return the type of constraint for this target .


<s> std :: pair < unsigned , const TargetRegisterClass * > BPFTargetLowering :: getRegForInlineAsmConstraint ( const TargetRegisterInfo * TRI , StringRef Constraint , MVT VT ) const { if ( Constraint . size ( ) == 1 ) switch ( Constraint [ 0 ] ) { case 'r' : return std :: make_pair ( 0U , & BPF :: GPRRegClass ) ; case 'w' : if ( HasAlu32 ) return std :: make_pair ( 0U , & BPF :: GPR32RegClass ) ; break ; default : break ; } return TargetLowering :: getRegForInlineAsmConstraint ( TRI , Constraint , VT ) ; } </s>

Given a physical register constraint ( e.g .


<s> bool BPFTargetLowering :: isLegalAddressingMode ( const DataLayout & DL , const AddrMode & AM , Type * Ty , unsigned AS , Instruction * I ) const { if ( AM . BaseGV ) return false ; switch ( AM . Scale ) { case 0 : break ; case 1 : if ( ! AM . HasBaseReg ) break ; return false ; default : return false ; } return true ; } </s>

isLegalAddressingMode - Return true if the addressing mode represented by AM is legal for this target , for a load/store of the specified type .


<s> bool BPFTargetLowering :: isTruncateFree ( EVT VT1 , EVT VT2 ) const { if ( ! VT1 . isInteger ( ) || ! VT2 . isInteger ( ) ) return false ; unsigned NumBits1 = VT1 . getSizeInBits ( ) ; unsigned NumBits2 = VT2 . getSizeInBits ( ) ; return NumBits1 > NumBits2 ; } </s>

Return true if it 's free to truncate a value of type Ty1 to type Ty2 .


<s> bool BPFTargetLowering :: isZExtFree ( EVT VT1 , EVT VT2 ) const { if ( ! getHasAlu32 ( ) || ! VT1 . isInteger ( ) || ! VT2 . isInteger ( ) ) return false ; unsigned NumBits1 = VT1 . getSizeInBits ( ) ; unsigned NumBits2 = VT2 . getSizeInBits ( ) ; return NumBits1 == 32 && NumBits2 == 64 ; } </s>

Return true if zero-extending the specific node Val to type VT2 is free ( either because it 's implicitly zero-extended such as ARM ldrb / ldrh or because it 's folded such as X86 zero-extending loads ) .


"LowerFormalArguments Unhandled argument type: "

"functions with VarArgs or StructRet are not supported"


<s>
SDValue
BPFTargetLowering
::
LowerOperation
(
SDValue
Op
,
SelectionDAG
&
DAG
)
const
{
switch
(
Op
.
getOpcode
(
)
)
{
case
ISD
::
BR_CC
:
return
LowerBR_CC
(
Op
,
DAG
)
;
case
ISD
::
GlobalAddress
:
return
LowerGlobalAddress
(
Op
,
DAG
)
;
case
ISD
::
SELECT_CC
:
return
LowerSELECT_CC
(
Op
,
DAG
)
;
case
ISD
::
DYNAMIC_STACKALLOC
:
report_fatal_error
(
"Unsupported dynamic stack allocation"
)
;
default
:
llvm_unreachable
(
"unimplemented operand"
)
;
}
}
</s>


"Unsupported atomic operations, please use 32/64 bit version"

"Unsupported atomic operations, please use 64 bit version"

ReplaceNodeResults - Replace the results of node with an illegal result type with new values built out of custom code .


<s> EVT getOptimalMemOpType ( uint64_t Size , unsigned DstAlign , unsigned SrcAlign , bool IsMemset , bool ZeroMemset , bool MemcpyStrSrc , const AttributeList & FuncAttributes ) const override { return Size >= 8 ? MVT :: i64 : MVT :: i32 ; } </s>


<s>
SDValue
BPFTargetLowering
::
LowerCallResult
(
SDValue
Chain
,
SDValue
InFlag
,
CallingConv
::
ID
CallConv
,
bool
IsVarArg
,
const
SmallVectorImpl
<
ISD
::
InputArg
>
&
Ins
,
SDLoc
DL
,
SelectionDAG
&
DAG
,
SmallVectorImpl
<
SDValue
>
&
InVals
)
const
{
MachineFunction
&
MF
=
DAG
.
getMachineFunction
(
)
;
SmallVector
<
CCValAssign
,
16
>
RVLocs
;
CCState
CCInfo
(
CallConv
,
IsVarArg
,
MF
,
RVLocs
,
*
DAG
.
getContext
(
)
)
;
if
(
Ins
.
size
(
)
>=
2
)
{
fail
(
DL
,
DAG
,
"only small returns supported"
)
;
for
(
unsigned
i
=
0
,
e
=
Ins
.
size
(
)
;
i
!=
e
;
++
i
)
InVals
.
push_back
(
DAG
.
getConstant
(
0
,
DL
,
Ins
[
i
]
.
VT
)
)
;
return
DAG
.
getCopyFromReg
(
Chain
,
DL
,
1
,
Ins
[
0
]
.
VT
,
InFlag
)
.
getValue
(
1
)
;
}
CCInfo
.
AnalyzeCallResult
(
Ins
,
RetCC_BPF64
)
;
for
(
auto
&
Val
:
RVLocs
)
{
Chain
=
DAG
.
getCopyFromReg
(
Chain
,
DL
,
Val
.
getLocReg
(
)
,
Val
.
getValVT
(
)
,
InFlag
)
.
getValue
(
1
)
;
InFlag
=
Chain
.
getValue
(
2
)
;
InVals
.
push_back
(
Chain
.
getValue
(
0
)
)
;
}
return
Chain
;
}
</s>


<s>
SDValue
BPFTargetLowering
::
LowerReturn
(
SDValue
Chain
,
CallingConv
::
ID
CallConv
,
bool
IsVarArg
,
const
SmallVectorImpl
<
ISD
::
OutputArg
>
&
Outs
,
const
SmallVectorImpl
<
SDValue
>
&
OutVals
,
SDLoc
DL
,
SelectionDAG
&
DAG
)
const
{
unsigned
Opc
=
BPFISD
::
RET_FLAG
;
SmallVector
<
CCValAssign
,
16
>
RVLocs
;
MachineFunction
&
MF
=
DAG
.
getMachineFunction
(
)
;
CCState
CCInfo
(
CallConv
,
IsVarArg
,
MF
,
RVLocs
,
*
DAG
.
getContext
(
)
)
;
if
(
MF
.
getFunction
(
)
->
getReturnType
(
)
->
isAggregateType
(
)
)
{
fail
(
DL
,
DAG
,
"only integer returns supported"
)
;
return
DAG
.
getNode
(
Opc
,
DL
,
MVT
::
Other
,
Chain
)
;
}
CCInfo
.
AnalyzeReturn
(
Outs
,
RetCC_BPF64
)
;
SDValue
Flag
;
SmallVector
<
SDValue
,
4
>
RetOps
(
1
,
Chain
)
;
for
(
unsigned
i
=
0
;
i
!=
RVLocs
.
size
(
)
;
++
i
)
{
CCValAssign
&
VA
=
RVLocs
[
i
]
;
assert
(
VA
.
isRegLoc
(
)
&&
"Can only return in registers!"
)
;
Chain
=
DAG
.
getCopyToReg
(
Chain
,
DL
,
VA
.
getLocReg
(
)
,
OutVals
[
i
]
,
Flag
)
;
Flag
=
Chain
.
getValue
(
1
)
;
RetOps
.
push_back
(
DAG
.
getRegister
(
VA
.
getLocReg
(
)
,
VA
.
getLocVT
(
)
)
)
;
}
RetOps
[
0
]
=
Chain
;
if
(
Flag
.
getNode
(
)
)
RetOps
.
push_back
(
Flag
)
;
return
DAG
.
getNode
(
Opc
,
DL
,
MVT
::
Other
,
RetOps
)
;
}
</s>


<s> const char * BPFTargetLowering :: getTargetNodeName ( unsigned Opcode ) const { switch ( Opcode ) { default : return NULL ; case BPFISD :: ADJDYNALLOC : return "BPFISD::ADJDYNALLOC" ; case BPFISD :: RET_FLAG : return "BPFISD::RET_FLAG" ; case BPFISD :: CALL : return "BPFISD::CALL" ; case BPFISD :: SELECT_CC : return "BPFISD::SELECT_CC" ; case BPFISD :: BR_CC : return "BPFISD::BR_CC" ; case BPFISD :: Wrapper : return "BPFISD::Wrapper" ; } } </s>


<s> SDValue BPFTargetLowering :: LowerCallResult ( SDValue Chain , SDValue InFlag , CallingConv :: ID CallConv , bool isVarArg , const SmallVectorImpl < ISD :: InputArg > & Ins , SDLoc dl , DebugLoc dl , SelectionDAG & DAG , SmallVectorImpl < SDValue > & InVals ) const { SmallVector < CCValAssign , 16 > RVLocs ; CCState CCInfo ( CallConv , isVarArg , DAG . getMachineFunction ( ) , getTargetMachine ( ) , RVLocs , * DAG . getContext ( ) ) ; CCInfo . AnalyzeCallResult ( Ins , RetCC_BPF64 ) ; for ( unsigned i = 0 ; i != RVLocs . size ( ) ; ++ i ) { Chain = DAG . getCopyFromReg ( Chain , dl , RVLocs [ i ] . getLocReg ( ) , RVLocs [ i ] . getValVT ( ) , InFlag ) . getValue ( 1 ) ; InFlag = Chain . getValue ( 2 ) ; InVals . push_back ( Chain . getValue ( 0 ) ) ; } return Chain ; } </s>


<s>
SDValue
BPFTargetLowering
::
LowerOperation
(
SDValue
Op
,
SelectionDAG
&
DAG
)
const
{
switch
(
Op
.
getOpcode
(
)
)
{
case
ISD
::
BR_CC
:
return
LowerBR_CC
(
Op
,
DAG
)
;
case
ISD
::
GlobalAddress
:
return
LowerGlobalAddress
(
Op
,
DAG
)
;
case
ISD
::
SELECT_CC
:
return
LowerSELECT_CC
(
Op
,
DAG
)
;
default
:
llvm_unreachable
(
"unimplemented operand"
)
;
}
}
</s>


<s>
SDValue
BPFTargetLowering
::
LowerReturn
(
SDValue
Chain
,
CallingConv
::
ID
CallConv
,
bool
isVarArg
,
const
SmallVectorImpl
<
ISD
::
OutputArg
>
&
Outs
,
const
SmallVectorImpl
<
SDValue
>
&
OutVals
,
SDLoc
dl
,
DebugLoc
dl
,
SelectionDAG
&
DAG
)
const
{
SmallVector
<
CCValAssign
,
16
>
RVLocs
;
CCState
CCInfo
(
CallConv
,
isVarArg
,
DAG
.
getMachineFunction
(
)
,
getTargetMachine
(
)
,
RVLocs
,
*
DAG
.
getContext
(
)
)
;
CCInfo
.
AnalyzeReturn
(
Outs
,
RetCC_BPF64
)
;
if
(
DAG
.
getMachineFunction
(
)
.
getRegInfo
(
)
.
liveout_empty
(
)
)
{
for
(
unsigned
i
=
0
;
i
!=
RVLocs
.
size
(
)
;
++
i
)
if
(
RVLocs
[
i
]
.
isRegLoc
(
)
)
DAG
.
getMachineFunction
(
)
.
getRegInfo
(
)
.
addLiveOut
(
RVLocs
[
i
]
.
getLocReg
(
)
)
;
}
SDValue
Flag
;
SmallVector
<
SDValue
,
4
>
RetOps
(
1
,
Chain
)
;
for
(
unsigned
i
=
0
;
i
!=
RVLocs
.
size
(
)
;
++
i
)
{
CCValAssign
&
VA
=
RVLocs
[
i
]
;
assert
(
VA
.
isRegLoc
(
)
&&
"Can only return in registers!"
)
;
Chain
=
DAG
.
getCopyToReg
(
Chain
,
dl
,
VA
.
getLocReg
(
)
,
OutVals
[
i
]
,
Flag
)
;
Flag
=
Chain
.
getValue
(
1
)
;
RetOps
.
push_back
(
DAG
.
getRegister
(
VA
.
getLocReg
(
)
,
VA
.
getLocVT
(
)
)
)
;
}
if
(
DAG
.
getMachineFunction
(
)
.
getFunction
(
)
->
hasStructRetAttr
(
)
)
{
errs
(
)
<<
"Function: "
<<
DAG
.
getMachineFunction
(
)
.
getName
(
)
<<
" "
;
DAG
.
getMachineFunction
(
)
.
getFunction
(
)
->
getFunctionType
(
)
->
dump
(
)
;
errs
(
)
<<
"\n"
;
report_fatal_error
(
"BPF doesn't support struct return"
)
;
}
unsigned
Opc
=
BPFISD
::
RET_FLAG
;
RetOps
[
0
]
=
Chain
;
if
(
Flag
.
getNode
(
)
)
RetOps
.
push_back
(
Flag
)
;
return
DAG
.
getNode
(
Opc
,
dl
,
MVT
::
Other
,
&
RetOps
[
0
]
,
RetOps
.
size
(
)
)
;
if
(
Flag
.
getNode
(
)
)
return
DAG
.
getNode
(
Opc
,
dl
,
MVT
::
Other
,
Chain
,
Flag
)
;
return
DAG
.
getNode
(
Opc
,
dl
,
MVT
::
Other
,
Chain
)
;
}
</s>


<s>
SDValue
BPFTargetLowering
::
LowerCallResult
(
SDValue
Chain
,
SDValue
InFlag
,
CallingConv
::
ID
CallConv
,
bool
IsVarArg
,
const
SmallVectorImpl
<
ISD
::
InputArg
>
&
Ins
,
SDLoc
DL
,
SelectionDAG
&
DAG
,
SmallVectorImpl
<
SDValue
>
&
InVals
)
const
{
MachineFunction
&
MF
=
DAG
.
getMachineFunction
(
)
;
SmallVector
<
CCValAssign
,
16
>
RVLocs
;
CCState
CCInfo
(
CallConv
,
IsVarArg
,
MF
,
RVLocs
,
*
DAG
.
getContext
(
)
)
;
if
(
Ins
.
size
(
)
>=
2
)
{
fail
(
DL
,
DAG
,
"only small returns supported"
)
;
}
CCInfo
.
AnalyzeCallResult
(
Ins
,
RetCC_BPF64
)
;
for
(
auto
&
Val
:
RVLocs
)
{
Chain
=
DAG
.
getCopyFromReg
(
Chain
,
DL
,
Val
.
getLocReg
(
)
,
Val
.
getValVT
(
)
,
InFlag
)
.
getValue
(
1
)
;
InFlag
=
Chain
.
getValue
(
2
)
;
InVals
.
push_back
(
Chain
.
getValue
(
0
)
)
;
}
return
Chain
;
}
</s>


<s>
SDValue
BPFTargetLowering
::
LowerReturn
(
SDValue
Chain
,
CallingConv
::
ID
CallConv
,
bool
IsVarArg
,
const
SmallVectorImpl
<
ISD
::
OutputArg
>
&
Outs
,
const
SmallVectorImpl
<
SDValue
>
&
OutVals
,
SDLoc
DL
,
SelectionDAG
&
DAG
)
const
{
SmallVector
<
CCValAssign
,
16
>
RVLocs
;
MachineFunction
&
MF
=
DAG
.
getMachineFunction
(
)
;
CCState
CCInfo
(
CallConv
,
IsVarArg
,
MF
,
RVLocs
,
*
DAG
.
getContext
(
)
)
;
if
(
MF
.
getFunction
(
)
->
getReturnType
(
)
->
isAggregateType
(
)
)
{
fail
(
DL
,
DAG
,
"only integer returns supported"
)
;
}
CCInfo
.
AnalyzeReturn
(
Outs
,
RetCC_BPF64
)
;
SDValue
Flag
;
SmallVector
<
SDValue
,
4
>
RetOps
(
1
,
Chain
)
;
for
(
unsigned
i
=
0
;
i
!=
RVLocs
.
size
(
)
;
++
i
)
{
CCValAssign
&
VA
=
RVLocs
[
i
]
;
assert
(
VA
.
isRegLoc
(
)
&&
"Can only return in registers!"
)
;
Chain
=
DAG
.
getCopyToReg
(
Chain
,
DL
,
VA
.
getLocReg
(
)
,
OutVals
[
i
]
,
Flag
)
;
Flag
=
Chain
.
getValue
(
1
)
;
RetOps
.
push_back
(
DAG
.
getRegister
(
VA
.
getLocReg
(
)
,
VA
.
getLocVT
(
)
)
)
;
}
unsigned
Opc
=
BPFISD
::
RET_FLAG
;
RetOps
[
0
]
=
Chain
;
if
(
Flag
.
getNode
(
)
)
RetOps
.
push_back
(
Flag
)
;
return
DAG
.
getNode
(
Opc
,
DL
,
MVT
::
Other
,
RetOps
)
;
}
</s>


<s> std :: pair < unsigned , const TargetRegisterClass * > BPFTargetLowering :: getRegForInlineAsmConstraint ( const TargetRegisterInfo * TRI , StringRef Constraint , MVT VT ) const { if ( Constraint . size ( ) == 1 ) switch ( Constraint [ 0 ] ) { case 'r' : return std :: make_pair ( 0U , & BPF :: GPRRegClass ) ; default : break ; } return TargetLowering :: getRegForInlineAsmConstraint ( TRI , Constraint , VT ) ; } </s>


<s> MVT BPFTargetLowering :: getScalarShiftAmountTy ( const DataLayout & DL , EVT VT ) const { return ( getHasAlu32 ( ) && VT == MVT :: i32 ) ? MVT :: i32 : MVT :: i64 ; } </s>

Return the type to use for a scalar shift opcode , given the shifted amount type .


<s> EVT BPFTargetLowering :: getSetCCResultType ( const DataLayout & , LLVMContext & , EVT VT ) const { return getHasAlu32 ( ) ? MVT :: i32 : MVT :: i64 ; } </s>

Return the value type to use for ISD : :SETCC .


<s> const char * BPFTargetLowering :: getTargetNodeName ( unsigned Opcode ) const { switch ( ( BPFISD :: NodeType ) Opcode ) { case BPFISD :: FIRST_NUMBER : break ; case BPFISD :: RET_FLAG : return "BPFISD::RET_FLAG" ; case BPFISD :: CALL : return "BPFISD::CALL" ; case BPFISD :: SELECT_CC : return "BPFISD::SELECT_CC" ; case BPFISD :: BR_CC : return "BPFISD::BR_CC" ; case BPFISD :: Wrapper : return "BPFISD::Wrapper" ; case BPFISD :: MEMCPY : return "BPFISD::MEMCPY" ; } return nullptr ; } </s>

getTargetNodeName - This method returns the name of a target specific


<s> bool BPFTargetLowering :: isOffsetFoldingLegal ( const GlobalAddressSDNode * GA ) const { return false ; } </s>

Return true if folding a constant offset with the given GlobalAddress is legal .


<s>
SDValue
BPFTargetLowering
::
LowerCallResult
(
SDValue
Chain
,
SDValue
InFlag
,
CallingConv
::
ID
CallConv
,
bool
IsVarArg
,
const
SmallVectorImpl
<
ISD
::
InputArg
>
&
Ins
,
const
SDLoc
&
DL
,
SelectionDAG
&
DAG
,
SmallVectorImpl
<
SDValue
>
&
InVals
)
const
{
MachineFunction
&
MF
=
DAG
.
getMachineFunction
(
)
;
SmallVector
<
CCValAssign
,
16
>
RVLocs
;
CCState
CCInfo
(
CallConv
,
IsVarArg
,
MF
,
RVLocs
,
*
DAG
.
getContext
(
)
)
;
if
(
Ins
.
size
(
)
>=
2
)
{
fail
(
DL
,
DAG
,
"only small returns supported"
)
;
for
(
unsigned
i
=
0
,
e
=
Ins
.
size
(
)
;
i
!=
e
;
++
i
)
InVals
.
push_back
(
DAG
.
getConstant
(
0
,
DL
,
Ins
[
i
]
.
VT
)
)
;
return
DAG
.
getCopyFromReg
(
Chain
,
DL
,
1
,
Ins
[
0
]
.
VT
,
InFlag
)
.
getValue
(
1
)
;
}
CCInfo
.
AnalyzeCallResult
(
Ins
,
getHasAlu32
(
)
RetCC_BPF32
:
RetCC_BPF64
)
;
for
(
auto
&
Val
:
RVLocs
)
{
Chain
=
DAG
.
getCopyFromReg
(
Chain
,
DL
,
Val
.
getLocReg
(
)
,
Val
.
getValVT
(
)
,
InFlag
)
.
getValue
(
1
)
;
InFlag
=
Chain
.
getValue
(
2
)
;
InVals
.
push_back
(
Chain
.
getValue
(
0
)
)
;
}
return
Chain
;
}
</s>

LowerCallResult - Lower the result values of an ISD : :CALL into the appropriate copies out of appropriate physical registers .


"LowerFormalArguments Unhandled argument type: "

"functions with VarArgs or StructRet are not supported"

This hook must be implemented to lower the incoming ( formal ) arguments , described by the Ins array , into the specified DAG .


<s>
SDValue
BPFTargetLowering
::
LowerReturn
(
SDValue
Chain
,
CallingConv
::
ID
CallConv
,
bool
IsVarArg
,
const
SmallVectorImpl
<
ISD
::
OutputArg
>
&
Outs
,
const
SmallVectorImpl
<
SDValue
>
&
OutVals
,
const
SDLoc
&
DL
,
SelectionDAG
&
DAG
)
const
{
unsigned
Opc
=
BPFISD
::
RET_FLAG
;
SmallVector
<
CCValAssign
,
16
>
RVLocs
;
MachineFunction
&
MF
=
DAG
.
getMachineFunction
(
)
;
CCState
CCInfo
(
CallConv
,
IsVarArg
,
MF
,
RVLocs
,
*
DAG
.
getContext
(
)
)
;
if
(
MF
.
getFunction
(
)
.
getReturnType
(
)
->
isAggregateType
(
)
)
{
fail
(
DL
,
DAG
,
"only integer returns supported"
)
;
return
DAG
.
getNode
(
Opc
,
DL
,
MVT
::
Other
,
Chain
)
;
}
CCInfo
.
AnalyzeReturn
(
Outs
,
getHasAlu32
(
)
RetCC_BPF32
:
RetCC_BPF64
)
;
SDValue
Flag
;
SmallVector
<
SDValue
,
4
>
RetOps
(
1
,
Chain
)
;
for
(
unsigned
i
=
0
;
i
!=
RVLocs
.
size
(
)
;
++
i
)
{
CCValAssign
&
VA
=
RVLocs
[
i
]
;
assert
(
VA
.
isRegLoc
(
)
&&
"Can only return in registers!"
)
;
Chain
=
DAG
.
getCopyToReg
(
Chain
,
DL
,
VA
.
getLocReg
(
)
,
OutVals
[
i
]
,
Flag
)
;
Flag
=
Chain
.
getValue
(
1
)
;
RetOps
.
push_back
(
DAG
.
getRegister
(
VA
.
getLocReg
(
)
,
VA
.
getLocVT
(
)
)
)
;
}
RetOps
[
0
]
=
Chain
;
if
(
Flag
.
getNode
(
)
)
RetOps
.
push_back
(
Flag
)
;
return
DAG
.
getNode
(
Opc
,
DL
,
MVT
::
Other
,
RetOps
)
;
}
</s>

This hook must be implemented to lower outgoing return values , described by the Outs array , into the specified DAG .


<s> void BPFMCCodeEmitter :: encodeInstruction ( const MCInst & MI , raw_ostream & OS , SmallVectorImpl < MCFixup > & Fixups , const MCSubtargetInfo & STI ) const { verifyInstructionPredicates ( MI , computeAvailableFeatures ( STI . getFeatureBits ( ) ) ) ; unsigned Opcode = MI . getOpcode ( ) ; support :: endian :: Writer OSE ( OS , IsLittleEndian ? support :: little : support :: big ) ; if ( Opcode == BPF :: LD_imm64 || Opcode == BPF :: LD_pseudo ) { uint64_t Value = getBinaryCodeForInstr ( MI , Fixups , STI ) ; OS << char ( Value >> 56 ) ; if ( IsLittleEndian ) OS << char ( ( Value >> 48 ) & 0xff ) ; else OS << char ( SwapBits ( ( Value >> 48 ) & 0xff ) ) ; OSE . write < uint16_t > ( 0 ) ; OSE . write < uint32_t > ( Value & 0xffffFFFF ) ; const MCOperand & MO = MI . getOperand ( 1 ) ; uint64_t Imm = MO . isImm ( ) ? MO . getImm ( ) : 0 ; OSE . write < uint8_t > ( 0 ) ; OSE . write < uint8_t > ( 0 ) ; OSE . write < uint16_t > ( 0 ) ; OSE . write < uint32_t > ( Imm >> 32 ) ; } else { uint64_t Value = getBinaryCodeForInstr ( MI , Fixups , STI ) ; OS << char ( Value >> 56 ) ; if ( IsLittleEndian ) OS << char ( ( Value >> 48 ) & 0xff ) ; else OS << char ( SwapBits ( ( Value >> 48 ) & 0xff ) ) ; OSE . write < uint16_t > ( ( Value >> 32 ) & 0xffff ) ; OSE . write < uint32_t > ( Value & 0xffffFFFF ) ; } } </s>

Encode the given Inst to bytes and append to CB .


<s> unsigned BPFMCCodeEmitter :: getMachineOpValue ( const MCInst & MI , const MCOperand & MO , SmallVectorImpl < MCFixup > & Fixups , const MCSubtargetInfo & STI ) const { if ( MO . isReg ( ) ) return MRI . getEncodingValue ( MO . getReg ( ) ) ; if ( MO . isImm ( ) ) return static_cast < unsigned > ( MO . getImm ( ) ) ; assert ( MO . isExpr ( ) ) ; const MCExpr * Expr = MO . getExpr ( ) ; assert ( Expr -> getKind ( ) == MCExpr :: SymbolRef ) ; if ( MI . getOpcode ( ) == BPF :: JAL ) Fixups . push_back ( MCFixup :: create ( 0 , Expr , FK_PCRel_4 ) ) ; else if ( MI . getOpcode ( ) == BPF :: LD_imm64 ) Fixups . push_back ( MCFixup :: create ( 0 , Expr , FK_SecRel_8 ) ) ; else Fixups . push_back ( MCFixup :: create ( 0 , Expr , FK_PCRel_2 ) ) ; return 0 ; } </s>

getMachineOpValue - Return binary encoding of operand .


<s> void BPFMCCodeEmitter :: encodeInstruction ( const MCInst & MI , raw_ostream & OS , SmallVectorImpl < MCFixup > & Fixups , const MCSubtargetInfo & STI ) const { verifyInstructionPredicates ( MI , computeAvailableFeatures ( STI . getFeatureBits ( ) ) ) ; unsigned Opcode = MI . getOpcode ( ) ; support :: endian :: Writer < support :: little > LE ( OS ) ; support :: endian :: Writer < support :: big > BE ( OS ) ; if ( Opcode == BPF :: LD_imm64 || Opcode == BPF :: LD_pseudo ) { uint64_t Value = getBinaryCodeForInstr ( MI , Fixups , STI ) ; LE . write < uint8_t > ( Value >> 56 ) ; if ( IsLittleEndian ) LE . write < uint8_t > ( ( Value >> 48 ) & 0xff ) ; else LE . write < uint8_t > ( SwapBits ( ( Value >> 48 ) & 0xff ) ) ; LE . write < uint16_t > ( 0 ) ; if ( IsLittleEndian ) LE . write < uint32_t > ( Value & 0xffffFFFF ) ; else BE . write < uint32_t > ( Value & 0xffffFFFF ) ; const MCOperand & MO = MI . getOperand ( 1 ) ; uint64_t Imm = MO . isImm ( ) ? MO . getImm ( ) : 0 ; LE . write < uint8_t > ( 0 ) ; LE . write < uint8_t > ( 0 ) ; LE . write < uint16_t > ( 0 ) ; if ( IsLittleEndian ) LE . write < uint32_t > ( Imm >> 32 ) ; else BE . write < uint32_t > ( Imm >> 32 ) ; } else { uint64_t Value = getBinaryCodeForInstr ( MI , Fixups , STI ) ; LE . write < uint8_t > ( Value >> 56 ) ; if ( IsLittleEndian ) { LE . write < uint8_t > ( ( Value >> 48 ) & 0xff ) ; LE . write < uint16_t > ( ( Value >> 32 ) & 0xffff ) ; LE . write < uint32_t > ( Value & 0xffffFFFF ) ; } else { LE . write < uint8_t > ( SwapBits ( ( Value >> 48 ) & 0xff ) ) ; BE . write < uint16_t > ( ( Value >> 32 ) & 0xffff ) ; BE . write < uint32_t > ( Value & 0xffffFFFF ) ; } } } </s>