<s> bool AVRAsmBackend :: shouldForceRelocation ( const MCAssembler & Asm , const MCFixup & Fixup , const MCValue & Target ) { switch ( ( unsigned ) Fixup . getKind ( ) ) { default : return false ; case AVR :: fixup_7_pcrel : case AVR :: fixup_13_pcrel : case AVR :: fixup_call : return true ; } } </s>

Hook to check if a relocation is needed for some target specific reason .


<s>
bool
AVRAsmBackend
::
writeNopData
(
raw_ostream
&
OS
,
uint64_t
Count
,
const
MCSubtargetInfo
*
STI
)
const
{
assert
(
(
Count
%
2
)
==
0
&&
"NOP instructions must be 2 bytes"
)
;
OS
.
write_zeros
(
Count
)
;
return
true
;
}
</s>

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


<s>
MCFixupKindInfo
const
&
AVRAsmBackend
::
getFixupKindInfo
(
MCFixupKind
Kind
)
const
{
const
static
MCFixupKindInfo
Infos
[
AVR
::
NumTargetFixupKinds
]
=
{
{
"fixup_32"
,
0
,
32
,
0
}
,
{
"fixup_7_pcrel"
,
3
,
7
,
MCFixupKindInfo
::
FKF_IsPCRel
}
,
{
"fixup_13_pcrel"
,
0
,
12
,
MCFixupKindInfo
::
FKF_IsPCRel
}
,
{
"fixup_16"
,
0
,
16
,
0
}
,
{
"fixup_16_pm"
,
0
,
16
,
0
}
,
{
"fixup_ldi"
,
0
,
8
,
0
}
,
{
"fixup_lo8_ldi"
,
0
,
8
,
0
}
,
{
"fixup_hi8_ldi"
,
0
,
8
,
0
}
,
{
"fixup_hh8_ldi"
,
0
,
8
,
0
}
,
{
"fixup_ms8_ldi"
,
0
,
8
,
0
}
,
{
"fixup_lo8_ldi_neg"
,
0
,
8
,
0
}
,
{
"fixup_hi8_ldi_neg"
,
0
,
8
,
0
}
,
{
"fixup_hh8_ldi_neg"
,
0
,
8
,
0
}
,
{
"fixup_ms8_ldi_neg"
,
0
,
8
,
0
}
,
{
"fixup_lo8_ldi_pm"
,
0
,
8
,
0
}
,
{
"fixup_hi8_ldi_pm"
,
0
,
8
,
0
}
,
{
"fixup_hh8_ldi_pm"
,
0
,
8
,
0
}
,
{
"fixup_lo8_ldi_pm_neg"
,
0
,
8
,
0
}
,
{
"fixup_hi8_ldi_pm_neg"
,
0
,
8
,
0
}
,
{
"fixup_hh8_ldi_pm_neg"
,
0
,
8
,
0
}
,
{
"fixup_call"
,
0
,
22
,
0
}
,
{
"fixup_6"
,
0
,
16
,
0
}
,
{
"fixup_6_adiw"
,
0
,
6
,
0
}
,
{
"fixup_lo8_ldi_gs"
,
0
,
8
,
0
}
,
{
"fixup_hi8_ldi_gs"
,
0
,
8
,
0
}
,
{
"fixup_8"
,
0
,
8
,
0
}
,
{
"fixup_8_lo8"
,
0
,
8
,
0
}
,
{
"fixup_8_hi8"
,
0
,
8
,
0
}
,
{
"fixup_8_hlo8"
,
0
,
8
,
0
}
,
{
"fixup_sym_diff"
,
0
,
32
,
0
}
,
{
"fixup_16_ldst"
,
0
,
16
,
0
}
,
{
"fixup_lds_sts_16"
,
0
,
16
,
0
}
,
{
"fixup_port6"
,
0
,
16
,
0
}
,
{
"fixup_port5"
,
3
,
5
,
0
}
,
}
;
if
(
Kind
<
FirstTargetFixupKind
)
return
MCAsmBackend
::
getFixupKindInfo
(
Kind
)
;
assert
(
unsigned
(
Kind
FirstTargetFixupKind
)
<
getNumFixupKinds
(
)
&&
"Invalid kind!"
)
;
return
Infos
[
Kind
FirstTargetFixupKind
]
;
}
</s>


<s> MCObjectWriter * AVRAsmBackend :: createObjectWriter ( raw_pwrite_stream & OS ) const { return createAVRELFObjectWriter ( OS , MCELFObjectTargetWriter :: getOSABI ( OSType ) ) ; } </s>

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


<s>
void
AVRAsmBackend
::
applyFixup
(
const
MCAssembler
&
Asm
,
const
MCFixup
&
Fixup
,
const
MCValue
&
Target
,
MutableArrayRef
<
char
>
Data
,
uint64_t
Value
,
bool
IsPCRel
)
const
{
adjustFixupValue
(
Fixup
,
Target
,
Value
,
&
Asm
.
getContext
(
)
)
;
if
(
Value
==
0
)
return
;
MCFixupKindInfo
Info
=
getFixupKindInfo
(
Fixup
.
getKind
(
)
)
;
auto
NumBits
=
Info
.
TargetSize
+
Info
.
TargetOffset
;
auto
NumBytes
=
(
NumBits
/
8
)
+
(
(
NumBits
%
8
)
==
0
0
:
1
)
;
Value
<<=
Info
.
TargetOffset
;
unsigned
Offset
=
Fixup
.
getOffset
(
)
;
assert
(
Offset
+
NumBytes
<=
Data
.
size
(
)
&&
"Invalid fixup offset!"
)
;
for
(
unsigned
i
=
0
;
i
<
NumBytes
;
++
i
)
{
uint8_t
mask
=
(
(
(
Value
>>
(
i
*
8
)
)
&
0xff
)
)
;
Data
[
Offset
+
i
]
|=
mask
;
}
}
</s>

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


<s> std :: unique_ptr < MCObjectWriter > AVRAsmBackend :: createObjectWriter ( raw_pwrite_stream & OS ) const { return createAVRELFObjectWriter ( OS , MCELFObjectTargetWriter :: getOSABI ( OSType ) ) ; } </s>


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

Check whether the given instruction may need relaxation .


<s>
bool
AVRAsmBackend
::
writeNopData
(
uint64_t
Count
,
MCObjectWriter
*
OW
)
const
{
assert
(
(
Count
%
2
)
==
0
&&
"NOP instructions must be 2 bytes"
)
;
OW
->
WriteZeros
(
Count
)
;
return
true
;
}
</s>


<s>
void
AVRAsmBackend
::
applyFixup
(
const
MCFixup
&
Fixup
,
char
*
Data
,
unsigned
DataSize
,
uint64_t
Value
,
bool
IsPCRel
)
const
{
if
(
Value
==
0
)
return
;
MCFixupKindInfo
Info
=
getFixupKindInfo
(
Fixup
.
getKind
(
)
)
;
auto
NumBits
=
Info
.
TargetSize
+
Info
.
TargetOffset
;
auto
NumBytes
=
(
NumBits
/
8
)
+
(
(
NumBits
%
8
)
==
0
0
:
1
)
;
Value
<<=
Info
.
TargetOffset
;
unsigned
Offset
=
Fixup
.
getOffset
(
)
;
assert
(
Offset
+
NumBytes
<=
DataSize
&&
"Invalid fixup offset!"
)
;
for
(
unsigned
i
=
0
;
i
<
NumBytes
;
++
i
)
{
uint8_t
mask
=
(
(
(
Value
>>
(
i
*
8
)
)
&
0xff
)
)
;
Data
[
Offset
+
i
]
|=
mask
;
}
}
</s>


<s>
void
AVRAsmBackend
::
applyFixup
(
const
MCFixup
&
Fixup
,
char
*
Data
,
unsigned
DataSize
,
uint64_t
Value
,
bool
IsPCRel
,
MCContext
&
Ctx
)
const
{
if
(
Value
==
0
)
return
;
MCFixupKindInfo
Info
=
getFixupKindInfo
(
Fixup
.
getKind
(
)
)
;
auto
NumBits
=
Info
.
TargetSize
+
Info
.
TargetOffset
;
auto
NumBytes
=
(
NumBits
/
8
)
+
(
(
NumBits
%
8
)
==
0
0
:
1
)
;
Value
<<=
Info
.
TargetOffset
;
unsigned
Offset
=
Fixup
.
getOffset
(
)
;
assert
(
Offset
+
NumBytes
<=
DataSize
&&
"Invalid fixup offset!"
)
;
for
(
unsigned
i
=
0
;
i
<
NumBytes
;
++
i
)
{
uint8_t
mask
=
(
(
(
Value
>>
(
i
*
8
)
)
&
0xff
)
)
;
Data
[
Offset
+
i
]
|=
mask
;
}
}
</s>


<s>
void
AVRAsmBackend
::
applyFixup
(
const
MCAssembler
&
Asm
,
const
MCFixup
&
Fixup
,
const
MCValue
&
Target
,
MutableArrayRef
<
char
>
Data
,
uint64_t
Value
,
bool
IsResolved
,
const
MCSubtargetInfo
*
STI
)
const
{
adjustFixupValue
(
Fixup
,
Target
,
Value
,
&
Asm
.
getContext
(
)
)
;
if
(
Value
==
0
)
return
;
MCFixupKindInfo
Info
=
getFixupKindInfo
(
Fixup
.
getKind
(
)
)
;
auto
NumBits
=
Info
.
TargetSize
+
Info
.
TargetOffset
;
auto
NumBytes
=
(
NumBits
/
8
)
+
(
(
NumBits
%
8
)
==
0
0
:
1
)
;
Value
<<=
Info
.
TargetOffset
;
unsigned
Offset
=
Fixup
.
getOffset
(
)
;
assert
(
Offset
+
NumBytes
<=
Data
.
size
(
)
&&
"Invalid fixup offset!"
)
;
for
(
unsigned
i
=
0
;
i
<
NumBytes
;
++
i
)
{
uint8_t
mask
=
(
(
(
Value
>>
(
i
*
8
)
)
&
0xff
)
)
;
Data
[
Offset
+
i
]
|=
mask
;
}
}
</s>


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

Simple predicate for targets where ! Resolved implies requiring relaxation .


<s> unsigned getNumFixupKinds ( ) const override { return AVR :: NumTargetFixupKinds ; } </s>

Get the number of target specific fixup kinds .


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


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

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


<s>
bool
AVRAsmBackend
::
writeNopData
(
raw_ostream
&
OS
,
uint64_t
Count
)
const
{
assert
(
(
Count
%
2
)
==
0
&&
"NOP instructions must be 2 bytes"
)
;
OS
.
write_zeros
(
Count
)
;
return
true
;
}
</s>


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

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


<s>
unsigned
getReg
(
)
const
override
{
assert
(
(
Kind
==
k_Register
||
Kind
==
k_Memri
)
&&
"Invalid access!"
)
;
return
RegImm
.
Reg
;
}
</s>

Returns the register associated with this edge .


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

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


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


<s> bool isMem ( ) const override { return Kind == k_Memri ; } </s>


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


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


<s>
void
print
(
raw_ostream
&
O
)
const
override
{
switch
(
Kind
)
{
case
k_Token
:
O
<<
"Token: \""
<<
getToken
(
)
<<
"\""
;
break
;
case
k_Register
:
O
<<
"Register: "
<<
getReg
(
)
;
break
;
case
k_Immediate
:
O
<<
"Immediate: \""
<<
*
getImm
(
)
<<
"\""
;
break
;
case
k_Memri
:
{
O
<<
"Memri: \""
<<
getReg
(
)
<<
'+'
<<
*
getImm
(
)
<<
"\""
;
break
;
}
}
O
<<
"\n"
;
}
</s>

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


<s> unsigned AVRAsmParser :: validateTargetOperandClass ( MCParsedAsmOperand & AsmOp , unsigned ExpectedKind ) { AVROperand & Op = static_cast < AVROperand & > ( AsmOp ) ; MatchClassKind Expected = static_cast < MatchClassKind > ( ExpectedKind ) ; if ( Op . isImm ( ) ) { if ( MCConstantExpr const * Const = dyn_cast < MCConstantExpr > ( Op . getImm ( ) ) ) { int64_t RegNum = Const -> getValue ( ) ; std :: ostringstream RegName ; RegName << "r" << RegNum ; RegNum = MatchRegisterName ( RegName . str ( ) ) ; if ( RegNum != AVR :: NoRegister ) { Op . makeReg ( RegNum ) ; if ( validateOperandClass ( Op , Expected ) == Match_Success ) { return Match_Success ; } } } } if ( Op . isReg ( ) ) { if ( isSubclass ( Expected , MCK_DREGS ) ) { unsigned correspondingDREG = toDREG ( Op . getReg ( ) ) ; if ( correspondingDREG != AVR :: NoRegister ) { Op . makeReg ( correspondingDREG ) ; return validateOperandClass ( Op , Expected ) ; } } } return Match_InvalidOperand ; } </s>

Allow a target to add special case operand matching for things that tblgen doesn't/ca n't handle effectively .

AVR AVR AVR AVR "r" AVR::NoRegister AVR::NoRegister


<s>
bool
AVRAsmParser
::
MatchAndEmitInstruction
(
SMLoc
Loc
,
unsigned
&
Opcode
,
OperandVector
&
Operands
,
MCStreamer
&
Out
,
uint64_t
&
ErrorInfo
,
bool
MatchingInlineAsm
)
{
MCInst
Inst
;
unsigned
MatchResult
=
MatchInstructionImpl
(
Operands
,
Inst
,
ErrorInfo
,
MatchingInlineAsm
)
;
switch
(
MatchResult
)
{
case
Match_Success
:
return
emit
(
Inst
,
Loc
,
Out
)
;
case
Match_MissingFeature
:
return
missingFeature
(
Loc
,
ErrorInfo
)
;
case
Match_InvalidOperand
:
return
invalidOperand
(
Loc
,
Operands
,
ErrorInfo
)
;
case
Match_MnemonicFail
:
return
Error
(
Loc
,
"invalid instruction"
)
;
default
:
return
true
;
}
}
</s>

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


<s> static std :: unique_ptr < AVROperand > CreateReg ( unsigned RegNum , SMLoc S , SMLoc E ) { return make_unique < AVROperand > ( RegNum , S , E ) ; } </s>

CreateReg - Allocate a single virtual register for the given type .


<s> bool AVRAsmParser :: emit ( MCInst & Inst , SMLoc const & Loc , MCStreamer & Out ) const { Inst . setLoc ( Loc ) ; Out . EmitInstruction ( Inst , STI ) ; return false ; } </s>

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


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

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


<s>
bool
AVRAsmParser
::
MatchAndEmitInstruction
(
SMLoc
Loc
,
unsigned
&
Opcode
,
OperandVector
&
Operands
,
MCStreamer
&
Out
,
uint64_t
&
ErrorInfo
,
bool
MatchingInlineAsm
)
{
MCInst
Inst
;
unsigned
MatchResult
=
MatchInstructionImpl
(
Operands
,
Inst
,
ErrorInfo
,
MatchingInlineAsm
)
;
switch
(
MatchResult
)
{
case
Match_Success
:
return
emit
(
Inst
,
Loc
,
Out
)
;
case
Match_MissingFeature
:
return
missingFeature
(
Loc
,
ErrorInfo
)
;
case
Match_InvalidOperand
:
return
invalidOperand
(
Loc
,
Operands
,
ErrorInfo
)
;
case
Match_MnemonicFail
:
return
Error
(
Loc
,
"invalid instruction"
)
;
case
Match_InvalidRegisterOnTiny
:
return
Error
(
Loc
,
"invalid register on avrtiny"
)
;
default
:
return
true
;
}
}
</s>

AVR
AVR
"invalid instruction"
"invalid register on avrtiny"


<s> unsigned AVRAsmParser :: validateTargetOperandClass ( MCParsedAsmOperand & AsmOp , unsigned ExpectedKind ) { AVROperand & Op = static_cast < AVROperand & > ( AsmOp ) ; MatchClassKind Expected = static_cast < MatchClassKind > ( ExpectedKind ) ; if ( Op . isImm ( ) ) { if ( MCConstantExpr const * Const = dyn_cast < MCConstantExpr > ( Op . getImm ( ) ) ) { int64_t RegNum = Const -> getValue ( ) ; if ( 0 <= RegNum && RegNum <= 15 && STI . hasFeature ( AVR :: FeatureTinyEncoding ) ) return Match_InvalidRegisterOnTiny ; std :: ostringstream RegName ; RegName << "r" << RegNum ; RegNum = MatchRegisterName ( RegName . str ( ) ) ; if ( RegNum != AVR :: NoRegister ) { Op . makeReg ( RegNum ) ; if ( validateOperandClass ( Op , Expected ) == Match_Success ) { return Match_Success ; } } } } if ( Op . isReg ( ) ) { if ( isSubclass ( Expected , MCK_DREGS ) ) { unsigned correspondingDREG = toDREG ( Op . getReg ( ) ) ; if ( correspondingDREG != AVR :: NoRegister ) { Op . makeReg ( correspondingDREG ) ; return validateOperandClass ( Op , Expected ) ; } } } return Match_InvalidOperand ; } </s>

AVR AVR AVR AVR 0 15 AVR::FeatureTinyEncoding "r" AVR::NoRegister AVR::NoRegister


<s> void addExpr ( MCInst & Inst , const MCExpr * Expr ) const { if ( ! Expr ) Inst . addOperand ( MCOperand :: createImm ( 0 ) ) ; else if ( const MCConstantExpr * CE = dyn_cast < MCConstantExpr > ( Expr ) ) Inst . addOperand ( MCOperand :: createImm ( CE -> getValue ( ) ) ) ; else Inst . addOperand ( MCOperand :: createExpr ( Expr ) ) ; } </s>


<s> static std :: unique_ptr < AVROperand > CreateReg ( unsigned RegNum , SMLoc S , SMLoc E ) { return std :: make_unique < AVROperand > ( RegNum , S , E ) ; } </s>


<s> bool AVRAsmParser :: emit ( MCInst & Inst , SMLoc const & Loc , MCStreamer & Out ) const { Inst . setLoc ( Loc ) ; Out . emitInstruction ( Inst , STI ) ; return false ; } </s>


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


<s>
unsigned
getReg
(
)
const
{
assert
(
(
Kind
==
k_Register
||
Kind
==
k_Memri
)
&&
"Invalid access!"
)
;
return
RegImm
.
Reg
;
}
</s>


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


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


<s> bool isMem ( ) const { return Kind == k_Memri ; } </s>


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


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


<s> bool AVRAsmParser :: ParseDirective ( llvm :: AsmToken DirectiveID ) { StringRef IDVal = DirectiveID . getIdentifier ( ) ; if ( IDVal . lower ( ) == ".long" ) { parseLiteralValues ( SIZE_LONG , DirectiveID . getLoc ( ) ) ; } else if ( IDVal . lower ( ) == ".word" || IDVal . lower ( ) == ".short" ) { parseLiteralValues ( SIZE_WORD , DirectiveID . getLoc ( ) ) ; } else if ( IDVal . lower ( ) == ".byte" ) { parseLiteralValues ( 1 , DirectiveID . getLoc ( ) ) ; } return true ; } </s>


"failed to parse register and immediate pair"

ParseInstruction - Parse one assembly instruction .


<s>
virtual
void
print
(
raw_ostream
&
O
)
const
{
switch
(
Kind
)
{
case
k_Token
:
O
<<
"Token: \""
<<
getToken
(
)
<<
"\""
;
break
;
case
k_Register
:
O
<<
"Register: "
<<
getReg
(
)
;
break
;
case
k_Immediate
:
O
<<
"Immediate: \""
<<
*
getImm
(
)
<<
"\""
;
break
;
case
k_Memri
:
{
O
<<
"Memri: \""
<<
getReg
(
)
<<
'+'
<<
*
getImm
(
)
<<
"\""
;
break
;
}
}
O
<<
"\n"
;
}
</s>


<s> OperandMatchResultTy AVRAsmParser :: tryParseRegister ( unsigned & RegNo , SMLoc & StartLoc , SMLoc & EndLoc ) { StartLoc = Parser . getTok ( ) . getLoc ( ) ; RegNo = parseRegister ( true ) ; EndLoc = Parser . getTok ( ) . getLoc ( ) ; if ( RegNo == AVR :: NoRegister ) return MatchOperand_NoMatch ; return MatchOperand_Success ; } </s>

tryParseRegister - parse one register if possible


<s> unsigned AVRAsmParser :: validateTargetOperandClass ( MCParsedAsmOperand & AsmOp , unsigned ExpectedKind ) { AVROperand & Op = static_cast < AVROperand & > ( AsmOp ) ; MatchClassKind Expected = static_cast < MatchClassKind > ( ExpectedKind ) ; if ( Op . isImm ( ) ) { if ( MCConstantExpr const * Const = dyn_cast < MCConstantExpr > ( Op . getImm ( ) ) ) { int64_t RegNum = Const -> getValue ( ) ; std :: ostringstream RegName ; RegName << "r" << RegNum ; RegNum = MatchRegisterName ( RegName . str ( ) . c_str ( ) ) ; if ( RegNum != AVR :: NoRegister ) { Op . makeReg ( RegNum ) ; if ( validateOperandClass ( Op , Expected ) == Match_Success ) { return Match_Success ; } } } } if ( Op . isReg ( ) ) { if ( isSubclass ( Expected , MCK_DREGS ) ) { unsigned correspondingDREG = toDREG ( Op . getReg ( ) ) ; if ( correspondingDREG != AVR :: NoRegister ) { Op . makeReg ( correspondingDREG ) ; return validateOperandClass ( Op , Expected ) ; } } } return Match_InvalidOperand ; } </s>


"Operand must be a register when you're"

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


"Wrong register class for memory operand."

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


<s> void AVRAsmPrinter :: EmitInstruction ( const MachineInstr * MI ) { AVRMCInstLower MCInstLowering ( OutContext , * this ) ; MCInst I ; MCInstLowering . lowerInstruction ( * MI , I ) ; EmitToStreamer ( * OutStreamer , I ) ; } </s>

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


<s> void AVRAsmPrinter :: emitStartOfAsmFile ( Module & M ) { const AVRTargetMachine & TM = ( const AVRTargetMachine & ) MMI -> getTarget ( ) ; const AVRSubtarget * SubTM = ( const AVRSubtarget * ) TM . getSubtargetImpl ( ) ; if ( ! SubTM ) return ; OutStreamer -> emitAssignment ( MMI -> getContext ( ) . getOrCreateSymbol ( StringRef ( "__tmp_reg__" ) ) , MCConstantExpr :: create ( SubTM -> getRegTmpIndex ( ) , MMI -> getContext ( ) ) ) ; OutStreamer -> emitAssignment ( MMI -> getContext ( ) . getOrCreateSymbol ( StringRef ( "__zero_reg__" ) ) , MCConstantExpr :: create ( SubTM -> getRegZeroIndex ( ) , MMI -> getContext ( ) ) ) ; OutStreamer -> emitAssignment ( MMI -> getContext ( ) . getOrCreateSymbol ( StringRef ( "__SREG__" ) ) , MCConstantExpr :: create ( SubTM -> getIORegSREG ( ) , MMI -> getContext ( ) ) ) ; if ( ! SubTM -> hasSmallStack ( ) ) OutStreamer -> emitAssignment ( MMI -> getContext ( ) . getOrCreateSymbol ( StringRef ( "__SP_H__" ) ) , MCConstantExpr :: create ( SubTM -> getIORegSPH ( ) , MMI -> getContext ( ) ) ) ; OutStreamer -> emitAssignment ( MMI -> getContext ( ) . getOrCreateSymbol ( StringRef ( "__SP_L__" ) ) , MCConstantExpr :: create ( SubTM -> getIORegSPL ( ) , MMI -> getContext ( ) ) ) ; if ( SubTM -> hasEIJMPCALL ( ) ) OutStreamer -> emitAssignment ( MMI -> getContext ( ) . getOrCreateSymbol ( StringRef ( "__EIND__" ) ) , MCConstantExpr :: create ( SubTM -> getIORegEIND ( ) , MMI -> getContext ( ) ) ) ; if ( SubTM -> hasELPM ( ) ) OutStreamer -> emitAssignment ( MMI -> getContext ( ) . getOrCreateSymbol ( StringRef ( "__RAMPZ__" ) ) , MCConstantExpr :: create ( SubTM -> getIORegRAMPZ ( ) , MMI -> getContext ( ) ) ) ; } </s>

This virtual method can be overridden by targets that want to emit something at the start of their file .


" Declaring this symbol tells the CRT that it should"

"copy all variables from program memory to RAM on startup"

"clear the zeroed data section on startup"

doFinalization - Virtual method overriden by subclasses to do any necessary clean up after all passes have run .


<s> void AVRAsmPrinter :: emitInstruction ( const MachineInstr * MI ) { AVRMCInstLower MCInstLowering ( OutContext , * this ) ; MCInst I ; MCInstLowering . lowerInstruction ( * MI , I ) ; EmitToStreamer ( * OutStreamer , I ) ; } </s>

Targets should implement this to emit instructions .


" Emitting these undefined symbol references causes us to link the"

" libgcc code that runs our constructors/destructors"

Targets can override this to change how global constants that are part of a C++ static/global constructor list are emitted .


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

getPassName - Return a nice clean name for a pass .


<s> const MCExpr * AVRAsmPrinter :: lowerConstant ( const Constant * CV ) { MCContext & Ctx = OutContext ; if ( const GlobalValue * GV = dyn_cast < GlobalValue > ( CV ) ) { bool IsProgMem = GV -> getAddressSpace ( ) == AVR :: ProgramMemory ; if ( IsProgMem ) { const MCExpr * Expr = MCSymbolRefExpr :: create ( getSymbol ( GV ) , Ctx ) ; return AVRMCExpr :: create ( AVRMCExpr :: VK_AVR_PM , Expr , false , Ctx ) ; } } return AsmPrinter :: lowerConstant ( CV ) ; } </s>

Lower the specified LLVM Constant to an MCExpr .


<s> DecodeStatus AVRDisassembler :: getInstruction ( MCInst & Instr , uint64_t & Size , ArrayRef < uint8_t > Bytes , uint64_t Address , raw_ostream & CStream ) const { uint32_t Insn ; DecodeStatus Result ; { Result = readInstruction16 ( Bytes , Address , Size , Insn ) ; if ( Result == MCDisassembler :: Fail ) return MCDisassembler :: Fail ; Result = decodeInstruction ( getDecoderTable ( Size ) , Instr , Insn , Address , this , STI ) ; if ( Result != MCDisassembler :: Fail ) return Result ; Result = decodeLoadStore ( Instr , Insn , Address , this ) ; if ( Result != MCDisassembler :: Fail ) return Result ; } { Result = readInstruction32 ( Bytes , Address , Size , Insn ) ; if ( Result == MCDisassembler :: Fail ) return MCDisassembler :: Fail ; Result = decodeInstruction ( getDecoderTable ( Size ) , Instr , Insn , Address , this , STI ) ; if ( Result != MCDisassembler :: Fail ) { return Result ; } return MCDisassembler :: Fail ; } } </s>

Returns the disassembly of a single instruction .


<s> DecodeStatus AVRDisassembler :: getInstruction ( MCInst & Instr , uint64_t & Size , ArrayRef < uint8_t > Bytes , uint64_t Address , raw_ostream & VStream , raw_ostream & CStream ) const { uint32_t Insn ; DecodeStatus Result ; { Result = readInstruction16 ( Bytes , Address , Size , Insn ) ; if ( Result == MCDisassembler :: Fail ) return MCDisassembler :: Fail ; Result = decodeInstruction ( getDecoderTable ( Size ) , Instr , Insn , Address , this , STI ) ; if ( Result != MCDisassembler :: Fail ) return Result ; } { Result = readInstruction32 ( Bytes , Address , Size , Insn ) ; if ( Result == MCDisassembler :: Fail ) return MCDisassembler :: Fail ; Result = decodeInstruction ( getDecoderTable ( Size ) , Instr , Insn , Address , this , STI ) ; if ( Result != MCDisassembler :: Fail ) { return Result ; } return MCDisassembler :: Fail ; } } </s>


<s> DecodeStatus AVRDisassembler :: getInstruction ( MCInst & Instr , uint64_t & Size , ArrayRef < uint8_t > Bytes , uint64_t Address , raw_ostream & CStream ) const { uint32_t Insn ; DecodeStatus Result ; { Result = readInstruction16 ( Bytes , Address , Size , Insn ) ; if ( Result == MCDisassembler :: Fail ) return MCDisassembler :: Fail ; Result = decodeInstruction ( getDecoderTable ( Size ) , Instr , Insn , Address , this , STI ) ; if ( Result != MCDisassembler :: Fail ) return Result ; } { Result = readInstruction32 ( Bytes , Address , Size , Insn ) ; if ( Result == MCDisassembler :: Fail ) return MCDisassembler :: Fail ; Result = decodeInstruction ( getDecoderTable ( Size ) , Instr , Insn , Address , this , STI ) ; if ( Result != MCDisassembler :: Fail ) { return Result ; } return MCDisassembler :: Fail ; } } </s>


<s> MCELFStreamer & getStreamer ( ) { return static_cast < MCELFStreamer & > ( Streamer ) ; } </s>

Return the output streamer for the assembler .


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


<s> MachineRegisterInfo & getRegInfo ( Block & MBB ) { return MBB . getParent ( ) -> getRegInfo ( ) ; } </s>

getRegInfo - Return information about the registers currently in use .


<s>
bool
AVRExpandPseudo
::
runOnMachineFunction
(
MachineFunction
&
MF
)
{
bool
Modified
=
false
;
const
AVRSubtarget
&
STI
=
MF
.
getSubtarget
<
AVRSubtarget
>
(
)
;
TRI
=
STI
.
getRegisterInfo
(
)
;
TII
=
STI
.
getInstrInfo
(
)
;
MF
.
getProperties
(
)
.
set
(
MachineFunctionProperties
::
Property
::
TracksLiveness
)
;
for
(
Block
&
MBB
:
MF
)
{
bool
ContinueExpanding
=
true
;
unsigned
ExpandCount
=
0
;
do
{
assert
(
ExpandCount
<
10
&&
"pseudo expand limit reached"
)
;
bool
BlockModified
=
expandMBB
(
MBB
)
;
Modified
|=
BlockModified
;
ExpandCount
++
;
ContinueExpanding
=
BlockModified
;
}
while
(
ContinueExpanding
)
;
}
return
Modified
;
}
</s>

runOnMachineFunction - Emit the function body .

AVR
AVR
AVR
AVR
0
10
"pseudo expand limit reached"


<s>
bool
AVRExpandPseudo
::
runOnMachineFunction
(
MachineFunction
&
MF
)
{
bool
Modified
=
false
;
const
AVRSubtarget
&
STI
=
MF
.
getSubtarget
<
AVRSubtarget
>
(
)
;
TRI
=
STI
.
getRegisterInfo
(
)
;
TII
=
STI
.
getInstrInfo
(
)
;
MF
.
getProperties
(
)
.
set
(
MachineFunctionProperties
::
Property
::
TracksLiveness
)
;
for
(
Block
&
MBB
:
MF
)
{
bool
ContinueExpanding
=
true
;
unsigned
ExpandCount
=
0
;
do
{
assert
(
ExpandCount
<
10
&&
"pseudo expand limit reached"
)
;
(
void
)
ExpandCount
;
bool
BlockModified
=
expandMBB
(
MBB
)
;
Modified
|=
BlockModified
;
ExpandCount
++
;
ContinueExpanding
=
BlockModified
;
}
while
(
ContinueExpanding
)
;
}
return
Modified
;
}
</s>


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

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


<s> void AVRFrameLowering :: determineCalleeSaves ( MachineFunction & MF , BitVector & SavedRegs , RegScavenger * RS ) const { TargetFrameLowering :: determineCalleeSaves ( MF , SavedRegs , RS ) ; if ( hasFP ( MF ) ) { SavedRegs . set ( AVR :: R29 ) ; SavedRegs . set ( AVR :: R28 ) ; } } </s>

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


<s>
MachineBasicBlock
::
iterator
AVRFrameLowering
::
eliminateCallFramePseudoInstr
(
MachineFunction
&
MF
,
MachineBasicBlock
&
MBB
,
MachineBasicBlock
::
iterator
MI
)
const
{
const
AVRSubtarget
&
STI
=
MF
.
getSubtarget
<
AVRSubtarget
>
(
)
;
const
AVRInstrInfo
&
TII
=
*
STI
.
getInstrInfo
(
)
;
if
(
hasReservedCallFrame
(
MF
)
)
{
return
MBB
.
erase
(
MI
)
;
}
DebugLoc
DL
=
MI
->
getDebugLoc
(
)
;
unsigned
int
Opcode
=
MI
->
getOpcode
(
)
;
int
Amount
=
TII
.
getFrameSize
(
*
MI
)
;
if
(
Amount
==
0
)
{
return
MBB
.
erase
(
MI
)
;
}
assert
(
getStackAlign
(
)
==
Align
(
1
)
&&
"Unsupported stack alignment"
)
;
if
(
Opcode
==
TII
.
getCallFrameSetupOpcode
(
)
)
{
BuildMI
(
MBB
,
MI
,
DL
,
TII
.
get
(
AVR
::
SPREAD
)
,
AVR
::
R31R30
)
.
addReg
(
AVR
::
SP
)
;
MachineInstr
*
New
=
BuildMI
(
MBB
,
MI
,
DL
,
TII
.
get
(
AVR
::
SUBIWRdK
)
,
AVR
::
R31R30
)
.
addReg
(
AVR
::
R31R30
,
RegState
::
Kill
)
.
addImm
(
Amount
)
;
New
->
getOperand
(
3
)
.
setIsDead
(
)
;
BuildMI
(
MBB
,
MI
,
DL
,
TII
.
get
(
AVR
::
SPWRITE
)
,
AVR
::
SP
)
.
addReg
(
AVR
::
R31R30
)
;
fixStackStores
(
MBB
,
MI
,
TII
)
;
}
else
{
assert
(
Opcode
==
TII
.
getCallFrameDestroyOpcode
(
)
)
;
unsigned
AddOpcode
;
if
(
isUInt
<
6
>
(
Amount
)
)
{
AddOpcode
=
AVR
::
ADIWRdK
;
}
else
{
AddOpcode
=
AVR
::
SUBIWRdK
;
Amount
=
Amount
;
}
BuildMI
(
MBB
,
MI
,
DL
,
TII
.
get
(
AVR
::
SPREAD
)
,
AVR
::
R31R30
)
.
addReg
(
AVR
::
SP
)
;
MachineInstr
*
New
=
BuildMI
(
MBB
,
MI
,
DL
,
TII
.
get
(
AddOpcode
)
,
AVR
::
R31R30
)
.
addReg
(
AVR
::
R31R30
,
RegState
::
Kill
)
.
addImm
(
Amount
)
;
New
->
getOperand
(
3
)
.
setIsDead
(
)
;
BuildMI
(
MBB
,
MI
,
DL
,
TII
.
get
(
AVR
::
SPWRITE
)
,
AVR
::
SP
)
.
addReg
(
AVR
::
R31R30
,
RegState
::
Kill
)
;
}
return
MBB
.
erase
(
MI
)
;
}
</s>

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


"Can only insert epilog into returning blocks"


<s>
StringRef
getPassName
(
)
const
override
{
return
"AVR Frame Analyzer"
;
}
</s>


<s> bool AVRFrameLowering :: hasFP ( const MachineFunction & MF ) const { const AVRMachineFunctionInfo * FuncInfo = MF . getInfo < AVRMachineFunctionInfo > ( ) ; return ( FuncInfo -> getHasSpills ( ) || FuncInfo -> getHasAllocas ( ) || FuncInfo -> getHasStackArgs ( ) || MF . getFrameInfo ( ) . hasVarSizedObjects ( ) ) ; } </s>

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


<s> bool AVRFrameLowering :: hasReservedCallFrame ( const MachineFunction & MF ) const { const MachineFrameInfo & MFI = MF . getFrameInfo ( ) ; return hasFP ( MF ) && ! MFI . 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
AVRFrameLowering
::
restoreCalleeSavedRegisters
(
MachineBasicBlock
&
MBB
,
MachineBasicBlock
::
iterator
MI
,
MutableArrayRef
<
CalleeSavedInfo
>
CSI
,
const
TargetRegisterInfo
*
TRI
)
const
{
if
(
CSI
.
empty
(
)
)
{
return
false
;
}
DebugLoc
DL
=
MBB
.
findDebugLoc
(
MI
)
;
const
MachineFunction
&
MF
=
*
MBB
.
getParent
(
)
;
const
AVRSubtarget
&
STI
=
MF
.
getSubtarget
<
AVRSubtarget
>
(
)
;
const
TargetInstrInfo
&
TII
=
*
STI
.
getInstrInfo
(
)
;
for
(
const
CalleeSavedInfo
&
CCSI
:
CSI
)
{
Register
Reg
=
CCSI
.
getReg
(
)
;
assert
(
TRI
->
getRegSizeInBits
(
*
TRI
->
getMinimalPhysRegClass
(
Reg
)
)
==
8
&&
"Invalid register size"
)
;
BuildMI
(
MBB
,
MI
,
DL
,
TII
.
get
(
AVR
::
POPRd
)
,
Reg
)
;
}
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 ( ) .

AVR
AVR
AVR
AVR
8
"Invalid register size"
AVR::POPRd


<s> bool runOnMachineFunction ( MachineFunction & MF ) override { const MachineFrameInfo & MFI = MF . getFrameInfo ( ) ; AVRMachineFunctionInfo * AFI = MF . getInfo < AVRMachineFunctionInfo > ( ) ; if ( MFI . getNumObjects ( ) != MFI . getNumFixedObjects ( ) ) { for ( unsigned i = 0 , e = MFI . getObjectIndexEnd ( ) ; i != e ; ++ i ) { if ( MFI . getObjectSize ( i ) ) { AFI -> setHasAllocas ( true ) ; break ; } } } if ( MFI . getNumFixedObjects ( ) == 0 ) { return false ; } for ( const MachineBasicBlock & BB : MF ) { for ( const MachineInstr & MI : BB ) { int Opcode = MI . getOpcode ( ) ; if ( ( Opcode != AVR :: LDDRdPtrQ ) && ( Opcode != AVR :: LDDWRdPtrQ ) && ( Opcode != AVR :: STDPtrQRr ) && ( Opcode != AVR :: STDWPtrQRr ) ) { continue ; } for ( const MachineOperand & MO : MI . operands ( ) ) { if ( ! MO . isFI ( ) ) { continue ; } if ( MFI . isFixedObjectIndex ( MO . getIndex ( ) ) ) { AFI -> setHasStackArgs ( true ) ; return false ; } } } } return false ; } </s>

AVR AVR AVR 0 0 AVR::LDDRdPtrQ AVR::LDDWRdPtrQ AVR::STDPtrQRr AVR::STDWPtrQRr


<s>
bool
AVRFrameLowering
::
spillCalleeSavedRegisters
(
MachineBasicBlock
&
MBB
,
MachineBasicBlock
::
iterator
MI
,
ArrayRef
<
CalleeSavedInfo
>
CSI
,
const
TargetRegisterInfo
*
TRI
)
const
{
if
(
CSI
.
empty
(
)
)
{
return
false
;
}
unsigned
CalleeFrameSize
=
0
;
DebugLoc
DL
=
MBB
.
findDebugLoc
(
MI
)
;
MachineFunction
&
MF
=
*
MBB
.
getParent
(
)
;
const
AVRSubtarget
&
STI
=
MF
.
getSubtarget
<
AVRSubtarget
>
(
)
;
const
TargetInstrInfo
&
TII
=
*
STI
.
getInstrInfo
(
)
;
AVRMachineFunctionInfo
*
AVRFI
=
MF
.
getInfo
<
AVRMachineFunctionInfo
>
(
)
;
for
(
const
CalleeSavedInfo
&
I
:
llvm
::
reverse
(
CSI
)
)
{
Register
Reg
=
I
.
getReg
(
)
;
bool
IsNotLiveIn
=
!
MBB
.
isLiveIn
(
Reg
)
;
assert
(
TRI
->
getRegSizeInBits
(
*
TRI
->
getMinimalPhysRegClass
(
Reg
)
)
==
8
&&
"Invalid register size"
)
;
if
(
IsNotLiveIn
)
{
MBB
.
addLiveIn
(
Reg
)
;
}
BuildMI
(
MBB
,
MI
,
DL
,
TII
.
get
(
AVR
::
PUSHRr
)
)
.
addReg
(
Reg
,
getKillRegState
(
IsNotLiveIn
)
)
.
setMIFlag
(
MachineInstr
::
FrameSetup
)
;
++
CalleeFrameSize
;
}
AVRFI
->
setCalleeSavedFrameSize
(
CalleeFrameSize
)
;
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 ( ) .

AVR
AVR
0
AVR
AVR
AVR
AVR
AVR
8
"Invalid register size"
AVR::PUSHRr
AVR


<s>
MachineBasicBlock
::
iterator
AVRFrameLowering
::
eliminateCallFramePseudoInstr
(
MachineFunction
&
MF
,
MachineBasicBlock
&
MBB
,
MachineBasicBlock
::
iterator
MI
)
const
{
const
AVRSubtarget
&
STI
=
MF
.
getSubtarget
<
AVRSubtarget
>
(
)
;
const
AVRInstrInfo
&
TII
=
*
STI
.
getInstrInfo
(
)
;
if
(
hasReservedCallFrame
(
MF
)
)
{
fixStackStores
(
MBB
,
MI
,
TII
,
false
)
;
return
MBB
.
erase
(
MI
)
;
}
DebugLoc
DL
=
MI
->
getDebugLoc
(
)
;
unsigned
int
Opcode
=
MI
->
getOpcode
(
)
;
int
Amount
=
TII
.
getFrameSize
(
*
MI
)
;
if
(
Amount
!=
0
)
{
assert
(
getStackAlignment
(
)
==
1
&&
"Unsupported stack alignment"
)
;
if
(
Opcode
==
TII
.
getCallFrameSetupOpcode
(
)
)
{
fixStackStores
(
MBB
,
MI
,
TII
,
true
)
;
}
else
{
assert
(
Opcode
==
TII
.
getCallFrameDestroyOpcode
(
)
)
;
unsigned
addOpcode
;
if
(
isUInt
<
6
>
(
Amount
)
)
{
addOpcode
=
AVR
::
ADIWRdK
;
}
else
{
addOpcode
=
AVR
::
SUBIWRdK
;
Amount
=
Amount
;
}
BuildMI
(
MBB
,
MI
,
DL
,
TII
.
get
(
AVR
::
SPREAD
)
,
AVR
::
R31R30
)
.
addReg
(
AVR
::
SP
)
;
MachineInstr
*
New
=
BuildMI
(
MBB
,
MI
,
DL
,
TII
.
get
(
addOpcode
)
,
AVR
::
R31R30
)
.
addReg
(
AVR
::
R31R30
,
RegState
::
Kill
)
.
addImm
(
Amount
)
;
New
->
getOperand
(
3
)
.
setIsDead
(
)
;
BuildMI
(
MBB
,
MI
,
DL
,
TII
.
get
(
AVR
::
SPWRITE
)
,
AVR
::
SP
)
.
addReg
(
AVR
::
R31R30
,
RegState
::
Kill
)
;
}
}
return
MBB
.
erase
(
MI
)
;
}
</s>


<s> void AVRFrameLowering :: determineCalleeSaves ( MachineFunction & MF , BitVector & SavedRegs , RegScavenger * RS ) const { TargetFrameLowering :: determineCalleeSaves ( MF , SavedRegs , RS ) ; if ( hasFP ( MF ) ) { SavedRegs . set ( AVR :: R29R28 ) ; SavedRegs . set ( AVR :: R29 ) ; SavedRegs . set ( AVR :: R28 ) ; } } </s>


<s>
MachineBasicBlock
::
iterator
AVRFrameLowering
::
eliminateCallFramePseudoInstr
(
MachineFunction
&
MF
,
MachineBasicBlock
&
MBB
,
MachineBasicBlock
::
iterator
MI
)
const
{
const
AVRSubtarget
&
STI
=
MF
.
getSubtarget
<
AVRSubtarget
>
(
)
;
const
TargetFrameLowering
&
TFI
=
*
STI
.
getFrameLowering
(
)
;
const
AVRInstrInfo
&
TII
=
*
STI
.
getInstrInfo
(
)
;
if
(
TFI
.
hasReservedCallFrame
(
MF
)
)
{
fixStackStores
(
MBB
,
MI
,
TII
,
false
)
;
return
MBB
.
erase
(
MI
)
;
}
DebugLoc
DL
=
MI
->
getDebugLoc
(
)
;
unsigned
int
Opcode
=
MI
->
getOpcode
(
)
;
int
Amount
=
MI
->
getOperand
(
0
)
.
getImm
(
)
;
if
(
Amount
!=
0
)
{
assert
(
TFI
.
getStackAlignment
(
)
==
1
&&
"Unsupported stack alignment"
)
;
if
(
Opcode
==
TII
.
getCallFrameSetupOpcode
(
)
)
{
fixStackStores
(
MBB
,
MI
,
TII
,
true
)
;
}
else
{
assert
(
Opcode
==
TII
.
getCallFrameDestroyOpcode
(
)
)
;
unsigned
addOpcode
;
if
(
isUInt
<
6
>
(
Amount
)
)
{
addOpcode
=
AVR
::
ADIWRdK
;
}
else
{
addOpcode
=
AVR
::
SUBIWRdK
;
Amount
=
Amount
;
}
BuildMI
(
MBB
,
MI
,
DL
,
TII
.
get
(
AVR
::
SPREAD
)
,
AVR
::
R31R30
)
.
addReg
(
AVR
::
SP
)
;
MachineInstr
*
New
=
BuildMI
(
MBB
,
MI
,
DL
,
TII
.
get
(
addOpcode
)
,
AVR
::
R31R30
)
.
addReg
(
AVR
::
R31R30
,
RegState
::
Kill
)
.
addImm
(
Amount
)
;
New
->
getOperand
(
3
)
.
setIsDead
(
)
;
BuildMI
(
MBB
,
MI
,
DL
,
TII
.
get
(
AVR
::
SPWRITE
)
,
AVR
::
SP
)
.
addReg
(
AVR
::
R31R30
,
RegState
::
Kill
)
;
}
}
return
MBB
.
erase
(
MI
)
;
}
</s>


<s>
bool
AVRFrameLowering
::
restoreCalleeSavedRegisters
(
MachineBasicBlock
&
MBB
,
MachineBasicBlock
::
iterator
MI
,
const
std
::
vector
<
CalleeSavedInfo
>
&
CSI
,
const
TargetRegisterInfo
*
TRI
)
const
{
if
(
CSI
.
empty
(
)
)
{
return
false
;
}
DebugLoc
DL
=
MBB
.
findDebugLoc
(
MI
)
;
const
MachineFunction
&
MF
=
*
MBB
.
getParent
(
)
;
const
AVRSubtarget
&
STI
=
MF
.
getSubtarget
<
AVRSubtarget
>
(
)
;
const
TargetInstrInfo
&
TII
=
*
STI
.
getInstrInfo
(
)
;
for
(
const
CalleeSavedInfo
&
CCSI
:
CSI
)
{
unsigned
Reg
=
CCSI
.
getReg
(
)
;
assert
(
TRI
->
getMinimalPhysRegClass
(
Reg
)
->
getSize
(
)
==
1
&&
"Invalid register size"
)
;
BuildMI
(
MBB
,
MI
,
DL
,
TII
.
get
(
AVR
::
POPRd
)
,
Reg
)
;
}
return
true
;
}
</s>

AVR
AVR
AVR
AVR
1
"Invalid register size"
AVR::POPRd


<s>
bool
AVRFrameLowering
::
spillCalleeSavedRegisters
(
MachineBasicBlock
&
MBB
,
MachineBasicBlock
::
iterator
MI
,
const
std
::
vector
<
CalleeSavedInfo
>
&
CSI
,
const
TargetRegisterInfo
*
TRI
)
const
{
if
(
CSI
.
empty
(
)
)
{
return
false
;
}
unsigned
CalleeFrameSize
=
0
;
DebugLoc
DL
=
MBB
.
findDebugLoc
(
MI
)
;
MachineFunction
&
MF
=
*
MBB
.
getParent
(
)
;
const
AVRSubtarget
&
STI
=
MF
.
getSubtarget
<
AVRSubtarget
>
(
)
;
const
TargetInstrInfo
&
TII
=
*
STI
.
getInstrInfo
(
)
;
AVRMachineFunctionInfo
*
AVRFI
=
MF
.
getInfo
<
AVRMachineFunctionInfo
>
(
)
;
for
(
unsigned
i
=
CSI
.
size
(
)
;
i
!=
0
;
i
)
{
unsigned
Reg
=
CSI
[
i
1
]
.
getReg
(
)
;
bool
IsNotLiveIn
=
!
MBB
.
isLiveIn
(
Reg
)
;
assert
(
TRI
->
getMinimalPhysRegClass
(
Reg
)
->
getSize
(
)
==
1
&&
"Invalid register size"
)
;
if
(
IsNotLiveIn
)
{
MBB
.
addLiveIn
(
Reg
)
;
}
BuildMI
(
MBB
,
MI
,
DL
,
TII
.
get
(
AVR
::
PUSHRr
)
)
.
addReg
(
Reg
,
getKillRegState
(
IsNotLiveIn
)
)
.
setMIFlag
(
MachineInstr
::
FrameSetup
)
;
++
CalleeFrameSize
;
}
AVRFI
->
setCalleeSavedFrameSize
(
CalleeFrameSize
)
;
return
true
;
}
</s>

AVR
AVR
0
AVR
AVR
AVR
AVR
AVR
0
1
1
"Invalid register size"
AVR::PUSHRr
AVR


<s>
MachineBasicBlock
::
iterator
AVRFrameLowering
::
eliminateCallFramePseudoInstr
(
MachineFunction
&
MF
,
MachineBasicBlock
&
MBB
,
MachineBasicBlock
::
iterator
MI
)
const
{
const
AVRSubtarget
&
STI
=
MF
.
getSubtarget
<
AVRSubtarget
>
(
)
;
const
AVRInstrInfo
&
TII
=
*
STI
.
getInstrInfo
(
)
;
if
(
hasReservedCallFrame
(
MF
)
)
{
fixStackStores
(
MBB
,
MI
,
TII
,
AVR
::
R29R28
)
;
return
MBB
.
erase
(
MI
)
;
}
DebugLoc
DL
=
MI
->
getDebugLoc
(
)
;
unsigned
int
Opcode
=
MI
->
getOpcode
(
)
;
int
Amount
=
TII
.
getFrameSize
(
*
MI
)
;
if
(
Amount
!=
0
)
{
assert
(
getStackAlign
(
)
==
Align
(
1
)
&&
"Unsupported stack alignment"
)
;
if
(
Opcode
==
TII
.
getCallFrameSetupOpcode
(
)
)
{
BuildMI
(
MBB
,
MI
,
DL
,
TII
.
get
(
AVR
::
SPREAD
)
,
AVR
::
R31R30
)
.
addReg
(
AVR
::
SP
)
;
MachineInstr
*
New
=
BuildMI
(
MBB
,
MI
,
DL
,
TII
.
get
(
AVR
::
SUBIWRdK
)
,
AVR
::
R31R30
)
.
addReg
(
AVR
::
R31R30
,
RegState
::
Kill
)
.
addImm
(
Amount
)
;
New
->
getOperand
(
3
)
.
setIsDead
(
)
;
BuildMI
(
MBB
,
MI
,
DL
,
TII
.
get
(
AVR
::
SPWRITE
)
,
AVR
::
SP
)
.
addReg
(
AVR
::
R31R30
)
;
fixStackStores
(
MBB
,
MI
,
TII
,
AVR
::
R31R30
)
;
}
else
{
assert
(
Opcode
==
TII
.
getCallFrameDestroyOpcode
(
)
)
;
unsigned
addOpcode
;
if
(
isUInt
<
6
>
(
Amount
)
)
{
addOpcode
=
AVR
::
ADIWRdK
;
}
else
{
addOpcode
=
AVR
::
SUBIWRdK
;
Amount
=
Amount
;
}
BuildMI
(
MBB
,
MI
,
DL
,
TII
.
get
(
AVR
::
SPREAD
)
,
AVR
::
R31R30
)
.
addReg
(
AVR
::
SP
)
;
MachineInstr
*
New
=
BuildMI
(
MBB
,
MI
,
DL
,
TII
.
get
(
addOpcode
)
,
AVR
::
R31R30
)
.
addReg
(
AVR
::
R31R30
,
RegState
::
Kill
)
.
addImm
(
Amount
)
;
New
->
getOperand
(
3
)
.
setIsDead
(
)
;
BuildMI
(
MBB
,
MI
,
DL
,
TII
.
get
(
AVR
::
SPWRITE
)
,
AVR
::
SP
)
.
addReg
(
AVR
::
R31R30
,
RegState
::
Kill
)
;
}
}
return
MBB
.
erase
(
MI
)
;
}
</s>


"AVR dynalloca stack pointer save/restore"


<s> bool runOnMachineFunction ( MachineFunction & MF ) override { if ( ! MF . getFrameInfo ( ) . hasVarSizedObjects ( ) ) { return false ; } const AVRSubtarget & STI = MF . getSubtarget < AVRSubtarget > ( ) ; const TargetInstrInfo & TII = * STI . getInstrInfo ( ) ; MachineBasicBlock & EntryMBB = MF . front ( ) ; MachineBasicBlock :: iterator MBBI = EntryMBB . begin ( ) ; DebugLoc DL = EntryMBB . findDebugLoc ( MBBI ) ; Register SPCopy = MF . getRegInfo ( ) . createVirtualRegister ( & AVR :: DREGSRegClass ) ; BuildMI ( EntryMBB , MBBI , DL , TII . get ( AVR :: COPY ) , SPCopy ) . addReg ( AVR :: SP ) ; for ( MachineBasicBlock & MBB : MF ) { if ( ! MBB . empty ( ) && MBB . back ( ) . isReturn ( ) ) { MBBI = MBB . getLastNonDebugInstr ( ) ; DL = MBBI -> getDebugLoc ( ) ; BuildMI ( MBB , MBBI , DL , TII . get ( AVR :: COPY ) , AVR :: SP ) . addReg ( SPCopy , RegState :: Kill ) ; } } return true ; } </s>

AVR AVR AVR AVR::DREGSRegClass AVR::COPY AVR::SP AVR::COPY AVR::SP


<s>
bool
AVRFrameLowering
::
restoreCalleeSavedRegisters
(
MachineBasicBlock
&
MBB
,
MachineBasicBlock
::
iterator
MI
,
const
std
::
vector
<
CalleeSavedInfo
>
&
CSI
,
const
TargetRegisterInfo
*
TRI
)
const
{
if
(
CSI
.
empty
(
)
)
{
return
false
;
}
DebugLoc
DL
=
MBB
.
findDebugLoc
(
MI
)
;
const
MachineFunction
&
MF
=
*
MBB
.
getParent
(
)
;
const
AVRSubtarget
&
STI
=
MF
.
getSubtarget
<
AVRSubtarget
>
(
)
;
const
TargetInstrInfo
&
TII
=
*
STI
.
getInstrInfo
(
)
;
for
(
const
CalleeSavedInfo
&
CCSI
:
CSI
)
{
unsigned
Reg
=
CCSI
.
getReg
(
)
;
assert
(
TRI
->
getRegSizeInBits
(
*
TRI
->
getMinimalPhysRegClass
(
Reg
)
)
==
8
&&
"Invalid register size"
)
;
BuildMI
(
MBB
,
MI
,
DL
,
TII
.
get
(
AVR
::
POPRd
)
,
Reg
)
;
}
return
true
;
}
</s>


<s> void AVRFrameLowering :: determineCalleeSaves ( MachineFunction & MF , BitVector & SavedRegs , RegScavenger * RS ) const { TargetFrameLowering :: determineCalleeSaves ( MF , SavedRegs , RS ) ; } </s>


<s>
MachineBasicBlock
::
iterator
AVRFrameLowering
::
eliminateCallFramePseudoInstr
(
MachineFunction
&
MF
,
MachineBasicBlock
&
MBB
,
MachineBasicBlock
::
iterator
MI
)
const
{
const
AVRSubtarget
&
STI
=
MF
.
getSubtarget
<
AVRSubtarget
>
(
)
;
const
TargetFrameLowering
&
TFI
=
*
STI
.
getFrameLowering
(
)
;
const
AVRInstrInfo
&
TII
=
*
STI
.
getInstrInfo
(
)
;
if
(
TFI
.
hasReservedCallFrame
(
MF
)
)
{
fixStackStores
(
MBB
,
MI
,
TII
,
false
)
;
return
MBB
.
erase
(
MI
)
;
}
DebugLoc
DL
=
MI
->
getDebugLoc
(
)
;
unsigned
int
Opcode
=
MI
->
getOpcode
(
)
;
int
Amount
=
TII
.
getFrameSize
(
*
MI
)
;
if
(
Amount
!=
0
)
{
assert
(
TFI
.
getStackAlignment
(
)
==
1
&&
"Unsupported stack alignment"
)
;
if
(
Opcode
==
TII
.
getCallFrameSetupOpcode
(
)
)
{
fixStackStores
(
MBB
,
MI
,
TII
,
true
)
;
}
else
{
assert
(
Opcode
==
TII
.
getCallFrameDestroyOpcode
(
)
)
;
unsigned
addOpcode
;
if
(
isUInt
<
6
>
(
Amount
)
)
{
addOpcode
=
AVR
::
ADIWRdK
;
}
else
{
addOpcode
=
AVR
::
SUBIWRdK
;
Amount
=
Amount
;
}
BuildMI
(
MBB
,
MI
,
DL
,
TII
.
get
(
AVR
::
SPREAD
)
,
AVR
::
R31R30
)
.
addReg
(
AVR
::
SP
)
;
MachineInstr
*
New
=
BuildMI
(
MBB
,
MI
,
DL
,
TII
.
get
(
addOpcode
)
,
AVR
::
R31R30
)
.
addReg
(
AVR
::
R31R30
,
RegState
::
Kill
)
.
addImm
(
Amount
)
;
New
->
getOperand
(
3
)
.
setIsDead
(
)
;
BuildMI
(
MBB
,
MI
,
DL
,
TII
.
get
(
AVR
::
SPWRITE
)
,
AVR
::
SP
)
.
addReg
(
AVR
::
R31R30
,
RegState
::
Kill
)
;
}
}
return
MBB
.
erase
(
MI
)
;
}
</s>


"Can only insert epilog into returning blocks"


<s>
bool
AVRFrameLowering
::
restoreCalleeSavedRegisters
(
MachineBasicBlock
&
MBB
,
MachineBasicBlock
::
iterator
MI
,
std
::
vector
<
CalleeSavedInfo
>
&
CSI
,
const
TargetRegisterInfo
*
TRI
)
const
{
if
(
CSI
.
empty
(
)
)
{
return
false
;
}
DebugLoc
DL
=
MBB
.
findDebugLoc
(
MI
)
;
const
MachineFunction
&
MF
=
*
MBB
.
getParent
(
)
;
const
AVRSubtarget
&
STI
=
MF
.
getSubtarget
<
AVRSubtarget
>
(
)
;
const
TargetInstrInfo
&
TII
=
*
STI
.
getInstrInfo
(
)
;
for
(
const
CalleeSavedInfo
&
CCSI
:
CSI
)
{
unsigned
Reg
=
CCSI
.
getReg
(
)
;
assert
(
TRI
->
getRegSizeInBits
(
*
TRI
->
getMinimalPhysRegClass
(
Reg
)
)
==
8
&&
"Invalid register size"
)
;
BuildMI
(
MBB
,
MI
,
DL
,
TII
.
get
(
AVR
::
POPRd
)
,
Reg
)
;
}
return
true
;
}
</s>


<s> bool runOnMachineFunction ( MachineFunction & MF ) { if ( ! MF . getFrameInfo ( ) . hasVarSizedObjects ( ) ) { return false ; } const AVRSubtarget & STI = MF . getSubtarget < AVRSubtarget > ( ) ; const TargetInstrInfo & TII = * STI . getInstrInfo ( ) ; MachineBasicBlock & EntryMBB = MF . front ( ) ; MachineBasicBlock :: iterator MBBI = EntryMBB . begin ( ) ; DebugLoc DL = EntryMBB . findDebugLoc ( MBBI ) ; unsigned SPCopy = MF . getRegInfo ( ) . createVirtualRegister ( & AVR :: DREGSRegClass ) ; BuildMI ( EntryMBB , MBBI , DL , TII . get ( AVR :: COPY ) , SPCopy ) . addReg ( AVR :: SP ) ; for ( MachineBasicBlock & MBB : MF ) { if ( ! MBB . empty ( ) && MBB . back ( ) . isReturn ( ) ) { MBBI = MBB . getLastNonDebugInstr ( ) ; DL = MBBI -> getDebugLoc ( ) ; BuildMI ( MBB , MBBI , DL , TII . get ( AVR :: COPY ) , AVR :: SP ) . addReg ( SPCopy , RegState :: Kill ) ; } } return true ; } </s>


<s>
bool
AVRFrameLowering
::
spillCalleeSavedRegisters
(
MachineBasicBlock
&
MBB
,
MachineBasicBlock
::
iterator
MI
,
const
std
::
vector
<
CalleeSavedInfo
>
&
CSI
,
const
TargetRegisterInfo
*
TRI
)
const
{
if
(
CSI
.
empty
(
)
)
{
return
false
;
}
unsigned
CalleeFrameSize
=
0
;
DebugLoc
DL
=
MBB
.
findDebugLoc
(
MI
)
;
MachineFunction
&
MF
=
*
MBB
.
getParent
(
)
;
const
AVRSubtarget
&
STI
=
MF
.
getSubtarget
<
AVRSubtarget
>
(
)
;
const
TargetInstrInfo
&
TII
=
*
STI
.
getInstrInfo
(
)
;
AVRMachineFunctionInfo
*
AVRFI
=
MF
.
getInfo
<
AVRMachineFunctionInfo
>
(
)
;
for
(
unsigned
i
=
CSI
.
size
(
)
;
i
!=
0
;
i
)
{
unsigned
Reg
=
CSI
[
i
1
]
.
getReg
(
)
;
bool
IsNotLiveIn
=
!
MBB
.
isLiveIn
(
Reg
)
;
assert
(
TRI
->
getRegSizeInBits
(
*
TRI
->
getMinimalPhysRegClass
(
Reg
)
)
==
8
&&
"Invalid register size"
)
;
if
(
IsNotLiveIn
)
{
MBB
.
addLiveIn
(
Reg
)
;
}
BuildMI
(
MBB
,
MI
,
DL
,
TII
.
get
(
AVR
::
PUSHRr
)
)
.
addReg
(
Reg
,
getKillRegState
(
IsNotLiveIn
)
)
.
setMIFlag
(
MachineInstr
::
FrameSetup
)
;
++
CalleeFrameSize
;
}
AVRFI
->
setCalleeSavedFrameSize
(
CalleeFrameSize
)
;
return
true
;
}
</s>

AVR
AVR
0
AVR
AVR
AVR
AVR
AVR
0
1
8
"Invalid register size"
AVR::PUSHRr
AVR


<s>
MachineBasicBlock
::
iterator
AVRFrameLowering
::
eliminateCallFramePseudoInstr
(
MachineFunction
&
MF
,
MachineBasicBlock
&
MBB
,
MachineBasicBlock
::
iterator
MI
)
const
{
const
AVRSubtarget
&
STI
=
MF
.
getSubtarget
<
AVRSubtarget
>
(
)
;
const
AVRInstrInfo
&
TII
=
*
STI
.
getInstrInfo
(
)
;
if
(
hasReservedCallFrame
(
MF
)
)
{
fixStackStores
(
MBB
,
MI
,
TII
,
false
)
;
return
MBB
.
erase
(
MI
)
;
}
DebugLoc
DL
=
MI
->
getDebugLoc
(
)
;
unsigned
int
Opcode
=
MI
->
getOpcode
(
)
;
int
Amount
=
TII
.
getFrameSize
(
*
MI
)
;
if
(
Amount
!=
0
)
{
assert
(
getStackAlign
(
)
==
Align
(
1
)
&&
"Unsupported stack alignment"
)
;
if
(
Opcode
==
TII
.
getCallFrameSetupOpcode
(
)
)
{
fixStackStores
(
MBB
,
MI
,
TII
,
true
)
;
}
else
{
assert
(
Opcode
==
TII
.
getCallFrameDestroyOpcode
(
)
)
;
unsigned
addOpcode
;
if
(
isUInt
<
6
>
(
Amount
)
)
{
addOpcode
=
AVR
::
ADIWRdK
;
}
else
{
addOpcode
=
AVR
::
SUBIWRdK
;
Amount
=
Amount
;
}
BuildMI
(
MBB
,
MI
,
DL
,
TII
.
get
(
AVR
::
SPREAD
)
,
AVR
::
R31R30
)
.
addReg
(
AVR
::
SP
)
;
MachineInstr
*
New
=
BuildMI
(
MBB
,
MI
,
DL
,
TII
.
get
(
addOpcode
)
,
AVR
::
R31R30
)
.
addReg
(
AVR
::
R31R30
,
RegState
::
Kill
)
.
addImm
(
Amount
)
;
New
->
getOperand
(
3
)
.
setIsDead
(
)
;
BuildMI
(
MBB
,
MI
,
DL
,
TII
.
get
(
AVR
::
SPWRITE
)
,
AVR
::
SP
)
.
addReg
(
AVR
::
R31R30
,
RegState
::
Kill
)
;
}
}
return
MBB
.
erase
(
MI
)
;
}
</s>


<s>
bool
AVRFrameLowering
::
spillCalleeSavedRegisters
(
MachineBasicBlock
&
MBB
,
MachineBasicBlock
::
iterator
MI
,
ArrayRef
<
CalleeSavedInfo
>
CSI
,
const
TargetRegisterInfo
*
TRI
)
const
{
if
(
CSI
.
empty
(
)
)
{
return
false
;
}
unsigned
CalleeFrameSize
=
0
;
DebugLoc
DL
=
MBB
.
findDebugLoc
(
MI
)
;
MachineFunction
&
MF
=
*
MBB
.
getParent
(
)
;
const
AVRSubtarget
&
STI
=
MF
.
getSubtarget
<
AVRSubtarget
>
(
)
;
const
TargetInstrInfo
&
TII
=
*
STI
.
getInstrInfo
(
)
;
AVRMachineFunctionInfo
*
AVRFI
=
MF
.
getInfo
<
AVRMachineFunctionInfo
>
(
)
;
for
(
const
CalleeSavedInfo
&
I
:
llvm
::
reverse
(
CSI
)
)
{
unsigned
Reg
=
I
.
getReg
(
)
;
bool
IsNotLiveIn
=
!
MBB
.
isLiveIn
(
Reg
)
;
assert
(
TRI
->
getRegSizeInBits
(
*
TRI
->
getMinimalPhysRegClass
(
Reg
)
)
==
8
&&
"Invalid register size"
)
;
if
(
IsNotLiveIn
)
{
MBB
.
addLiveIn
(
Reg
)
;
}
BuildMI
(
MBB
,
MI
,
DL
,
TII
.
get
(
AVR
::
PUSHRr
)
)
.
addReg
(
Reg
,
getKillRegState
(
IsNotLiveIn
)
)
.
setMIFlag
(
MachineInstr
::
FrameSetup
)
;
++
CalleeFrameSize
;
}
AVRFI
->
setCalleeSavedFrameSize
(
CalleeFrameSize
)
;
return
true
;
}
</s>


<s>
MachineBasicBlock
::
iterator
AVRFrameLowering
::
eliminateCallFramePseudoInstr
(
MachineFunction
&
MF
,
MachineBasicBlock
&
MBB
,
MachineBasicBlock
::
iterator
MI
)
const
{
const
AVRSubtarget
&
STI
=
MF
.
getSubtarget
<
AVRSubtarget
>
(
)
;
const
AVRInstrInfo
&
TII
=
*
STI
.
getInstrInfo
(
)
;
if
(
hasReservedCallFrame
(
MF
)
)
{
fixStackStores
(
MBB
,
MI
,
TII
,
false
)
;
return
MBB
.
erase
(
MI
)
;
}
DebugLoc
DL
=
MI
->
getDebugLoc
(
)
;
unsigned
int
Opcode
=
MI
->
getOpcode
(
)
;
int
Amount
=
TII
.
getFrameSize
(
*
MI
)
;
if
(
Amount
!=
0
)
{
assert
(
TFI
.
getStackAlignment
(
)
==
1
&&
"Unsupported stack alignment"
)
;
if
(
Opcode
==
TII
.
getCallFrameSetupOpcode
(
)
)
{
fixStackStores
(
MBB
,
MI
,
TII
,
true
)
;
}
else
{
assert
(
Opcode
==
TII
.
getCallFrameDestroyOpcode
(
)
)
;
unsigned
addOpcode
;
if
(
isUInt
<
6
>
(
Amount
)
)
{
addOpcode
=
AVR
::
ADIWRdK
;
}
else
{
addOpcode
=
AVR
::
SUBIWRdK
;
Amount
=
Amount
;
}
BuildMI
(
MBB
,
MI
,
DL
,
TII
.
get
(
AVR
::
SPREAD
)
,
AVR
::
R31R30
)
.
addReg
(
AVR
::
SP
)
;
MachineInstr
*
New
=
BuildMI
(
MBB
,
MI
,
DL
,
TII
.
get
(
addOpcode
)
,
AVR
::
R31R30
)
.
addReg
(
AVR
::
R31R30
,
RegState
::
Kill
)
.
addImm
(
Amount
)
;
New
->
getOperand
(
3
)
.
setIsDead
(
)
;
BuildMI
(
MBB
,
MI
,
DL
,
TII
.
get
(
AVR
::
SPWRITE
)
,
AVR
::
SP
)
.
addReg
(
AVR
::
R31R30
,
RegState
::
Kill
)
;
}
}
return
MBB
.
erase
(
MI
)
;
}
</s>


<s>
MachineBasicBlock
::
iterator
AVRFrameLowering
::
eliminateCallFramePseudoInstr
(
MachineFunction
&
MF
,
MachineBasicBlock
&
MBB
,
MachineBasicBlock
::
iterator
MI
)
const
{
const
AVRSubtarget
&
STI
=
MF
.
getSubtarget
<
AVRSubtarget
>
(
)
;
const
AVRInstrInfo
&
TII
=
*
STI
.
getInstrInfo
(
)
;
if
(
hasReservedCallFrame
(
MF
)
)
{
fixStackStores
(
MBB
,
MI
,
TII
,
AVR
::
R29R28
)
;
return
MBB
.
erase
(
MI
)
;
}
DebugLoc
DL
=
MI
->
getDebugLoc
(
)
;
unsigned
int
Opcode
=
MI
->
getOpcode
(
)
;
int
Amount
=
TII
.
getFrameSize
(
*
MI
)
;
if
(
Amount
!=
0
)
{
assert
(
getStackAlign
(
)
==
Align
(
1
)
&&
"Unsupported stack alignment"
)
;
if
(
Opcode
==
TII
.
getCallFrameSetupOpcode
(
)
)
{
BuildMI
(
MBB
,
MI
,
DL
,
TII
.
get
(
AVR
::
SPREAD
)
,
AVR
::
R31R30
)
.
addReg
(
AVR
::
SP
)
;
MachineInstr
*
New
=
BuildMI
(
MBB
,
MI
,
DL
,
TII
.
get
(
AVR
::
SUBIWRdK
)
,
AVR
::
R31R30
)
.
addReg
(
AVR
::
R31R30
,
RegState
::
Kill
)
.
addImm
(
Amount
)
;
New
->
getOperand
(
3
)
.
setIsDead
(
)
;
BuildMI
(
MBB
,
MI
,
DL
,
TII
.
get
(
AVR
::
SPWRITE
)
,
AVR
::
SP
)
.
addReg
(
AVR
::
R31R30
,
RegState
::
Kill
)
;
fixStackStores
(
MBB
,
MI
,
TII
,
AVR
::
R31R30
)
;
}
else
{
assert
(
Opcode
==
TII
.
getCallFrameDestroyOpcode
(
)
)
;
unsigned
addOpcode
;
if
(
isUInt
<
6
>
(
Amount
)
)
{
addOpcode
=
AVR
::
ADIWRdK
;
}
else
{
addOpcode
=
AVR
::
SUBIWRdK
;
Amount
=
Amount
;
}
BuildMI
(
MBB
,
MI
,
DL
,
TII
.
get
(
AVR
::
SPREAD
)
,
AVR
::
R31R30
)
.
addReg
(
AVR
::
SP
)
;
MachineInstr
*
New
=
BuildMI
(
MBB
,
MI
,
DL
,
TII
.
get
(
addOpcode
)
,
AVR
::
R31R30
)
.
addReg
(
AVR
::
R31R30
,
RegState
::
Kill
)
.
addImm
(
Amount
)
;
New
->
getOperand
(
3
)
.
setIsDead
(
)
;
BuildMI
(
MBB
,
MI
,
DL
,
TII
.
get
(
AVR
::
SPWRITE
)
,
AVR
::
SP
)
.
addReg
(
AVR
::
R31R30
,
RegState
::
Kill
)
;
}
}
return
MBB
.
erase
(
MI
)
;
}
</s>


<s> bool AVRFrameLowering :: hasFP ( const MachineFunction & MF ) const { const AVRMachineFunctionInfo * FuncInfo = MF . getInfo < AVRMachineFunctionInfo > ( ) ; return ( FuncInfo -> getHasSpills ( ) || FuncInfo -> getHasAllocas ( ) || FuncInfo -> getHasStackArgs ( ) ) ; } </s>


<s>
bool
AVRFrameLowering
::
restoreCalleeSavedRegisters
(
MachineBasicBlock
&
MBB
,
MachineBasicBlock
::
iterator
MI
,
MutableArrayRef
<
CalleeSavedInfo
>
CSI
,
const
TargetRegisterInfo
*
TRI
)
const
{
if
(
CSI
.
empty
(
)
)
{
return
false
;
}
DebugLoc
DL
=
MBB
.
findDebugLoc
(
MI
)
;
const
MachineFunction
&
MF
=
*
MBB
.
getParent
(
)
;
const
AVRSubtarget
&
STI
=
MF
.
getSubtarget
<
AVRSubtarget
>
(
)
;
const
TargetInstrInfo
&
TII
=
*
STI
.
getInstrInfo
(
)
;
for
(
const
CalleeSavedInfo
&
CCSI
:
CSI
)
{
unsigned
Reg
=
CCSI
.
getReg
(
)
;
assert
(
TRI
->
getRegSizeInBits
(
*
TRI
->
getMinimalPhysRegClass
(
Reg
)
)
==
8
&&
"Invalid register size"
)
;
BuildMI
(
MBB
,
MI
,
DL
,
TII
.
get
(
AVR
::
POPRd
)
,
Reg
)
;
}
return
true
;
}
</s>


<s> bool runOnMachineFunction ( MachineFunction & MF ) { if ( ! MF . getFrameInfo ( ) . hasVarSizedObjects ( ) ) { return false ; } const AVRSubtarget & STI = MF . getSubtarget < AVRSubtarget > ( ) ; const TargetInstrInfo & TII = * STI . getInstrInfo ( ) ; MachineBasicBlock & EntryMBB = MF . front ( ) ; MachineBasicBlock :: iterator MBBI = EntryMBB . begin ( ) ; DebugLoc DL = EntryMBB . findDebugLoc ( MBBI ) ; Register SPCopy = MF . getRegInfo ( ) . createVirtualRegister ( & AVR :: DREGSRegClass ) ; BuildMI ( EntryMBB , MBBI , DL , TII . get ( AVR :: COPY ) , SPCopy ) . addReg ( AVR :: SP ) ; for ( MachineBasicBlock & MBB : MF ) { if ( ! MBB . empty ( ) && MBB . back ( ) . isReturn ( ) ) { MBBI = MBB . getLastNonDebugInstr ( ) ; DL = MBBI -> getDebugLoc ( ) ; BuildMI ( MBB , MBBI , DL , TII . get ( AVR :: COPY ) , AVR :: SP ) . addReg ( SPCopy , RegState :: Kill ) ; } } return true ; } </s>


<s>
bool
AVRFrameLowering
::
spillCalleeSavedRegisters
(
MachineBasicBlock
&
MBB
,
MachineBasicBlock
::
iterator
MI
,
ArrayRef
<
CalleeSavedInfo
>
CSI
,
const
TargetRegisterInfo
*
TRI
)
const
{
if
(
CSI
.
empty
(
)
)
{
return
false
;
}
unsigned
CalleeFrameSize
=
0
;
DebugLoc
DL
=
MBB
.
findDebugLoc
(
MI
)
;
MachineFunction
&
MF
=
*
MBB
.
getParent
(
)
;
const
AVRSubtarget
&
STI
=
MF
.
getSubtarget
<
AVRSubtarget
>
(
)
;
const
TargetInstrInfo
&
TII
=
*
STI
.
getInstrInfo
(
)
;
AVRMachineFunctionInfo
*
AVRFI
=
MF
.
getInfo
<
AVRMachineFunctionInfo
>
(
)
;
for
(
unsigned
i
=
CSI
.
size
(
)
;
i
!=
0
;
i
)
{
unsigned
Reg
=
CSI
[
i
1
]
.
getReg
(
)
;
bool
IsNotLiveIn
=
!
MBB
.
isLiveIn
(
Reg
)
;
assert
(
TRI
->
getRegSizeInBits
(
*
TRI
->
getMinimalPhysRegClass
(
Reg
)
)
==
8
&&
"Invalid register size"
)
;
if
(
IsNotLiveIn
)
{
MBB
.
addLiveIn
(
Reg
)
;
}
BuildMI
(
MBB
,
MI
,
DL
,
TII
.
get
(
AVR
::
PUSHRr
)
)
.
addReg
(
Reg
,
getKillRegState
(
IsNotLiveIn
)
)
.
setMIFlag
(
MachineInstr
::
FrameSetup
)
;
++
CalleeFrameSize
;
}
AVRFI
->
setCalleeSavedFrameSize
(
CalleeFrameSize
)
;
return
true
;
}
</s>


<s> void printPCRelImm ( const MCInst * MI , uint64_t , unsigned OpNo , raw_ostream & O ) { printPCRelImm ( MI , OpNo , O ) ; } </s>


<s>
void
AVRInstPrinter
::
printInst
(
const
MCInst
*
MI
,
uint64_t
Address
,
StringRef
Annot
,
const
MCSubtargetInfo
&
STI
,
raw_ostream
&
O
)
{
unsigned
Opcode
=
MI
->
getOpcode
(
)
;
switch
(
Opcode
)
{
case
AVR
::
LDRdPtr
:
case
AVR
::
LDRdPtrPi
:
case
AVR
::
LDRdPtrPd
:
O
<<
"\tld\t"
;
printOperand
(
MI
,
0
,
O
)
;
O
<<
", "
;
if
(
Opcode
==
AVR
::
LDRdPtrPd
)
O
<<
'-'
;
printOperand
(
MI
,
1
,
O
)
;
if
(
Opcode
==
AVR
::
LDRdPtrPi
)
O
<<
'+'
;
break
;
case
AVR
::
STPtrRr
:
O
<<
"\tst\t"
;
printOperand
(
MI
,
0
,
O
)
;
O
<<
", "
;
printOperand
(
MI
,
1
,
O
)
;
break
;
case
AVR
::
STPtrPiRr
:
case
AVR
::
STPtrPdRr
:
O
<<
"\tst\t"
;
if
(
Opcode
==
AVR
::
STPtrPdRr
)
O
<<
'-'
;
printOperand
(
MI
,
1
,
O
)
;
if
(
Opcode
==
AVR
::
STPtrPiRr
)
O
<<
'+'
;
O
<<
", "
;
printOperand
(
MI
,
2
,
O
)
;
break
;
default
:
if
(
!
printAliasInstr
(
MI
,
O
)
)
printInstruction
(
MI
,
Address
,
O
)
;
printAnnotation
(
O
,
Annot
)
;
break
;
}
}
</s>

Print the specified MCInst to the specified raw_ostream .

AVR
AVR
AVR::LDRdPtr
AVR::LDRdPtrPi
AVR::LDRdPtrPd
"\tld\t"
0
", "
AVR::LDRdPtrPd
1
AVR::LDRdPtrPi
AVR::STPtrRr
"\tst\t"
0
", "
1
AVR::STPtrPiRr
AVR::STPtrPdRr
"\tst\t"
AVR::STPtrPdRr
1
AVR::STPtrPiRr
", "
2


<s>
void
AVRInstPrinter
::
printPCRelImm
(
const
MCInst
*
MI
,
unsigned
OpNo
,
raw_ostream
&
O
)
{
const
MCOperand
&
Op
=
MI
->
getOperand
(
OpNo
)
;
if
(
Op
.
isImm
(
)
)
{
int64_t
Imm
=
Op
.
getImm
(
)
;
O
<<
'.'
;
if
(
Imm
>=
0
)
O
<<
'+'
;
O
<<
Imm
;
}
else
{
assert
(
Op
.
isExpr
(
)
&&
"Unknown pcrel immediate operand"
)
;
O
<<
*
Op
.
getExpr
(
)
;
}
}
</s>

AVR
AVR
0
"Unknown pcrel immediate operand"


<s>
void
AVRInstPrinter
::
printInst
(
const
MCInst
*
MI
,
raw_ostream
&
O
,
StringRef
Annot
,
const
MCSubtargetInfo
&
STI
)
{
unsigned
Opcode
=
MI
->
getOpcode
(
)
;
switch
(
Opcode
)
{
case
AVR
::
LDRdPtr
:
case
AVR
::
LDRdPtrPi
:
case
AVR
::
LDRdPtrPd
:
O
<<
"\tld\t"
;
printOperand
(
MI
,
0
,
O
)
;
O
<<
", "
;
if
(
Opcode
==
AVR
::
LDRdPtrPd
)
O
<<
'-'
;
printOperand
(
MI
,
1
,
O
)
;
if
(
Opcode
==
AVR
::
LDRdPtrPi
)
O
<<
'+'
;
break
;
case
AVR
::
STPtrRr
:
O
<<
"\tst\t"
;
printOperand
(
MI
,
0
,
O
)
;
O
<<
", "
;
printOperand
(
MI
,
1
,
O
)
;
break
;
case
AVR
::
STPtrPiRr
:
case
AVR
::
STPtrPdRr
:
O
<<
"\tst\t"
;
if
(
Opcode
==
AVR
::
STPtrPdRr
)
O
<<
'-'
;
printOperand
(
MI
,
1
,
O
)
;
if
(
Opcode
==
AVR
::
STPtrPiRr
)
O
<<
'+'
;
O
<<
", "
;
printOperand
(
MI
,
2
,
O
)
;
break
;
default
:
if
(
!
printAliasInstr
(
MI
,
O
)
)
printInstruction
(
MI
,
O
)
;
printAnnotation
(
O
,
Annot
)
;
break
;
}
}
</s>


<s>
void
AVRInstPrinter
::
printInst
(
const
MCInst
*
MI
,
uint64_t
Address
,
StringRef
Annot
,
const
MCSubtargetInfo
&
STI
,
raw_ostream
&
O
)
{
unsigned
Opcode
=
MI
->
getOpcode
(
)
;
switch
(
Opcode
)
{
case
AVR
::
LDRdPtr
:
case
AVR
::
LDRdPtrPi
:
case
AVR
::
LDRdPtrPd
:
O
<<
"\tld\t"
;
printOperand
(
MI
,
0
,
O
)
;
O
<<
", "
;
if
(
Opcode
==
AVR
::
LDRdPtrPd
)
O
<<
'-'
;
printOperand
(
MI
,
1
,
O
)
;
if
(
Opcode
==
AVR
::
LDRdPtrPi
)
O
<<
'+'
;
break
;
case
AVR
::
STPtrRr
:
O
<<
"\tst\t"
;
printOperand
(
MI
,
0
,
O
)
;
O
<<
", "
;
printOperand
(
MI
,
1
,
O
)
;
break
;
case
AVR
::
STPtrPiRr
:
case
AVR
::
STPtrPdRr
:
O
<<
"\tst\t"
;
if
(
Opcode
==
AVR
::
STPtrPdRr
)
O
<<
'-'
;
printOperand
(
MI
,
1
,
O
)
;
if
(
Opcode
==
AVR
::
STPtrPiRr
)
O
<<
'+'
;
O
<<
", "
;
printOperand
(
MI
,
2
,
O
)
;
break
;
default
:
if
(
!
printAliasInstr
(
MI
,
Address
,
O
)
)
printInstruction
(
MI
,
Address
,
O
)
;
printAnnotation
(
O
,
Annot
)
;
break
;
}
}
</s>


<s>
void
AVRInstPrinter
::
printPCRelImm
(
const
MCInst
*
MI
,
unsigned
OpNo
,
raw_ostream
&
O
)
{
if
(
OpNo
>=
MI
->
size
(
)
)
{
O
<<
"<unknown>"
;
return
;
}
const
MCOperand
&
Op
=
MI
->
getOperand
(
OpNo
)
;
if
(
Op
.
isImm
(
)
)
{
int64_t
Imm
=
Op
.
getImm
(
)
;
O
<<
'.'
;
if
(
Imm
>=
0
)
O
<<
'+'
;
O
<<
Imm
;
}
else
{
assert
(
Op
.
isExpr
(
)
&&
"Unknown pcrel immediate operand"
)
;
O
<<
*
Op
.
getExpr
(
)
;
}
}
</s>

AVR
AVR
"<unknown>"
0
"Unknown pcrel immediate operand"


<s>
void
AVRInstrInfo
::
copyPhysReg
(
MachineBasicBlock
&
MBB
,
MachineBasicBlock
::
iterator
MI
,
const
DebugLoc
&
DL
,
unsigned
DestReg
,
unsigned
SrcReg
,
bool
KillSrc
)
const
{
const
AVRSubtarget
&
STI
=
MBB
.
getParent
(
)
->
getSubtarget
<
AVRSubtarget
>
(
)
;
const
AVRRegisterInfo
&
TRI
=
*
STI
.
getRegisterInfo
(
)
;
unsigned
Opc
;
if
(
AVR
::
DREGSRegClass
.
contains
(
DestReg
,
SrcReg
)
)
{
if
(
STI
.
hasMOVW
(
)
)
{
BuildMI
(
MBB
,
MI
,
DL
,
get
(
AVR
::
MOVWRdRr
)
,
DestReg
)
.
addReg
(
SrcReg
,
getKillRegState
(
KillSrc
)
)
;
}
else
{
unsigned
DestLo
,
DestHi
,
SrcLo
,
SrcHi
;
TRI
.
splitReg
(
DestReg
,
DestLo
,
DestHi
)
;
TRI
.
splitReg
(
SrcReg
,
SrcLo
,
SrcHi
)
;
BuildMI
(
MBB
,
MI
,
DL
,
get
(
AVR
::
MOVRdRr
)
,
DestLo
)
.
addReg
(
SrcLo
,
getKillRegState
(
KillSrc
)
)
;
BuildMI
(
MBB
,
MI
,
DL
,
get
(
AVR
::
MOVRdRr
)
,
DestHi
)
.
addReg
(
SrcHi
,
getKillRegState
(
KillSrc
)
)
;
}
}
else
{
if
(
AVR
::
GPR8RegClass
.
contains
(
DestReg
,
SrcReg
)
)
{
Opc
=
AVR
::
MOVRdRr
;
}
else
if
(
SrcReg
==
AVR
::
SP
&&
AVR
::
DREGSRegClass
.
contains
(
DestReg
)
)
{
Opc
=
AVR
::
SPREAD
;
}
else
if
(
DestReg
==
AVR
::
SP
&&
AVR
::
DREGSRegClass
.
contains
(
SrcReg
)
)
{
Opc
=
AVR
::
SPWRITE
;
}
else
{
llvm_unreachable
(
"Impossible reg-to-reg copy"
)
;
}
BuildMI
(
MBB
,
MI
,
DL
,
get
(
Opc
)
,
DestReg
)
.
addReg
(
SrcReg
,
getKillRegState
(
KillSrc
)
)
;
}
}
</s>

AVR
AVR
AVR
AVR
AVR
AVR::DREGSRegClass
AVR::MOVWRdRr
AVR::MOVRdRr
AVR::MOVRdRr
AVR::GPR8RegClass
AVR::MOVRdRr
AVR::SP
AVR::DREGSRegClass
AVR::SPREAD
AVR::SP
AVR::DREGSRegClass
AVR::SPWRITE
"Impossible reg-to-reg copy"


<s> unsigned AVRInstrInfo :: getInstSizeInBytes ( const MachineInstr & MI ) const { unsigned Opcode = MI . getOpcode ( ) ; switch ( Opcode ) { default : { const MCInstrDesc & Desc = get ( Opcode ) ; return Desc . getSize ( ) ; } case TargetOpcode :: EH_LABEL : case TargetOpcode :: IMPLICIT_DEF : case TargetOpcode :: KILL : case TargetOpcode :: DBG_VALUE : return 0 ; case TargetOpcode :: INLINEASM : { const MachineFunction & MF = * MI . getParent ( ) -> getParent ( ) ; const AVRTargetMachine & TM = static_cast < const AVRTargetMachine & > ( MF . getTarget ( ) ) ; const AVRSubtarget & STI = MF . getSubtarget < AVRSubtarget > ( ) ; const TargetInstrInfo & TII = * STI . getInstrInfo ( ) ; return TII . getInlineAsmLength ( MI . getOperand ( 0 ) . getSymbolName ( ) , * TM . getMCAsmInfo ( ) ) ; } } } </s>

Returns the size in bytes of the specified MachineInstr , or ~0U when this function is not implemented by a target .


"Cannot load this register from a stack slot!"

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


"Cannot store this register into a stack slot!"

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


<s>
void
AVRInstrInfo
::
copyPhysReg
(
MachineBasicBlock
&
MBB
,
MachineBasicBlock
::
iterator
MI
,
const
DebugLoc
&
DL
,
MCRegister
DestReg
,
MCRegister
SrcReg
,
bool
KillSrc
)
const
{
const
AVRSubtarget
&
STI
=
MBB
.
getParent
(
)
->
getSubtarget
<
AVRSubtarget
>
(
)
;
const
AVRRegisterInfo
&
TRI
=
*
STI
.
getRegisterInfo
(
)
;
unsigned
Opc
;
if
(
AVR
::
DREGSRegClass
.
contains
(
DestReg
,
SrcReg
)
)
{
if
(
STI
.
hasMOVW
(
)
)
{
BuildMI
(
MBB
,
MI
,
DL
,
get
(
AVR
::
MOVWRdRr
)
,
DestReg
)
.
addReg
(
SrcReg
,
getKillRegState
(
KillSrc
)
)
;
}
else
{
Register
DestLo
,
DestHi
,
SrcLo
,
SrcHi
;
TRI
.
splitReg
(
DestReg
,
DestLo
,
DestHi
)
;
TRI
.
splitReg
(
SrcReg
,
SrcLo
,
SrcHi
)
;
BuildMI
(
MBB
,
MI
,
DL
,
get
(
AVR
::
MOVRdRr
)
,
DestLo
)
.
addReg
(
SrcLo
,
getKillRegState
(
KillSrc
)
)
;
BuildMI
(
MBB
,
MI
,
DL
,
get
(
AVR
::
MOVRdRr
)
,
DestHi
)
.
addReg
(
SrcHi
,
getKillRegState
(
KillSrc
)
)
;
}
}
else
{
if
(
AVR
::
GPR8RegClass
.
contains
(
DestReg
,
SrcReg
)
)
{
Opc
=
AVR
::
MOVRdRr
;
}
else
if
(
SrcReg
==
AVR
::
SP
&&
AVR
::
DREGSRegClass
.
contains
(
DestReg
)
)
{
Opc
=
AVR
::
SPREAD
;
}
else
if
(
DestReg
==
AVR
::
SP
&&
AVR
::
DREGSRegClass
.
contains
(
SrcReg
)
)
{
Opc
=
AVR
::
SPWRITE
;
}
else
{
llvm_unreachable
(
"Impossible reg-to-reg copy"
)
;
}
BuildMI
(
MBB
,
MI
,
DL
,
get
(
Opc
)
,
DestReg
)
.
addReg
(
SrcReg
,
getKillRegState
(
KillSrc
)
)
;
}
}
</s>


<s> unsigned AVRInstrInfo :: getInstSizeInBytes ( const MachineInstr & MI ) const { unsigned Opcode = MI . getOpcode ( ) ; switch ( Opcode ) { default : { const MCInstrDesc & Desc = get ( Opcode ) ; return Desc . getSize ( ) ; } case TargetOpcode :: EH_LABEL : case TargetOpcode :: IMPLICIT_DEF : case TargetOpcode :: KILL : case TargetOpcode :: DBG_VALUE : return 0 ; case TargetOpcode :: INLINEASM : case TargetOpcode :: INLINEASM_BR : { const MachineFunction & MF = * MI . getParent ( ) -> getParent ( ) ; const AVRTargetMachine & TM = static_cast < const AVRTargetMachine & > ( MF . getTarget ( ) ) ; const AVRSubtarget & STI = MF . getSubtarget < AVRSubtarget > ( ) ; const TargetInstrInfo & TII = * STI . getInstrInfo ( ) ; return TII . getInlineAsmLength ( MI . getOperand ( 0 ) . getSymbolName ( ) , * TM . getMCAsmInfo ( ) ) ; } } } </s>


<s>
void
AVRInstrInfo
::
copyPhysReg
(
MachineBasicBlock
&
MBB
,
MachineBasicBlock
::
iterator
MI
,
DebugLoc
DL
,
unsigned
DestReg
,
unsigned
SrcReg
,
bool
KillSrc
)
const
{
unsigned
Opc
;
if
(
AVR
::
GPR8RegClass
.
contains
(
DestReg
,
SrcReg
)
)
{
Opc
=
AVR
::
MOVRdRr
;
}
else
if
(
AVR
::
DREGSRegClass
.
contains
(
DestReg
,
SrcReg
)
)
{
Opc
=
AVR
::
MOVWRdRr
;
}
else
if
(
SrcReg
==
AVR
::
SP
&&
AVR
::
DREGSRegClass
.
contains
(
DestReg
)
)
{
Opc
=
AVR
::
SPREAD
;
}
else
if
(
DestReg
==
AVR
::
SP
&&
AVR
::
DREGSRegClass
.
contains
(
SrcReg
)
)
{
Opc
=
AVR
::
SPWRITE
;
}
else
{
llvm_unreachable
(
"Impossible reg-to-reg copy"
)
;
}
BuildMI
(
MBB
,
MI
,
DL
,
get
(
Opc
)
,
DestReg
)
.
addReg
(
SrcReg
,
getKillRegState
(
KillSrc
)
)
;
}
</s>

AVR
AVR
AVR::GPR8RegClass
AVR::MOVRdRr
AVR::DREGSRegClass
AVR::MOVWRdRr
AVR::SP
AVR::DREGSRegClass
AVR::SPREAD
AVR::SP
AVR::DREGSRegClass
AVR::SPWRITE
"Impossible reg-to-reg copy"


<s> unsigned AVRInstrInfo :: isLoadFromStackSlot ( const MachineInstr * MI , int & FrameIndex ) const { switch ( MI -> getOpcode ( ) ) { case AVR :: LDDRdPtrQ : case AVR :: LDDWRdYQ : { if ( ( MI -> getOperand ( 1 ) . isFI ( ) ) && ( MI -> getOperand ( 2 ) . isImm ( ) ) && ( MI -> getOperand ( 2 ) . getImm ( ) == 0 ) ) { FrameIndex = MI -> getOperand ( 1 ) . getIndex ( ) ; return MI -> getOperand ( 0 ) . getReg ( ) ; } break ; } default : break ; } return 0 ; } </s>

isLoadFromStackSlot - If the specified machine instruction is a direct load from a stack slot , return the virtual or physical register number of the destination along with the FrameIndex of the loaded stack slot .


<s> unsigned AVRInstrInfo :: isStoreToStackSlot ( const MachineInstr * MI , int & FrameIndex ) const { switch ( MI -> getOpcode ( ) ) { case AVR :: STDPtrQRr : case AVR :: STDWPtrQRr : { if ( ( MI -> getOperand ( 0 ) . isFI ( ) ) && ( MI -> getOperand ( 1 ) . isImm ( ) ) && ( MI -> getOperand ( 1 ) . getImm ( ) == 0 ) ) { FrameIndex = MI -> getOperand ( 0 ) . getIndex ( ) ; return MI -> getOperand ( 2 ) . getReg ( ) ; } break ; } default : break ; } return 0 ; } </s>

isStoreToStackSlot - If the specified machine instruction is a direct store to a stack slot , return the virtual or physical register number of the source reg along with the FrameIndex of the loaded stack slot .


<s>
void
AVRInstrInfo
::
copyPhysReg
(
MachineBasicBlock
&
MBB
,
MachineBasicBlock
::
iterator
MI
,
const
DebugLoc
&
DL
,
MCRegister
DestReg
,
MCRegister
SrcReg
,
bool
KillSrc
)
const
{
const
AVRSubtarget
&
STI
=
MBB
.
getParent
(
)
->
getSubtarget
<
AVRSubtarget
>
(
)
;
const
AVRRegisterInfo
&
TRI
=
*
STI
.
getRegisterInfo
(
)
;
unsigned
Opc
;
if
(
AVR
::
DREGSRegClass
.
contains
(
DestReg
,
SrcReg
)
)
{
if
(
STI
.
hasMOVW
(
)
&&
AVR
::
DREGSMOVWRegClass
.
contains
(
DestReg
,
SrcReg
)
)
{
BuildMI
(
MBB
,
MI
,
DL
,
get
(
AVR
::
MOVWRdRr
)
,
DestReg
)
.
addReg
(
SrcReg
,
getKillRegState
(
KillSrc
)
)
;
}
else
{
Register
DestLo
,
DestHi
,
SrcLo
,
SrcHi
;
TRI
.
splitReg
(
DestReg
,
DestLo
,
DestHi
)
;
TRI
.
splitReg
(
SrcReg
,
SrcLo
,
SrcHi
)
;
BuildMI
(
MBB
,
MI
,
DL
,
get
(
AVR
::
MOVRdRr
)
,
DestLo
)
.
addReg
(
SrcLo
,
getKillRegState
(
KillSrc
)
)
;
BuildMI
(
MBB
,
MI
,
DL
,
get
(
AVR
::
MOVRdRr
)
,
DestHi
)
.
addReg
(
SrcHi
,
getKillRegState
(
KillSrc
)
)
;
}
}
else
{
if
(
AVR
::
GPR8RegClass
.
contains
(
DestReg
,
SrcReg
)
)
{
Opc
=
AVR
::
MOVRdRr
;
}
else
if
(
SrcReg
==
AVR
::
SP
&&
AVR
::
DREGSRegClass
.
contains
(
DestReg
)
)
{
Opc
=
AVR
::
SPREAD
;
}
else
if
(
DestReg
==
AVR
::
SP
&&
AVR
::
DREGSRegClass
.
contains
(
SrcReg
)
)
{
Opc
=
AVR
::
SPWRITE
;
}
else
{
llvm_unreachable
(
"Impossible reg-to-reg copy"
)
;
}
BuildMI
(
MBB
,
MI
,
DL
,
get
(
Opc
)
,
DestReg
)
.
addReg
(
SrcReg
,
getKillRegState
(
KillSrc
)
)
;
}
}
</s>

AVR
AVR
AVR
AVR
AVR
AVR::DREGSRegClass
AVR::DREGSMOVWRegClass
AVR::MOVWRdRr
AVR::MOVRdRr
AVR::MOVRdRr
AVR::GPR8RegClass
AVR::MOVRdRr
AVR::SP
AVR::DREGSRegClass
AVR::SPREAD
AVR::SP
AVR::DREGSRegClass
AVR::SPWRITE
"Impossible reg-to-reg copy"


<s>
void
AVRInstrInfo
::
copyPhysReg
(
MachineBasicBlock
&
MBB
,
MachineBasicBlock
::
iterator
MI
,
const
DebugLoc
&
DL
,
MCRegister
DestReg
,
MCRegister
SrcReg
,
bool
KillSrc
)
const
{
const
AVRSubtarget
&
STI
=
MBB
.
getParent
(
)
->
getSubtarget
<
AVRSubtarget
>
(
)
;
const
AVRRegisterInfo
&
TRI
=
*
STI
.
getRegisterInfo
(
)
;
unsigned
Opc
;
if
(
AVR
::
DREGSRegClass
.
contains
(
DestReg
,
SrcReg
)
)
{
if
(
STI
.
hasMOVW
(
)
)
{
BuildMI
(
MBB
,
MI
,
DL
,
get
(
AVR
::
MOVWRdRr
)
,
DestReg
)
.
addReg
(
SrcReg
,
getKillRegState
(
KillSrc
)
)
;
}
else
{
unsigned
DestLo
,
DestHi
,
SrcLo
,
SrcHi
;
TRI
.
splitReg
(
DestReg
,
DestLo
,
DestHi
)
;
TRI
.
splitReg
(
SrcReg
,
SrcLo
,
SrcHi
)
;
BuildMI
(
MBB
,
MI
,
DL
,
get
(
AVR
::
MOVRdRr
)
,
DestLo
)
.
addReg
(
SrcLo
,
getKillRegState
(
KillSrc
)
)
;
BuildMI
(
MBB
,
MI
,
DL
,
get
(
AVR
::
MOVRdRr
)
,
DestHi
)
.
addReg
(
SrcHi
,
getKillRegState
(
KillSrc
)
)
;
}
}
else
{
if
(
AVR
::
GPR8RegClass
.
contains
(
DestReg
,
SrcReg
)
)
{
Opc
=
AVR
::
MOVRdRr
;
}
else
if
(
SrcReg
==
AVR
::
SP
&&
AVR
::
DREGSRegClass
.
contains
(
DestReg
)
)
{
Opc
=
AVR
::
SPREAD
;
}
else
if
(
DestReg
==
AVR
::
SP
&&
AVR
::
DREGSRegClass
.
contains
(
SrcReg
)
)
{
Opc
=
AVR
::
SPWRITE
;
}
else
{
llvm_unreachable
(
"Impossible reg-to-reg copy"
)
;
}
BuildMI
(
MBB
,
MI
,
DL
,
get
(
Opc
)
,
DestReg
)
.
addReg
(
SrcReg
,
getKillRegState
(
KillSrc
)
)
;
}
}
</s>


"insertBranch must not be told to insert a fallthrough"

"AVR branch conditions have one component!"

"Unconditional branch with multiple successors!"

Insert branch code into the end of the specified MachineBasicBlock .


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

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

AVR
AVR
"code size not handled"
0
AVR::RJMPk
AVRCC::COND_INVALID


<s>
void
AVRInstrInfo
::
copyPhysReg
(
MachineBasicBlock
&
MBB
,
MachineBasicBlock
::
iterator
MI
,
const
DebugLoc
&
DL
,
unsigned
DestReg
,
unsigned
SrcReg
,
bool
KillSrc
)
const
{
unsigned
Opc
;
if
(
AVR
::
GPR8RegClass
.
contains
(
DestReg
,
SrcReg
)
)
{
Opc
=
AVR
::
MOVRdRr
;
}
else
if
(
AVR
::
DREGSRegClass
.
contains
(
DestReg
,
SrcReg
)
)
{
Opc
=
AVR
::
MOVWRdRr
;
}
else
if
(
SrcReg
==
AVR
::
SP
&&
AVR
::
DREGSRegClass
.
contains
(
DestReg
)
)
{
Opc
=
AVR
::
SPREAD
;
}
else
if
(
DestReg
==
AVR
::
SP
&&
AVR
::
DREGSRegClass
.
contains
(
SrcReg
)
)
{
Opc
=
AVR
::
SPWRITE
;
}
else
{
llvm_unreachable
(
"Impossible reg-to-reg copy"
)
;
}
BuildMI
(
MBB
,
MI
,
DL
,
get
(
Opc
)
,
DestReg
)
.
addReg
(
SrcReg
,
getKillRegState
(
KillSrc
)
)
;
}
</s>


<s> unsigned AVRInstrInfo :: getInstSizeInBytes ( const MachineInstr * MI ) const { unsigned Opcode = MI -> getOpcode ( ) ; switch ( Opcode ) { default : { const MCInstrDesc & Desc = get ( Opcode ) ; return Desc . getSize ( ) ; } case TargetOpcode :: EH_LABEL : case TargetOpcode :: IMPLICIT_DEF : case TargetOpcode :: KILL : case TargetOpcode :: DBG_VALUE : return 0 ; case TargetOpcode :: INLINEASM : { const MachineFunction * MF = MI -> getParent ( ) -> getParent ( ) ; const AVRTargetMachine & TM = static_cast < const AVRTargetMachine & > ( MF -> getTarget ( ) ) ; const TargetInstrInfo & TII = * TM . getSubtargetImpl ( ) -> getInstrInfo ( ) ; return TII . getInlineAsmLength ( MI -> getOperand ( 0 ) . getSymbolName ( ) , * TM . getMCAsmInfo ( ) ) ; } } } </s>


<s> unsigned AVRInstrInfo :: removeBranch ( MachineBasicBlock & MBB , int * BytesRemoved ) const { if ( BytesRemoved ) * BytesRemoved = 0 ; MachineBasicBlock :: iterator I = MBB . end ( ) ; unsigned Count = 0 ; while ( I != MBB . begin ( ) ) { -- I ; if ( I -> isDebugValue ( ) ) { continue ; } if ( I -> getOpcode ( ) != AVR :: RJMPk && getCondFromBranchOpc ( I -> getOpcode ( ) ) == AVRCC :: COND_INVALID ) { break ; } if ( BytesRemoved ) * BytesRemoved += getInstSizeInBytes ( * I ) ; I -> eraseFromParent ( ) ; I = MBB . end ( ) ; ++ Count ; } return Count ; } </s>


<s> void AVRInstrInfo :: insertIndirectBranch ( MachineBasicBlock & MBB , MachineBasicBlock & NewDestBB , MachineBasicBlock & RestoreBB , const DebugLoc & DL , int64_t BrOffset , RegScavenger * RS ) const { BuildMI ( & MBB , DL , get ( AVR :: JMPk ) ) . addMBB ( & NewDestBB ) ; } </s>

Insert an unconditional indirect branch at the end of MBB to NewDestBB .


<s> unsigned AVRInstrInfo :: getInstSizeInBytes ( const MachineInstr & MI ) const { unsigned Opcode = MI . getOpcode ( ) ; switch ( Opcode ) { default : { const MCInstrDesc & Desc = get ( Opcode ) ; return Desc . getSize ( ) ; } case TargetOpcode :: EH_LABEL : case TargetOpcode :: IMPLICIT_DEF : case TargetOpcode :: KILL : case TargetOpcode :: DBG_VALUE : return 0 ; case TargetOpcode :: INLINEASM : { const MachineFunction * MF = MI . getParent ( ) -> getParent ( ) ; const AVRTargetMachine & TM = static_cast < const AVRTargetMachine & > ( MF -> getTarget ( ) ) ; const TargetInstrInfo & TII = * TM . getSubtargetImpl ( ) -> getInstrInfo ( ) ; return TII . getInlineAsmLength ( MI . getOperand ( 0 ) . getSymbolName ( ) , * TM . getMCAsmInfo ( ) ) ; } } } </s>


<s>
bool
AVRInstrInfo
::
isBranchOffsetInRange
(
unsigned
BranchOp
,
int64_t
BrOffset
)
const
{
switch
(
BranchOp
)
{
default
:
llvm_unreachable
(
"unexpected opcode!"
)
;
case
AVR
::
JMPk
:
case
AVR
::
CALLk
:
assert
(
BrOffset
>=
0
&&
"offset must be absolute address"
)
;
return
isUIntN
(
16
,
BrOffset
)
;
case
AVR
::
RCALLk
:
case
AVR
::
RJMPk
:
return
isIntN
(
13
,
BrOffset
)
;
case
AVR
::
BRBSsk
:
case
AVR
::
BRBCsk
:
case
AVR
::
BREQk
:
case
AVR
::
BRNEk
:
case
AVR
::
BRSHk
:
case
AVR
::
BRLOk
:
case
AVR
::
BRMIk
:
case
AVR
::
BRPLk
:
case
AVR
::
BRGEk
:
case
AVR
::
BRLTk
:
return
isIntN
(
7
,
BrOffset
)
;
}
}
</s>

Determine if the branch target is in range .

AVR
AVR
"unexpected opcode!"
AVR::JMPk
AVR::CALLk
0
"offset must be absolute address"
16
AVR::RCALLk
AVR::RJMPk
13
AVR::BRBSsk
AVR::BRBCsk
AVR::BREQk
AVR::BRNEk
AVR::BRSHk
AVR::BRLOk
AVR::BRMIk
AVR::BRPLk
AVR::BRGEk
AVR::BRLTk
7


<s> void AVRInstrInfo :: insertIndirectBranch ( MachineBasicBlock & MBB , MachineBasicBlock & NewDestBB , MachineBasicBlock & RestoreBB , const DebugLoc & DL , int64_t BrOffset , RegScavenger * RS ) const { BuildMI ( & MBB , DL , get ( AVR :: JMPk ) ) . addMBB ( & NewDestBB ) ; return ; } </s>


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

getRegisterInfo - TargetInstrInfo is a superset of MRegister info .


<s> unsigned AVRInstrInfo :: insertIndirectBranch ( MachineBasicBlock & MBB , MachineBasicBlock & NewDestBB , const DebugLoc & DL , int64_t BrOffset , RegScavenger * RS ) const { auto & MI = * BuildMI ( & MBB , DL , get ( AVR :: JMPk ) ) . addMBB ( & NewDestBB ) ; return getInstSizeInBytes ( MI ) ; } </s>


<s>
bool
AVRInstrInfo
::
isBranchOffsetInRange
(
unsigned
BranchOp
,
int64_t
BrOffset
)
const
{
switch
(
BranchOp
)
{
default
:
llvm_unreachable
(
"unexpected opcode!"
)
;
case
AVR
::
JMPk
:
case
AVR
::
CALLk
:
return
true
;
case
AVR
::
RCALLk
:
case
AVR
::
RJMPk
:
return
isIntN
(
13
,
BrOffset
)
;
case
AVR
::
BRBSsk
:
case
AVR
::
BRBCsk
:
case
AVR
::
BREQk
:
case
AVR
::
BRNEk
:
case
AVR
::
BRSHk
:
case
AVR
::
BRLOk
:
case
AVR
::
BRMIk
:
case
AVR
::
BRPLk
:
case
AVR
::
BRGEk
:
case
AVR
::
BRLTk
:
return
isIntN
(
7
,
BrOffset
)
;
}
}
</s>

AVR
AVR
"unexpected opcode!"
AVR::JMPk
AVR::CALLk
AVR::RCALLk
AVR::RJMPk
13
AVR::BRBSsk
AVR::BRBCsk
AVR::BREQk
AVR::BRNEk
AVR::BRSHk
AVR::BRLOk
AVR::BRMIk
AVR::BRPLk
AVR::BRGEk
AVR::BRLTk
7


<s> unsigned AVRInstrInfo :: isLoadFromStackSlot ( const MachineInstr & MI , int & FrameIndex ) const { switch ( MI . getOpcode ( ) ) { case AVR :: LDDRdPtrQ : case AVR :: LDDWRdYQ : { if ( MI . getOperand ( 1 ) . isFI ( ) && MI . getOperand ( 2 ) . isImm ( ) && MI . getOperand ( 2 ) . getImm ( ) == 0 ) { FrameIndex = MI . getOperand ( 1 ) . getIndex ( ) ; return MI . getOperand ( 0 ) . getReg ( ) ; } break ; } default : break ; } return 0 ; } </s>


<s> unsigned AVRInstrInfo :: isStoreToStackSlot ( const MachineInstr & MI , int & FrameIndex ) const { switch ( MI . getOpcode ( ) ) { case AVR :: STDPtrQRr : case AVR :: STDWPtrQRr : { if ( MI . getOperand ( 0 ) . isFI ( ) && MI . getOperand ( 1 ) . isImm ( ) && MI . getOperand ( 1 ) . getImm ( ) == 0 ) { FrameIndex = MI . getOperand ( 0 ) . getIndex ( ) ; return MI . getOperand ( 2 ) . getReg ( ) ; } break ; } default : break ; } return 0 ; } </s>


"Cannot load this register from a stack slot!"


<s> unsigned AVRInstrInfo :: removeBranch ( MachineBasicBlock & MBB , int * BytesRemoved ) const { if ( BytesRemoved ) * BytesRemoved = 0 ; MachineBasicBlock :: iterator I = MBB . end ( ) ; unsigned Count = 0 ; while ( I != MBB . begin ( ) ) { -- I ; if ( I -> isDebugInstr ( ) ) { continue ; } if ( I -> getOpcode ( ) != AVR :: RJMPk && getCondFromBranchOpc ( I -> getOpcode ( ) ) == AVRCC :: COND_INVALID ) { break ; } if ( BytesRemoved ) * BytesRemoved += getInstSizeInBytes ( * I ) ; I -> eraseFromParent ( ) ; I = MBB . end ( ) ; ++ Count ; } return Count ; } </s>


<s>
bool
AVRInstrInfo
::
reverseBranchCondition
(
SmallVectorImpl
<
MachineOperand
>
&
Cond
)
const
{
assert
(
Cond
.
size
(
)
==
1
&&
"Invalid AVR branch condition!"
)
;
AVRCC
::
CondCodes
CC
=
static_cast
<
AVRCC
::
CondCodes
>
(
Cond
[
0
]
.
getImm
(
)
)
;
Cond
[
0
]
.
setImm
(
getOppositeCondition
(
CC
)
)
;
return
false
;
}
</s>

Reverses the branch condition of the specified condition list , returning false on success and true if it can not be reversed .


"Cannot store this register into a stack slot!"


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

getPassName - Return a nice clean name for a pass .


<s> bool AVRInstrumentFunctions :: runOnFunction ( Function & F ) { if ( ShouldInstrument ( F ) ) { BuildEntryBlock ( F ) ; BuildExitHooks ( F ) ; } return true ; } </s>

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


<s>
void
AVRDAGToDAGISel
::
Select
(
SDNode
*
N
)
{
DEBUG
(
errs
(
)
<<
"Selecting: "
;
N
->
dump
(
CurDAG
)
;
errs
(
)
<<
"\n"
)
;
if
(
N
->
isMachineOpcode
(
)
)
{
DEBUG
(
errs
(
)
<<
"== "
;
N
->
dump
(
CurDAG
)
;
errs
(
)
<<
"\n"
)
;
N
->
setNodeId
(
1
)
;
return
;
}
if
(
trySelect
(
N
)
)
return
;
SelectCode
(
N
)
;
}
</s>

Main hook for targets to transform nodes into machine nodes .


<s>
void
AVRDAGToDAGISel
::
Select
(
SDNode
*
N
)
{
if
(
N
->
isMachineOpcode
(
)
)
{
DEBUG
(
errs
(
)
<<
"== "
;
N
->
dump
(
CurDAG
)
;
errs
(
)
<<
"\n"
)
;
N
->
setNodeId
(
1
)
;
return
;
}
if
(
trySelect
(
N
)
)
return
;
SelectCode
(
N
)
;
}
</s>


<s>
StringRef
getPassName
(
)
const
override
{
return
"AVR DAG->DAG Instruction Selection"
;
}
</s>

AVR
"AVR DAG->DAG Instruction Selection"


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

runOnMachineFunction - Emit the function body .


<s>
void
AVRDAGToDAGISel
::
Select
(
SDNode
*
N
)
{
if
(
N
->
isMachineOpcode
(
)
)
{
LLVM_DEBUG
(
errs
(
)
<<
"== "
;
N
->
dump
(
CurDAG
)
;
errs
(
)
<<
"\n"
)
;
N
->
setNodeId
(
1
)
;
return
;
}
if
(
trySelect
(
N
)
)
return
;
SelectCode
(
N
)
;
}
</s>


<s> MVT :: SimpleValueType getCmpLibcallReturnType ( ) const override { return MVT :: i8 ; } </s>

Return the ValueType for comparison libcalls .


<s> MVT getScalarShiftAmountTy ( const DataLayout & , EVT LHSTy ) const override { return MVT :: i8 ; } </s>

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


<s>
MachineBasicBlock
*
AVRTargetLowering
::
EmitInstrWithCustomInserter
(
MachineInstr
&
MI
,
MachineBasicBlock
*
MBB
)
const
{
int
Opc
=
MI
.
getOpcode
(
)
;
switch
(
Opc
)
{
case
AVR
::
Lsl8
:
case
AVR
::
Lsl16
:
case
AVR
::
Lsr8
:
case
AVR
::
Lsr16
:
case
AVR
::
Rol8
:
case
AVR
::
Rol16
:
case
AVR
::
Ror8
:
case
AVR
::
Ror16
:
case
AVR
::
Asr8
:
case
AVR
::
Asr16
:
return
insertShift
(
MI
,
MBB
)
;
case
AVR
::
MULRdRr
:
case
AVR
::
MULSRdRr
:
return
insertMul
(
MI
,
MBB
)
;
}
assert
(
(
Opc
==
AVR
::
Select16
||
Opc
==
AVR
::
Select8
)
&&
"Unexpected instr type to insert"
)
;
const
AVRInstrInfo
&
TII
=
(
const
AVRInstrInfo
&
)
*
MI
.
getParent
(
)
->
getParent
(
)
->
getSubtarget
(
)
.
getInstrInfo
(
)
;
DebugLoc
dl
=
MI
.
getDebugLoc
(
)
;
MachineFunction
*
MF
=
MBB
->
getParent
(
)
;
const
BasicBlock
*
LLVM_BB
=
MBB
->
getBasicBlock
(
)
;
MachineBasicBlock
*
trueMBB
=
MF
->
CreateMachineBasicBlock
(
LLVM_BB
)
;
MachineBasicBlock
*
falseMBB
=
MF
->
CreateMachineBasicBlock
(
LLVM_BB
)
;
MachineFunction
::
iterator
I
;
for
(
I
=
MF
->
begin
(
)
;
I
!=
MF
->
end
(
)
&&
&
(
*
I
)
!=
MBB
;
++
I
)
;
if
(
I
!=
MF
->
end
(
)
)
++
I
;
MF
->
insert
(
I
,
trueMBB
)
;
MF
->
insert
(
I
,
falseMBB
)
;
trueMBB
->
splice
(
trueMBB
->
begin
(
)
,
MBB
,
std
::
next
(
MachineBasicBlock
::
iterator
(
MI
)
)
,
MBB
->
end
(
)
)
;
trueMBB
->
transferSuccessorsAndUpdatePHIs
(
MBB
)
;
AVRCC
::
CondCodes
CC
=
(
AVRCC
::
CondCodes
)
MI
.
getOperand
(
3
)
.
getImm
(
)
;
BuildMI
(
MBB
,
dl
,
TII
.
getBrCond
(
CC
)
)
.
addMBB
(
trueMBB
)
;
BuildMI
(
MBB
,
dl
,
TII
.
get
(
AVR
::
RJMPk
)
)
.
addMBB
(
falseMBB
)
;
MBB
->
addSuccessor
(
falseMBB
)
;
MBB
->
addSuccessor
(
trueMBB
)
;
BuildMI
(
falseMBB
,
dl
,
TII
.
get
(
AVR
::
RJMPk
)
)
.
addMBB
(
trueMBB
)
;
falseMBB
->
addSuccessor
(
trueMBB
)
;
BuildMI
(
*
trueMBB
,
trueMBB
->
begin
(
)
,
dl
,
TII
.
get
(
AVR
::
PHI
)
,
MI
.
getOperand
(
0
)
.
getReg
(
)
)
.
addReg
(
MI
.
getOperand
(
1
)
.
getReg
(
)
)
.
addMBB
(
MBB
)
.
addReg
(
MI
.
getOperand
(
2
)
.
getReg
(
)
)
.
addMBB
(
falseMBB
)
;
MI
.
eraseFromParent
(
)
;
return
trueMBB
;
}
</s>

This method should be implemented by targets that mark instructions with the 'usesCustomInserter ' flag .


<s>
std
::
pair
<
unsigned
,
const
TargetRegisterClass
*
>
AVRTargetLowering
::
getRegForInlineAsmConstraint
(
const
TargetRegisterInfo
*
TRI
,
StringRef
Constraint
,
MVT
VT
)
const
{
auto
STI
=
static_cast
<
const
AVRTargetMachine
&
>
(
this
->
getTargetMachine
(
)
)
.
getSubtargetImpl
(
)
;
if
(
Constraint
.
size
(
)
==
1
)
{
switch
(
Constraint
[
0
]
)
{
case
'a'
:
return
std
::
make_pair
(
0U
,
&
AVR
::
LD8loRegClass
)
;
case
'b'
:
return
std
::
make_pair
(
0U
,
&
AVR
::
PTRDISPREGSRegClass
)
;
case
'd'
:
return
std
::
make_pair
(
0U
,
&
AVR
::
LD8RegClass
)
;
case
'l'
:
return
std
::
make_pair
(
0U
,
&
AVR
::
GPR8loRegClass
)
;
case
'e'
:
return
std
::
make_pair
(
0U
,
&
AVR
::
PTRREGSRegClass
)
;
case
'q'
:
return
std
::
make_pair
(
0U
,
&
AVR
::
GPRSPRegClass
)
;
case
'r'
:
if
(
VT
==
MVT
::
i8
)
return
std
::
make_pair
(
0U
,
&
AVR
::
GPR8RegClass
)
;
assert
(
VT
==
MVT
::
i16
&&
"inline asm constraint too large"
)
;
return
std
::
make_pair
(
0U
,
&
AVR
::
DREGSRegClass
)
;
case
't'
:
return
std
::
make_pair
(
unsigned
(
AVR
::
R0
)
,
&
AVR
::
GPR8RegClass
)
;
case
'w'
:
return
std
::
make_pair
(
0U
,
&
AVR
::
IWREGSRegClass
)
;
case
'x'
:
case
'X'
:
return
std
::
make_pair
(
unsigned
(
AVR
::
R27R26
)
,
&
AVR
::
PTRREGSRegClass
)
;
case
'y'
:
case
'Y'
:
return
std
::
make_pair
(
unsigned
(
AVR
::
R29R28
)
,
&
AVR
::
PTRREGSRegClass
)
;
case
'z'
:
case
'Z'
:
return
std
::
make_pair
(
unsigned
(
AVR
::
R31R30
)
,
&
AVR
::
PTRREGSRegClass
)
;
default
:
break
;
}
}
return
TargetLowering
::
getRegForInlineAsmConstraint
(
STI
->
getRegisterInfo
(
)
,
Constraint
,
VT
)
;
}
</s>

Given a physical register constraint ( e.g .


<s> bool AVRTargetLowering :: CanLowerReturn ( CallingConv :: ID CallConv , MachineFunction & MF , bool isVarArg , const SmallVectorImpl < ISD :: OutputArg > & Outs , LLVMContext & Context ) const { if ( CallConv == CallingConv :: AVR_BUILTIN ) { SmallVector < CCValAssign , 16 > RVLocs ; CCState CCInfo ( CallConv , isVarArg , MF , RVLocs , Context ) ; return CCInfo . CheckReturn ( Outs , RetCC_AVR_BUILTIN ) ; } unsigned TotalBytes = getTotalArgumentsSizeInBytes ( Outs ) ; return TotalBytes <= 8 ; } </s>

This hook should be implemented to check whether the return values described by the Outs array can fit into the return registers .


<s>
Register
AVRTargetLowering
::
getRegisterByName
(
const
char
*
RegName
,
LLT
VT
,
const
MachineFunction
&
MF
)
const
{
Register
Reg
;
if
(
VT
==
LLT
::
scalar
(
8
)
)
{
Reg
=
StringSwitch
<
unsigned
>
(
RegName
)
.
Case
(
"r0"
,
AVR
::
R0
)
.
Case
(
"r1"
,
AVR
::
R1
)
.
Default
(
0
)
;
}
else
{
Reg
=
StringSwitch
<
unsigned
>
(
RegName
)
.
Case
(
"r0"
,
AVR
::
R1R0
)
.
Case
(
"sp"
,
AVR
::
SP
)
.
Default
(
0
)
;
}
if
(
Reg
)
return
Reg
;
report_fatal_error
(
Twine
(
"Invalid register name \""
+
StringRef
(
RegName
)
+
"\"."
)
)
;
}
</s>

Return the register ID of the name passed in .


<s> SDValue AVRTargetLowering :: LowerCallResult ( SDValue Chain , SDValue InFlag , CallingConv :: ID CallConv , bool isVarArg , const SmallVectorImpl < ISD :: InputArg > & Ins , const SDLoc & dl , SelectionDAG & DAG , SmallVectorImpl < SDValue > & InVals ) const { SmallVector < CCValAssign , 16 > RVLocs ; CCState CCInfo ( CallConv , isVarArg , DAG . getMachineFunction ( ) , RVLocs , * DAG . getContext ( ) ) ; if ( CallConv == CallingConv :: AVR_BUILTIN ) { CCInfo . AnalyzeCallResult ( Ins , RetCC_AVR_BUILTIN ) ; } else { analyzeReturnValues ( Ins , CCInfo ) ; } for ( CCValAssign const & RVLoc : RVLocs ) { Chain = DAG . getCopyFromReg ( Chain , dl , RVLoc . getLocReg ( ) , RVLoc . getValVT ( ) , InFlag ) . getValue ( 1 ) ; InFlag = Chain . getValue ( 2 ) ; InVals . push_back ( Chain . getValue ( 0 ) ) ; } return Chain ; } </s>

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


<s>
SDValue
AVRTargetLowering
::
LowerReturn
(
SDValue
Chain
,
CallingConv
::
ID
CallConv
,
bool
isVarArg
,
const
SmallVectorImpl
<
ISD
::
OutputArg
>
&
Outs
,
const
SmallVectorImpl
<
SDValue
>
&
OutVals
,
const
SDLoc
&
dl
,
SelectionDAG
&
DAG
)
const
{
SmallVector
<
CCValAssign
,
16
>
RVLocs
;
CCState
CCInfo
(
CallConv
,
isVarArg
,
DAG
.
getMachineFunction
(
)
,
RVLocs
,
*
DAG
.
getContext
(
)
)
;
MachineFunction
&
MF
=
DAG
.
getMachineFunction
(
)
;
if
(
CallConv
==
CallingConv
::
AVR_BUILTIN
)
{
CCInfo
.
AnalyzeReturn
(
Outs
,
RetCC_AVR_BUILTIN
)
;
}
else
{
analyzeReturnValues
(
Outs
,
CCInfo
)
;
}
SDValue
Flag
;
SmallVector
<
SDValue
,
4
>
RetOps
(
1
,
Chain
)
;
for
(
unsigned
i
=
0
,
e
=
RVLocs
.
size
(
)
;
i
!=
e
;
++
i
)
{
CCValAssign
&
VA
=
RVLocs
[
i
]
;
assert
(
VA
.
isRegLoc
(
)
&&
"Can only return in registers!"
)
;
Chain
=
DAG
.
getCopyToReg
(
Chain
,
dl
,
VA
.
getLocReg
(
)
,
OutVals
[
i
]
,
Flag
)
;
Flag
=
Chain
.
getValue
(
1
)
;
RetOps
.
push_back
(
DAG
.
getRegister
(
VA
.
getLocReg
(
)
,
VA
.
getLocVT
(
)
)
)
;
}
if
(
MF
.
getFunction
(
)
.
getAttributes
(
)
.
hasFnAttr
(
Attribute
::
Naked
)
)
{
return
Chain
;
}
const
AVRMachineFunctionInfo
*
AFI
=
MF
.
getInfo
<
AVRMachineFunctionInfo
>
(
)
;
unsigned
RetOpc
=
AFI
->
isInterruptOrSignalHandler
(
)
AVRISD
::
RETI_FLAG
:
AVRISD
::
RET_FLAG
;
RetOps
[
0
]
=
Chain
;
if
(
Flag
.
getNode
(
)
)
{
RetOps
.
push_back
(
Flag
)
;
}
return
DAG
.
getNode
(
RetOpc
,
dl
,
MVT
::
Other
,
RetOps
)
;
}
</s>

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


<s> AVRTargetLowering :: ConstraintType AVRTargetLowering :: getConstraintType ( StringRef Constraint ) const { if ( Constraint . size ( ) == 1 ) { switch ( Constraint [ 0 ] ) { default : break ; case 'a' : case 'b' : case 'd' : case 'l' : case 'e' : case 'q' : case 'r' : case 'w' : return C_RegisterClass ; case 't' : case 'x' : case 'X' : case 'y' : case 'Y' : case 'z' : case 'Z' : return C_Register ; case 'Q' : return C_Memory ; case 'G' : case 'I' : case 'J' : case 'K' : case 'L' : case 'M' : case 'N' : case 'O' : case 'P' : case 'R' : return C_Immediate ; } } return TargetLowering :: getConstraintType ( Constraint ) ; } </s>

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


<s> const char * AVRTargetLowering :: getTargetNodeName ( unsigned Opcode ) const { case AVRISD :: name : \ return # name switch ( Opcode ) { default : return nullptr ; NODE ( RET_FLAG ) ; NODE ( RETI_FLAG ) ; NODE ( CALL ) ; NODE ( WRAPPER ) ; NODE ( LSL ) ; NODE ( LSR ) ; NODE ( ROL ) ; NODE ( ROR ) ; NODE ( ASR ) ; NODE ( LSLLOOP ) ; NODE ( LSRLOOP ) ; NODE ( ROLLOOP ) ; NODE ( RORLOOP ) ; NODE ( ASRLOOP ) ; NODE ( BRCOND ) ; NODE ( CMP ) ; NODE ( CMPC ) ; NODE ( TST ) ; NODE ( SELECT_CC ) ; } </s>

getTargetNodeName - This method returns the name of a target specific


<s> bool AVRTargetLowering :: isLegalAddressingMode ( const DataLayout & DL , const AddrMode & AM , Type * Ty , unsigned AS , Instruction * I ) const { int64_t Offs = AM . BaseOffs ; if ( AM . BaseGV && ! AM . HasBaseReg && AM . Scale == 0 && Offs == 0 ) { return true ; } if ( isa < PointerType > ( Ty ) && AS == AVR :: ProgramMemory ) { return false ; } if ( Offs < 0 ) Offs = - Offs ; if ( AM . BaseGV == nullptr && AM . HasBaseReg && AM . Scale == 0 && isUInt < 6 > ( Offs ) ) { return true ; } return false ; } </s>

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


<s> SDValue AVRTargetLowering :: LowerCallResult ( SDValue Chain , SDValue InFlag , CallingConv :: ID CallConv , bool isVarArg , const SmallVectorImpl < ISD :: InputArg > & Ins , const SDLoc & dl , SelectionDAG & DAG , SmallVectorImpl < SDValue > & InVals ) const { SmallVector < CCValAssign , 16 > RVLocs ; CCState CCInfo ( CallConv , isVarArg , DAG . getMachineFunction ( ) , RVLocs , * DAG . getContext ( ) ) ; if ( CallConv == CallingConv :: AVR_BUILTIN ) { CCInfo . AnalyzeCallResult ( Ins , RetCC_AVR_BUILTIN ) ; } else { analyzeReturnValues ( Ins , CCInfo , Subtarget . hasTinyEncoding ( ) ) ; } for ( CCValAssign const & RVLoc : RVLocs ) { Chain = DAG . getCopyFromReg ( Chain , dl , RVLoc . getLocReg ( ) , RVLoc . getValVT ( ) , InFlag ) . getValue ( 1 ) ; InFlag = Chain . getValue ( 2 ) ; InVals . push_back ( Chain . getValue ( 0 ) ) ; } return Chain ; } </s>


<s>
SDValue
AVRTargetLowering
::
LowerReturn
(
SDValue
Chain
,
CallingConv
::
ID
CallConv
,
bool
isVarArg
,
const
SmallVectorImpl
<
ISD
::
OutputArg
>
&
Outs
,
const
SmallVectorImpl
<
SDValue
>
&
OutVals
,
const
SDLoc
&
dl
,
SelectionDAG
&
DAG
)
const
{
SmallVector
<
CCValAssign
,
16
>
RVLocs
;
CCState
CCInfo
(
CallConv
,
isVarArg
,
DAG
.
getMachineFunction
(
)
,
RVLocs
,
*
DAG
.
getContext
(
)
)
;
MachineFunction
&
MF
=
DAG
.
getMachineFunction
(
)
;
if
(
CallConv
==
CallingConv
::
AVR_BUILTIN
)
{
CCInfo
.
AnalyzeReturn
(
Outs
,
RetCC_AVR_BUILTIN
)
;
}
else
{
analyzeReturnValues
(
Outs
,
CCInfo
,
Subtarget
.
hasTinyEncoding
(
)
)
;
}
SDValue
Flag
;
SmallVector
<
SDValue
,
4
>
RetOps
(
1
,
Chain
)
;
for
(
unsigned
i
=
0
,
e
=
RVLocs
.
size
(
)
;
i
!=
e
;
++
i
)
{
CCValAssign
&
VA
=
RVLocs
[
i
]
;
assert
(
VA
.
isRegLoc
(
)
&&
"Can only return in registers!"
)
;
Chain
=
DAG
.
getCopyToReg
(
Chain
,
dl
,
VA
.
getLocReg
(
)
,
OutVals
[
i
]
,
Flag
)
;
Flag
=
Chain
.
getValue
(
1
)
;
RetOps
.
push_back
(
DAG
.
getRegister
(
VA
.
getLocReg
(
)
,
VA
.
getLocVT
(
)
)
)
;
}
if
(
MF
.
getFunction
(
)
.
getAttributes
(
)
.
hasFnAttr
(
Attribute
::
Naked
)
)
{
return
Chain
;
}
const
AVRMachineFunctionInfo
*
AFI
=
MF
.
getInfo
<
AVRMachineFunctionInfo
>
(
)
;
unsigned
RetOpc
=
AFI
->
isInterruptOrSignalHandler
(
)
AVRISD
::
RETI_FLAG
:
AVRISD
::
RET_FLAG
;
RetOps
[
0
]
=
Chain
;
if
(
Flag
.
getNode
(
)
)
{
RetOps
.
push_back
(
Flag
)
;
}
return
DAG
.
getNode
(
RetOpc
,
dl
,
MVT
::
Other
,
RetOps
)
;
}
</s>


<s> std :: pair < unsigned , const TargetRegisterClass * > AVRTargetLowering :: getRegForInlineAsmConstraint ( const TargetRegisterInfo * TRI , StringRef Constraint , MVT VT ) const { if ( Constraint . size ( ) == 1 ) { switch ( Constraint [ 0 ] ) { case 'a' : return std :: make_pair ( 0U , & AVR :: LD8loRegClass ) ; case 'b' : return std :: make_pair ( 0U , & AVR :: PTRDISPREGSRegClass ) ; case 'd' : return std :: make_pair ( 0U , & AVR :: LD8RegClass ) ; case 'l' : return std :: make_pair ( 0U , & AVR :: GPR8loRegClass ) ; case 'e' : return std :: make_pair ( 0U , & AVR :: PTRREGSRegClass ) ; case 'q' : return std :: make_pair ( 0U , & AVR :: GPRSPRegClass ) ; case 'r' : if ( VT == MVT :: i8 ) return std :: make_pair ( 0U , & AVR :: GPR8RegClass ) ; return std :: make_pair ( 0U , & AVR :: DREGSRegClass ) ; case 't' : return std :: make_pair ( unsigned ( AVR :: R0 ) , & AVR :: GPR8RegClass ) ; case 'w' : return std :: make_pair ( 0U , & AVR :: IWREGSRegClass ) ; case 'x' : case 'X' : return std :: make_pair ( unsigned ( AVR :: R27R26 ) , & AVR :: PTRREGSRegClass ) ; case 'y' : case 'Y' : return std :: make_pair ( unsigned ( AVR :: R29R28 ) , & AVR :: PTRREGSRegClass ) ; case 'z' : case 'Z' : return std :: make_pair ( unsigned ( AVR :: R31R30 ) , & AVR :: PTRREGSRegClass ) ; default : break ; } } return TargetLowering :: getRegForInlineAsmConstraint ( Subtarget . getRegisterInfo ( ) , Constraint , VT ) ; } </s>


<s>
SDValue
AVRTargetLowering
::
LowerReturn
(
SDValue
Chain
,
CallingConv
::
ID
CallConv
,
bool
isVarArg
,
const
SmallVectorImpl
<
ISD
::
OutputArg
>
&
Outs
,
const
SmallVectorImpl
<
SDValue
>
&
OutVals
,
const
SDLoc
&
dl
,
SelectionDAG
&
DAG
)
const
{
SmallVector
<
CCValAssign
,
16
>
RVLocs
;
CCState
CCInfo
(
CallConv
,
isVarArg
,
DAG
.
getMachineFunction
(
)
,
RVLocs
,
*
DAG
.
getContext
(
)
)
;
MachineFunction
&
MF
=
DAG
.
getMachineFunction
(
)
;
if
(
CallConv
==
CallingConv
::
AVR_BUILTIN
)
{
CCInfo
.
AnalyzeReturn
(
Outs
,
RetCC_AVR_BUILTIN
)
;
}
else
{
analyzeReturnValues
(
Outs
,
CCInfo
)
;
}
SDValue
Flag
;
SmallVector
<
SDValue
,
4
>
RetOps
(
1
,
Chain
)
;
for
(
unsigned
i
=
0
,
e
=
RVLocs
.
size
(
)
;
i
!=
e
;
++
i
)
{
CCValAssign
&
VA
=
RVLocs
[
i
]
;
assert
(
VA
.
isRegLoc
(
)
&&
"Can only return in registers!"
)
;
Chain
=
DAG
.
getCopyToReg
(
Chain
,
dl
,
VA
.
getLocReg
(
)
,
OutVals
[
i
]
,
Flag
)
;
Flag
=
Chain
.
getValue
(
1
)
;
RetOps
.
push_back
(
DAG
.
getRegister
(
VA
.
getLocReg
(
)
,
VA
.
getLocVT
(
)
)
)
;
}
if
(
MF
.
getFunction
(
)
.
getAttributes
(
)
.
hasAttribute
(
AttributeList
::
FunctionIndex
,
Attribute
::
Naked
)
)
{
return
Chain
;
}
const
AVRMachineFunctionInfo
*
AFI
=
MF
.
getInfo
<
AVRMachineFunctionInfo
>
(
)
;
unsigned
RetOpc
=
AFI
->
isInterruptOrSignalHandler
(
)
AVRISD
::
RETI_FLAG
:
AVRISD
::
RET_FLAG
;
RetOps
[
0
]
=
Chain
;
if
(
Flag
.
getNode
(
)
)
{
RetOps
.
push_back
(
Flag
)
;
}
return
DAG
.
getNode
(
RetOpc
,
dl
,
MVT
::
Other
,
RetOps
)
;
}
</s>


<s>
MachineBasicBlock
*
AVRTargetLowering
::
EmitInstrWithCustomInserter
(
MachineInstr
&
MI
,
MachineBasicBlock
*
MBB
)
const
{
int
Opc
=
MI
.
getOpcode
(
)
;
switch
(
Opc
)
{
case
AVR
::
Lsl8
:
case
AVR
::
Lsl16
:
case
AVR
::
Lsr8
:
case
AVR
::
Lsr16
:
case
AVR
::
Asr8
:
case
AVR
::
Asr16
:
return
insertShift
(
MI
,
MBB
)
;
case
AVR
::
MULRdRr
:
case
AVR
::
MULSRdRr
:
return
insertMul
(
MI
,
MBB
)
;
}
assert
(
(
Opc
==
AVR
::
Select16
||
Opc
==
AVR
::
Select8
)
&&
"Unexpected instr type to insert"
)
;
const
AVRInstrInfo
&
TII
=
(
const
AVRInstrInfo
&
)
*
MI
.
getParent
(
)
->
getParent
(
)
->
getSubtarget
(
)
.
getInstrInfo
(
)
;
DebugLoc
dl
=
MI
.
getDebugLoc
(
)
;
MachineFunction
*
MF
=
MBB
->
getParent
(
)
;
const
BasicBlock
*
LLVM_BB
=
MBB
->
getBasicBlock
(
)
;
MachineBasicBlock
*
trueMBB
=
MF
->
CreateMachineBasicBlock
(
LLVM_BB
)
;
MachineBasicBlock
*
falseMBB
=
MF
->
CreateMachineBasicBlock
(
LLVM_BB
)
;
MachineFunction
::
iterator
I
=
MBB
->
getParent
(
)
->
begin
(
)
;
++
I
;
MF
->
insert
(
I
,
trueMBB
)
;
MF
->
insert
(
I
,
falseMBB
)
;
trueMBB
->
splice
(
trueMBB
->
begin
(
)
,
MBB
,
std
::
next
(
MachineBasicBlock
::
iterator
(
MI
)
)
,
MBB
->
end
(
)
)
;
trueMBB
->
transferSuccessorsAndUpdatePHIs
(
MBB
)
;
AVRCC
::
CondCodes
CC
=
(
AVRCC
::
CondCodes
)
MI
.
getOperand
(
3
)
.
getImm
(
)
;
BuildMI
(
MBB
,
dl
,
TII
.
getBrCond
(
CC
)
)
.
addMBB
(
trueMBB
)
;
BuildMI
(
MBB
,
dl
,
TII
.
get
(
AVR
::
RJMPk
)
)
.
addMBB
(
falseMBB
)
;
MBB
->
addSuccessor
(
falseMBB
)
;
MBB
->
addSuccessor
(
trueMBB
)
;
BuildMI
(
falseMBB
,
dl
,
TII
.
get
(
AVR
::
RJMPk
)
)
.
addMBB
(
trueMBB
)
;
falseMBB
->
addSuccessor
(
trueMBB
)
;
BuildMI
(
*
trueMBB
,
trueMBB
->
begin
(
)
,
dl
,
TII
.
get
(
AVR
::
PHI
)
,
MI
.
getOperand
(
0
)
.
getReg
(
)
)
.
addReg
(
MI
.
getOperand
(
1
)
.
getReg
(
)
)
.
addMBB
(
MBB
)
.
addReg
(
MI
.
getOperand
(
2
)
.
getReg
(
)
)
.
addMBB
(
falseMBB
)
;
MI
.
eraseFromParent
(
)
;
return
trueMBB
;
}
</s>


<s> bool AVRTargetLowering :: isLegalAddressingMode ( const DataLayout & DL , const AddrMode & AM , Type * Ty , unsigned AS ) const { int64_t Offs = AM . BaseOffs ; if ( AM . BaseGV && ! AM . HasBaseReg && AM . Scale == 0 && Offs == 0 ) { return true ; } if ( isa < PointerType > ( Ty ) && AS == AVR :: ProgramMemory ) { return false ; } if ( Offs < 0 ) Offs = - Offs ; if ( AM . BaseGV == 0 && AM . HasBaseReg && AM . Scale == 0 && isUInt < 6 > ( Offs ) ) { return true ; } return false ; } </s>


<s>
SDValue
AVRTargetLowering
::
LowerReturn
(
SDValue
Chain
,
CallingConv
::
ID
CallConv
,
bool
isVarArg
,
const
SmallVectorImpl
<
ISD
::
OutputArg
>
&
Outs
,
const
SmallVectorImpl
<
SDValue
>
&
OutVals
,
const
SDLoc
&
dl
,
SelectionDAG
&
DAG
)
const
{
SmallVector
<
CCValAssign
,
16
>
RVLocs
;
CCState
CCInfo
(
CallConv
,
isVarArg
,
DAG
.
getMachineFunction
(
)
,
RVLocs
,
*
DAG
.
getContext
(
)
)
;
auto
CCFunction
=
CCAssignFnForReturn
(
CallConv
)
;
CCInfo
.
AnalyzeReturn
(
Outs
,
CCFunction
)
;
MachineFunction
&
MF
=
DAG
.
getMachineFunction
(
)
;
unsigned
e
=
RVLocs
.
size
(
)
;
if
(
e
>
1
)
{
std
::
reverse
(
RVLocs
.
begin
(
)
,
RVLocs
.
end
(
)
)
;
}
SDValue
Flag
;
SmallVector
<
SDValue
,
4
>
RetOps
(
1
,
Chain
)
;
for
(
unsigned
i
=
0
;
i
!=
e
;
++
i
)
{
CCValAssign
&
VA
=
RVLocs
[
i
]
;
assert
(
VA
.
isRegLoc
(
)
&&
"Can only return in registers!"
)
;
Chain
=
DAG
.
getCopyToReg
(
Chain
,
dl
,
VA
.
getLocReg
(
)
,
OutVals
[
i
]
,
Flag
)
;
Flag
=
Chain
.
getValue
(
1
)
;
RetOps
.
push_back
(
DAG
.
getRegister
(
VA
.
getLocReg
(
)
,
VA
.
getLocVT
(
)
)
)
;
}
if
(
MF
.
getFunction
(
)
->
getAttributes
(
)
.
hasAttribute
(
AttributeSet
::
FunctionIndex
,
Attribute
::
Naked
)
)
{
return
Chain
;
}
unsigned
RetOpc
=
(
CallConv
==
CallingConv
::
AVR_INTR
||
CallConv
==
CallingConv
::
AVR_SIGNAL
)
AVRISD
::
RETI_FLAG
:
AVRISD
::
RET_FLAG
;
RetOps
[
0
]
=
Chain
;
if
(
Flag
.
getNode
(
)
)
{
RetOps
.
push_back
(
Flag
)
;
}
return
DAG
.
getNode
(
RetOpc
,
dl
,
MVT
::
Other
,
RetOps
)
;
}
</s>


<s>
SDValue
AVRTargetLowering
::
LowerReturn
(
SDValue
Chain
,
CallingConv
::
ID
CallConv
,
bool
isVarArg
,
const
SmallVectorImpl
<
ISD
::
OutputArg
>
&
Outs
,
const
SmallVectorImpl
<
SDValue
>
&
OutVals
,
const
SDLoc
&
dl
,
SelectionDAG
&
DAG
)
const
{
SmallVector
<
CCValAssign
,
16
>
RVLocs
;
CCState
CCInfo
(
CallConv
,
isVarArg
,
DAG
.
getMachineFunction
(
)
,
RVLocs
,
*
DAG
.
getContext
(
)
)
;
auto
CCFunction
=
CCAssignFnForReturn
(
CallConv
)
;
CCInfo
.
AnalyzeReturn
(
Outs
,
CCFunction
)
;
MachineFunction
&
MF
=
DAG
.
getMachineFunction
(
)
;
unsigned
e
=
RVLocs
.
size
(
)
;
if
(
e
>
1
)
{
std
::
reverse
(
RVLocs
.
begin
(
)
,
RVLocs
.
end
(
)
)
;
}
SDValue
Flag
;
SmallVector
<
SDValue
,
4
>
RetOps
(
1
,
Chain
)
;
for
(
unsigned
i
=
0
;
i
!=
e
;
++
i
)
{
CCValAssign
&
VA
=
RVLocs
[
i
]
;
assert
(
VA
.
isRegLoc
(
)
&&
"Can only return in registers!"
)
;
Chain
=
DAG
.
getCopyToReg
(
Chain
,
dl
,
VA
.
getLocReg
(
)
,
OutVals
[
i
]
,
Flag
)
;
Flag
=
Chain
.
getValue
(
1
)
;
RetOps
.
push_back
(
DAG
.
getRegister
(
VA
.
getLocReg
(
)
,
VA
.
getLocVT
(
)
)
)
;
}
if
(
MF
.
getFunction
(
)
.
getAttributes
(
)
.
hasAttribute
(
AttributeList
::
FunctionIndex
,
Attribute
::
Naked
)
)
{
return
Chain
;
}
const
AVRMachineFunctionInfo
*
AFI
=
MF
.
getInfo
<
AVRMachineFunctionInfo
>
(
)
;
unsigned
RetOpc
=
AFI
->
isInterruptOrSignalHandler
(
)
AVRISD
::
RETI_FLAG
:
AVRISD
::
RET_FLAG
;
RetOps
[
0
]
=
Chain
;
if
(
Flag
.
getNode
(
)
)
{
RetOps
.
push_back
(
Flag
)
;
}
return
DAG
.
getNode
(
RetOpc
,
dl
,
MVT
::
Other
,
RetOps
)
;
}
</s>