<s>
bool
ThumbDisassembler
::
getInstruction
(
MCInst
&
MI
,
uint64_t
&
Size
,
const
MemoryObject
&
Region
,
uint64_t
Address
,
raw_ostream
&
os
)
const
{
unsigned
insn
=
0
;
uint16_t
insn1
=
0
;
uint8_t
bytes
[
2
]
;
if
(
Region
.
readBytes
(
Address
,
2
,
(
uint8_t
*
)
bytes
,
)
==
1
)
return
false
;
insn
=
(
bytes
[
1
]
<<
8
)
|
bytes
[
0
]
;
unsigned
bits15_11
=
slice
(
insn
,
15
,
11
)
;
bool
IsThumb2
=
false
;
if
(
bits15_11
==
0x1D
||
bits15_11
==
0x1E
||
bits15_11
==
0x1F
)
{
IsThumb2
=
true
;
if
(
Region
.
readBytes
(
Address
+
2
,
2
,
(
uint8_t
*
)
bytes
,
)
==
1
)
return
false
;
insn1
=
(
bytes
[
1
]
<<
8
)
|
bytes
[
0
]
;
insn
=
(
insn
<<
16
|
insn1
)
;
}
unsigned
Opcode
=
decodeThumbSideEffect
(
IsThumb2
,
insn
)
;
ARMFormat
Format
=
ARMFormats
[
Opcode
]
;
Size
=
IsThumb2
4
:
2
;
DEBUG
(
{
errs
(
)
<<
"Opcode="
<<
Opcode
<<
" Name="
<<
ARMUtils
::
OpcodeName
(
Opcode
)
<<
" Format="
<<
stringForARMFormat
(
Format
)
<<
'('
<<
(
int
)
Format
<<
")\n"
;
showBitVector
(
errs
(
)
,
insn
)
;
}
)
;
ARMBasicMCBuilder
*
Builder
=
CreateMCBuilder
(
Opcode
,
Format
)
;
if
(
!
Builder
)
return
false
;
Builder
->
SetSession
(
const_cast
<
Session
*
>
(
&
SO
)
)
;
if
(
!
Builder
->
Build
(
MI
,
insn
)
)
return
false
;
delete
Builder
;
return
true
;
}
</s>


<s>
bool
ThumbDisassembler
::
getInstruction
(
MCInst
&
MI
,
uint64_t
&
Size
,
const
MemoryObject
&
Region
,
uint64_t
Address
,
raw_ostream
&
os
)
const
{
unsigned
insn
=
0
;
uint16_t
insn1
=
0
;
uint8_t
bytes
[
2
]
;
if
(
Region
.
readBytes
(
Address
,
2
,
(
uint8_t
*
)
bytes
,
)
==
1
)
return
false
;
insn
=
(
bytes
[
1
]
<<
8
)
|
bytes
[
0
]
;
unsigned
bits15_11
=
slice
(
insn
,
15
,
11
)
;
bool
IsThumb2
=
false
;
if
(
bits15_11
==
0x1D
||
bits15_11
==
0x1E
||
bits15_11
==
0x1F
)
{
IsThumb2
=
true
;
if
(
Region
.
readBytes
(
Address
+
2
,
2
,
(
uint8_t
*
)
bytes
,
)
==
1
)
return
false
;
insn1
=
(
bytes
[
1
]
<<
8
)
|
bytes
[
0
]
;
insn
=
(
insn
<<
16
|
insn1
)
;
}
unsigned
Opcode
=
decodeThumbSideEffect
(
IsThumb2
,
insn
)
;
if
(
Thumb2PreloadOpcodeNoPCI
(
Opcode
)
&&
slice
(
insn
,
19
,
16
)
==
15
)
Opcode
=
T2Morph2Preload2PCI
(
Opcode
)
;
ARMFormat
Format
=
ARMFormats
[
Opcode
]
;
Size
=
IsThumb2
4
:
2
;
DEBUG
(
{
errs
(
)
<<
"Opcode="
<<
Opcode
<<
" Name="
<<
ARMUtils
::
OpcodeName
(
Opcode
)
<<
" Format="
<<
stringForARMFormat
(
Format
)
<<
'('
<<
(
int
)
Format
<<
")\n"
;
showBitVector
(
errs
(
)
,
insn
)
;
}
)
;
ARMBasicMCBuilder
*
Builder
=
CreateMCBuilder
(
Opcode
,
Format
)
;
if
(
!
Builder
)
return
false
;
Builder
->
SetSession
(
const_cast
<
Session
*
>
(
&
SO
)
)
;
if
(
!
Builder
->
Build
(
MI
,
insn
)
)
return
false
;
delete
Builder
;
return
true
;
}
</s>

Returns the disassembly of a single instruction .


<s> DecodeStatus ARMDisassembler :: getInstruction ( MCInst & MI , uint64_t & Size , ArrayRef < uint8_t > Bytes , uint64_t Address , raw_ostream & OS , raw_ostream & CS ) const { if ( STI . getFeatureBits ( ) [ ARM :: ModeThumb ] ) return getThumbInstruction ( MI , Size , Bytes , Address , OS , CS ) ; return getARMInstruction ( MI , Size , Bytes , Address , OS , CS ) ; } </s>


<s> static void tryAddingPcLoadReferenceComment ( uint64_t Address , int Value , const MCDisassembler * Decoder ) { const MCDisassembler * Dis = static_cast < const MCDisassembler * > ( Decoder ) ; Dis -> tryAddingPcLoadReferenceComment ( Value , Address ) ; } </s>

Try to add a comment on the PC-relative load .


<s> static bool tryAddingSymbolicOperand ( uint64_t Address , int32_t Value , bool isBranch , uint64_t InstSize , MCInst & MI , const MCDisassembler * Decoder ) { return Decoder -> tryAddingSymbolicOperand ( MI , ( uint32_t ) Value , Address , isBranch , 0 , 0 , InstSize ) ; } </s>

Try to add a symbolic operand instead of Value to the MCInst .


"Asked to disassemble an ARM instruction but Subtarget is in Thumb "


<s> static bool tryAddingSymbolicOperand ( uint64_t Address , int32_t Value , bool isBranch , uint64_t InstSize , MCInst & MI , const MCDisassembler * Decoder ) { return Decoder -> tryAddingSymbolicOperand ( MI , ( uint32_t ) Value , Address , isBranch , 0 , InstSize ) ; } </s>


<s> static inline unsigned slice ( uint32_t Bits , unsigned From , unsigned To ) { assert ( From < 32 && To < 32 && From >= To ) ; return ( Bits >> To ) & ( ( 1 << ( From - To + 1 ) ) - 1 ) ; } </s>

Return a reference to the substring from [ Start , End ) .


<s> size_t ARMELFAttributeData :: emit ( char * pBuf ) const { char * buffer = pBuf ; const ELFAttributeValue & attr_conformance = m_Attrs [ Tag_conformance ] ; if ( attr_conformance . shouldEmit ( ) ) { if ( ! ELFAttributeData :: WriteAttribute ( Tag_conformance , attr_conformance , buffer ) ) { return 0 ; } } const ELFAttributeValue & attr_nodefaults = m_Attrs [ Tag_nodefaults ] ; if ( attr_nodefaults . shouldEmit ( ) ) { if ( ! ELFAttributeData :: WriteAttribute ( Tag_nodefaults , attr_nodefaults , buffer ) ) { return 0 ; } } for ( unsigned i = 0 ; i < Tag_nodefaults ; ++ i ) { TagType tag = static_cast < TagType > ( i ) ; const ELFAttributeValue & value = m_Attrs [ tag ] ; if ( value . shouldEmit ( ) && ! ELFAttributeData :: WriteAttribute ( tag , value , buffer ) ) { return 0 ; } } for ( unsigned i = ( Tag_nodefaults + 1 ) ; i <= Tag_Max ; ++ i ) { TagType tag = static_cast < TagType > ( i ) ; const ELFAttributeValue & value = m_Attrs [ tag ] ; if ( value . shouldEmit ( ) && ( i != Tag_conformance ) && ! ELFAttributeData :: WriteAttribute ( tag , value , buffer ) ) { return 0 ; } } for ( UnknownAttrsMap :: const_iterator unknown_attr_it = m_UnknownAttrs . begin ( ) , unknown_attr_end = m_UnknownAttrs . end ( ) ; unknown_attr_it != unknown_attr_end ; ++ unknown_attr_it ) { TagType tag = unknown_attr_it -> first ; const ELFAttributeValue & value = unknown_attr_it -> second ; if ( value . shouldEmit ( ) && ! ELFAttributeData :: WriteAttribute ( tag , value , buffer ) ) { return 0 ; } } return ( buffer - pBuf ) ; } </s>

Output the remark via the diagnostic handler and to the optimization record file .


<s> const ELFAttributeValue * ARMELFAttributeData :: getAttributeValue ( TagType pTag ) const { if ( pTag <= Tag_Max ) { const ELFAttributeValue & attr_value = m_Attrs [ pTag ] ; if ( attr_value . isInitialized ( ) ) { return & attr_value ; } else { return NULL ; } } else { UnknownAttrsMap :: const_iterator attr_it = m_UnknownAttrs . find ( pTag ) ; if ( attr_it == m_UnknownAttrs . end ( ) ) { return NULL ; } else { return & attr_it -> second ; } } } </s>

Extract a DWARF form value from a DIE specified by DIE offset .


<s> void ARMTargetELFStreamer :: emitInst ( uint32_t Inst , char Suffix ) { getStreamer ( ) . emitInst ( Inst , Suffix ) ; } </s>

Callback used to implement the .inst directive .


<s> void EmitInstruction ( const MCInst & Inst , const MCSubtargetInfo & STI ) override { if ( IsThumb ) EmitThumbMappingSymbol ( ) ; else EmitARMMappingSymbol ( ) ; MCELFStreamer :: EmitInstruction ( Inst , STI ) ; } </s>

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


<s> void ARMTargetELFStreamer :: emitLabel ( MCSymbol * Symbol ) { ARMELFStreamer & Streamer = getStreamer ( ) ; if ( ! Streamer . IsThumb ) return ; Streamer . getAssembler ( ) . registerSymbol ( * Symbol ) ; unsigned Type = cast < MCSymbolELF > ( Symbol ) -> getType ( ) ; if ( Type == ELF :: STT_FUNC || Type == ELF :: STT_GNU_IFUNC ) Streamer . EmitThumbFunc ( Symbol ) ; } </s>

Emit a label for Symbol into the current section .


<s> ARMELFStreamer & ARMTargetELFStreamer :: getStreamer ( ) { return static_cast < ARMELFStreamer & > ( Streamer ) ; } </s>

Return the output streamer for the assembler .


<s> void ARMELFStreamer :: Reset ( ) { ExTab = nullptr ; FnStart = nullptr ; Personality = nullptr ; PersonalityIndex = ARM :: EHABI :: NUM_PERSONALITY_INDEX ; FPReg = ARM :: SP ; FPOffset = 0 ; SPOffset = 0 ; PendingOffset = 0 ; UsedFP = false ; CantUnwind = false ; Opcodes . clear ( ) ; UnwindOpAsm . Reset ( ) ; } </s>


<s> void EmitInstruction ( const MCInst & Inst , const MCSubtargetInfo & STI , bool ) override { if ( IsThumb ) EmitThumbMappingSymbol ( ) ; else EmitARMMappingSymbol ( ) ; MCELFStreamer :: EmitInstruction ( Inst , STI ) ; } </s>


<s> void ARMELFStreamer :: reset ( ) { MCTargetStreamer & TS = * getTargetStreamer ( ) ; ARMTargetStreamer & ATS = static_cast < ARMTargetStreamer & > ( TS ) ; ATS . reset ( ) ; MappingSymbolCounter = 0 ; MCELFStreamer :: reset ( ) ; getAssembler ( ) . setELFHeaderEFlags ( ELF :: EF_ARM_EABI_VER5 ) ; } </s>

Reset an existing scalar value for Def and a given Instance .


<s>
void
emitInst
(
uint32_t
Inst
,
char
Suffix
)
{
unsigned
Size
;
char
Buffer
[
4
]
;
const
bool
LittleEndian
=
getContext
(
)
.
getAsmInfo
(
)
->
isLittleEndian
(
)
;
switch
(
Suffix
)
{
case
'\0'
:
Size
=
4
;
assert
(
!
IsThumb
)
;
EmitARMMappingSymbol
(
)
;
for
(
unsigned
II
=
0
,
IE
=
Size
;
II
!=
IE
;
II
++
)
{
const
unsigned
I
=
LittleEndian
(
Size
II
1
)
:
II
;
Buffer
[
Size
II
1
]
=
uint8_t
(
Inst
>>
I
*
CHAR_BIT
)
;
}
break
;
case
'n'
:
case
'w'
:
Size
=
(
Suffix
==
'n'
2
:
4
)
;
assert
(
IsThumb
)
;
EmitThumbMappingSymbol
(
)
;
for
(
unsigned
II
=
0
,
IE
=
Size
;
II
!=
IE
;
II
=
II
+
2
)
{
const
unsigned
I0
=
LittleEndian
II
+
0
:
II
+
1
;
const
unsigned
I1
=
LittleEndian
II
+
1
:
II
+
0
;
Buffer
[
Size
II
2
]
=
uint8_t
(
Inst
>>
I0
*
CHAR_BIT
)
;
Buffer
[
Size
II
1
]
=
uint8_t
(
Inst
>>
I1
*
CHAR_BIT
)
;
}
break
;
default
:
llvm_unreachable
(
"Invalid Suffix"
)
;
}
MCELFStreamer
::
EmitBytes
(
StringRef
(
Buffer
,
Size
)
)
;
}
</s>


<s> void ARMELFStreamer :: reset ( ) { MCTargetStreamer & TS = * getTargetStreamer ( ) ; ARMTargetStreamer & ATS = static_cast < ARMTargetStreamer & > ( TS ) ; ATS . reset ( ) ; MappingSymbolCounter = 0 ; MCELFStreamer :: reset ( ) ; LastMappingSymbols . clear ( ) ; LastEMSInfo . reset ( ) ; getAssembler ( ) . setELFHeaderEFlags ( ELF :: EF_ARM_EABI_VER5 ) ; } </s>


<s> void ARMTargetAsmStreamer :: emitInst ( uint32_t Inst , char Suffix ) { OS << "\t.inst" ; if ( Suffix ) OS << "." << Suffix ; OS << "\t0x" << utohexstr ( Inst ) << "\n" ; } </s>


<s> void ARMELFStreamer :: Reset ( ) { ExTab = NULL ; FnStart = NULL ; Personality = NULL ; PersonalityIndex = ARM :: EHABI :: NUM_PERSONALITY_INDEX ; FPReg = ARM :: SP ; FPOffset = 0 ; SPOffset = 0 ; PendingOffset = 0 ; UsedFP = false ; CantUnwind = false ; Opcodes . clear ( ) ; UnwindOpAsm . Reset ( ) ; } </s>


<s> void emitFill ( const MCExpr & NumBytes , uint64_t FillValue , SMLoc Loc ) override { EmitDataMappingSymbol ( ) ; MCObjectStreamer :: emitFill ( NumBytes , FillValue , Loc ) ; } </s>

Emit Size bytes worth of the value specified by FillValue .


<s> static bool classof ( const MCStreamer * S ) { return S -> getKind ( ) == SK_ARMELFStreamer ; } </s>

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


<s> virtual void EmitInstruction ( const MCInst & Inst ) { if ( IsThumb ) EmitThumbMappingSymbol ( ) ; else EmitARMMappingSymbol ( ) ; MCELFStreamer :: EmitInstruction ( Inst ) ; } </s>


<s> void ARMELFStreamer :: EmitRegSave ( const SmallVectorImpl < unsigned > & RegList , bool IsVector ) { } </s>

Emit unwind opcodes for .save directives .


<s> void ARMELFStreamer :: Reset ( ) { ExTab = NULL ; FnStart = NULL ; Personality = NULL ; CantUnwind = false ; } </s>


<s> void ARMTargetELFStreamer :: emitLabel ( MCSymbol * Symbol ) { ARMELFStreamer & Streamer = getStreamer ( ) ; if ( ! Streamer . IsThumb ) return ; const MCSymbolData & SD = Streamer . getOrCreateSymbolData ( Symbol ) ; unsigned Type = MCELF :: GetType ( SD ) ; if ( Type == ELF_STT_Func || Type == ELF_STT_GnuIFunc ) Streamer . EmitThumbFunc ( Symbol ) ; } </s>


<s> void changeSection ( MCSection * Section , const MCExpr * Subsection ) override { LastMappingSymbols [ getCurrentSection ( ) . first ] = std :: move ( LastEMSInfo ) ; MCELFStreamer :: changeSection ( Section , Subsection ) ; auto LastMappingSymbol = LastMappingSymbols . find ( Section ) ; if ( LastMappingSymbol != LastMappingSymbols . end ( ) ) { LastEMSInfo = std :: move ( LastMappingSymbol -> second ) ; return ; } LastEMSInfo . reset ( new ElfMappingSymbolInfo ( SMLoc ( ) , nullptr , 0 ) ) ; } </s>

Update streamer for a new active section .


<s> void emitAssemblerFlag ( MCAssemblerFlag Flag ) override { MCELFStreamer :: emitAssemblerFlag ( Flag ) ; switch ( Flag ) { case MCAF_SyntaxUnified : return ; case MCAF_Code16 : IsThumb = true ; return ; case MCAF_Code32 : IsThumb = false ; return ; case MCAF_Code64 : return ; case MCAF_SubsectionsViaSymbols : return ; } } </s>


<s> void emitBytes ( StringRef Data ) override { emitDataMappingSymbol ( ) ; MCELFStreamer :: emitBytes ( Data ) ; } </s>

Emit the bytes in Data into the output .


<s> void emitFill ( const MCExpr & NumBytes , uint64_t FillValue , SMLoc Loc ) override { emitDataMappingSymbol ( ) ; MCObjectStreamer :: emitFill ( NumBytes , FillValue , Loc ) ; } </s>


<s>
void
emitInst
(
uint32_t
Inst
,
char
Suffix
)
{
unsigned
Size
;
char
Buffer
[
4
]
;
const
bool
LittleEndian
=
getContext
(
)
.
getAsmInfo
(
)
->
isLittleEndian
(
)
;
switch
(
Suffix
)
{
case
'\0'
:
Size
=
4
;
assert
(
!
IsThumb
)
;
EmitARMMappingSymbol
(
)
;
for
(
unsigned
II
=
0
,
IE
=
Size
;
II
!=
IE
;
II
++
)
{
const
unsigned
I
=
LittleEndian
(
Size
II
1
)
:
II
;
Buffer
[
Size
II
1
]
=
uint8_t
(
Inst
>>
I
*
CHAR_BIT
)
;
}
break
;
case
'n'
:
case
'w'
:
Size
=
(
Suffix
==
'n'
2
:
4
)
;
assert
(
IsThumb
)
;
EmitThumbMappingSymbol
(
)
;
for
(
unsigned
II
=
0
,
IE
=
Size
;
II
!=
IE
;
II
=
II
+
2
)
{
const
unsigned
I0
=
LittleEndian
II
+
0
:
II
+
1
;
const
unsigned
I1
=
LittleEndian
II
+
1
:
II
+
0
;
Buffer
[
Size
II
2
]
=
uint8_t
(
Inst
>>
I0
*
CHAR_BIT
)
;
Buffer
[
Size
II
1
]
=
uint8_t
(
Inst
>>
I1
*
CHAR_BIT
)
;
}
break
;
default
:
llvm_unreachable
(
"Invalid Suffix"
)
;
}
MCELFStreamer
::
emitBytes
(
StringRef
(
Buffer
,
Size
)
)
;
}
</s>


<s> void emitInstruction ( const MCInst & Inst , const MCSubtargetInfo & STI ) override { if ( IsThumb ) EmitThumbMappingSymbol ( ) ; else EmitARMMappingSymbol ( ) ; MCELFStreamer :: emitInstruction ( Inst , STI ) ; } </s>

Targets should implement this to emit instructions .


<s> void ARMTargetELFStreamer :: emitLabel ( MCSymbol * Symbol ) { ARMELFStreamer & Streamer = getStreamer ( ) ; if ( ! Streamer . IsThumb ) return ; Streamer . getAssembler ( ) . registerSymbol ( * Symbol ) ; unsigned Type = cast < MCSymbolELF > ( Symbol ) -> getType ( ) ; if ( Type == ELF :: STT_FUNC || Type == ELF :: STT_GNU_IFUNC ) Streamer . emitThumbFunc ( Symbol ) ; } </s>


<s> bool emitSymbolAttribute ( MCSymbol * Symbol , MCSymbolAttr Attribute ) override { bool Val = MCELFStreamer :: emitSymbolAttribute ( Symbol , Attribute ) ; if ( ! IsThumb ) return Val ; unsigned Type = cast < MCSymbolELF > ( Symbol ) -> getType ( ) ; if ( ( Type == ELF :: STT_FUNC || Type == ELF :: STT_GNU_IFUNC ) && Symbol -> isDefined ( ) ) getAssembler ( ) . setIsThumbFunc ( Symbol ) ; return Val ; } </s>


<s> void emitThumbFunc ( MCSymbol * Func ) override { getAssembler ( ) . setIsThumbFunc ( Func ) ; emitSymbolAttribute ( Func , MCSA_ELF_TypeFunction ) ; } </s>

Note in the output that the specified Func is a Thumb mode function ( ARM target only ) .


<s>
void
emitValueImpl
(
const
MCExpr
*
Value
,
unsigned
Size
,
SMLoc
Loc
)
override
{
if
(
const
MCSymbolRefExpr
*
SRE
=
dyn_cast_or_null
<
MCSymbolRefExpr
>
(
Value
)
)
{
if
(
SRE
->
getKind
(
)
==
MCSymbolRefExpr
::
VK_ARM_SBREL
&&
!
(
Size
==
4
)
)
{
getContext
(
)
.
reportError
(
Loc
,
"relocated expression must be 32-bit"
)
;
return
;
}
getOrCreateDataFragment
(
)
;
}
emitDataMappingSymbol
(
)
;
MCELFStreamer
::
emitValueImpl
(
Value
,
Size
,
Loc
)
;
}
</s>

Overriding these functions allows us to dismiss all labels that are candidates for marking as microMIPS when .word/.long/.4byte etc directives are emitted .

ARM
ARM
4
"relocated expression must be 32-bit"


<s> void ARMELFStreamer :: finishImpl ( ) { MCTargetStreamer & TS = * getTargetStreamer ( ) ; ARMTargetStreamer & ATS = static_cast < ARMTargetStreamer & > ( TS ) ; ATS . finishAttributeSection ( ) ; MCELFStreamer :: finishImpl ( ) ; } </s>


<s> void EmitInstruction ( const MCInst & Inst , const MCSubtargetInfo & STI ) override { if ( IsThumb ) EmitThumbMappingSymbol ( ) ; else EmitARMMappingSymbol ( ) ; MCELFStreamer :: EmitInstruction ( Inst , STI ) ; } </s>


<s> void ARMTargetELFStreamer :: emitLabel ( MCSymbol * Symbol ) { ARMELFStreamer & Streamer = getStreamer ( ) ; if ( ! Streamer . IsThumb ) return ; const MCSymbolData & SD = Streamer . getOrCreateSymbolData ( Symbol ) ; if ( MCELF :: GetType ( SD ) & ( ELF :: STT_FUNC << ELF_STT_Shift ) ) Streamer . EmitThumbFunc ( Symbol ) ; } </s>


<s>
void
ARMELFStreamer
::
EmitRegSave
(
const
SmallVectorImpl
<
unsigned
>
&
RegList
,
bool
IsVector
)
{
unsigned
Count
=
0
;
uint32_t
Mask
=
0
;
const
MCRegisterInfo
*
MRI
=
getContext
(
)
.
getRegisterInfo
(
)
;
for
(
size_t
i
=
0
;
i
<
RegList
.
size
(
)
;
++
i
)
{
unsigned
Reg
=
MRI
->
getEncodingValue
(
RegList
[
i
]
)
;
assert
(
Reg
<
(
IsVector
32U
:
16U
)
&&
"Register out of range"
)
;
unsigned
Bit
=
(
1u
<<
Reg
)
;
if
(
(
Mask
&
Bit
)
==
0
)
{
Mask
|=
Bit
;
++
Count
;
}
}
SPOffset
-=
Count
*
(
IsVector
8
:
4
)
;
FlushPendingOffset
(
)
;
if
(
IsVector
)
UnwindOpAsm
.
EmitVFPRegSave
(
Mask
)
;
else
UnwindOpAsm
.
EmitRegSave
(
Mask
)
;
}
</s>


<s> void ARMELFStreamer :: Reset ( ) { ExTab = NULL ; FnStart = NULL ; Personality = NULL ; PersonalityIndex = NUM_PERSONALITY_INDEX ; FPReg = ARM :: SP ; FPOffset = 0 ; SPOffset = 0 ; PendingOffset = 0 ; UsedFP = false ; CantUnwind = false ; Opcodes . clear ( ) ; UnwindOpAsm . Reset ( ) ; } </s>


<s> ARMELFStreamer & ARMTargetELFStreamer :: getStreamer ( ) { ARMELFStreamer * S = static_cast < ARMELFStreamer * > ( Streamer ) ; return * S ; } </s>


<s> const_iterator begin ( ) const { return m_SectToExData . begin ( ) ; } </s>


<s> std :: unique_ptr < ARMInputExMap > ARMInputExMap :: create ( Input & pInput ) { std :: unique_ptr < ARMInputExMap > exMap ( new ARMInputExMap ( ) ) ; LDContext * ctx = pInput . context ( ) ; for ( LDContext :: sect_iterator it = ctx -> sectBegin ( ) , end = ctx -> sectEnd ( ) ; it != end ; ++ it ) { LDSection * sect = * it ; if ( sect -> type ( ) == llvm :: ELF :: SHT_ARM_EXIDX ) { ARMExSectionTuple * exTuple = exMap -> getOrCreateByExSection ( * sect ) ; exTuple -> setExIdxSection ( sect ) ; exTuple -> setTextSection ( sect -> getLink ( ) ) ; if ( sect -> getLink ( ) == NULL ) { fatal ( diag :: eh_missing_text_section ) << sect -> name ( ) << pInput . name ( ) ; } } } ARMInputExMap :: iterator it = exMap -> begin ( ) ; ARMInputExMap :: iterator end = exMap -> end ( ) ; while ( it != end ) { ARMExSectionTuple * exTuple = it -> second . get ( ) ; LDSection * const text = exTuple -> getTextSection ( ) ; LDSection * const exIdx = exTuple -> getExIdxSection ( ) ; if ( ( text -> kind ( ) == LDFileFormat :: Ignore ) || ( text -> kind ( ) == LDFileFormat :: Folded ) ) { exIdx -> setKind ( LDFileFormat :: Ignore ) ; ARMInputExMap :: iterator deadIt = it ++ ; exMap -> erase ( deadIt ) ; continue ; } RegionFragment * textFrag = findRegionFragment ( * text ) ; RegionFragment * exIdxFrag = findRegionFragment ( * exIdx ) ; exTuple -> setTextFragment ( textFrag ) ; exTuple -> setExIdxFragment ( exIdxFrag ) ; if ( exIdxFrag == NULL ) { ARMInputExMap :: iterator deadIt = it ++ ; exMap -> erase ( deadIt ) ; continue ; } ++ it ; } return exMap ; } </s>

ARM ARM ARMInputExMap::create ARM ARM ARM ARM ARMInputExMap::iterator ARMInputExMap::iterator ARM ARMInputExMap::iterator ARMInputExMap::iterator


<s> const_iterator end ( ) const { return m_SectToExData . end ( ) ; } </s>

Get a const_iterator to the end of the symbol table .


<s> void erase ( iterator it ) { m_SectToExData . erase ( it ) ; } </s>

erase - Erases an element identified by Key , if it exists .


<s>
const
char
*
getPassName
(
)
const
override
{
return
"ARM pseudo instruction expansion pass"
;
}
</s>

getPassName - Return a nice clean name for a pass .

ARM
"ARM pseudo instruction expansion pass"


"After expanding ARM pseudo instructions."

runOnMachineFunction - Emit the function body .


<s>
virtual
const
char
*
getPassName
(
)
const
{
return
"ARM pseudo instruction expansion pass"
;
}
</s>


<s> StringRef getPassName ( ) const override { return ARM_EXPAND_PSEUDO_NAME ; } </s>


"********** ARM EXPAND PSEUDO INSTRUCTIONS **********\n"


<s>
StringRef
getPassName
(
)
const
override
{
return
"ARM pseudo instruction expansion pass"
;
}
</s>


<s> bool ARMExpandPseudo :: runOnMachineFunction ( MachineFunction & MF ) { TII = MF . getTarget ( ) . getInstrInfo ( ) ; TRI = MF . getTarget ( ) . getRegisterInfo ( ) ; bool Modified = false ; for ( MachineFunction :: iterator MFI = MF . begin ( ) , E = MF . end ( ) ; MFI != E ; ++ MFI ) Modified |= ExpandMBB ( * MFI ) ; return Modified ; } </s>


<s> bool ARMExpandPseudo :: runOnMachineFunction ( MachineFunction & MF ) { TII = static_cast < const ARMBaseInstrInfo * > ( MF . getTarget ( ) . getInstrInfo ( ) ) ; TRI = MF . getTarget ( ) . getRegisterInfo ( ) ; STI = & MF . getTarget ( ) . getSubtarget < ARMSubtarget > ( ) ; bool Modified = false ; for ( MachineFunction :: iterator MFI = MF . begin ( ) , E = MF . end ( ) ; MFI != E ; ++ MFI ) Modified |= ExpandMBB ( * MFI ) ; return Modified ; } </s>


<s> bool ARMExpandPseudo :: runOnMachineFunction ( MachineFunction & MF ) { const TargetMachine & TM = MF . getTarget ( ) ; TII = static_cast < const ARMBaseInstrInfo * > ( TM . getInstrInfo ( ) ) ; TRI = TM . getRegisterInfo ( ) ; STI = & TM . getSubtarget < ARMSubtarget > ( ) ; AFI = MF . getInfo < ARMFunctionInfo > ( ) ; bool Modified = false ; for ( MachineFunction :: iterator MFI = MF . begin ( ) , E = MF . end ( ) ; MFI != E ; ++ MFI ) Modified |= ExpandMBB ( * MFI ) ; return Modified ; } </s>


<s> bool ARMExpandPseudo :: runOnMachineFunction ( MachineFunction & MF ) { TII = MF . getTarget ( ) . getInstrInfo ( ) ; bool Modified = false ; for ( MachineFunction :: iterator MFI = MF . begin ( ) , E = MF . end ( ) ; MFI != E ; ++ MFI ) Modified |= ExpandMBB ( * MFI ) ; return Modified ; } </s>


<s> FastISel * ARM :: createFastISel ( FunctionLoweringInfo & funcInfo , const TargetLibraryInfo * libInfo ) { const TargetMachine & TM = funcInfo . MF -> getTarget ( ) ; const ARMSubtarget * Subtarget = & TM . getSubtarget < ARMSubtarget > ( ) ; bool UseFastISel = false ; UseFastISel |= Subtarget -> isTargetIOS ( ) && ! Subtarget -> isThumb1Only ( ) ; UseFastISel |= Subtarget -> isTargetLinux ( ) && ! Subtarget -> isThumb ( ) ; UseFastISel |= Subtarget -> isTargetNaCl ( ) && ! Subtarget -> isThumb ( ) ; if ( UseFastISel ) { TM . Options . NoFramePointerElim = true ; return new ARMFastISel ( funcInfo , libInfo ) ; } return 0 ; } </s>

This method returns a target specific FastISel object , or null if the target does not support `` fast '' ISel .


<s>
CCAssignFn
*
ARMFastISel
::
CCAssignFnForCall
(
CallingConv
::
ID
CC
,
bool
Return
,
bool
isVarArg
)
{
switch
(
CC
)
{
default
:
report_fatal_error
(
"Unsupported calling convention"
)
;
case
CallingConv
::
Fast
:
if
(
Subtarget
->
hasVFP2
(
)
&&
!
isVarArg
)
{
if
(
!
Subtarget
->
isAAPCS_ABI
(
)
)
return
(
Return
RetFastCC_ARM_APCS
:
FastCC_ARM_APCS
)
;
return
(
Return
RetCC_ARM_AAPCS_VFP
:
CC_ARM_AAPCS_VFP
)
;
}
LLVM_FALLTHROUGH
;
case
CallingConv
::
C
:
case
CallingConv
::
CXX_FAST_TLS
:
if
(
Subtarget
->
isAAPCS_ABI
(
)
)
{
if
(
Subtarget
->
hasVFP2
(
)
&&
TM
.
Options
.
FloatABIType
==
FloatABI
::
Hard
&&
!
isVarArg
)
return
(
Return
RetCC_ARM_AAPCS_VFP
:
CC_ARM_AAPCS_VFP
)
;
else
return
(
Return
RetCC_ARM_AAPCS
:
CC_ARM_AAPCS
)
;
}
else
{
return
(
Return
RetCC_ARM_APCS
:
CC_ARM_APCS
)
;
}
case
CallingConv
::
ARM_AAPCS_VFP
:
case
CallingConv
::
Swift
:
if
(
!
isVarArg
)
return
(
Return
RetCC_ARM_AAPCS_VFP
:
CC_ARM_AAPCS_VFP
)
;
LLVM_FALLTHROUGH
;
case
CallingConv
::
ARM_AAPCS
:
return
(
Return
RetCC_ARM_AAPCS
:
CC_ARM_AAPCS
)
;
case
CallingConv
::
ARM_APCS
:
return
(
Return
RetCC_ARM_APCS
:
CC_ARM_APCS
)
;
case
CallingConv
::
GHC
:
if
(
Return
)
report_fatal_error
(
"Can't return in GHC call convention"
)
;
else
return
CC_ARM_APCS_GHC
;
}
}
</s>

Selects the correct CCAssignFn for a given CallingConvention value .

ARM
ARM
"Unsupported calling convention"
ARM
ARM
ARM
ARM
ARM
ARM
ARM
ARM
ARM
ARM
ARM
ARM
ARM
ARM
ARM
ARM
ARM
ARM
ARM
"Can't return in GHC call convention"
ARM


<s> FastISel * ARM :: createFastISel ( FunctionLoweringInfo & funcInfo , const TargetLibraryInfo * libInfo ) { if ( funcInfo . MF -> getSubtarget < ARMSubtarget > ( ) . useFastISel ( ) ) return new ARMFastISel ( funcInfo , libInfo ) ; return nullptr ; } </s>


<s> unsigned ARMFastISel :: fastEmitInst_i ( unsigned MachineInstOpcode , const TargetRegisterClass * RC , uint64_t Imm ) { unsigned ResultReg = createResultReg ( RC ) ; const MCInstrDesc & II = TII . get ( MachineInstOpcode ) ; if ( II . getNumDefs ( ) >= 1 ) { AddOptionalDefs ( BuildMI ( * FuncInfo . MBB , FuncInfo . InsertPt , DbgLoc , II , ResultReg ) . addImm ( Imm ) ) ; } else { AddOptionalDefs ( BuildMI ( * FuncInfo . MBB , FuncInfo . InsertPt , DbgLoc , II ) . addImm ( Imm ) ) ; AddOptionalDefs ( BuildMI ( * FuncInfo . MBB , FuncInfo . InsertPt , DbgLoc , TII . get ( TargetOpcode :: COPY ) , ResultReg ) . addReg ( II . ImplicitDefs [ 0 ] ) ) ; } return ResultReg ; } </s>

Emit a MachineInstr with a single immediate operand , and a result register in the given register class .


<s> unsigned ARMFastISel :: fastEmitInst_r ( unsigned MachineInstOpcode , const TargetRegisterClass * RC , unsigned Op0 , bool Op0IsKill ) { unsigned ResultReg = createResultReg ( RC ) ; const MCInstrDesc & II = TII . get ( MachineInstOpcode ) ; Op0 = constrainOperandRegClass ( II , Op0 , 1 ) ; if ( II . getNumDefs ( ) >= 1 ) { AddOptionalDefs ( BuildMI ( * FuncInfo . MBB , FuncInfo . InsertPt , DbgLoc , II , ResultReg ) . addReg ( Op0 , Op0IsKill * RegState :: Kill ) ) ; } else { AddOptionalDefs ( BuildMI ( * FuncInfo . MBB , FuncInfo . InsertPt , DbgLoc , II ) . addReg ( Op0 , Op0IsKill * RegState :: Kill ) ) ; AddOptionalDefs ( BuildMI ( * FuncInfo . MBB , FuncInfo . InsertPt , DbgLoc , TII . get ( TargetOpcode :: COPY ) , ResultReg ) . addReg ( II . ImplicitDefs [ 0 ] ) ) ; } return ResultReg ; } </s>

Emit a MachineInstr with one register operand and a result register in the given register class .


<s> unsigned ARMFastISel :: fastEmitInst_ri ( unsigned MachineInstOpcode , const TargetRegisterClass * RC , unsigned Op0 , bool Op0IsKill , uint64_t Imm ) { unsigned ResultReg = createResultReg ( RC ) ; const MCInstrDesc & II = TII . get ( MachineInstOpcode ) ; Op0 = constrainOperandRegClass ( II , Op0 , 1 ) ; if ( II . getNumDefs ( ) >= 1 ) { AddOptionalDefs ( BuildMI ( * FuncInfo . MBB , FuncInfo . InsertPt , DbgLoc , II , ResultReg ) . addReg ( Op0 , Op0IsKill * RegState :: Kill ) . addImm ( Imm ) ) ; } else { AddOptionalDefs ( BuildMI ( * FuncInfo . MBB , FuncInfo . InsertPt , DbgLoc , II ) . addReg ( Op0 , Op0IsKill * RegState :: Kill ) . addImm ( Imm ) ) ; AddOptionalDefs ( BuildMI ( * FuncInfo . MBB , FuncInfo . InsertPt , DbgLoc , TII . get ( TargetOpcode :: COPY ) , ResultReg ) . addReg ( II . ImplicitDefs [ 0 ] ) ) ; } return ResultReg ; } </s>

Emit a MachineInstr with a register operand , an immediate , and a result register in the given register class .


<s> unsigned ARMFastISel :: fastEmitInst_rr ( unsigned MachineInstOpcode , const TargetRegisterClass * RC , unsigned Op0 , bool Op0IsKill , unsigned Op1 , bool Op1IsKill ) { unsigned ResultReg = createResultReg ( RC ) ; const MCInstrDesc & II = TII . get ( MachineInstOpcode ) ; Op0 = constrainOperandRegClass ( II , Op0 , 1 ) ; Op1 = constrainOperandRegClass ( II , Op1 , 2 ) ; if ( II . getNumDefs ( ) >= 1 ) { AddOptionalDefs ( BuildMI ( * FuncInfo . MBB , FuncInfo . InsertPt , DbgLoc , II , ResultReg ) . addReg ( Op0 , Op0IsKill * RegState :: Kill ) . addReg ( Op1 , Op1IsKill * RegState :: Kill ) ) ; } else { AddOptionalDefs ( BuildMI ( * FuncInfo . MBB , FuncInfo . InsertPt , DbgLoc , II ) . addReg ( Op0 , Op0IsKill * RegState :: Kill ) . addReg ( Op1 , Op1IsKill * RegState :: Kill ) ) ; AddOptionalDefs ( BuildMI ( * FuncInfo . MBB , FuncInfo . InsertPt , DbgLoc , TII . get ( TargetOpcode :: COPY ) , ResultReg ) . addReg ( II . ImplicitDefs [ 0 ] ) ) ; } return ResultReg ; } </s>

Emit a MachineInstr with two register operands and a result register in the given register class .


<s> unsigned ARMFastISel :: fastMaterializeAlloca ( const AllocaInst * AI ) { if ( ! FuncInfo . StaticAllocaMap . count ( AI ) ) return 0 ; MVT VT ; if ( ! isLoadTypeLegal ( AI -> getType ( ) , VT ) ) return 0 ; DenseMap < const AllocaInst * , int > :: iterator SI = FuncInfo . StaticAllocaMap . find ( AI ) ; if ( SI != FuncInfo . StaticAllocaMap . end ( ) ) { unsigned Opc = isThumb2 ? ARM :: t2ADDri : ARM :: ADDri ; const TargetRegisterClass * RC = TLI . getRegClassFor ( VT ) ; unsigned ResultReg = createResultReg ( RC ) ; ResultReg = constrainOperandRegClass ( TII . get ( Opc ) , ResultReg , 0 ) ; AddOptionalDefs ( BuildMI ( * FuncInfo . MBB , FuncInfo . InsertPt , DbgLoc , TII . get ( Opc ) , ResultReg ) . addFrameIndex ( SI -> second ) . addImm ( 0 ) ) ; return ResultReg ; } return 0 ; } </s>

Emit an alloca address in a register using target-specific logic .


<s> unsigned ARMFastISel :: fastMaterializeConstant ( const Constant * C ) { EVT CEVT = TLI . getValueType ( DL , C -> getType ( ) , true ) ; if ( ! CEVT . isSimple ( ) ) return 0 ; MVT VT = CEVT . getSimpleVT ( ) ; if ( const ConstantFP * CFP = dyn_cast < ConstantFP > ( C ) ) return ARMMaterializeFP ( CFP , VT ) ; else if ( const GlobalValue * GV = dyn_cast < GlobalValue > ( C ) ) return ARMMaterializeGV ( GV , VT ) ; else if ( isa < ConstantInt > ( C ) ) return ARMMaterializeInt ( C , VT ) ; return 0 ; } </s>

Emit a constant in a register using target-specific logic , such as constant pool loads .


<s> bool ARMFastISel :: isTypeLegal ( Type * Ty , MVT & VT ) { EVT evt = TLI . getValueType ( DL , Ty , true ) ; if ( evt == MVT :: Other || ! evt . isSimple ( ) ) return false ; VT = evt . getSimpleVT ( ) ; return TLI . isTypeLegal ( VT ) ; } </s>


<s>
CCAssignFn
*
ARMFastISel
::
CCAssignFnForCall
(
CallingConv
::
ID
CC
,
bool
Return
,
bool
isVarArg
)
{
switch
(
CC
)
{
default
:
llvm_unreachable
(
"Unsupported calling convention"
)
;
case
CallingConv
::
Fast
:
if
(
Subtarget
->
hasVFP2
(
)
&&
!
isVarArg
)
{
if
(
!
Subtarget
->
isAAPCS_ABI
(
)
)
return
(
Return
RetFastCC_ARM_APCS
:
FastCC_ARM_APCS
)
;
return
(
Return
RetCC_ARM_AAPCS_VFP
:
CC_ARM_AAPCS_VFP
)
;
}
LLVM_FALLTHROUGH
;
case
CallingConv
::
C
:
case
CallingConv
::
CXX_FAST_TLS
:
if
(
Subtarget
->
isAAPCS_ABI
(
)
)
{
if
(
Subtarget
->
hasVFP2
(
)
&&
TM
.
Options
.
FloatABIType
==
FloatABI
::
Hard
&&
!
isVarArg
)
return
(
Return
RetCC_ARM_AAPCS_VFP
:
CC_ARM_AAPCS_VFP
)
;
else
return
(
Return
RetCC_ARM_AAPCS
:
CC_ARM_AAPCS
)
;
}
else
{
return
(
Return
RetCC_ARM_APCS
:
CC_ARM_APCS
)
;
}
case
CallingConv
::
ARM_AAPCS_VFP
:
case
CallingConv
::
Swift
:
if
(
!
isVarArg
)
return
(
Return
RetCC_ARM_AAPCS_VFP
:
CC_ARM_AAPCS_VFP
)
;
LLVM_FALLTHROUGH
;
case
CallingConv
::
ARM_AAPCS
:
return
(
Return
RetCC_ARM_AAPCS
:
CC_ARM_AAPCS
)
;
case
CallingConv
::
ARM_APCS
:
return
(
Return
RetCC_ARM_APCS
:
CC_ARM_APCS
)
;
case
CallingConv
::
GHC
:
if
(
Return
)
llvm_unreachable
(
"Can't return in GHC call convention"
)
;
else
return
CC_ARM_APCS_GHC
;
}
}
</s>


<s> bool ARMFastISel :: fastLowerArguments ( ) { if ( ! FuncInfo . CanLowerReturn ) return false ; const Function * F = FuncInfo . Fn ; if ( F -> isVarArg ( ) ) return false ; CallingConv :: ID CC = F -> getCallingConv ( ) ; switch ( CC ) { default : return false ; case CallingConv :: Fast : case CallingConv :: C : case CallingConv :: ARM_AAPCS_VFP : case CallingConv :: ARM_AAPCS : case CallingConv :: ARM_APCS : case CallingConv :: Swift : break ; } for ( const Argument & Arg : F -> args ( ) ) { if ( Arg . getArgNo ( ) >= 4 ) return false ; if ( Arg . hasAttribute ( Attribute :: InReg ) || Arg . hasAttribute ( Attribute :: StructRet ) || Arg . hasAttribute ( Attribute :: SwiftSelf ) || Arg . hasAttribute ( Attribute :: SwiftError ) || Arg . hasAttribute ( Attribute :: ByVal ) ) return false ; Type * ArgTy = Arg . getType ( ) ; if ( ArgTy -> isStructTy ( ) || ArgTy -> isArrayTy ( ) || ArgTy -> isVectorTy ( ) ) return false ; EVT ArgVT = TLI . getValueType ( DL , ArgTy ) ; if ( ! ArgVT . isSimple ( ) ) return false ; switch ( ArgVT . getSimpleVT ( ) . SimpleTy ) { case MVT :: i8 : case MVT :: i16 : case MVT :: i32 : break ; default : return false ; } } static const MCPhysReg GPRArgRegs [ ] = { ARM :: R0 , ARM :: R1 , ARM :: R2 , ARM :: R3 } ; const TargetRegisterClass * RC = & ARM :: rGPRRegClass ; for ( const Argument & Arg : F -> args ( ) ) { unsigned ArgNo = Arg . getArgNo ( ) ; unsigned SrcReg = GPRArgRegs [ ArgNo ] ; unsigned DstReg = FuncInfo . MF -> addLiveIn ( SrcReg , RC ) ; unsigned ResultReg = createResultReg ( RC ) ; BuildMI ( * FuncInfo . MBB , FuncInfo . InsertPt , DbgLoc , TII . get ( TargetOpcode :: COPY ) , ResultReg ) . addReg ( DstReg , getKillRegState ( true ) ) ; updateValueMap ( & Arg , ResultReg ) ; } return true ; } </s>

This method is called by target-independent code to do target- specific argument lowering .


<s>
CCAssignFn
*
ARMFastISel
::
CCAssignFnForCall
(
CallingConv
::
ID
CC
,
bool
Return
,
bool
isVarArg
)
{
switch
(
CC
)
{
default
:
llvm_unreachable
(
"Unsupported calling convention"
)
;
case
CallingConv
::
Fast
:
if
(
Subtarget
->
hasVFP2
(
)
&&
!
isVarArg
)
{
if
(
!
Subtarget
->
isAAPCS_ABI
(
)
)
return
(
Return
RetFastCC_ARM_APCS
:
FastCC_ARM_APCS
)
;
return
(
Return
RetCC_ARM_AAPCS_VFP
:
CC_ARM_AAPCS_VFP
)
;
}
case
CallingConv
::
C
:
if
(
Subtarget
->
isAAPCS_ABI
(
)
)
{
if
(
Subtarget
->
hasVFP2
(
)
&&
TM
.
Options
.
FloatABIType
==
FloatABI
::
Hard
&&
!
isVarArg
)
return
(
Return
RetCC_ARM_AAPCS_VFP
:
CC_ARM_AAPCS_VFP
)
;
else
return
(
Return
RetCC_ARM_AAPCS
:
CC_ARM_AAPCS
)
;
}
else
return
(
Return
RetCC_ARM_APCS
:
CC_ARM_APCS
)
;
case
CallingConv
::
ARM_AAPCS_VFP
:
if
(
!
isVarArg
)
return
(
Return
RetCC_ARM_AAPCS_VFP
:
CC_ARM_AAPCS_VFP
)
;
case
CallingConv
::
ARM_AAPCS
:
return
(
Return
RetCC_ARM_AAPCS
:
CC_ARM_AAPCS
)
;
case
CallingConv
::
ARM_APCS
:
return
(
Return
RetCC_ARM_APCS
:
CC_ARM_APCS
)
;
case
CallingConv
::
GHC
:
if
(
Return
)
llvm_unreachable
(
"Can't return in GHC call convention"
)
;
else
return
CC_ARM_APCS_GHC
;
}
}
</s>


<s> unsigned ARMFastISel :: constrainOperandRegClass ( const MCInstrDesc & II , unsigned Op , unsigned OpNum ) { if ( TargetRegisterInfo :: isVirtualRegister ( Op ) ) { const TargetRegisterClass * RegClass = TII . getRegClass ( II , OpNum , & TRI , * FuncInfo . MF ) ; if ( ! MRI . constrainRegClass ( Op , RegClass ) ) { unsigned NewOp = createResultReg ( RegClass ) ; AddOptionalDefs ( BuildMI ( * FuncInfo . MBB , FuncInfo . InsertPt , DbgLoc , TII . get ( TargetOpcode :: COPY ) , NewOp ) . addReg ( Op ) ) ; return NewOp ; } } return Op ; } </s>

Try to constrain Op so that it is usable by argument OpNum of the provided MCInstrDesc .


<s> FastISel * ARM :: createFastISel ( FunctionLoweringInfo & funcInfo , const TargetLibraryInfo * libInfo ) { const TargetMachine & TM = funcInfo . MF -> getTarget ( ) ; const ARMSubtarget * Subtarget = & TM . getSubtarget < ARMSubtarget > ( ) ; bool UseFastISel = false ; UseFastISel |= Subtarget -> isTargetMachO ( ) && ! Subtarget -> isThumb1Only ( ) ; UseFastISel |= Subtarget -> isTargetLinux ( ) && ! Subtarget -> isThumb ( ) ; UseFastISel |= Subtarget -> isTargetNaCl ( ) && ! Subtarget -> isThumb ( ) ; if ( UseFastISel ) { TM . Options . NoFramePointerElim = true ; return new ARMFastISel ( funcInfo , libInfo ) ; } return 0 ; } </s>


<s> bool ARMFastISel :: isTypeLegal ( Type * Ty , MVT & VT ) { EVT evt = TLI . getValueType ( Ty , true ) ; if ( evt == MVT :: Other || ! evt . isSimple ( ) ) return false ; VT = evt . getSimpleVT ( ) ; return TLI . isTypeLegal ( VT ) ; } </s>


<s>
CCAssignFn
*
ARMFastISel
::
CCAssignFnForCall
(
CallingConv
::
ID
CC
,
bool
Return
,
bool
isVarArg
)
{
switch
(
CC
)
{
default
:
llvm_unreachable
(
"Unsupported calling convention"
)
;
case
CallingConv
::
Fast
:
if
(
Subtarget
->
hasVFP2
(
)
&&
!
isVarArg
)
{
if
(
!
Subtarget
->
isAAPCS_ABI
(
)
)
return
(
Return
RetFastCC_ARM_APCS
:
FastCC_ARM_APCS
)
;
return
(
Return
RetCC_ARM_AAPCS_VFP
:
CC_ARM_AAPCS_VFP
)
;
}
case
CallingConv
::
C
:
if
(
Subtarget
->
isAAPCS_ABI
(
)
)
{
if
(
Subtarget
->
hasVFP2
(
)
&&
TM
.
Options
.
FloatABIType
==
FloatABI
::
Hard
&&
!
isVarArg
)
return
(
Return
RetCC_ARM_AAPCS_VFP
:
CC_ARM_AAPCS_VFP
)
;
else
return
(
Return
RetCC_ARM_AAPCS
:
CC_ARM_AAPCS
)
;
}
else
{
return
(
Return
RetCC_ARM_APCS
:
CC_ARM_APCS
)
;
}
case
CallingConv
::
ARM_AAPCS_VFP
:
if
(
!
isVarArg
)
return
(
Return
RetCC_ARM_AAPCS_VFP
:
CC_ARM_AAPCS_VFP
)
;
case
CallingConv
::
ARM_AAPCS
:
return
(
Return
RetCC_ARM_AAPCS
:
CC_ARM_AAPCS
)
;
case
CallingConv
::
ARM_APCS
:
return
(
Return
RetCC_ARM_APCS
:
CC_ARM_APCS
)
;
case
CallingConv
::
GHC
:
if
(
Return
)
llvm_unreachable
(
"Can't return in GHC call convention"
)
;
else
return
CC_ARM_APCS_GHC
;
}
}
</s>


<s> unsigned ARMFastISel :: fastEmitInst_rri ( unsigned MachineInstOpcode , const TargetRegisterClass * RC , unsigned Op0 , bool Op0IsKill , unsigned Op1 , bool Op1IsKill , uint64_t Imm ) { unsigned ResultReg = createResultReg ( RC ) ; const MCInstrDesc & II = TII . get ( MachineInstOpcode ) ; Op0 = constrainOperandRegClass ( II , Op0 , 1 ) ; Op1 = constrainOperandRegClass ( II , Op1 , 2 ) ; if ( II . getNumDefs ( ) >= 1 ) { AddOptionalDefs ( BuildMI ( * FuncInfo . MBB , FuncInfo . InsertPt , DbgLoc , II , ResultReg ) . addReg ( Op0 , Op0IsKill * RegState :: Kill ) . addReg ( Op1 , Op1IsKill * RegState :: Kill ) . addImm ( Imm ) ) ; } else { AddOptionalDefs ( BuildMI ( * FuncInfo . MBB , FuncInfo . InsertPt , DbgLoc , II ) . addReg ( Op0 , Op0IsKill * RegState :: Kill ) . addReg ( Op1 , Op1IsKill * RegState :: Kill ) . addImm ( Imm ) ) ; AddOptionalDefs ( BuildMI ( * FuncInfo . MBB , FuncInfo . InsertPt , DbgLoc , TII . get ( TargetOpcode :: COPY ) , ResultReg ) . addReg ( II . ImplicitDefs [ 0 ] ) ) ; } return ResultReg ; } </s>

Emit a MachineInstr with two register operands , an immediate , and a result register in the given register class .


<s> unsigned ARMFastISel :: fastEmitInst_rrr ( unsigned MachineInstOpcode , const TargetRegisterClass * RC , unsigned Op0 , bool Op0IsKill , unsigned Op1 , bool Op1IsKill , unsigned Op2 , bool Op2IsKill ) { unsigned ResultReg = createResultReg ( RC ) ; const MCInstrDesc & II = TII . get ( MachineInstOpcode ) ; Op0 = constrainOperandRegClass ( II , Op0 , 1 ) ; Op1 = constrainOperandRegClass ( II , Op1 , 2 ) ; Op2 = constrainOperandRegClass ( II , Op1 , 3 ) ; if ( II . getNumDefs ( ) >= 1 ) { AddOptionalDefs ( BuildMI ( * FuncInfo . MBB , FuncInfo . InsertPt , DbgLoc , II , ResultReg ) . addReg ( Op0 , Op0IsKill * RegState :: Kill ) . addReg ( Op1 , Op1IsKill * RegState :: Kill ) . addReg ( Op2 , Op2IsKill * RegState :: Kill ) ) ; } else { AddOptionalDefs ( BuildMI ( * FuncInfo . MBB , FuncInfo . InsertPt , DbgLoc , II ) . addReg ( Op0 , Op0IsKill * RegState :: Kill ) . addReg ( Op1 , Op1IsKill * RegState :: Kill ) . addReg ( Op2 , Op2IsKill * RegState :: Kill ) ) ; AddOptionalDefs ( BuildMI ( * FuncInfo . MBB , FuncInfo . InsertPt , DbgLoc , TII . get ( TargetOpcode :: COPY ) , ResultReg ) . addReg ( II . ImplicitDefs [ 0 ] ) ) ; } return ResultReg ; } </s>

Emit a MachineInstr with three register operands and a result register in the given register class .


<s> bool ARMFastISel :: fastLowerArguments ( ) { if ( ! FuncInfo . CanLowerReturn ) return false ; const Function * F = FuncInfo . Fn ; if ( F -> isVarArg ( ) ) return false ; CallingConv :: ID CC = F -> getCallingConv ( ) ; switch ( CC ) { default : return false ; case CallingConv :: Fast : case CallingConv :: C : case CallingConv :: ARM_AAPCS_VFP : case CallingConv :: ARM_AAPCS : case CallingConv :: ARM_APCS : break ; } unsigned Idx = 1 ; for ( Function :: const_arg_iterator I = F -> arg_begin ( ) , E = F -> arg_end ( ) ; I != E ; ++ I , ++ Idx ) { if ( Idx > 4 ) return false ; if ( F -> getAttributes ( ) . hasAttribute ( Idx , Attribute :: InReg ) || F -> getAttributes ( ) . hasAttribute ( Idx , Attribute :: StructRet ) || F -> getAttributes ( ) . hasAttribute ( Idx , Attribute :: ByVal ) ) return false ; Type * ArgTy = I -> getType ( ) ; if ( ArgTy -> isStructTy ( ) || ArgTy -> isArrayTy ( ) || ArgTy -> isVectorTy ( ) ) return false ; EVT ArgVT = TLI . getValueType ( DL , ArgTy ) ; if ( ! ArgVT . isSimple ( ) ) return false ; switch ( ArgVT . getSimpleVT ( ) . SimpleTy ) { case MVT :: i8 : case MVT :: i16 : case MVT :: i32 : break ; default : return false ; } } static const MCPhysReg GPRArgRegs [ ] = { ARM :: R0 , ARM :: R1 , ARM :: R2 , ARM :: R3 } ; const TargetRegisterClass * RC = & ARM :: rGPRRegClass ; Idx = 0 ; for ( Function :: const_arg_iterator I = F -> arg_begin ( ) , E = F -> arg_end ( ) ; I != E ; ++ I , ++ Idx ) { unsigned SrcReg = GPRArgRegs [ Idx ] ; unsigned DstReg = FuncInfo . MF -> addLiveIn ( SrcReg , RC ) ; unsigned ResultReg = createResultReg ( RC ) ; BuildMI ( * FuncInfo . MBB , FuncInfo . InsertPt , DbgLoc , TII . get ( TargetOpcode :: COPY ) , ResultReg ) . addReg ( DstReg , getKillRegState ( true ) ) ; updateValueMap ( & * I , ResultReg ) ; } return true ; } </s>


<s>
CCAssignFn
*
ARMFastISel
::
CCAssignFnForCall
(
CallingConv
::
ID
CC
,
bool
Return
,
bool
isVarArg
)
{
switch
(
CC
)
{
default
:
report_fatal_error
(
"Unsupported calling convention"
)
;
case
CallingConv
::
Fast
:
if
(
Subtarget
->
hasVFP2Base
(
)
&&
!
isVarArg
)
{
if
(
!
Subtarget
->
isAAPCS_ABI
(
)
)
return
(
Return
RetFastCC_ARM_APCS
:
FastCC_ARM_APCS
)
;
return
(
Return
RetCC_ARM_AAPCS_VFP
:
CC_ARM_AAPCS_VFP
)
;
}
LLVM_FALLTHROUGH
;
case
CallingConv
::
C
:
case
CallingConv
::
CXX_FAST_TLS
:
if
(
Subtarget
->
isAAPCS_ABI
(
)
)
{
if
(
Subtarget
->
hasVFP2Base
(
)
&&
TM
.
Options
.
FloatABIType
==
FloatABI
::
Hard
&&
!
isVarArg
)
return
(
Return
RetCC_ARM_AAPCS_VFP
:
CC_ARM_AAPCS_VFP
)
;
else
return
(
Return
RetCC_ARM_AAPCS
:
CC_ARM_AAPCS
)
;
}
else
{
return
(
Return
RetCC_ARM_APCS
:
CC_ARM_APCS
)
;
}
case
CallingConv
::
ARM_AAPCS_VFP
:
case
CallingConv
::
Swift
:
if
(
!
isVarArg
)
return
(
Return
RetCC_ARM_AAPCS_VFP
:
CC_ARM_AAPCS_VFP
)
;
LLVM_FALLTHROUGH
;
case
CallingConv
::
ARM_AAPCS
:
return
(
Return
RetCC_ARM_AAPCS
:
CC_ARM_AAPCS
)
;
case
CallingConv
::
ARM_APCS
:
return
(
Return
RetCC_ARM_APCS
:
CC_ARM_APCS
)
;
case
CallingConv
::
GHC
:
if
(
Return
)
report_fatal_error
(
"Can't return in GHC call convention"
)
;
else
return
CC_ARM_APCS_GHC
;
case
CallingConv
::
CFGuard_Check
:
return
(
Return
RetCC_ARM_AAPCS
:
CC_ARM_Win32_CFGuard_Check
)
;
}
}
</s>

ARM
ARM
"Unsupported calling convention"
ARM
ARM
ARM
ARM
ARM
ARM
ARM
ARM
ARM
ARM
ARM
ARM
ARM
ARM
ARM
ARM
ARM
ARM
ARM
"Can't return in GHC call convention"
ARM
ARM
ARM


<s> unsigned ARMFastISel :: fastEmitInst_r ( unsigned MachineInstOpcode , const TargetRegisterClass * RC , unsigned Op0 , bool Op0IsKill ) { Register ResultReg = createResultReg ( RC ) ; const MCInstrDesc & II = TII . get ( MachineInstOpcode ) ; Op0 = constrainOperandRegClass ( II , Op0 , 1 ) ; if ( II . getNumDefs ( ) >= 1 ) { AddOptionalDefs ( BuildMI ( * FuncInfo . MBB , FuncInfo . InsertPt , DbgLoc , II , ResultReg ) . addReg ( Op0 , Op0IsKill * RegState :: Kill ) ) ; } else { AddOptionalDefs ( BuildMI ( * FuncInfo . MBB , FuncInfo . InsertPt , DbgLoc , II ) . addReg ( Op0 , Op0IsKill * RegState :: Kill ) ) ; AddOptionalDefs ( BuildMI ( * FuncInfo . MBB , FuncInfo . InsertPt , DbgLoc , TII . get ( TargetOpcode :: COPY ) , ResultReg ) . addReg ( II . ImplicitDefs [ 0 ] ) ) ; } return ResultReg ; } </s>


<s> bool ARMFastISel :: fastLowerArguments ( ) { if ( ! FuncInfo . CanLowerReturn ) return false ; const Function * F = FuncInfo . Fn ; if ( F -> isVarArg ( ) ) return false ; CallingConv :: ID CC = F -> getCallingConv ( ) ; switch ( CC ) { default : return false ; case CallingConv :: Fast : case CallingConv :: C : case CallingConv :: ARM_AAPCS_VFP : case CallingConv :: ARM_AAPCS : case CallingConv :: ARM_APCS : break ; } unsigned Idx = 1 ; for ( Function :: const_arg_iterator I = F -> arg_begin ( ) , E = F -> arg_end ( ) ; I != E ; ++ I , ++ Idx ) { if ( Idx > 4 ) return false ; if ( F -> getAttributes ( ) . hasAttribute ( Idx , Attribute :: InReg ) || F -> getAttributes ( ) . hasAttribute ( Idx , Attribute :: StructRet ) || F -> getAttributes ( ) . hasAttribute ( Idx , Attribute :: ByVal ) ) return false ; Type * ArgTy = I -> getType ( ) ; if ( ArgTy -> isStructTy ( ) || ArgTy -> isArrayTy ( ) || ArgTy -> isVectorTy ( ) ) return false ; EVT ArgVT = TLI . getValueType ( DL , ArgTy ) ; if ( ! ArgVT . isSimple ( ) ) return false ; switch ( ArgVT . getSimpleVT ( ) . SimpleTy ) { case MVT :: i8 : case MVT :: i16 : case MVT :: i32 : break ; default : return false ; } } static const uint16_t GPRArgRegs [ ] = { ARM :: R0 , ARM :: R1 , ARM :: R2 , ARM :: R3 } ; const TargetRegisterClass * RC = & ARM :: rGPRRegClass ; Idx = 0 ; for ( Function :: const_arg_iterator I = F -> arg_begin ( ) , E = F -> arg_end ( ) ; I != E ; ++ I , ++ Idx ) { unsigned SrcReg = GPRArgRegs [ Idx ] ; unsigned DstReg = FuncInfo . MF -> addLiveIn ( SrcReg , RC ) ; unsigned ResultReg = createResultReg ( RC ) ; BuildMI ( * FuncInfo . MBB , FuncInfo . InsertPt , DbgLoc , TII . get ( TargetOpcode :: COPY ) , ResultReg ) . addReg ( DstReg , getKillRegState ( true ) ) ; updateValueMap ( & * I , ResultReg ) ; } return true ; } </s>


<s> FastISel * ARM :: createFastISel ( FunctionLoweringInfo & funcInfo , const TargetLibraryInfo * libInfo ) { const TargetMachine & TM = funcInfo . MF -> getTarget ( ) ; const ARMSubtarget * Subtarget = & TM . getSubtarget < ARMSubtarget > ( ) ; if ( Subtarget -> isTargetIOS ( ) && ! Subtarget -> isThumb1Only ( ) ) return new ARMFastISel ( funcInfo , libInfo ) ; return 0 ; } </s>


<s> FastISel * ARM :: createFastISel ( FunctionLoweringInfo & funcInfo , const TargetLibraryInfo * libInfo ) { const TargetMachine & TM = funcInfo . MF -> getTarget ( ) ; const ARMSubtarget & STI = static_cast < const ARMSubtarget & > ( funcInfo . MF -> getSubtarget ( ) ) ; bool UseFastISel = false ; UseFastISel |= STI . isTargetMachO ( ) && ! STI . isThumb1Only ( ) ; UseFastISel |= STI . isTargetLinux ( ) && ! STI . isThumb ( ) ; UseFastISel |= STI . isTargetNaCl ( ) && ! STI . isThumb ( ) ; if ( UseFastISel ) { TM . Options . NoFramePointerElim = true ; return new ARMFastISel ( funcInfo , libInfo ) ; } return nullptr ; } </s>


<s> bool ARMFastISel :: fastLowerArguments ( ) { if ( ! FuncInfo . CanLowerReturn ) return false ; const Function * F = FuncInfo . Fn ; if ( F -> isVarArg ( ) ) return false ; CallingConv :: ID CC = F -> getCallingConv ( ) ; switch ( CC ) { default : return false ; case CallingConv :: Fast : case CallingConv :: C : case CallingConv :: ARM_AAPCS_VFP : case CallingConv :: ARM_AAPCS : case CallingConv :: ARM_APCS : break ; } unsigned Idx = 1 ; for ( Function :: const_arg_iterator I = F -> arg_begin ( ) , E = F -> arg_end ( ) ; I != E ; ++ I , ++ Idx ) { if ( Idx > 4 ) return false ; if ( F -> getAttributes ( ) . hasAttribute ( Idx , Attribute :: InReg ) || F -> getAttributes ( ) . hasAttribute ( Idx , Attribute :: StructRet ) || F -> getAttributes ( ) . hasAttribute ( Idx , Attribute :: ByVal ) ) return false ; Type * ArgTy = I -> getType ( ) ; if ( ArgTy -> isStructTy ( ) || ArgTy -> isArrayTy ( ) || ArgTy -> isVectorTy ( ) ) return false ; EVT ArgVT = TLI . getValueType ( ArgTy ) ; if ( ! ArgVT . isSimple ( ) ) return false ; switch ( ArgVT . getSimpleVT ( ) . SimpleTy ) { case MVT :: i8 : case MVT :: i16 : case MVT :: i32 : break ; default : return false ; } } static const uint16_t GPRArgRegs [ ] = { ARM :: R0 , ARM :: R1 , ARM :: R2 , ARM :: R3 } ; const TargetRegisterClass * RC = & ARM :: rGPRRegClass ; Idx = 0 ; for ( Function :: const_arg_iterator I = F -> arg_begin ( ) , E = F -> arg_end ( ) ; I != E ; ++ I , ++ Idx ) { unsigned SrcReg = GPRArgRegs [ Idx ] ; unsigned DstReg = FuncInfo . MF -> addLiveIn ( SrcReg , RC ) ; unsigned ResultReg = createResultReg ( RC ) ; BuildMI ( * FuncInfo . MBB , FuncInfo . InsertPt , DbgLoc , TII . get ( TargetOpcode :: COPY ) , ResultReg ) . addReg ( DstReg , getKillRegState ( true ) ) ; updateValueMap ( I , ResultReg ) ; } return true ; } </s>


<s> unsigned ARMFastISel :: fastMaterializeConstant ( const Constant * C ) { EVT CEVT = TLI . getValueType ( C -> getType ( ) , true ) ; if ( ! CEVT . isSimple ( ) ) return 0 ; MVT VT = CEVT . getSimpleVT ( ) ; if ( const ConstantFP * CFP = dyn_cast < ConstantFP > ( C ) ) return ARMMaterializeFP ( CFP , VT ) ; else if ( const GlobalValue * GV = dyn_cast < GlobalValue > ( C ) ) return ARMMaterializeGV ( GV , VT ) ; else if ( isa < ConstantInt > ( C ) ) return ARMMaterializeInt ( C , VT ) ; return 0 ; } </s>


<s>
CCAssignFn
*
ARMFastISel
::
CCAssignFnForCall
(
CallingConv
::
ID
CC
,
bool
Return
,
bool
isVarArg
)
{
switch
(
CC
)
{
default
:
report_fatal_error
(
"Unsupported calling convention"
)
;
case
CallingConv
::
Fast
:
if
(
Subtarget
->
hasVFP2Base
(
)
&&
!
isVarArg
)
{
if
(
!
Subtarget
->
isAAPCS_ABI
(
)
)
return
(
Return
RetFastCC_ARM_APCS
:
FastCC_ARM_APCS
)
;
return
(
Return
RetCC_ARM_AAPCS_VFP
:
CC_ARM_AAPCS_VFP
)
;
}
LLVM_FALLTHROUGH
;
case
CallingConv
::
C
:
case
CallingConv
::
CXX_FAST_TLS
:
if
(
Subtarget
->
isAAPCS_ABI
(
)
)
{
if
(
Subtarget
->
hasVFP2Base
(
)
&&
TM
.
Options
.
FloatABIType
==
FloatABI
::
Hard
&&
!
isVarArg
)
return
(
Return
RetCC_ARM_AAPCS_VFP
:
CC_ARM_AAPCS_VFP
)
;
else
return
(
Return
RetCC_ARM_AAPCS
:
CC_ARM_AAPCS
)
;
}
else
{
return
(
Return
RetCC_ARM_APCS
:
CC_ARM_APCS
)
;
}
case
CallingConv
::
ARM_AAPCS_VFP
:
case
CallingConv
::
Swift
:
if
(
!
isVarArg
)
return
(
Return
RetCC_ARM_AAPCS_VFP
:
CC_ARM_AAPCS_VFP
)
;
LLVM_FALLTHROUGH
;
case
CallingConv
::
ARM_AAPCS
:
return
(
Return
RetCC_ARM_AAPCS
:
CC_ARM_AAPCS
)
;
case
CallingConv
::
ARM_APCS
:
return
(
Return
RetCC_ARM_APCS
:
CC_ARM_APCS
)
;
case
CallingConv
::
GHC
:
if
(
Return
)
report_fatal_error
(
"Can't return in GHC call convention"
)
;
else
return
CC_ARM_APCS_GHC
;
}
}
</s>


<s> llvm :: FastISel * ARM :: createFastISel ( FunctionLoweringInfo & funcInfo ) { if ( EnableARMFastISel ) return new ARMFastISel ( funcInfo ) ; return 0 ; } </s>


<s> bool ARMFastISel :: isTypeLegal ( const Type * Ty , EVT & VT ) { VT = TLI . getValueType ( Ty , true ) ; if ( VT == MVT :: Other || ! VT . isSimple ( ) ) return false ; return TLI . isTypeLegal ( VT ) ; } </s>


<s>
CCAssignFn
*
ARMFastISel
::
CCAssignFnForCall
(
CallingConv
::
ID
CC
,
bool
Return
,
bool
isVarArg
)
{
switch
(
CC
)
{
default
:
report_fatal_error
(
"Unsupported calling convention"
)
;
case
CallingConv
::
Fast
:
if
(
Subtarget
->
hasVFP2Base
(
)
&&
!
isVarArg
)
{
if
(
!
Subtarget
->
isAAPCS_ABI
(
)
)
return
(
Return
RetFastCC_ARM_APCS
:
FastCC_ARM_APCS
)
;
return
(
Return
RetCC_ARM_AAPCS_VFP
:
CC_ARM_AAPCS_VFP
)
;
}
LLVM_FALLTHROUGH
;
case
CallingConv
::
C
:
case
CallingConv
::
CXX_FAST_TLS
:
if
(
Subtarget
->
isAAPCS_ABI
(
)
)
{
if
(
Subtarget
->
hasVFP2Base
(
)
&&
TM
.
Options
.
FloatABIType
==
FloatABI
::
Hard
&&
!
isVarArg
)
return
(
Return
RetCC_ARM_AAPCS_VFP
:
CC_ARM_AAPCS_VFP
)
;
else
return
(
Return
RetCC_ARM_AAPCS
:
CC_ARM_AAPCS
)
;
}
else
{
return
(
Return
RetCC_ARM_APCS
:
CC_ARM_APCS
)
;
}
case
CallingConv
::
ARM_AAPCS_VFP
:
case
CallingConv
::
Swift
:
case
CallingConv
::
SwiftTail
:
if
(
!
isVarArg
)
return
(
Return
RetCC_ARM_AAPCS_VFP
:
CC_ARM_AAPCS_VFP
)
;
LLVM_FALLTHROUGH
;
case
CallingConv
::
ARM_AAPCS
:
return
(
Return
RetCC_ARM_AAPCS
:
CC_ARM_AAPCS
)
;
case
CallingConv
::
ARM_APCS
:
return
(
Return
RetCC_ARM_APCS
:
CC_ARM_APCS
)
;
case
CallingConv
::
GHC
:
if
(
Return
)
report_fatal_error
(
"Can't return in GHC call convention"
)
;
else
return
CC_ARM_APCS_GHC
;
case
CallingConv
::
CFGuard_Check
:
return
(
Return
RetCC_ARM_AAPCS
:
CC_ARM_Win32_CFGuard_Check
)
;
}
}
</s>


<s> unsigned ARMFastISel :: fastEmitInst_r ( unsigned MachineInstOpcode , const TargetRegisterClass * RC , unsigned Op0 ) { Register ResultReg = createResultReg ( RC ) ; const MCInstrDesc & II = TII . get ( MachineInstOpcode ) ; Op0 = constrainOperandRegClass ( II , Op0 , 1 ) ; if ( II . getNumDefs ( ) >= 1 ) { AddOptionalDefs ( BuildMI ( * FuncInfo . MBB , FuncInfo . InsertPt , DbgLoc , II , ResultReg ) . addReg ( Op0 ) ) ; } else { AddOptionalDefs ( BuildMI ( * FuncInfo . MBB , FuncInfo . InsertPt , DbgLoc , II ) . addReg ( Op0 ) ) ; AddOptionalDefs ( BuildMI ( * FuncInfo . MBB , FuncInfo . InsertPt , DbgLoc , TII . get ( TargetOpcode :: COPY ) , ResultReg ) . addReg ( II . ImplicitDefs [ 0 ] ) ) ; } return ResultReg ; } </s>


<s> unsigned ARMFastISel :: fastEmitInst_ri ( unsigned MachineInstOpcode , const TargetRegisterClass * RC , unsigned Op0 , uint64_t Imm ) { unsigned ResultReg = createResultReg ( RC ) ; const MCInstrDesc & II = TII . get ( MachineInstOpcode ) ; Op0 = constrainOperandRegClass ( II , Op0 , 1 ) ; if ( II . getNumDefs ( ) >= 1 ) { AddOptionalDefs ( BuildMI ( * FuncInfo . MBB , FuncInfo . InsertPt , DbgLoc , II , ResultReg ) . addReg ( Op0 ) . addImm ( Imm ) ) ; } else { AddOptionalDefs ( BuildMI ( * FuncInfo . MBB , FuncInfo . InsertPt , DbgLoc , II ) . addReg ( Op0 ) . addImm ( Imm ) ) ; AddOptionalDefs ( BuildMI ( * FuncInfo . MBB , FuncInfo . InsertPt , DbgLoc , TII . get ( TargetOpcode :: COPY ) , ResultReg ) . addReg ( II . ImplicitDefs [ 0 ] ) ) ; } return ResultReg ; } </s>


<s> unsigned ARMFastISel :: fastEmitInst_rr ( unsigned MachineInstOpcode , const TargetRegisterClass * RC , unsigned Op0 , unsigned Op1 ) { unsigned ResultReg = createResultReg ( RC ) ; const MCInstrDesc & II = TII . get ( MachineInstOpcode ) ; Op0 = constrainOperandRegClass ( II , Op0 , 1 ) ; Op1 = constrainOperandRegClass ( II , Op1 , 2 ) ; if ( II . getNumDefs ( ) >= 1 ) { AddOptionalDefs ( BuildMI ( * FuncInfo . MBB , FuncInfo . InsertPt , DbgLoc , II , ResultReg ) . addReg ( Op0 ) . addReg ( Op1 ) ) ; } else { AddOptionalDefs ( BuildMI ( * FuncInfo . MBB , FuncInfo . InsertPt , DbgLoc , II ) . addReg ( Op0 ) . addReg ( Op1 ) ) ; AddOptionalDefs ( BuildMI ( * FuncInfo . MBB , FuncInfo . InsertPt , DbgLoc , TII . get ( TargetOpcode :: COPY ) , ResultReg ) . addReg ( II . ImplicitDefs [ 0 ] ) ) ; } return ResultReg ; } </s>


<s>
CCAssignFn
*
ARMFastISel
::
CCAssignFnForCall
(
CallingConv
::
ID
CC
,
bool
Return
)
{
switch
(
CC
)
{
default
:
llvm_unreachable
(
"Unsupported calling convention"
)
;
case
CallingConv
::
Fast
:
(
void
)
RetFastCC_ARM_APCS
;
(
void
)
FastCC_ARM_APCS
;
case
CallingConv
::
C
:
if
(
Subtarget
->
isAAPCS_ABI
(
)
)
{
if
(
Subtarget
->
hasVFP2
(
)
&&
FloatABIType
==
FloatABI
::
Hard
)
return
(
Return
RetCC_ARM_AAPCS_VFP
:
CC_ARM_AAPCS_VFP
)
;
else
return
(
Return
RetCC_ARM_AAPCS
:
CC_ARM_AAPCS
)
;
}
else
return
(
Return
RetCC_ARM_APCS
:
CC_ARM_APCS
)
;
case
CallingConv
::
ARM_AAPCS_VFP
:
return
(
Return
RetCC_ARM_AAPCS_VFP
:
CC_ARM_AAPCS_VFP
)
;
case
CallingConv
::
ARM_AAPCS
:
return
(
Return
RetCC_ARM_AAPCS
:
CC_ARM_AAPCS
)
;
case
CallingConv
::
ARM_APCS
:
return
(
Return
RetCC_ARM_APCS
:
CC_ARM_APCS
)
;
}
}
</s>

ARM
ARM
"Unsupported calling convention"
ARM
ARM
ARM
ARM
ARM
ARM
ARM
ARM
ARM
ARM
ARM
ARM
ARM
ARM
ARM
ARM
ARM


<s> llvm :: FastISel * ARM :: createFastISel ( FunctionLoweringInfo & funcInfo ) { const TargetMachine & TM = funcInfo . MF -> getTarget ( ) ; const ARMSubtarget * Subtarget = & TM . getSubtarget < ARMSubtarget > ( ) ; if ( Subtarget -> isTargetDarwin ( ) && ! Subtarget -> isThumb1Only ( ) && ! DisableARMFastISel ) return new ARMFastISel ( funcInfo ) ; return 0 ; } </s>

ARM ARM::createFastISel ARM ARM ARM ARM 0


<s> bool ARMFastISel :: isTypeLegal ( const Type * Ty , MVT & VT ) { EVT evt = TLI . getValueType ( Ty , true ) ; if ( evt == MVT :: Other || ! evt . isSimple ( ) ) return false ; VT = evt . getSimpleVT ( ) ; return TLI . isTypeLegal ( VT ) ; } </s>


<s>
CCAssignFn
*
ARMFastISel
::
CCAssignFnForCall
(
CallingConv
::
ID
CC
,
bool
Return
)
{
switch
(
CC
)
{
default
:
llvm_unreachable
(
"Unsupported calling convention"
)
;
case
CallingConv
::
Fast
:
(
void
)
RetFastCC_ARM_APCS
;
(
void
)
FastCC_ARM_APCS
;
case
CallingConv
::
C
:
if
(
Subtarget
->
isAAPCS_ABI
(
)
)
{
if
(
Subtarget
->
hasVFP2
(
)
&&
TM
.
Options
.
FloatABIType
==
FloatABI
::
Hard
)
return
(
Return
RetCC_ARM_AAPCS_VFP
:
CC_ARM_AAPCS_VFP
)
;
else
return
(
Return
RetCC_ARM_AAPCS
:
CC_ARM_AAPCS
)
;
}
else
return
(
Return
RetCC_ARM_APCS
:
CC_ARM_APCS
)
;
case
CallingConv
::
ARM_AAPCS_VFP
:
return
(
Return
RetCC_ARM_AAPCS_VFP
:
CC_ARM_AAPCS_VFP
)
;
case
CallingConv
::
ARM_AAPCS
:
return
(
Return
RetCC_ARM_AAPCS
:
CC_ARM_AAPCS
)
;
case
CallingConv
::
ARM_APCS
:
return
(
Return
RetCC_ARM_APCS
:
CC_ARM_APCS
)
;
}
}
</s>


<s> FastISel * ARM :: createFastISel ( FunctionLoweringInfo & funcInfo ) { const TargetMachine & TM = funcInfo . MF -> getTarget ( ) ; const ARMSubtarget * Subtarget = & TM . getSubtarget < ARMSubtarget > ( ) ; if ( Subtarget -> isTargetIOS ( ) && ! Subtarget -> isThumb1Only ( ) ) return new ARMFastISel ( funcInfo ) ; return 0 ; } </s>


<s> bool ARMFastISel :: fastLowerArguments ( ) { if ( ! FuncInfo . CanLowerReturn ) return false ; const Function * F = FuncInfo . Fn ; if ( F -> isVarArg ( ) ) return false ; CallingConv :: ID CC = F -> getCallingConv ( ) ; switch ( CC ) { default : return false ; case CallingConv :: Fast : case CallingConv :: C : case CallingConv :: ARM_AAPCS_VFP : case CallingConv :: ARM_AAPCS : case CallingConv :: ARM_APCS : case CallingConv :: Swift : break ; } unsigned Idx = 1 ; for ( Function :: const_arg_iterator I = F -> arg_begin ( ) , E = F -> arg_end ( ) ; I != E ; ++ I , ++ Idx ) { if ( Idx > 4 ) return false ; if ( F -> getAttributes ( ) . hasAttribute ( Idx , Attribute :: InReg ) || F -> getAttributes ( ) . hasAttribute ( Idx , Attribute :: StructRet ) || F -> getAttributes ( ) . hasAttribute ( Idx , Attribute :: SwiftSelf ) || F -> getAttributes ( ) . hasAttribute ( Idx , Attribute :: SwiftError ) || F -> getAttributes ( ) . hasAttribute ( Idx , Attribute :: ByVal ) ) return false ; Type * ArgTy = I -> getType ( ) ; if ( ArgTy -> isStructTy ( ) || ArgTy -> isArrayTy ( ) || ArgTy -> isVectorTy ( ) ) return false ; EVT ArgVT = TLI . getValueType ( DL , ArgTy ) ; if ( ! ArgVT . isSimple ( ) ) return false ; switch ( ArgVT . getSimpleVT ( ) . SimpleTy ) { case MVT :: i8 : case MVT :: i16 : case MVT :: i32 : break ; default : return false ; } } static const MCPhysReg GPRArgRegs [ ] = { ARM :: R0 , ARM :: R1 , ARM :: R2 , ARM :: R3 } ; const TargetRegisterClass * RC = & ARM :: rGPRRegClass ; Idx = 0 ; for ( Function :: const_arg_iterator I = F -> arg_begin ( ) , E = F -> arg_end ( ) ; I != E ; ++ I , ++ Idx ) { unsigned SrcReg = GPRArgRegs [ Idx ] ; unsigned DstReg = FuncInfo . MF -> addLiveIn ( SrcReg , RC ) ; unsigned ResultReg = createResultReg ( RC ) ; BuildMI ( * FuncInfo . MBB , FuncInfo . InsertPt , DbgLoc , TII . get ( TargetOpcode :: COPY ) , ResultReg ) . addReg ( DstReg , getKillRegState ( true ) ) ; updateValueMap ( & * I , ResultReg ) ; } return true ; } </s>


<s> FastISel * ARM :: createFastISel ( FunctionLoweringInfo & funcInfo , const TargetLibraryInfo * libInfo ) { const TargetMachine & TM = funcInfo . MF -> getTarget ( ) ; const ARMSubtarget * Subtarget = & TM . getSubtarget < ARMSubtarget > ( ) ; bool UseFastISel = false ; UseFastISel |= Subtarget -> isTargetMachO ( ) && ! Subtarget -> isThumb1Only ( ) ; UseFastISel |= Subtarget -> isTargetLinux ( ) && ! Subtarget -> isThumb ( ) ; UseFastISel |= Subtarget -> isTargetNaCl ( ) && ! Subtarget -> isThumb ( ) ; if ( UseFastISel ) { TM . Options . NoFramePointerElim = true ; return new ARMFastISel ( funcInfo , libInfo ) ; } return nullptr ; } </s>


<s> unsigned ARMFastISel :: fastEmitInst_i ( unsigned MachineInstOpcode , const TargetRegisterClass * RC , uint64_t Imm ) { Register ResultReg = createResultReg ( RC ) ; const MCInstrDesc & II = TII . get ( MachineInstOpcode ) ; if ( II . getNumDefs ( ) >= 1 ) { AddOptionalDefs ( BuildMI ( * FuncInfo . MBB , FuncInfo . InsertPt , DbgLoc , II , ResultReg ) . addImm ( Imm ) ) ; } else { AddOptionalDefs ( BuildMI ( * FuncInfo . MBB , FuncInfo . InsertPt , DbgLoc , II ) . addImm ( Imm ) ) ; AddOptionalDefs ( BuildMI ( * FuncInfo . MBB , FuncInfo . InsertPt , DbgLoc , TII . get ( TargetOpcode :: COPY ) , ResultReg ) . addReg ( II . ImplicitDefs [ 0 ] ) ) ; } return ResultReg ; } </s>


<s> unsigned ARMFastISel :: fastEmitInst_ri ( unsigned MachineInstOpcode , const TargetRegisterClass * RC , unsigned Op0 , uint64_t Imm ) { Register ResultReg = createResultReg ( RC ) ; const MCInstrDesc & II = TII . get ( MachineInstOpcode ) ; Op0 = constrainOperandRegClass ( II , Op0 , 1 ) ; if ( II . getNumDefs ( ) >= 1 ) { AddOptionalDefs ( BuildMI ( * FuncInfo . MBB , FuncInfo . InsertPt , DbgLoc , II , ResultReg ) . addReg ( Op0 ) . addImm ( Imm ) ) ; } else { AddOptionalDefs ( BuildMI ( * FuncInfo . MBB , FuncInfo . InsertPt , DbgLoc , II ) . addReg ( Op0 ) . addImm ( Imm ) ) ; AddOptionalDefs ( BuildMI ( * FuncInfo . MBB , FuncInfo . InsertPt , DbgLoc , TII . get ( TargetOpcode :: COPY ) , ResultReg ) . addReg ( II . ImplicitDefs [ 0 ] ) ) ; } return ResultReg ; } </s>


<s> unsigned ARMFastISel :: fastEmitInst_rr ( unsigned MachineInstOpcode , const TargetRegisterClass * RC , unsigned Op0 , unsigned Op1 ) { Register ResultReg = createResultReg ( RC ) ; const MCInstrDesc & II = TII . get ( MachineInstOpcode ) ; Op0 = constrainOperandRegClass ( II , Op0 , 1 ) ; Op1 = constrainOperandRegClass ( II , Op1 , 2 ) ; if ( II . getNumDefs ( ) >= 1 ) { AddOptionalDefs ( BuildMI ( * FuncInfo . MBB , FuncInfo . InsertPt , DbgLoc , II , ResultReg ) . addReg ( Op0 ) . addReg ( Op1 ) ) ; } else { AddOptionalDefs ( BuildMI ( * FuncInfo . MBB , FuncInfo . InsertPt , DbgLoc , II ) . addReg ( Op0 ) . addReg ( Op1 ) ) ; AddOptionalDefs ( BuildMI ( * FuncInfo . MBB , FuncInfo . InsertPt , DbgLoc , TII . get ( TargetOpcode :: COPY ) , ResultReg ) . addReg ( II . ImplicitDefs [ 0 ] ) ) ; } return ResultReg ; } </s>


<s> unsigned ARMFastISel :: fastMaterializeAlloca ( const AllocaInst * AI ) { if ( ! FuncInfo . StaticAllocaMap . count ( AI ) ) return 0 ; MVT VT ; if ( ! isLoadTypeLegal ( AI -> getType ( ) , VT ) ) return 0 ; DenseMap < const AllocaInst * , int > :: iterator SI = FuncInfo . StaticAllocaMap . find ( AI ) ; if ( SI != FuncInfo . StaticAllocaMap . end ( ) ) { unsigned Opc = isThumb2 ? ARM :: t2ADDri : ARM :: ADDri ; const TargetRegisterClass * RC = TLI . getRegClassFor ( VT ) ; Register ResultReg = createResultReg ( RC ) ; ResultReg = constrainOperandRegClass ( TII . get ( Opc ) , ResultReg , 0 ) ; AddOptionalDefs ( BuildMI ( * FuncInfo . MBB , FuncInfo . InsertPt , DbgLoc , TII . get ( Opc ) , ResultReg ) . addFrameIndex ( SI -> second ) . addImm ( 0 ) ) ; return ResultReg ; } return 0 ; } </s>


<s>
CCAssignFn
*
ARMFastISel
::
CCAssignFnForCall
(
CallingConv
::
ID
CC
,
bool
Return
,
bool
isVarArg
)
{
switch
(
CC
)
{
default
:
llvm_unreachable
(
"Unsupported calling convention"
)
;
case
CallingConv
::
Fast
:
if
(
Subtarget
->
hasVFP2
(
)
&&
!
isVarArg
)
{
if
(
!
Subtarget
->
isAAPCS_ABI
(
)
)
return
(
Return
RetFastCC_ARM_APCS
:
FastCC_ARM_APCS
)
;
return
(
Return
RetCC_ARM_AAPCS_VFP
:
CC_ARM_AAPCS_VFP
)
;
}
case
CallingConv
::
C
:
case
CallingConv
::
CXX_FAST_TLS
:
if
(
Subtarget
->
isAAPCS_ABI
(
)
)
{
if
(
Subtarget
->
hasVFP2
(
)
&&
TM
.
Options
.
FloatABIType
==
FloatABI
::
Hard
&&
!
isVarArg
)
return
(
Return
RetCC_ARM_AAPCS_VFP
:
CC_ARM_AAPCS_VFP
)
;
else
return
(
Return
RetCC_ARM_AAPCS
:
CC_ARM_AAPCS
)
;
}
else
{
return
(
Return
RetCC_ARM_APCS
:
CC_ARM_APCS
)
;
}
case
CallingConv
::
ARM_AAPCS_VFP
:
case
CallingConv
::
Swift
:
if
(
!
isVarArg
)
return
(
Return
RetCC_ARM_AAPCS_VFP
:
CC_ARM_AAPCS_VFP
)
;
case
CallingConv
::
ARM_AAPCS
:
return
(
Return
RetCC_ARM_AAPCS
:
CC_ARM_AAPCS
)
;
case
CallingConv
::
ARM_APCS
:
return
(
Return
RetCC_ARM_APCS
:
CC_ARM_APCS
)
;
case
CallingConv
::
GHC
:
if
(
Return
)
llvm_unreachable
(
"Can't return in GHC call convention"
)
;
else
return
CC_ARM_APCS_GHC
;
}
}
</s>


<s> FastISel * ARM :: createFastISel ( FunctionLoweringInfo & funcInfo ) { const TargetMachine & TM = funcInfo . MF -> getTarget ( ) ; const ARMSubtarget * Subtarget = & TM . getSubtarget < ARMSubtarget > ( ) ; if ( Subtarget -> isTargetIOS ( ) && ! Subtarget -> isThumb1Only ( ) && ! DisableARMFastISel ) return new ARMFastISel ( funcInfo ) ; return 0 ; } </s>


<s> llvm :: FastISel * ARM :: createFastISel ( FunctionLoweringInfo & funcInfo ) { const TargetMachine & TM = funcInfo . MF -> getTarget ( ) ; const ARMSubtarget * Subtarget = & TM . getSubtarget < ARMSubtarget > ( ) ; if ( Subtarget -> isTargetIOS ( ) && ! Subtarget -> isThumb1Only ( ) && ! DisableARMFastISel ) return new ARMFastISel ( funcInfo ) ; return 0 ; } </s>


<s> bool ARMFastISel :: fastLowerArguments ( ) { if ( ! FuncInfo . CanLowerReturn ) return false ; const Function * F = FuncInfo . Fn ; if ( F -> isVarArg ( ) ) return false ; CallingConv :: ID CC = F -> getCallingConv ( ) ; switch ( CC ) { default : return false ; case CallingConv :: Fast : case CallingConv :: C : case CallingConv :: ARM_AAPCS_VFP : case CallingConv :: ARM_AAPCS : case CallingConv :: ARM_APCS : case CallingConv :: Swift : break ; } for ( const Argument & Arg : F -> args ( ) ) { if ( Arg . getArgNo ( ) >= 4 ) return false ; if ( Arg . hasAttribute ( Attribute :: InReg ) || Arg . hasAttribute ( Attribute :: StructRet ) || Arg . hasAttribute ( Attribute :: SwiftSelf ) || Arg . hasAttribute ( Attribute :: SwiftError ) || Arg . hasAttribute ( Attribute :: ByVal ) ) return false ; Type * ArgTy = Arg . getType ( ) ; if ( ArgTy -> isStructTy ( ) || ArgTy -> isArrayTy ( ) || ArgTy -> isVectorTy ( ) ) return false ; EVT ArgVT = TLI . getValueType ( DL , ArgTy ) ; if ( ! ArgVT . isSimple ( ) ) return false ; switch ( ArgVT . getSimpleVT ( ) . SimpleTy ) { case MVT :: i8 : case MVT :: i16 : case MVT :: i32 : break ; default : return false ; } } static const MCPhysReg GPRArgRegs [ ] = { ARM :: R0 , ARM :: R1 , ARM :: R2 , ARM :: R3 } ; const TargetRegisterClass * RC = & ARM :: rGPRRegClass ; for ( Function :: const_arg_iterator I = F -> arg_begin ( ) , E = F -> arg_end ( ) ; I != E ; ++ I ) { unsigned ArgNo = I -> getArgNo ( ) ; unsigned SrcReg = GPRArgRegs [ ArgNo ] ; unsigned DstReg = FuncInfo . MF -> addLiveIn ( SrcReg , RC ) ; unsigned ResultReg = createResultReg ( RC ) ; BuildMI ( * FuncInfo . MBB , FuncInfo . InsertPt , DbgLoc , TII . get ( TargetOpcode :: COPY ) , ResultReg ) . addReg ( DstReg , getKillRegState ( true ) ) ; updateValueMap ( & * I , ResultReg ) ; } return true ; } </s>


<s> unsigned ARMFastISel :: constrainOperandRegClass ( const MCInstrDesc & II , unsigned Op , unsigned OpNum ) { if ( TargetRegisterInfo :: isVirtualRegister ( Op ) ) { const TargetRegisterClass * RegClass = TII . getRegClass ( II , OpNum , & TRI , * FuncInfo . MF ) ; if ( ! MRI . constrainRegClass ( Op , RegClass ) ) { unsigned NewOp = createResultReg ( RegClass ) ; AddOptionalDefs ( BuildMI ( * FuncInfo . MBB , FuncInfo . InsertPt , DL , TII . get ( TargetOpcode :: COPY ) , NewOp ) . addReg ( Op ) ) ; return NewOp ; } } return Op ; } </s>


<s>
CCAssignFn
*
ARMFastISel
::
CCAssignFnForCall
(
CallingConv
::
ID
CC
,
bool
Return
)
{
switch
(
CC
)
{
default
:
llvm_unreachable
(
"Unsupported calling convention"
)
;
case
CallingConv
::
Fast
:
(
void
)
RetFastCC_ARM_APCS
;
(
void
)
FastCC_ARM_APCS
;
case
CallingConv
::
C
:
if
(
Subtarget
->
isAAPCS_ABI
(
)
)
{
if
(
Subtarget
->
hasVFP2
(
)
&&
FloatABIType
==
FloatABI
::
Hard
)
return
(
Return
RetCC_ARM_AAPCS_VFP
:
CC_ARM_AAPCS_VFP
)
;
else
return
(
Return
RetCC_ARM_AAPCS
:
CC_ARM_AAPCS
)
;
}
else
return
(
Return
RetCC_ARM_APCS
:
CC_ARM_APCS
)
;
case
CallingConv
::
ARM_AAPCS_VFP
:
return
(
Return
RetCC_ARM_AAPCS_VFP
:
CC_ARM_AAPCS_VFP
)
;
case
CallingConv
::
ARM_AAPCS
:
return
(
Return
RetCC_ARM_AAPCS
:
CC_ARM_AAPCS
)
;
case
CallingConv
::
ARM_APCS
:
return
(
Return
RetCC_ARM_APCS
:
CC_ARM_APCS
)
;
case
CallingConv
::
GHC
:
if
(
Return
)
llvm_unreachable
(
"Can't return in GHC call convention"
)
;
else
return
CC_ARM_APCS_GHC
;
}
}
</s>

ARM
ARM
"Unsupported calling convention"
ARM
ARM
ARM
ARM
ARM
ARM
ARM
ARM
ARM
ARM
ARM
ARM
ARM
ARM
ARM
ARM
ARM
"Can't return in GHC call convention"
ARM


<s> bool ARMFastISel :: fastLowerArguments ( ) { if ( ! FuncInfo . CanLowerReturn ) return false ; const Function * F = FuncInfo . Fn ; if ( F -> isVarArg ( ) ) return false ; CallingConv :: ID CC = F -> getCallingConv ( ) ; switch ( CC ) { default : return false ; case CallingConv :: Fast : case CallingConv :: C : case CallingConv :: ARM_AAPCS_VFP : case CallingConv :: ARM_AAPCS : case CallingConv :: ARM_APCS : break ; } unsigned Idx = 1 ; for ( Function :: const_arg_iterator I = F -> arg_begin ( ) , E = F -> arg_end ( ) ; I != E ; ++ I , ++ Idx ) { if ( Idx > 4 ) return false ; if ( F -> getAttributes ( ) . hasAttribute ( Idx , Attribute :: InReg ) || F -> getAttributes ( ) . hasAttribute ( Idx , Attribute :: StructRet ) || F -> getAttributes ( ) . hasAttribute ( Idx , Attribute :: ByVal ) ) return false ; Type * ArgTy = I -> getType ( ) ; if ( ArgTy -> isStructTy ( ) || ArgTy -> isArrayTy ( ) || ArgTy -> isVectorTy ( ) ) return false ; EVT ArgVT = TLI . getValueType ( DL , ArgTy ) ; if ( ! ArgVT . isSimple ( ) ) return false ; switch ( ArgVT . getSimpleVT ( ) . SimpleTy ) { case MVT :: i8 : case MVT :: i16 : case MVT :: i32 : break ; default : return false ; } } static const uint16_t GPRArgRegs [ ] = { ARM :: R0 , ARM :: R1 , ARM :: R2 , ARM :: R3 } ; const TargetRegisterClass * RC = & ARM :: rGPRRegClass ; Idx = 0 ; for ( Function :: const_arg_iterator I = F -> arg_begin ( ) , E = F -> arg_end ( ) ; I != E ; ++ I , ++ Idx ) { unsigned SrcReg = GPRArgRegs [ Idx ] ; unsigned DstReg = FuncInfo . MF -> addLiveIn ( SrcReg , RC ) ; unsigned ResultReg = createResultReg ( RC ) ; BuildMI ( * FuncInfo . MBB , FuncInfo . InsertPt , DbgLoc , TII . get ( TargetOpcode :: COPY ) , ResultReg ) . addReg ( DstReg , getKillRegState ( true ) ) ; updateValueMap ( I , ResultReg ) ; } return true ; } </s>


<s> void getAnalysisUsage ( AnalysisUsage & AU ) const override { AU . addRequired < ReachingDefAnalysis > ( ) ; AU . setPreservesCFG ( ) ; MachineFunctionPass :: getAnalysisUsage ( AU ) ; } </s>

getAnalysisUsage - Subclasses that override getAnalysisUsage must call this .


"ARM fix for Cortex-A57 AES Erratum 1742098"


<s> bool ARMFrameInfo :: canSimplifyCallFramePseudos ( const MachineFunction & MF ) const { return hasReservedCallFrame ( MF ) || MF . getFrameInfo ( ) -> hasVarSizedObjects ( ) ; } </s>

canSimplifyCallFramePseudos - If there is a reserved call frame , the call frame pseudos can be simplified .


<s> int ARMFrameInfo :: getFrameIndexReference ( const MachineFunction & MF , int FI , unsigned & FrameReg ) const { return ResolveFrameIndexReference ( MF , FI , FrameReg , 0 ) ; } </s>

getFrameIndexReference - This method should return the base register and offset used to reference a frame index location .


<s> bool ARMFrameInfo :: hasFP ( const MachineFunction & MF ) const { const TargetRegisterInfo * RegInfo = MF . getTarget ( ) . getRegisterInfo ( ) ; if ( STI . isTargetDarwin ( ) ) return true ; const MachineFrameInfo * MFI = MF . getFrameInfo ( ) ; return ( ( DisableFramePointerElim ( MF ) && MFI -> hasCalls ( ) ) || RegInfo -> needsStackRealignment ( MF ) || MFI -> hasVarSizedObjects ( ) || MFI -> isFrameAddressTaken ( ) ) ; } </s>

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


<s> bool ARMFrameInfo :: hasReservedCallFrame ( const MachineFunction & MF ) const { const MachineFrameInfo * FFI = MF . getFrameInfo ( ) ; unsigned CFSize = FFI -> getMaxCallFrameSize ( ) ; if ( CFSize >= ( ( 1 << 12 ) - 1 ) / 2 ) return false ; return ! MF . getFrameInfo ( ) -> hasVarSizedObjects ( ) ; } </s>

hasReservedCallFrame - Under normal circumstances , when a frame pointer is not required , we reserve argument space for call sites in the function immediately on entry to the current function .


<s> bool ARMFrameInfo :: restoreCalleeSavedRegisters ( MachineBasicBlock & MBB , MachineBasicBlock :: iterator MI , const std :: vector < CalleeSavedInfo > & CSI , const TargetRegisterInfo * TRI ) const { if ( CSI . empty ( ) ) return false ; MachineFunction & MF = * MBB . getParent ( ) ; ARMFunctionInfo * AFI = MF . getInfo < ARMFunctionInfo > ( ) ; bool isVarArg = AFI -> getVarArgsRegSaveSize ( ) > 0 ; DebugLoc DL = MI -> getDebugLoc ( ) ; unsigned PopOpc = AFI -> isThumbFunction ( ) ? ARM :: t2LDMIA_UPD : ARM :: LDMIA_UPD ; unsigned LdrOpc = AFI -> isThumbFunction ( ) ? ARM :: t2LDR_POST : ARM :: LDR_POST ; unsigned FltOpc = ARM :: VLDMDIA_UPD ; emitPopInst ( MBB , MI , CSI , FltOpc , 0 , isVarArg , true , & isARMArea3Register ) ; emitPopInst ( MBB , MI , CSI , PopOpc , LdrOpc , isVarArg , false , & isARMArea2Register ) ; emitPopInst ( MBB , MI , CSI , PopOpc , LdrOpc , isVarArg , false , & isARMArea1Register ) ; return true ; } </s>

restoreCalleeSavedRegisters - Issues instruction ( s ) to restore all callee saved registers and returns true if it is n't possible / profitable to do so by issuing a series of load instructions via loadRegToStackSlot ( ) .


<s> bool ARMFrameInfo :: spillCalleeSavedRegisters ( MachineBasicBlock & MBB , MachineBasicBlock :: iterator MI , const std :: vector < CalleeSavedInfo > & CSI , const TargetRegisterInfo * TRI ) const { if ( CSI . empty ( ) ) return false ; MachineFunction & MF = * MBB . getParent ( ) ; ARMFunctionInfo * AFI = MF . getInfo < ARMFunctionInfo > ( ) ; DebugLoc DL = MI -> getDebugLoc ( ) ; unsigned PushOpc = AFI -> isThumbFunction ( ) ? ARM :: t2STMDB_UPD : ARM :: STMDB_UPD ; unsigned PushOneOpc = AFI -> isThumbFunction ( ) ? ARM :: t2STR_PRE : ARM :: STR_PRE ; unsigned FltOpc = ARM :: VSTMDDB_UPD ; emitPushInst ( MBB , MI , CSI , PushOpc , PushOneOpc , false , & isARMArea1Register ) ; emitPushInst ( MBB , MI , CSI , PushOpc , PushOneOpc , false , & isARMArea2Register ) ; emitPushInst ( MBB , MI , CSI , FltOpc , 0 , true , & isARMArea3Register ) ; return true ; } </s>

spillCalleeSavedRegisters - Issues instruction ( s ) to spill all callee saved registers and returns true if it is n't possible / profitable to do so by issuing a series of store instructions via storeRegToStackSlot ( ) .


<s> void addInst ( MachineBasicBlock :: iterator I , unsigned SPAdjust , bool BeforeFPSet = false ) { InstInfo Info = { I , SPAdjust , BeforeFPSet } ; Insts . push_back ( Info ) ; } </s>


"This eliminateCallFramePseudoInstr does not support Thumb1!"

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> bool ARMFrameLowering :: hasFP ( const MachineFunction & MF ) const { const TargetRegisterInfo * RegInfo = MF . getSubtarget ( ) . getRegisterInfo ( ) ; if ( STI . isTargetIOS ( ) || STI . isTargetWatchOS ( ) ) return true ; const MachineFrameInfo * MFI = MF . getFrameInfo ( ) ; return ( ( MF . getTarget ( ) . Options . DisableFramePointerElim ( MF ) && MFI -> hasCalls ( ) ) || RegInfo -> needsStackRealignment ( MF ) || MFI -> hasVarSizedObjects ( ) || MFI -> isFrameAddressTaken ( ) ) ; } </s>


<s> bool ARMFrameLowering :: canSimplifyCallFramePseudos ( const MachineFunction & MF ) const { return hasReservedCallFrame ( MF ) || MF . getFrameInfo ( ) -> hasVarSizedObjects ( ) ; } </s>


<s> static void emitSPUpdate ( bool isARM , MachineBasicBlock & MBB , MachineBasicBlock :: iterator & MBBI , DebugLoc dl , const ARMBaseInstrInfo & TII , int NumBytes , unsigned MIFlags = MachineInstr :: NoFlags , ARMCC :: CondCodes Pred = ARMCC :: AL , unsigned PredReg = 0 ) { emitRegPlusImmediate ( isARM , MBB , MBBI , dl , TII , ARM :: SP , ARM :: SP , NumBytes , MIFlags , Pred , PredReg ) ; } </s>

Emit a series of instructions to increment / decrement the stack pointer by a constant value .

ARM ARM ARM ARMCC::CondCodes ARMCC::AL 0 ARM ARM::SP ARM::SP


<s> bool enableShrinkWrapping ( const MachineFunction & MF ) const override { return true ; } </s>

Returns true if the target will correctly handle shrink wrapping .


<s> int ARMFrameLowering :: getFrameIndexReference ( const MachineFunction & MF , int FI , unsigned & FrameReg ) const { return ResolveFrameIndexReference ( MF , FI , FrameReg , 0 ) ; } </s>


<s> bool ARMFrameLowering :: hasFP ( const MachineFunction & MF ) const { const TargetRegisterInfo * RegInfo = MF . getTarget ( ) . getRegisterInfo ( ) ; if ( STI . isTargetIOS ( ) ) return true ; const MachineFrameInfo * MFI = MF . getFrameInfo ( ) ; return ( ( MF . getTarget ( ) . Options . DisableFramePointerElim ( MF ) && MFI -> hasCalls ( ) ) || RegInfo -> needsStackRealignment ( MF ) || MFI -> hasVarSizedObjects ( ) || MFI -> isFrameAddressTaken ( ) ) ; } </s>


<s> bool ARMFrameLowering :: hasReservedCallFrame ( const MachineFunction & MF ) const { const MachineFrameInfo * FFI = MF . getFrameInfo ( ) ; unsigned CFSize = FFI -> getMaxCallFrameSize ( ) ; if ( CFSize >= ( ( 1 << 12 ) - 1 ) / 2 ) return false ; return ! MF . getFrameInfo ( ) -> hasVarSizedObjects ( ) ; } </s>


<s> bool ARMFrameLowering :: restoreCalleeSavedRegisters ( MachineBasicBlock & MBB , MachineBasicBlock :: iterator MI , const std :: vector < CalleeSavedInfo > & CSI , const TargetRegisterInfo * TRI ) const { if ( CSI . empty ( ) ) return false ; MachineFunction & MF = * MBB . getParent ( ) ; ARMFunctionInfo * AFI = MF . getInfo < ARMFunctionInfo > ( ) ; bool isVarArg = AFI -> getArgRegsSaveSize ( ) > 0 ; unsigned NumAlignedDPRCS2Regs = AFI -> getNumAlignedDPRCS2Regs ( ) ; if ( NumAlignedDPRCS2Regs ) emitAlignedDPRCS2Restores ( MBB , MI , NumAlignedDPRCS2Regs , CSI , TRI ) ; unsigned PopOpc = AFI -> isThumbFunction ( ) ? ARM :: t2LDMIA_UPD : ARM :: LDMIA_UPD ; unsigned LdrOpc = AFI -> isThumbFunction ( ) ? ARM :: t2LDR_POST : ARM :: LDR_POST_IMM ; unsigned FltOpc = ARM :: VLDMDIA_UPD ; emitPopInst ( MBB , MI , CSI , FltOpc , 0 , isVarArg , true , & isARMArea3Register , NumAlignedDPRCS2Regs ) ; emitPopInst ( MBB , MI , CSI , PopOpc , LdrOpc , isVarArg , false , & isARMArea2Register , 0 ) ; emitPopInst ( MBB , MI , CSI , PopOpc , LdrOpc , isVarArg , false , & isARMArea1Register , 0 ) ; return true ; } </s>


<s> bool ARMFrameLowering :: spillCalleeSavedRegisters ( MachineBasicBlock & MBB , MachineBasicBlock :: iterator MI , const std :: vector < CalleeSavedInfo > & CSI , const TargetRegisterInfo * TRI ) const { if ( CSI . empty ( ) ) return false ; MachineFunction & MF = * MBB . getParent ( ) ; ARMFunctionInfo * AFI = MF . getInfo < ARMFunctionInfo > ( ) ; unsigned PushOpc = AFI -> isThumbFunction ( ) ? ARM :: t2STMDB_UPD : ARM :: STMDB_UPD ; unsigned PushOneOpc = AFI -> isThumbFunction ( ) ? ARM :: t2STR_PRE : ARM :: STR_PRE_IMM ; unsigned FltOpc = ARM :: VSTMDDB_UPD ; unsigned NumAlignedDPRCS2Regs = AFI -> getNumAlignedDPRCS2Regs ( ) ; emitPushInst ( MBB , MI , CSI , PushOpc , PushOneOpc , false , & isARMArea1Register , 0 , MachineInstr :: FrameSetup ) ; emitPushInst ( MBB , MI , CSI , PushOpc , PushOneOpc , false , & isARMArea2Register , 0 , MachineInstr :: FrameSetup ) ; emitPushInst ( MBB , MI , CSI , FltOpc , 0 , true , & isARMArea3Register , NumAlignedDPRCS2Regs , MachineInstr :: FrameSetup ) ; if ( NumAlignedDPRCS2Regs ) emitAlignedDPRCS2Spills ( MBB , MI , NumAlignedDPRCS2Regs , CSI , TRI ) ; return true ; } </s>


<s> bool ARMFrameLowering :: assignCalleeSavedSpillSlots ( MachineFunction & MF , const TargetRegisterInfo * TRI , std :: vector < CalleeSavedInfo > & CSI ) const { if ( STI . hasV8_1MMainlineOps ( ) && MF . getInfo < ARMFunctionInfo > ( ) -> isCmseNSEntryFunction ( ) ) { CSI . emplace_back ( ARM :: FPCXTNS ) ; CSI . back ( ) . setRestored ( false ) ; } const auto & AFI = * MF . getInfo < ARMFunctionInfo > ( ) ; if ( AFI . shouldSignReturnAddress ( ) ) { CSI . insert ( find_if ( CSI , [ = ] ( const auto & CS ) { unsigned Reg = CS . getReg ( ) ; return Reg == ARM :: R10 || Reg == ARM :: R11 || Reg == ARM :: R8 || Reg == ARM :: R9 || ARM :: DPRRegClass . contains ( Reg ) ; } ) , CalleeSavedInfo ( ARM :: R12 ) ) ; } return false ; } </s>

This function will assign callee saved gprs to volatile vector registers for prologue spills when applicable .


<s> bool ARMFrameLowering :: canSimplifyCallFramePseudos ( const MachineFunction & MF ) const { return hasReservedCallFrame ( MF ) || MF . getFrameInfo ( ) . hasVarSizedObjects ( ) ; } </s>


<s> static void emitSPUpdate ( bool isARM , MachineBasicBlock & MBB , MachineBasicBlock :: iterator & MBBI , const DebugLoc & dl , const ARMBaseInstrInfo & TII , int NumBytes , unsigned MIFlags = MachineInstr :: NoFlags , ARMCC :: CondCodes Pred = ARMCC :: AL , unsigned PredReg = 0 ) { emitRegPlusImmediate ( isARM , MBB , MBBI , dl , TII , ARM :: SP , ARM :: SP , NumBytes , MIFlags , Pred , PredReg ) ; } </s>


<s> bool ARMFrameLowering :: enableCalleeSaveSkip ( const MachineFunction & MF ) const { assert ( MF . getFunction ( ) . hasFnAttribute ( Attribute :: NoReturn ) && MF . getFunction ( ) . hasFnAttribute ( Attribute :: NoUnwind ) && ! MF . getFunction ( ) . hasFnAttribute ( Attribute :: UWTable ) ) ; return true ; } </s>

Returns true if the target can safely skip saving callee-saved registers for noreturn nounwind functions .


<s> bool ARMFrameLowering :: enableShrinkWrapping ( const MachineFunction & MF ) const { if ( STI . hasV8_1MMainlineOps ( ) && MF . getInfo < ARMFunctionInfo > ( ) -> isCmseNSEntryFunction ( ) ) return false ; if ( MF . getInfo < ARMFunctionInfo > ( ) -> shouldSignReturnAddress ( false ) ) return false ; return true ; } </s>


<s> const TargetFrameLowering :: SpillSlot * ARMFrameLowering :: getCalleeSavedSpillSlots ( unsigned & NumEntries ) const { static const SpillSlot FixedSpillOffsets [ ] = { { ARM :: FPCXTNS , - 4 } } ; NumEntries = array_lengthof ( FixedSpillOffsets ) ; return FixedSpillOffsets ; } </s>

getCalleeSavedSpillSlots - This method returns a pointer to an array of pairs , that contains an entry for each callee saved register that must be spilled to a particular stack location if it is spilled .


<s> void ARMFrameLowering :: getCalleeSaves ( const MachineFunction & MF , BitVector & SavedRegs ) const { TargetFrameLowering :: getCalleeSaves ( MF , SavedRegs ) ; const ARMFunctionInfo * AFI = MF . getInfo < ARMFunctionInfo > ( ) ; if ( AFI -> getPreservesR0 ( ) ) SavedRegs . set ( ARM :: R0 ) ; } </s>

Returns the callee-saved registers as computed by determineCalleeSaves in the BitVector SavedRegs .


<s> StackOffset ARMFrameLowering :: getFrameIndexReference ( const MachineFunction & MF , int FI , Register & FrameReg ) const { return StackOffset :: getFixed ( ResolveFrameIndexReference ( MF , FI , FrameReg , 0 ) ) ; } </s>


<s> bool ARMFrameLowering :: hasFP ( const MachineFunction & MF ) const { const TargetRegisterInfo * RegInfo = MF . getSubtarget ( ) . getRegisterInfo ( ) ; const MachineFrameInfo & MFI = MF . getFrameInfo ( ) ; if ( MF . getTarget ( ) . Options . DisableFramePointerElim ( MF ) ) return true ; return ( RegInfo -> hasStackRealignment ( MF ) || MFI . hasVarSizedObjects ( ) || MFI . isFrameAddressTaken ( ) ) ; } </s>


<s> bool ARMFrameLowering :: hasReservedCallFrame ( const MachineFunction & MF ) const { const MachineFrameInfo & MFI = MF . getFrameInfo ( ) ; unsigned CFSize = MFI . getMaxCallFrameSize ( ) ; if ( CFSize >= ( ( 1 << 12 ) - 1 ) / 2 ) return false ; return ! MFI . hasVarSizedObjects ( ) ; } </s>


<s> bool ARMFrameLowering :: keepFramePointer ( const MachineFunction & MF ) const { return MF . getSubtarget < ARMSubtarget > ( ) . useFastISel ( ) ; } </s>

Return true if the target wants to keep the frame pointer regardless of the function attribute `` frame-pointer '' .


<s> bool ARMFrameLowering :: restoreCalleeSavedRegisters ( MachineBasicBlock & MBB , MachineBasicBlock :: iterator MI , MutableArrayRef < CalleeSavedInfo > CSI , const TargetRegisterInfo * TRI ) const { if ( CSI . empty ( ) ) return false ; MachineFunction & MF = * MBB . getParent ( ) ; ARMFunctionInfo * AFI = MF . getInfo < ARMFunctionInfo > ( ) ; bool isVarArg = AFI -> getArgRegsSaveSize ( ) > 0 ; unsigned NumAlignedDPRCS2Regs = AFI -> getNumAlignedDPRCS2Regs ( ) ; if ( NumAlignedDPRCS2Regs ) emitAlignedDPRCS2Restores ( MBB , MI , NumAlignedDPRCS2Regs , CSI , TRI ) ; unsigned PopOpc = AFI -> isThumbFunction ( ) ? ARM :: t2LDMIA_UPD : ARM :: LDMIA_UPD ; unsigned LdrOpc = AFI -> isThumbFunction ( ) ? ARM :: t2LDR_POST : ARM :: LDR_POST_IMM ; unsigned FltOpc = ARM :: VLDMDIA_UPD ; emitPopInst ( MBB , MI , CSI , FltOpc , 0 , isVarArg , true , & isARMArea3Register , NumAlignedDPRCS2Regs ) ; emitPopInst ( MBB , MI , CSI , PopOpc , LdrOpc , isVarArg , false , & isARMArea2Register , 0 ) ; emitPopInst ( MBB , MI , CSI , PopOpc , LdrOpc , isVarArg , false , & isARMArea1Register , 0 ) ; return true ; } </s>


<s> bool ARMFrameLowering :: spillCalleeSavedRegisters ( MachineBasicBlock & MBB , MachineBasicBlock :: iterator MI , ArrayRef < CalleeSavedInfo > CSI , const TargetRegisterInfo * TRI ) const { if ( CSI . empty ( ) ) return false ; MachineFunction & MF = * MBB . getParent ( ) ; ARMFunctionInfo * AFI = MF . getInfo < ARMFunctionInfo > ( ) ; unsigned PushOpc = AFI -> isThumbFunction ( ) ? ARM :: t2STMDB_UPD : ARM :: STMDB_UPD ; unsigned PushOneOpc = AFI -> isThumbFunction ( ) ? ARM :: t2STR_PRE : ARM :: STR_PRE_IMM ; unsigned FltOpc = ARM :: VSTMDDB_UPD ; unsigned NumAlignedDPRCS2Regs = AFI -> getNumAlignedDPRCS2Regs ( ) ; if ( AFI -> shouldSignReturnAddress ( ) ) { BuildMI ( MBB , MI , DebugLoc ( ) , STI . getInstrInfo ( ) -> get ( ARM :: t2PAC ) ) . setMIFlags ( MachineInstr :: FrameSetup ) ; } if ( llvm :: any_of ( CSI , [ ] ( const CalleeSavedInfo & C ) { return C . getReg ( ) == ARM :: FPCXTNS ; } ) ) { BuildMI ( MBB , MI , DebugLoc ( ) , STI . getInstrInfo ( ) -> get ( ARM :: VSTR_FPCXTNS_pre ) , ARM :: SP ) . addReg ( ARM :: SP ) . addImm ( - 4 ) . add ( predOps ( ARMCC :: AL ) ) ; } emitPushInst ( MBB , MI , CSI , PushOpc , PushOneOpc , false , & isARMArea1Register , 0 , MachineInstr :: FrameSetup ) ; emitPushInst ( MBB , MI , CSI , PushOpc , PushOneOpc , false , & isARMArea2Register , 0 , MachineInstr :: FrameSetup ) ; emitPushInst ( MBB , MI , CSI , FltOpc , 0 , true , & isARMArea3Register , NumAlignedDPRCS2Regs , MachineInstr :: FrameSetup ) ; if ( NumAlignedDPRCS2Regs ) emitAlignedDPRCS2Spills ( MBB , MI , NumAlignedDPRCS2Regs , CSI , TRI ) ; return true ; } </s>


"This eliminateCallFramePseudoInstr does not support Thumb1!"


<s> bool ARMFrameLowering :: hasFP ( const MachineFunction & MF ) const { const TargetRegisterInfo * RegInfo = MF . getSubtarget ( ) . getRegisterInfo ( ) ; const MachineFrameInfo & MFI = MF . getFrameInfo ( ) ; if ( MF . getTarget ( ) . Options . DisableFramePointerElim ( MF ) ) return true ; return ( RegInfo -> needsStackRealignment ( MF ) || MFI . hasVarSizedObjects ( ) || MFI . isFrameAddressTaken ( ) ) ; } </s>


<s> bool ARMFrameLowering :: restoreCalleeSavedRegisters ( MachineBasicBlock & MBB , MachineBasicBlock :: iterator MI , std :: vector < CalleeSavedInfo > & CSI , const TargetRegisterInfo * TRI ) const { if ( CSI . empty ( ) ) return false ; MachineFunction & MF = * MBB . getParent ( ) ; ARMFunctionInfo * AFI = MF . getInfo < ARMFunctionInfo > ( ) ; bool isVarArg = AFI -> getArgRegsSaveSize ( ) > 0 ; unsigned NumAlignedDPRCS2Regs = AFI -> getNumAlignedDPRCS2Regs ( ) ; if ( NumAlignedDPRCS2Regs ) emitAlignedDPRCS2Restores ( MBB , MI , NumAlignedDPRCS2Regs , CSI , TRI ) ; unsigned PopOpc = AFI -> isThumbFunction ( ) ? ARM :: t2LDMIA_UPD : ARM :: LDMIA_UPD ; unsigned LdrOpc = AFI -> isThumbFunction ( ) ? ARM :: t2LDR_POST : ARM :: LDR_POST_IMM ; unsigned FltOpc = ARM :: VLDMDIA_UPD ; emitPopInst ( MBB , MI , CSI , FltOpc , 0 , isVarArg , true , & isARMArea3Register , NumAlignedDPRCS2Regs ) ; emitPopInst ( MBB , MI , CSI , PopOpc , LdrOpc , isVarArg , false , & isARMArea2Register , 0 ) ; emitPopInst ( MBB , MI , CSI , PopOpc , LdrOpc , isVarArg , false , & isARMArea1Register , 0 ) ; return true ; } </s>


<s> bool ARMFrameLowering :: assignCalleeSavedSpillSlots ( MachineFunction & MF , const TargetRegisterInfo * TRI , std :: vector < CalleeSavedInfo > & CSI ) const { if ( STI . hasV8_1MMainlineOps ( ) && MF . getInfo < ARMFunctionInfo > ( ) -> isCmseNSEntryFunction ( ) ) { CSI . emplace_back ( ARM :: FPCXTNS ) ; CSI . back ( ) . setRestored ( false ) ; } return false ; } </s>


<s> bool ARMFrameLowering :: enableShrinkWrapping ( const MachineFunction & MF ) const { if ( STI . hasV8_1MMainlineOps ( ) && MF . getInfo < ARMFunctionInfo > ( ) -> isCmseNSEntryFunction ( ) ) return false ; return true ; } </s>


<s> bool ARMFrameLowering :: spillCalleeSavedRegisters ( MachineBasicBlock & MBB , MachineBasicBlock :: iterator MI , ArrayRef < CalleeSavedInfo > CSI , const TargetRegisterInfo * TRI ) const { if ( CSI . empty ( ) ) return false ; MachineFunction & MF = * MBB . getParent ( ) ; ARMFunctionInfo * AFI = MF . getInfo < ARMFunctionInfo > ( ) ; unsigned PushOpc = AFI -> isThumbFunction ( ) ? ARM :: t2STMDB_UPD : ARM :: STMDB_UPD ; unsigned PushOneOpc = AFI -> isThumbFunction ( ) ? ARM :: t2STR_PRE : ARM :: STR_PRE_IMM ; unsigned FltOpc = ARM :: VSTMDDB_UPD ; unsigned NumAlignedDPRCS2Regs = AFI -> getNumAlignedDPRCS2Regs ( ) ; if ( llvm :: any_of ( CSI , [ ] ( const CalleeSavedInfo & C ) { return C . getReg ( ) == ARM :: FPCXTNS ; } ) ) { BuildMI ( MBB , MI , DebugLoc ( ) , STI . getInstrInfo ( ) -> get ( ARM :: VSTR_FPCXTNS_pre ) , ARM :: SP ) . addReg ( ARM :: SP ) . addImm ( - 4 ) . add ( predOps ( ARMCC :: AL ) ) ; } emitPushInst ( MBB , MI , CSI , PushOpc , PushOneOpc , false , & isARMArea1Register , 0 , MachineInstr :: FrameSetup ) ; emitPushInst ( MBB , MI , CSI , PushOpc , PushOneOpc , false , & isARMArea2Register , 0 , MachineInstr :: FrameSetup ) ; emitPushInst ( MBB , MI , CSI , FltOpc , 0 , true , & isARMArea3Register , NumAlignedDPRCS2Regs , MachineInstr :: FrameSetup ) ; if ( NumAlignedDPRCS2Regs ) emitAlignedDPRCS2Spills ( MBB , MI , NumAlignedDPRCS2Regs , CSI , TRI ) ; return true ; } </s>


<s> static void emitSPUpdate ( bool isARM , MachineBasicBlock & MBB , MachineBasicBlock :: iterator & MBBI , DebugLoc dl , const ARMBaseInstrInfo & TII , int NumBytes , unsigned MIFlags = MachineInstr :: NoFlags ) { if ( isARM ) emitARMRegPlusImmediate ( MBB , MBBI , dl , ARM :: SP , ARM :: SP , NumBytes , ARMCC :: AL , 0 , TII , MIFlags ) ; else emitT2RegPlusImmediate ( MBB , MBBI , dl , ARM :: SP , ARM :: SP , NumBytes , ARMCC :: AL , 0 , TII , MIFlags ) ; } </s>

ARM ARM ARM ARM ARM ARM::SP ARM::SP ARMCC::AL 0 ARM::SP ARM::SP ARMCC::AL 0


<s> static unsigned estimateStackSize ( MachineFunction & MF ) { const MachineFrameInfo * MFI = MF . getFrameInfo ( ) ; const TargetFrameLowering * TFI = MF . getTarget ( ) . getFrameLowering ( ) ; const TargetRegisterInfo * RegInfo = MF . getTarget ( ) . getRegisterInfo ( ) ; unsigned MaxAlign = MFI -> getMaxAlignment ( ) ; int Offset = 0 ; for ( int i = MFI -> getObjectIndexBegin ( ) ; i != 0 ; ++ i ) { int FixedOff = - MFI -> getObjectOffset ( i ) ; if ( FixedOff > Offset ) Offset = FixedOff ; } for ( unsigned i = 0 , e = MFI -> getObjectIndexEnd ( ) ; i != e ; ++ i ) { if ( MFI -> isDeadObjectIndex ( i ) ) continue ; Offset += MFI -> getObjectSize ( i ) ; unsigned Align = MFI -> getObjectAlignment ( i ) ; Offset = ( Offset + Align - 1 ) / Align * Align ; MaxAlign = std :: max ( Align , MaxAlign ) ; } if ( MFI -> adjustsStack ( ) && TFI -> hasReservedCallFrame ( MF ) ) Offset += MFI -> getMaxCallFrameSize ( ) ; unsigned StackAlign ; if ( MFI -> adjustsStack ( ) || MFI -> hasVarSizedObjects ( ) || ( RegInfo -> needsStackRealignment ( MF ) && MFI -> getObjectIndexEnd ( ) != 0 ) ) StackAlign = TFI -> getStackAlignment ( ) ; else StackAlign = TFI -> getTransientStackAlignment ( ) ; StackAlign = std :: max ( StackAlign , MaxAlign ) ; unsigned AlignMask = StackAlign - 1 ; Offset = ( Offset + AlignMask ) & ~ uint64_t ( AlignMask ) ; return ( unsigned ) Offset ; } </s>

Estimate and return the size of the stack frame .


<s> int ARMFrameLowering :: getFrameIndexReference ( const MachineFunction & MF , int FI , Register & FrameReg ) const { return ResolveFrameIndexReference ( MF , FI , FrameReg , 0 ) ; } </s>


<s> bool ARMFrameLowering :: spillCalleeSavedRegisters ( MachineBasicBlock & MBB , MachineBasicBlock :: iterator MI , ArrayRef < CalleeSavedInfo > CSI , const TargetRegisterInfo * TRI ) const { if ( CSI . empty ( ) ) return false ; MachineFunction & MF = * MBB . getParent ( ) ; ARMFunctionInfo * AFI = MF . getInfo < ARMFunctionInfo > ( ) ; unsigned PushOpc = AFI -> isThumbFunction ( ) ? ARM :: t2STMDB_UPD : ARM :: STMDB_UPD ; unsigned PushOneOpc = AFI -> isThumbFunction ( ) ? ARM :: t2STR_PRE : ARM :: STR_PRE_IMM ; unsigned FltOpc = ARM :: VSTMDDB_UPD ; unsigned NumAlignedDPRCS2Regs = AFI -> getNumAlignedDPRCS2Regs ( ) ; emitPushInst ( MBB , MI , CSI , PushOpc , PushOneOpc , false , & isARMArea1Register , 0 , MachineInstr :: FrameSetup ) ; emitPushInst ( MBB , MI , CSI , PushOpc , PushOneOpc , false , & isARMArea2Register , 0 , MachineInstr :: FrameSetup ) ; emitPushInst ( MBB , MI , CSI , FltOpc , 0 , true , & isARMArea3Register , NumAlignedDPRCS2Regs , MachineInstr :: FrameSetup ) ; if ( NumAlignedDPRCS2Regs ) emitAlignedDPRCS2Spills ( MBB , MI , NumAlignedDPRCS2Regs , CSI , TRI ) ; return true ; } </s>


<s> bool isProfitableForNoCSROpt ( const Function & F ) const override { return false ; } </s>

Check if the no-CSR optimisation is profitable for the given function .


<s> static void emitSPUpdate ( bool isARM , MachineBasicBlock & MBB , MachineBasicBlock :: iterator & MBBI , DebugLoc dl , const ARMBaseInstrInfo & TII , int NumBytes , unsigned MIFlags = MachineInstr :: NoFlags , ARMCC :: CondCodes Pred = ARMCC :: AL , unsigned PredReg = 0 ) { if ( isARM ) emitARMRegPlusImmediate ( MBB , MBBI , dl , ARM :: SP , ARM :: SP , NumBytes , Pred , PredReg , TII , MIFlags ) ; else emitT2RegPlusImmediate ( MBB , MBBI , dl , ARM :: SP , ARM :: SP , NumBytes , Pred , PredReg , TII , MIFlags ) ; } </s>

ARM ARM ARM ARMCC::CondCodes ARMCC::AL 0 ARM ARM ARM::SP ARM::SP ARM::SP ARM::SP


<s> bool ARMFrameLowering :: restoreCalleeSavedRegisters ( MachineBasicBlock & MBB , MachineBasicBlock :: iterator MI , const std :: vector < CalleeSavedInfo > & CSI , const TargetRegisterInfo * TRI ) const { if ( CSI . empty ( ) ) return false ; MachineFunction & MF = * MBB . getParent ( ) ; ARMFunctionInfo * AFI = MF . getInfo < ARMFunctionInfo > ( ) ; bool isVarArg = AFI -> getVarArgsRegSaveSize ( ) > 0 ; unsigned NumAlignedDPRCS2Regs = AFI -> getNumAlignedDPRCS2Regs ( ) ; if ( NumAlignedDPRCS2Regs ) emitAlignedDPRCS2Restores ( MBB , MI , NumAlignedDPRCS2Regs , CSI , TRI ) ; unsigned PopOpc = AFI -> isThumbFunction ( ) ? ARM :: t2LDMIA_UPD : ARM :: LDMIA_UPD ; unsigned LdrOpc = AFI -> isThumbFunction ( ) ? ARM :: t2LDR_POST : ARM :: LDR_POST_IMM ; unsigned FltOpc = ARM :: VLDMDIA_UPD ; emitPopInst ( MBB , MI , CSI , FltOpc , 0 , isVarArg , true , & isARMArea3Register , NumAlignedDPRCS2Regs ) ; emitPopInst ( MBB , MI , CSI , PopOpc , LdrOpc , isVarArg , false , & isARMArea2Register , 0 ) ; emitPopInst ( MBB , MI , CSI , PopOpc , LdrOpc , isVarArg , false , & isARMArea1Register , 0 ) ; return true ; } </s>


<s> bool ARMFrameLowering :: hasFP ( const MachineFunction & MF ) const { const TargetRegisterInfo * RegInfo = MF . getTarget ( ) . getRegisterInfo ( ) ; if ( STI . isTargetDarwin ( ) ) return true ; const MachineFrameInfo * MFI = MF . getFrameInfo ( ) ; return ( ( DisableFramePointerElim ( MF ) && MFI -> hasCalls ( ) ) || RegInfo -> needsStackRealignment ( MF ) || MFI -> hasVarSizedObjects ( ) || MFI -> isFrameAddressTaken ( ) ) ; } </s>


<s> bool ARMFrameLowering :: restoreCalleeSavedRegisters ( MachineBasicBlock & MBB , MachineBasicBlock :: iterator MI , const std :: vector < CalleeSavedInfo > & CSI , const TargetRegisterInfo * TRI ) const { if ( CSI . empty ( ) ) return false ; MachineFunction & MF = * MBB . getParent ( ) ; ARMFunctionInfo * AFI = MF . getInfo < ARMFunctionInfo > ( ) ; bool isVarArg = AFI -> getVarArgsRegSaveSize ( ) > 0 ; unsigned PopOpc = AFI -> isThumbFunction ( ) ? ARM :: t2LDMIA_UPD : ARM :: LDMIA_UPD ; unsigned LdrOpc = AFI -> isThumbFunction ( ) ? ARM :: t2LDR_POST : ARM :: LDR_POST ; unsigned FltOpc = ARM :: VLDMDIA_UPD ; emitPopInst ( MBB , MI , CSI , FltOpc , 0 , isVarArg , true , & isARMArea3Register ) ; emitPopInst ( MBB , MI , CSI , PopOpc , LdrOpc , isVarArg , false , & isARMArea2Register ) ; emitPopInst ( MBB , MI , CSI , PopOpc , LdrOpc , isVarArg , false , & isARMArea1Register ) ; return true ; } </s>


<s> bool ARMFrameLowering :: spillCalleeSavedRegisters ( MachineBasicBlock & MBB , MachineBasicBlock :: iterator MI , const std :: vector < CalleeSavedInfo > & CSI , const TargetRegisterInfo * TRI ) const { if ( CSI . empty ( ) ) return false ; MachineFunction & MF = * MBB . getParent ( ) ; ARMFunctionInfo * AFI = MF . getInfo < ARMFunctionInfo > ( ) ; unsigned PushOpc = AFI -> isThumbFunction ( ) ? ARM :: t2STMDB_UPD : ARM :: STMDB_UPD ; unsigned PushOneOpc = AFI -> isThumbFunction ( ) ? ARM :: t2STR_PRE : ARM :: STR_PRE ; unsigned FltOpc = ARM :: VSTMDDB_UPD ; emitPushInst ( MBB , MI , CSI , PushOpc , PushOneOpc , false , & isARMArea1Register , MachineInstr :: FrameSetup ) ; emitPushInst ( MBB , MI , CSI , PushOpc , PushOneOpc , false , & isARMArea2Register , MachineInstr :: FrameSetup ) ; emitPushInst ( MBB , MI , CSI , FltOpc , 0 , true , & isARMArea3Register , MachineInstr :: FrameSetup ) ; return true ; } </s>


<s> bool ARMFrameLowering :: hasFP ( const MachineFunction & MF ) const { const TargetRegisterInfo * RegInfo = MF . getSubtarget ( ) . getRegisterInfo ( ) ; if ( STI . isTargetIOS ( ) || STI . isTargetWatchOS ( ) ) return true ; const MachineFrameInfo & MFI = MF . getFrameInfo ( ) ; return ( ( MF . getTarget ( ) . Options . DisableFramePointerElim ( MF ) && MFI . hasCalls ( ) ) || RegInfo -> needsStackRealignment ( MF ) || MFI . hasVarSizedObjects ( ) || MFI . isFrameAddressTaken ( ) ) ; } </s>


<s> bool ARMFrameLowering :: assignCalleeSavedSpillSlots ( MachineFunction & MF , const TargetRegisterInfo * TRI , std :: vector < CalleeSavedInfo > & CSI ) const { if ( STI . hasV8_1MMainlineOps ( ) && MF . getInfo < ARMFunctionInfo > ( ) -> isCmseNSEntryFunction ( ) ) { CSI . emplace_back ( ARM :: FPCXTNS ) ; CSI . back ( ) . setRestored ( false ) ; } const auto & AFI = * MF . getInfo < ARMFunctionInfo > ( ) ; if ( AFI . shouldSignReturnAddress ( ) ) { CSI . insert ( find_if ( CSI , [ = ] ( const auto & CS ) { Register Reg = CS . getReg ( ) ; return Reg == ARM :: R10 || Reg == ARM :: R11 || Reg == ARM :: R8 || Reg == ARM :: R9 || ARM :: DPRRegClass . contains ( Reg ) ; } ) , CalleeSavedInfo ( ARM :: R12 ) ) ; } return false ; } </s>


<s> bool ARMFrameLowering :: enableShrinkWrapping ( const MachineFunction & MF ) const { if ( STI . hasV8_1MMainlineOps ( ) && MF . getInfo < ARMFunctionInfo > ( ) -> isCmseNSEntryFunction ( ) ) return false ; if ( MF . getInfo < ARMFunctionInfo > ( ) -> shouldSignReturnAddress ( true ) ) return false ; return true ; } </s>


<s> bool ARMFrameLowering :: enableShrinkWrapping ( const MachineFunction & MF ) const { if ( MF . getFunction ( ) . hasMinSize ( ) ) return false ; return true ; } </s>


"This eliminateCallFramePseudoInstr does not support Thumb1!"