"OffsetRegShifted must imply OffsetIsReg!"

"Offset must exists unless register offset is used!"

"Cannot have shift amount without shifted register offset!"

"Cannot have expression offset and register offset!"


<s> static ARMOperand * CreateReg ( unsigned RegNum , SMLoc S , SMLoc E ) { ARMOperand * Op = new ARMOperand ( Register ) ; Op -> Reg . RegNum = RegNum ; Op -> StartLoc = S ; Op -> EndLoc = E ; return Op ; } </s>

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


<s>
void
ARMOperand
::
dump
(
raw_ostream
&
OS
)
const
{
switch
(
Kind
)
{
case
CondCode
:
OS
<<
"<ARMCC::"
<<
ARMCondCodeToString
(
getCondCode
(
)
)
<<
">"
;
break
;
case
CCOut
:
OS
<<
"<ccout "
<<
getReg
(
)
<<
">"
;
break
;
case
CoprocNum
:
OS
<<
"<coprocessor number: "
<<
getCoproc
(
)
<<
">"
;
break
;
case
CoprocReg
:
OS
<<
"<coprocessor register: "
<<
getCoproc
(
)
<<
">"
;
break
;
case
MSRMask
:
OS
<<
"<mask: "
<<
getMSRMask
(
)
<<
">"
;
break
;
case
Immediate
:
getImm
(
)
->
print
(
OS
)
;
break
;
case
MemBarrierOpt
:
OS
<<
"<ARM_MB::"
<<
MemBOptToString
(
getMemBarrierOpt
(
)
)
<<
">"
;
break
;
case
Memory
:
OS
<<
"<memory "
<<
"base:"
<<
getMemBaseRegNum
(
)
;
if
(
getMemOffsetIsReg
(
)
)
{
OS
<<
" offset:<register "
<<
getMemOffsetRegNum
(
)
;
if
(
getMemOffsetRegShifted
(
)
)
{
OS
<<
" offset-shift-type:"
<<
getMemShiftType
(
)
;
OS
<<
" offset-shift-amount:"
<<
*
getMemShiftAmount
(
)
;
}
}
else
{
OS
<<
" offset:"
<<
*
getMemOffset
(
)
;
}
if
(
getMemOffsetIsReg
(
)
)
OS
<<
" (offset-is-reg)"
;
if
(
getMemPreindexed
(
)
)
OS
<<
" (pre-indexed)"
;
if
(
getMemPostindexed
(
)
)
OS
<<
" (post-indexed)"
;
if
(
getMemNegative
(
)
)
OS
<<
" (negative)"
;
if
(
getMemWriteback
(
)
)
OS
<<
" (writeback)"
;
OS
<<
">"
;
break
;
case
ProcIFlags
:
{
OS
<<
"<ARM_PROC::"
;
unsigned
IFlags
=
getProcIFlags
(
)
;
for
(
int
i
=
2
;
i
>=
0
;
i
)
if
(
IFlags
&
(
1
<<
i
)
)
OS
<<
ARM_PROC
::
IFlagsToString
(
1
<<
i
)
;
OS
<<
">"
;
break
;
}
case
Register
:
OS
<<
"<register "
<<
getReg
(
)
<<
">"
;
break
;
case
Shifter
:
OS
<<
"<shifter "
<<
getShiftOpcStr
(
Shift
.
ShiftTy
)
<<
">"
;
break
;
case
RegisterList
:
case
DPRRegisterList
:
case
SPRRegisterList
:
{
OS
<<
"<register_list "
;
const
SmallVectorImpl
<
unsigned
>
&
RegList
=
getRegList
(
)
;
for
(
SmallVectorImpl
<
unsigned
>
::
const_iterator
I
=
RegList
.
begin
(
)
,
E
=
RegList
.
end
(
)
;
I
!=
E
;
)
{
OS
<<
*
I
;
if
(
++
I
<
E
)
OS
<<
", "
;
}
OS
<<
">"
;
break
;
}
case
Token
:
OS
<<
"'"
<<
getToken
(
)
<<
"'"
;
break
;
}
}
</s>

Dump the plan to stderr ( for debugging ) .

ARM
ARM
"<ARMCC::"
ARM
">"
"<ccout "
">"
"<coprocessor number: "
">"
"<coprocessor register: "
">"
"<mask: "
">"
"<ARM_MB::"
">"
"<memory "
"base:"
" offset:<register "
" offset-shift-type:"
" offset-shift-amount:"
" offset:"
" (offset-is-reg)"
" (pre-indexed)"
" (post-indexed)"
" (negative)"
" (writeback)"
">"
"<ARM_PROC::"
2
0
1
ARM_PROC::IFlagsToString
1
">"
"<register "
">"
"<shifter "
">"
"<register_list "
", "
">"
"'"
"'"


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

Returns the register associated with this edge .


<s>
bool
ARMAsmParser
::
ParseInstruction
(
StringRef
Name
,
SMLoc
NameLoc
,
SmallVectorImpl
<
MCParsedAsmOperand
*
>
&
Operands
)
{
size_t
Start
=
0
,
Next
=
Name
.
find
(
'.'
)
;
StringRef
Head
=
Name
.
slice
(
Start
,
Next
)
;
unsigned
PredicationCode
;
unsigned
ProcessorIMod
;
bool
CarrySetting
;
Head
=
SplitMnemonic
(
Head
,
PredicationCode
,
CarrySetting
,
ProcessorIMod
)
;
Operands
.
push_back
(
ARMOperand
::
CreateToken
(
Head
,
NameLoc
)
)
;
bool
CanAcceptCarrySet
,
CanAcceptPredicationCode
;
GetMnemonicAcceptInfo
(
Head
,
CanAcceptCarrySet
,
CanAcceptPredicationCode
)
;
if
(
CanAcceptCarrySet
)
{
Operands
.
push_back
(
ARMOperand
::
CreateCCOut
(
CarrySetting
ARM
::
CPSR
:
0
,
NameLoc
)
)
;
}
else
{
}
if
(
CanAcceptPredicationCode
)
{
Operands
.
push_back
(
ARMOperand
::
CreateCondCode
(
ARMCC
::
CondCodes
(
PredicationCode
)
,
NameLoc
)
)
;
}
else
{
}
if
(
ProcessorIMod
)
{
Operands
.
push_back
(
ARMOperand
::
CreateImm
(
MCConstantExpr
::
Create
(
ProcessorIMod
,
getContext
(
)
)
,
NameLoc
,
NameLoc
)
)
;
}
else
{
}
while
(
Next
!=
StringRef
::
npos
)
{
Start
=
Next
;
Next
=
Name
.
find
(
'.'
,
Start
+
1
)
;
StringRef
ExtraToken
=
Name
.
slice
(
Start
,
Next
)
;
Operands
.
push_back
(
ARMOperand
::
CreateToken
(
ExtraToken
,
NameLoc
)
)
;
}
if
(
getLexer
(
)
.
isNot
(
AsmToken
::
EndOfStatement
)
)
{
if
(
ParseOperand
(
Operands
,
Head
)
)
{
Parser
.
EatToEndOfStatement
(
)
;
return
true
;
}
while
(
getLexer
(
)
.
is
(
AsmToken
::
Comma
)
)
{
Parser
.
Lex
(
)
;
if
(
ParseOperand
(
Operands
,
Head
)
)
{
Parser
.
EatToEndOfStatement
(
)
;
return
true
;
}
}
}
if
(
getLexer
(
)
.
isNot
(
AsmToken
::
EndOfStatement
)
)
{
Parser
.
EatToEndOfStatement
(
)
;
return
TokError
(
"unexpected token in argument list"
)
;
}
Parser
.
Lex
(
)
;
return
false
;
}
</s>

ParseInstruction - Parse one assembly instruction .

ARM
ARM
0
ARM
ARM
ARM::CPSR
0
ARM
ARMCC::CondCodes
ARM
1
ARM
"unexpected token in argument list"


"flag setting instruction only valid outside IT block"

"instruction only valid inside IT block"

"instruction variant requires ARMv6 or later"

"immediate operand must be in the range [0,15]"

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


<s>
bool
ARMAsmParser
::
MatchAndEmitInstruction
(
SMLoc
IDLoc
,
unsigned
&
Opcode
,
OperandVector
&
Operands
,
MCStreamer
&
Out
,
uint64_t
&
ErrorInfo
,
bool
MatchingInlineAsm
)
{
MCInst
Inst
;
unsigned
MatchResult
;
bool
PendConditionalInstruction
=
false
;
SmallVector
<
NearMissInfo
,
4
>
NearMisses
;
MatchResult
=
MatchInstruction
(
Operands
,
Inst
,
NearMisses
,
MatchingInlineAsm
,
PendConditionalInstruction
,
Out
)
;
switch
(
MatchResult
)
{
case
Match_Success
:
LLVM_DEBUG
(
dbgs
(
)
<<
"Parsed as: "
;
Inst
.
dump_pretty
(
dbgs
(
)
,
MII
.
getName
(
Inst
.
getOpcode
(
)
)
)
;
dbgs
(
)
<<
"\n"
)
;
if
(
validateInstruction
(
Inst
,
Operands
)
)
{
forwardITPosition
(
)
;
return
true
;
}
{
bool
wasInITBlock
=
inITBlock
(
)
;
while
(
processInstruction
(
Inst
,
Operands
,
Out
)
)
LLVM_DEBUG
(
dbgs
(
)
<<
"Changed to: "
;
Inst
.
dump_pretty
(
dbgs
(
)
,
MII
.
getName
(
Inst
.
getOpcode
(
)
)
)
;
dbgs
(
)
<<
"\n"
)
;
if
(
wasInITBlock
&&
hasV8Ops
(
)
&&
isThumb
(
)
&&
!
isV8EligibleForIT
(
&
Inst
)
)
{
Warning
(
IDLoc
,
"deprecated instruction in IT block"
)
;
}
}
forwardITPosition
(
)
;
if
(
Inst
.
getOpcode
(
)
==
ARM
::
ITasm
)
return
false
;
Inst
.
setLoc
(
IDLoc
)
;
if
(
PendConditionalInstruction
)
{
PendingConditionalInsts
.
push_back
(
Inst
)
;
if
(
isITBlockFull
(
)
||
isITBlockTerminator
(
Inst
)
)
flushPendingInstructions
(
Out
)
;
}
else
{
Out
.
EmitInstruction
(
Inst
,
getSTI
(
)
)
;
}
return
false
;
case
Match_NearMisses
:
ReportNearMisses
(
NearMisses
,
IDLoc
,
Operands
)
;
return
true
;
case
Match_MnemonicFail
:
{
uint64_t
FBS
=
ComputeAvailableFeatures
(
getSTI
(
)
.
getFeatureBits
(
)
)
;
std
::
string
Suggestion
=
ARMMnemonicSpellCheck
(
(
(
ARMOperand
&
)
*
Operands
[
0
]
)
.
getToken
(
)
,
FBS
)
;
return
Error
(
IDLoc
,
"invalid instruction"
+
Suggestion
,
(
(
ARMOperand
&
)
*
Operands
[
0
]
)
.
getLocRange
(
)
)
;
}
}
llvm_unreachable
(
"Implement any new match types added!"
)
;
}
</s>

ARM
ARM
4
"Parsed as: "
"\n"
"Changed to: "
"\n"
"deprecated instruction in IT block"
ARM::ITasm
ARM
ARM
0
"invalid instruction"
ARM
0
"Implement any new match types added!"


<s> static ARMOperand * CreateMem ( unsigned BaseRegNum , bool OffsetIsReg , const MCExpr * Offset , unsigned OffsetRegNum , bool OffsetRegShifted , enum ShiftType ShiftType , const MCExpr * ShiftAmount , bool Preindexed , bool Postindexed , bool Negative , bool Writeback , SMLoc S , SMLoc E ) { ARMOperand * Op = new ARMOperand ( Memory ) ; Op -> Mem . BaseRegNum = BaseRegNum ; Op -> Mem . OffsetIsReg = OffsetIsReg ; Op -> Mem . Offset = Offset ; Op -> Mem . OffsetRegNum = OffsetRegNum ; Op -> Mem . OffsetRegShifted = OffsetRegShifted ; Op -> Mem . ShiftType = ShiftType ; Op -> Mem . ShiftAmount = ShiftAmount ; Op -> Mem . Preindexed = Preindexed ; Op -> Mem . Postindexed = Postindexed ; Op -> Mem . Negative = Negative ; Op -> Mem . Writeback = Writeback ; Op -> StartLoc = S ; Op -> EndLoc = E ; return Op ; } </s>


<s>
void
ARMOperand
::
dump
(
raw_ostream
&
OS
)
const
{
switch
(
Kind
)
{
case
CondCode
:
OS
<<
ARMCondCodeToString
(
getCondCode
(
)
)
;
break
;
case
CCOut
:
OS
<<
"<ccout "
<<
getReg
(
)
<<
">"
;
break
;
case
Immediate
:
getImm
(
)
->
print
(
OS
)
;
break
;
case
Memory
:
OS
<<
"<memory>"
;
break
;
case
Register
:
OS
<<
"<register "
<<
getReg
(
)
<<
">"
;
break
;
case
RegisterList
:
case
DPRRegisterList
:
case
SPRRegisterList
:
{
OS
<<
"<register_list "
;
const
SmallVectorImpl
<
unsigned
>
&
RegList
=
getRegList
(
)
;
for
(
SmallVectorImpl
<
unsigned
>
::
const_iterator
I
=
RegList
.
begin
(
)
,
E
=
RegList
.
end
(
)
;
I
!=
E
;
)
{
OS
<<
*
I
;
if
(
++
I
<
E
)
OS
<<
", "
;
}
OS
<<
">"
;
break
;
}
case
Token
:
OS
<<
"'"
<<
getToken
(
)
<<
"'"
;
break
;
}
}
</s>

ARM
ARM
ARM
"<ccout "
">"
"<memory>"
"<register "
">"
"<register_list "
", "
">"
"'"
"'"


<s>
bool
ARMAsmParser
::
ParseInstruction
(
StringRef
Name
,
SMLoc
NameLoc
,
SmallVectorImpl
<
MCParsedAsmOperand
*
>
&
Operands
)
{
size_t
Start
=
0
,
Next
=
Name
.
find
(
'.'
)
;
StringRef
Head
=
Name
.
slice
(
Start
,
Next
)
;
unsigned
CC
=
StringSwitch
<
unsigned
>
(
Head
.
substr
(
Head
.
size
(
)
2
)
)
.
Case
(
"eq"
,
ARMCC
::
EQ
)
.
Case
(
"ne"
,
ARMCC
::
NE
)
.
Case
(
"hs"
,
ARMCC
::
HS
)
.
Case
(
"lo"
,
ARMCC
::
LO
)
.
Case
(
"mi"
,
ARMCC
::
MI
)
.
Case
(
"pl"
,
ARMCC
::
PL
)
.
Case
(
"vs"
,
ARMCC
::
VS
)
.
Case
(
"vc"
,
ARMCC
::
VC
)
.
Case
(
"hi"
,
ARMCC
::
HI
)
.
Case
(
"ls"
,
ARMCC
::
LS
)
.
Case
(
"ge"
,
ARMCC
::
GE
)
.
Case
(
"lt"
,
ARMCC
::
LT
)
.
Case
(
"gt"
,
ARMCC
::
GT
)
.
Case
(
"le"
,
ARMCC
::
LE
)
.
Case
(
"al"
,
ARMCC
::
AL
)
.
Default
(
~
0U
)
;
if
(
CC
==
~
0U
||
(
CC
==
ARMCC
::
LS
&&
(
Head
==
"vmls"
||
Head
==
"vnmls"
)
)
)
{
CC
=
ARMCC
::
AL
;
}
else
{
Head
=
Head
.
slice
(
0
,
Head
.
size
(
)
2
)
;
}
Operands
.
push_back
(
ARMOperand
::
CreateToken
(
Head
,
NameLoc
)
)
;
if
(
Head
!=
"trap"
)
Operands
.
push_back
(
ARMOperand
::
CreateCondCode
(
ARMCC
::
CondCodes
(
CC
)
,
NameLoc
)
)
;
while
(
Next
!=
StringRef
::
npos
)
{
Start
=
Next
;
Next
=
Name
.
find
(
'.'
,
Start
+
1
)
;
Head
=
Name
.
slice
(
Start
,
Next
)
;
Operands
.
push_back
(
ARMOperand
::
CreateToken
(
Head
,
NameLoc
)
)
;
}
if
(
getLexer
(
)
.
isNot
(
AsmToken
::
EndOfStatement
)
)
{
if
(
ParseOperand
(
Operands
)
)
{
Parser
.
EatToEndOfStatement
(
)
;
return
true
;
}
while
(
getLexer
(
)
.
is
(
AsmToken
::
Comma
)
)
{
Parser
.
Lex
(
)
;
if
(
ParseOperand
(
Operands
)
)
{
Parser
.
EatToEndOfStatement
(
)
;
return
true
;
}
}
}
if
(
getLexer
(
)
.
isNot
(
AsmToken
::
EndOfStatement
)
)
{
Parser
.
EatToEndOfStatement
(
)
;
return
TokError
(
"unexpected token in argument list"
)
;
}
Parser
.
Lex
(
)
;
return
false
;
}
</s>

ARM
ARM
0
2
"eq"
ARMCC::EQ
"ne"
ARMCC::NE
"hs"
ARMCC::HS
"lo"
ARMCC::LO
"mi"
ARMCC::MI
"pl"
ARMCC::PL
"vs"
ARMCC::VS
"vc"
ARMCC::VC
"hi"
ARMCC::HI
"ls"
ARMCC::LS
"ge"
ARMCC::GE
"lt"
ARMCC::LT
"gt"
ARMCC::GT
"le"
ARMCC::LE
"al"
ARMCC::AL
0U
0U
ARMCC::LS
"vmls"
"vnmls"
ARMCC::AL
0
2
ARM
"trap"
ARM
ARMCC::CondCodes
1
ARM
"unexpected token in argument list"


"optionally flag setting instruction missing optional def operand"

checkTargetMatchPredicate - Validate the instruction match against any complex target predicates not expressible via match classes .


<s> void flushPendingInstructions ( MCStreamer & Out ) override { if ( ! inImplicitITBlock ( ) ) { assert ( PendingConditionalInsts . size ( ) == 0 ) ; return ; } unsigned Mask = getITMaskEncoding ( ) ; MCInst ITInst ; ITInst . setOpcode ( ARM :: t2IT ) ; ITInst . addOperand ( MCOperand :: createImm ( ITState . Cond ) ) ; ITInst . addOperand ( MCOperand :: createImm ( Mask ) ) ; Out . EmitInstruction ( ITInst , getSTI ( ) ) ; assert ( PendingConditionalInsts . size ( ) <= 4 ) ; for ( MCInst Inst : PendingConditionalInsts ) { Out . EmitInstruction ( Inst , getSTI ( ) ) ; } PendingConditionalInsts . clear ( ) ; ITState . Mask = 0 ; ITState . CurPosition = ~ 0U ; } </s>

Ensure that all previously parsed instructions have been emitted to the output streamer , if the target does not emit them immediately .


<s> static ARMOperand * CreateMem ( unsigned BaseRegNum , const MCConstantExpr * OffsetImm , unsigned OffsetRegNum , ARM_AM :: ShiftOpc ShiftType , unsigned ShiftImm , unsigned Alignment , bool isNegative , SMLoc S , SMLoc E , SMLoc AlignmentLoc = SMLoc ( ) ) { ARMOperand * Op = new ARMOperand ( k_Memory ) ; Op -> Memory . BaseRegNum = BaseRegNum ; Op -> Memory . OffsetImm = OffsetImm ; Op -> Memory . OffsetRegNum = OffsetRegNum ; Op -> Memory . ShiftType = ShiftType ; Op -> Memory . ShiftImm = ShiftImm ; Op -> Memory . Alignment = Alignment ; Op -> Memory . isNegative = isNegative ; Op -> StartLoc = S ; Op -> EndLoc = E ; Op -> AlignmentLoc = AlignmentLoc ; return Op ; } </s>


"expression value must be representable in 32 bits"

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


<s> static ARMOperand CreateMem ( unsigned BaseRegNum , bool OffsetIsReg , const MCExpr * Offset , unsigned OffsetRegNum , bool OffsetRegShifted , enum ShiftType ShiftType , const MCExpr * ShiftAmount , bool Preindexed , bool Postindexed , bool Negative , bool Writeback ) { ARMOperand Res ; Res . Kind = Memory ; Res . Mem . BaseRegNum = BaseRegNum ; Res . Mem . OffsetIsReg = OffsetIsReg ; Res . Mem . Offset = Offset ; Res . Mem . OffsetRegNum = OffsetRegNum ; Res . Mem . OffsetRegShifted = OffsetRegShifted ; Res . Mem . ShiftType = ShiftType ; Res . Mem . ShiftAmount = ShiftAmount ; Res . Mem . Preindexed = Preindexed ; Res . Mem . Postindexed = Postindexed ; Res . Mem . Negative = Negative ; Res . Mem . Writeback = Writeback ; return Res ; } </s>


<s> static ARMOperand CreateReg ( unsigned RegNum , bool Writeback ) { ARMOperand Res ; Res . Kind = Register ; Res . Reg . RegNum = RegNum ; Res . Reg . Writeback = Writeback ; return Res ; } </s>


<s> bool ARMAsmParser :: ParseInstruction ( const StringRef & Name , SMLoc NameLoc , SmallVectorImpl < MCParsedAsmOperand * > & Operands ) { Operands . push_back ( new ARMOperand ( ARMOperand :: CreateToken ( Name ) ) ) ; SMLoc Loc = Parser . getTok ( ) . getLoc ( ) ; if ( getLexer ( ) . isNot ( AsmToken :: EndOfStatement ) ) { ARMOperand Op ; if ( ParseOperand ( Op ) ) return true ; Operands . push_back ( new ARMOperand ( Op ) ) ; while ( getLexer ( ) . is ( AsmToken :: Comma ) ) { Parser . Lex ( ) ; if ( ParseOperand ( Op ) ) return true ; Operands . push_back ( new ARMOperand ( Op ) ) ; } } return false ; } </s>


"instruction requires a CPU feature not currently enabled"


"OffsetRegShifted must imply OffsetIsReg!"

"Offset must exists unless register offset is used!"

"Cannot have shift amount without shifted register offset!"

"Cannot have expression offset and register offset!"


<s>
void
ARMOperand
::
dump
(
raw_ostream
&
OS
)
const
{
switch
(
Kind
)
{
case
CondCode
:
OS
<<
"<ARMCC::"
<<
ARMCondCodeToString
(
getCondCode
(
)
)
<<
">"
;
break
;
case
CCOut
:
OS
<<
"<ccout "
<<
getReg
(
)
<<
">"
;
break
;
case
CoprocNum
:
OS
<<
"<coprocessor number: "
<<
getCoproc
(
)
<<
">"
;
break
;
case
CoprocReg
:
OS
<<
"<coprocessor register: "
<<
getCoproc
(
)
<<
">"
;
break
;
case
MSRMask
:
OS
<<
"<mask: "
<<
getMSRMask
(
)
<<
">"
;
break
;
case
Immediate
:
getImm
(
)
->
print
(
OS
)
;
break
;
case
MemBarrierOpt
:
OS
<<
"<ARM_MB::"
<<
MemBOptToString
(
getMemBarrierOpt
(
)
)
<<
">"
;
break
;
case
Memory
:
OS
<<
"<memory "
<<
"base:"
<<
getMemBaseRegNum
(
)
;
if
(
getMemOffsetIsReg
(
)
)
{
OS
<<
" offset:<register "
<<
getMemOffsetRegNum
(
)
;
if
(
getMemOffsetRegShifted
(
)
)
{
OS
<<
" offset-shift-type:"
<<
getMemShiftType
(
)
;
OS
<<
" offset-shift-amount:"
<<
*
getMemShiftAmount
(
)
;
}
}
else
{
OS
<<
" offset:"
<<
*
getMemOffset
(
)
;
}
if
(
getMemOffsetIsReg
(
)
)
OS
<<
" (offset-is-reg)"
;
if
(
getMemPreindexed
(
)
)
OS
<<
" (pre-indexed)"
;
if
(
getMemPostindexed
(
)
)
OS
<<
" (post-indexed)"
;
if
(
getMemNegative
(
)
)
OS
<<
" (negative)"
;
if
(
getMemWriteback
(
)
)
OS
<<
" (writeback)"
;
OS
<<
">"
;
break
;
case
ProcIFlags
:
{
OS
<<
"<ARM_PROC::"
;
unsigned
IFlags
=
getProcIFlags
(
)
;
for
(
int
i
=
2
;
i
>=
0
;
i
)
if
(
IFlags
&
(
1
<<
i
)
)
OS
<<
ARM_PROC
::
IFlagsToString
(
1
<<
i
)
;
OS
<<
">"
;
break
;
}
case
Register
:
OS
<<
"<register "
<<
getReg
(
)
<<
">"
;
break
;
case
RegisterList
:
case
DPRRegisterList
:
case
SPRRegisterList
:
{
OS
<<
"<register_list "
;
const
SmallVectorImpl
<
unsigned
>
&
RegList
=
getRegList
(
)
;
for
(
SmallVectorImpl
<
unsigned
>
::
const_iterator
I
=
RegList
.
begin
(
)
,
E
=
RegList
.
end
(
)
;
I
!=
E
;
)
{
OS
<<
*
I
;
if
(
++
I
<
E
)
OS
<<
", "
;
}
OS
<<
">"
;
break
;
}
case
Token
:
OS
<<
"'"
<<
getToken
(
)
<<
"'"
;
break
;
}
}
</s>

ARM
ARM
"<ARMCC::"
ARM
">"
"<ccout "
">"
"<coprocessor number: "
">"
"<coprocessor register: "
">"
"<mask: "
">"
"<ARM_MB::"
">"
"<memory "
"base:"
" offset:<register "
" offset-shift-type:"
" offset-shift-amount:"
" offset:"
" (offset-is-reg)"
" (pre-indexed)"
" (post-indexed)"
" (negative)"
" (writeback)"
">"
"<ARM_PROC::"
2
0
1
ARM_PROC::IFlagsToString
1
">"
"<register "
">"
"<register_list "
", "
">"
"'"
"'"


<s> bool Error ( SMLoc L , const Twine & Msg , ArrayRef < SMRange > Ranges = ArrayRef < SMRange > ( ) ) { return Parser . Error ( L , Msg , Ranges ) ; } </s>

Return an error at the location L , with the message Msg .


"flag setting instruction only valid outside IT block"

"instruction only valid inside IT block"

"instruction variant requires ARMv6 or later"

"immediate operand must be in the range [0,15]"


<s> bool ARMAsmParser :: ParseDirective ( AsmToken DirectiveID ) { StringRef IDVal = DirectiveID . getIdentifier ( ) ; if ( IDVal == ".word" ) return parseDirectiveWord ( 4 , DirectiveID . getLoc ( ) ) ; else if ( IDVal == ".thumb" ) return parseDirectiveThumb ( DirectiveID . getLoc ( ) ) ; else if ( IDVal == ".arm" ) return parseDirectiveARM ( DirectiveID . getLoc ( ) ) ; else if ( IDVal == ".thumb_func" ) return parseDirectiveThumbFunc ( DirectiveID . getLoc ( ) ) ; else if ( IDVal == ".code" ) return parseDirectiveCode ( DirectiveID . getLoc ( ) ) ; else if ( IDVal == ".syntax" ) return parseDirectiveSyntax ( DirectiveID . getLoc ( ) ) ; else if ( IDVal == ".unreq" ) return parseDirectiveUnreq ( DirectiveID . getLoc ( ) ) ; else if ( IDVal == ".arch" ) return parseDirectiveArch ( DirectiveID . getLoc ( ) ) ; else if ( IDVal == ".eabi_attribute" ) return parseDirectiveEabiAttr ( DirectiveID . getLoc ( ) ) ; return true ; } </s>

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


<s> bool Warning ( SMLoc L , const Twine & Msg , ArrayRef < SMRange > Ranges = ArrayRef < SMRange > ( ) ) { return Parser . Warning ( L , Msg , Ranges ) ; } </s>

Emit a warning at the location L , with the message Msg .


<s> void ARMAsmPrinter :: emitInlineAsmEnd ( const MCSubtargetInfo & StartInfo , const MCSubtargetInfo * EndInfo ) const { const bool WasThumb = isThumb ( StartInfo ) ; if ( ! EndInfo || WasThumb != isThumb ( * EndInfo ) ) { OutStreamer -> EmitAssemblerFlag ( WasThumb ? MCAF_Code16 : MCAF_Code32 ) ; } } </s>

Let the target do anything it needs to do after emitting inlineasm .


<s> static bool isThumb ( const MCSubtargetInfo & STI ) { return STI . getFeatureBits ( ) [ ARM :: ModeThumb ] ; } </s>

Tests whether the target is Thumb ( little and big endian ) .


<s>
bool
ARMAsmPrinter
::
PrintAsmMemoryOperand
(
const
MachineInstr
*
MI
,
unsigned
OpNum
,
unsigned
AsmVariant
,
const
char
*
ExtraCode
,
raw_ostream
&
O
)
{
if
(
ExtraCode
&&
ExtraCode
[
0
]
)
{
if
(
ExtraCode
[
1
]
!=
0
)
return
true
;
switch
(
ExtraCode
[
0
]
)
{
case
'A'
:
default
:
return
true
;
case
'm'
:
if
(
!
MI
->
getOperand
(
OpNum
)
.
isReg
(
)
)
return
true
;
O
<<
ARMInstPrinter
::
getRegisterName
(
MI
->
getOperand
(
OpNum
)
.
getReg
(
)
)
;
return
false
;
}
}
const
MachineOperand
&
MO
=
MI
->
getOperand
(
OpNum
)
;
assert
(
MO
.
isReg
(
)
&&
"unexpected inline asm memory operand"
)
;
O
<<
"["
<<
ARMInstPrinter
::
getRegisterName
(
MO
.
getReg
(
)
)
<<
"]"
;
return
false
;
}
</s>

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


<s> bool ARMAsmPrinter :: runOnMachineFunction ( MachineFunction & MF ) { AFI = MF . getInfo < ARMFunctionInfo > ( ) ; MCP = MF . getConstantPool ( ) ; Subtarget = & MF . getSubtarget < ARMSubtarget > ( ) ; SetupMachineFunction ( MF ) ; const Function * F = MF . getFunction ( ) ; const TargetMachine & TM = MF . getTarget ( ) ; for ( auto * GV : AFI -> getGlobalsPromotedToConstantPool ( ) ) PromotedGlobals . insert ( GV ) ; unsigned OptimizationGoal ; if ( F -> hasFnAttribute ( Attribute :: OptimizeNone ) ) OptimizationGoal = 6 ; else if ( F -> optForMinSize ( ) ) OptimizationGoal = 4 ; else if ( F -> optForSize ( ) ) OptimizationGoal = 3 ; else if ( TM . getOptLevel ( ) == CodeGenOpt :: Aggressive ) OptimizationGoal = 2 ; else if ( TM . getOptLevel ( ) > CodeGenOpt :: None ) OptimizationGoal = 1 ; else OptimizationGoal = 5 ; if ( OptimizationGoals == - 1 ) OptimizationGoals = OptimizationGoal ; else if ( OptimizationGoals != ( int ) OptimizationGoal ) OptimizationGoals = 0 ; if ( Subtarget -> isTargetCOFF ( ) ) { bool Internal = F -> hasInternalLinkage ( ) ; COFF :: SymbolStorageClass Scl = Internal ? COFF :: IMAGE_SYM_CLASS_STATIC : COFF :: IMAGE_SYM_CLASS_EXTERNAL ; int Type = COFF :: IMAGE_SYM_DTYPE_FUNCTION << COFF :: SCT_COMPLEX_TYPE_SHIFT ; OutStreamer -> BeginCOFFSymbolDef ( CurrentFnSym ) ; OutStreamer -> EmitCOFFSymbolStorageClass ( Scl ) ; OutStreamer -> EmitCOFFSymbolType ( Type ) ; OutStreamer -> EndCOFFSymbolDef ( ) ; } EmitFunctionBody ( ) ; emitXRayTable ( ) ; if ( ! ThumbIndirectPads . empty ( ) ) { OutStreamer -> EmitAssemblerFlag ( MCAF_Code16 ) ; EmitAlignment ( 1 ) ; for ( unsigned i = 0 , e = ThumbIndirectPads . size ( ) ; i < e ; i ++ ) { OutStreamer -> EmitLabel ( ThumbIndirectPads [ i ] . second ) ; EmitToStreamer ( * OutStreamer , MCInstBuilder ( ARM :: tBX ) . addReg ( ThumbIndirectPads [ i ] . first ) . addImm ( ARMCC :: AL ) . addReg ( 0 ) ) ; } ThumbIndirectPads . clear ( ) ; } return false ; } </s>

runOnMachineFunction - Emit the function body .


<s> void ARMAsmPrinter :: EmitInstruction ( const MachineInstr * MI ) { if ( EnableMCInst ) { printInstructionThroughMCStreamer ( MI ) ; } else { int Opc = MI -> getOpcode ( ) ; if ( Opc == ARM :: CONSTPOOL_ENTRY ) EmitAlignment ( 2 ) ; printInstruction ( MI ) ; OutStreamer . AddBlankLine ( ) ; } } </s>

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


<s> void getAnalysisUsage ( AnalysisUsage & AU ) const { AsmPrinter :: getAnalysisUsage ( AU ) ; AU . setPreservesAll ( ) ; AU . addRequired < MachineModuleInfo > ( ) ; AU . addRequired < DwarfWriter > ( ) ; } </s>

getAnalysisUsage - Subclasses that override getAnalysisUsage must call this .


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

getPassName - Return a nice clean name for a pass .


<s>
bool
ARMAsmPrinter
::
PrintAsmMemoryOperand
(
const
MachineInstr
*
MI
,
unsigned
OpNum
,
unsigned
AsmVariant
,
const
char
*
ExtraCode
)
{
if
(
ExtraCode
&&
ExtraCode
[
0
]
)
return
true
;
const
MachineOperand
&
MO
=
MI
->
getOperand
(
OpNum
)
;
assert
(
MO
.
isReg
(
)
&&
"unexpected inline asm memory operand"
)
;
O
<<
"["
<<
getRegisterName
(
MO
.
getReg
(
)
)
<<
"]"
;
return
false
;
}
</s>

ARM
ARM
0
"unexpected inline asm memory operand"
"["
"]"


<s> bool ARMAsmPrinter :: PrintAsmOperand ( const MachineInstr * MI , unsigned OpNum , unsigned AsmVariant , const char * ExtraCode ) { if ( ExtraCode && ExtraCode [ 0 ] ) { if ( ExtraCode [ 1 ] != 0 ) return true ; switch ( ExtraCode [ 0 ] ) { default : return true ; case 'a' : if ( MI -> getOperand ( OpNum ) . isReg ( ) ) { O << "[" << getRegisterName ( MI -> getOperand ( OpNum ) . getReg ( ) ) << "]" ; return false ; } case 'c' : if ( ! MI -> getOperand ( OpNum ) . isImm ( ) ) return true ; printNoHashImmediate ( MI , OpNum ) ; return false ; case 'P' : case 'q' : printOperand ( MI , OpNum ) ; return false ; case 'Q' : if ( TM . getTargetData ( ) -> isLittleEndian ( ) ) break ; case 'R' : if ( TM . getTargetData ( ) -> isBigEndian ( ) ) break ; case 'H' : if ( ! MI -> getOperand ( OpNum ) . isReg ( ) || OpNum + 1 == MI -> getNumOperands ( ) || ! MI -> getOperand ( OpNum + 1 ) . isReg ( ) ) return true ; ++ OpNum ; } } printOperand ( MI , OpNum ) ; return false ; } </s>

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


<s> bool ARMAsmPrinter :: runOnMachineFunction ( MachineFunction & MF ) { AFI = MF . getInfo < ARMFunctionInfo > ( ) ; MCP = MF . getConstantPool ( ) ; Subtarget = & MF . getSubtarget < ARMSubtarget > ( ) ; SetupMachineFunction ( MF ) ; const Function * F = MF . getFunction ( ) ; const TargetMachine & TM = MF . getTarget ( ) ; unsigned OptimizationGoal ; if ( F -> hasFnAttribute ( Attribute :: OptimizeNone ) ) OptimizationGoal = 6 ; else if ( F -> optForMinSize ( ) ) OptimizationGoal = 4 ; else if ( F -> optForSize ( ) ) OptimizationGoal = 3 ; else if ( TM . getOptLevel ( ) == CodeGenOpt :: Aggressive ) OptimizationGoal = 2 ; else if ( TM . getOptLevel ( ) > CodeGenOpt :: None ) OptimizationGoal = 1 ; else OptimizationGoal = 5 ; if ( OptimizationGoals == - 1 ) OptimizationGoals = OptimizationGoal ; else if ( OptimizationGoals != ( int ) OptimizationGoal ) OptimizationGoals = 0 ; if ( Subtarget -> isTargetCOFF ( ) ) { bool Internal = F -> hasInternalLinkage ( ) ; COFF :: SymbolStorageClass Scl = Internal ? COFF :: IMAGE_SYM_CLASS_STATIC : COFF :: IMAGE_SYM_CLASS_EXTERNAL ; int Type = COFF :: IMAGE_SYM_DTYPE_FUNCTION << COFF :: SCT_COMPLEX_TYPE_SHIFT ; OutStreamer -> BeginCOFFSymbolDef ( CurrentFnSym ) ; OutStreamer -> EmitCOFFSymbolStorageClass ( Scl ) ; OutStreamer -> EmitCOFFSymbolType ( Type ) ; OutStreamer -> EndCOFFSymbolDef ( ) ; } EmitFunctionBody ( ) ; if ( ! ThumbIndirectPads . empty ( ) ) { OutStreamer -> EmitAssemblerFlag ( MCAF_Code16 ) ; EmitAlignment ( 1 ) ; for ( unsigned i = 0 , e = ThumbIndirectPads . size ( ) ; i < e ; i ++ ) { OutStreamer -> EmitLabel ( ThumbIndirectPads [ i ] . second ) ; EmitToStreamer ( * OutStreamer , MCInstBuilder ( ARM :: tBX ) . addReg ( ThumbIndirectPads [ i ] . first ) . addImm ( ARMCC :: AL ) . addReg ( 0 ) ) ; } ThumbIndirectPads . clear ( ) ; } return false ; } </s>


<s> bool ARMAsmPrinter :: runOnMachineFunction ( MachineFunction & MF ) { AFI = MF . getInfo < ARMFunctionInfo > ( ) ; MCP = MF . getConstantPool ( ) ; Subtarget = & MF . getSubtarget < ARMSubtarget > ( ) ; SetupMachineFunction ( MF ) ; const Function & F = MF . getFunction ( ) ; const TargetMachine & TM = MF . getTarget ( ) ; for ( auto * GV : AFI -> getGlobalsPromotedToConstantPool ( ) ) PromotedGlobals . insert ( GV ) ; unsigned OptimizationGoal ; if ( F . hasFnAttribute ( Attribute :: OptimizeNone ) ) OptimizationGoal = 6 ; else if ( F . optForMinSize ( ) ) OptimizationGoal = 4 ; else if ( F . optForSize ( ) ) OptimizationGoal = 3 ; else if ( TM . getOptLevel ( ) == CodeGenOpt :: Aggressive ) OptimizationGoal = 2 ; else if ( TM . getOptLevel ( ) > CodeGenOpt :: None ) OptimizationGoal = 1 ; else OptimizationGoal = 5 ; if ( OptimizationGoals == - 1 ) OptimizationGoals = OptimizationGoal ; else if ( OptimizationGoals != ( int ) OptimizationGoal ) OptimizationGoals = 0 ; if ( Subtarget -> isTargetCOFF ( ) ) { bool Internal = F . hasInternalLinkage ( ) ; COFF :: SymbolStorageClass Scl = Internal ? COFF :: IMAGE_SYM_CLASS_STATIC : COFF :: IMAGE_SYM_CLASS_EXTERNAL ; int Type = COFF :: IMAGE_SYM_DTYPE_FUNCTION << COFF :: SCT_COMPLEX_TYPE_SHIFT ; OutStreamer -> BeginCOFFSymbolDef ( CurrentFnSym ) ; OutStreamer -> EmitCOFFSymbolStorageClass ( Scl ) ; OutStreamer -> EmitCOFFSymbolType ( Type ) ; OutStreamer -> EndCOFFSymbolDef ( ) ; } EmitFunctionBody ( ) ; emitXRayTable ( ) ; if ( ! ThumbIndirectPads . empty ( ) ) { OutStreamer -> EmitAssemblerFlag ( MCAF_Code16 ) ; EmitAlignment ( 1 ) ; for ( std :: pair < unsigned , MCSymbol * > & TIP : ThumbIndirectPads ) { OutStreamer -> EmitLabel ( TIP . second ) ; EmitToStreamer ( * OutStreamer , MCInstBuilder ( ARM :: tBX ) . addReg ( TIP . first ) . addImm ( ARMCC :: AL ) . addReg ( 0 ) ) ; } ThumbIndirectPads . clear ( ) ; } return false ; } </s>


<s> bool ARMAsmPrinter :: runOnMachineFunction ( MachineFunction & MF ) { AFI = MF . getInfo < ARMFunctionInfo > ( ) ; MCP = MF . getConstantPool ( ) ; if ( Subtarget -> isTargetNaCl ( ) ) { NaClAlignAllJumpTargetsAndConstantPools ( MF ) ; } SetupMachineFunction ( MF ) ; if ( Subtarget -> isTargetCOFF ( ) ) { bool Internal = MF . getFunction ( ) -> hasInternalLinkage ( ) ; COFF :: SymbolStorageClass Scl = Internal ? COFF :: IMAGE_SYM_CLASS_STATIC : COFF :: IMAGE_SYM_CLASS_EXTERNAL ; int Type = COFF :: IMAGE_SYM_DTYPE_FUNCTION << COFF :: SCT_COMPLEX_TYPE_SHIFT ; OutStreamer . BeginCOFFSymbolDef ( CurrentFnSym ) ; OutStreamer . EmitCOFFSymbolStorageClass ( Scl ) ; OutStreamer . EmitCOFFSymbolType ( Type ) ; OutStreamer . EndCOFFSymbolDef ( ) ; } EmitFunctionHeader ( ) ; EmitFunctionBody ( ) ; return false ; } </s>


<s> bool ARMAsmPrinter :: runOnMachineFunction ( MachineFunction & MF ) { AFI = MF . getInfo < ARMFunctionInfo > ( ) ; MCP = MF . getConstantPool ( ) ; Subtarget = & MF . getSubtarget < ARMSubtarget > ( ) ; SetupMachineFunction ( MF ) ; const Function & F = MF . getFunction ( ) ; const TargetMachine & TM = MF . getTarget ( ) ; for ( auto * GV : AFI -> getGlobalsPromotedToConstantPool ( ) ) PromotedGlobals . insert ( GV ) ; unsigned OptimizationGoal ; if ( F . hasOptNone ( ) ) OptimizationGoal = 6 ; else if ( F . hasMinSize ( ) ) OptimizationGoal = 4 ; else if ( F . hasOptSize ( ) ) OptimizationGoal = 3 ; else if ( TM . getOptLevel ( ) == CodeGenOpt :: Aggressive ) OptimizationGoal = 2 ; else if ( TM . getOptLevel ( ) > CodeGenOpt :: None ) OptimizationGoal = 1 ; else OptimizationGoal = 5 ; if ( OptimizationGoals == - 1 ) OptimizationGoals = OptimizationGoal ; else if ( OptimizationGoals != ( int ) OptimizationGoal ) OptimizationGoals = 0 ; if ( Subtarget -> isTargetCOFF ( ) ) { bool Internal = F . hasInternalLinkage ( ) ; COFF :: SymbolStorageClass Scl = Internal ? COFF :: IMAGE_SYM_CLASS_STATIC : COFF :: IMAGE_SYM_CLASS_EXTERNAL ; int Type = COFF :: IMAGE_SYM_DTYPE_FUNCTION << COFF :: SCT_COMPLEX_TYPE_SHIFT ; OutStreamer -> BeginCOFFSymbolDef ( CurrentFnSym ) ; OutStreamer -> EmitCOFFSymbolStorageClass ( Scl ) ; OutStreamer -> EmitCOFFSymbolType ( Type ) ; OutStreamer -> EndCOFFSymbolDef ( ) ; } EmitFunctionBody ( ) ; emitXRayTable ( ) ; if ( ! ThumbIndirectPads . empty ( ) ) { OutStreamer -> EmitAssemblerFlag ( MCAF_Code16 ) ; EmitAlignment ( 1 ) ; for ( std :: pair < unsigned , MCSymbol * > & TIP : ThumbIndirectPads ) { OutStreamer -> EmitLabel ( TIP . second ) ; EmitToStreamer ( * OutStreamer , MCInstBuilder ( ARM :: tBX ) . addReg ( TIP . first ) . addImm ( ARMCC :: AL ) . addReg ( 0 ) ) ; } ThumbIndirectPads . clear ( ) ; } return false ; } </s>


<s>
void
Finish
(
)
{
const
size_t
VendorHeaderSize
=
4
+
CurrentVendor
.
size
(
)
+
1
;
const
size_t
TagHeaderSize
=
1
+
4
;
Streamer
.
EmitIntValue
(
VendorHeaderSize
+
TagHeaderSize
+
ContentsSize
,
4
)
;
Streamer
.
EmitBytes
(
CurrentVendor
)
;
Streamer
.
EmitIntValue
(
0
,
1
)
;
Streamer
.
EmitIntValue
(
ARMBuildAttrs
::
File
,
1
)
;
Streamer
.
EmitIntValue
(
TagHeaderSize
+
ContentsSize
,
4
)
;
for
(
unsigned
int
i
=
0
;
i
<
Contents
.
size
(
)
;
++
i
)
{
AttributeItemType
item
=
Contents
[
i
]
;
Streamer
.
EmitULEB128IntValue
(
item
.
Tag
)
;
switch
(
item
.
Type
)
{
default
:
llvm_unreachable
(
"Invalid attribute type"
)
;
case
AttributeItemType
::
NumericAttribute
:
Streamer
.
EmitULEB128IntValue
(
item
.
IntValue
)
;
break
;
case
AttributeItemType
::
TextAttribute
:
Streamer
.
EmitBytes
(
item
.
StringValue
.
upper
(
)
)
;
Streamer
.
EmitIntValue
(
0
,
1
)
;
break
;
}
}
Contents
.
clear
(
)
;
}
</s>

Finish - Do final processing and write the object to the output stream .


<s>
void
Finish
(
)
{
const
size_t
VendorHeaderSize
=
4
+
CurrentVendor
.
size
(
)
+
1
;
const
size_t
TagHeaderSize
=
1
+
4
;
Streamer
.
EmitIntValue
(
VendorHeaderSize
+
TagHeaderSize
+
ContentsSize
,
4
)
;
Streamer
.
EmitBytes
(
CurrentVendor
,
0
)
;
Streamer
.
EmitIntValue
(
0
,
1
)
;
Streamer
.
EmitIntValue
(
ARMBuildAttrs
::
File
,
1
)
;
Streamer
.
EmitIntValue
(
TagHeaderSize
+
ContentsSize
,
4
)
;
for
(
unsigned
int
i
=
0
;
i
<
Contents
.
size
(
)
;
++
i
)
{
AttributeItemType
item
=
Contents
[
i
]
;
Streamer
.
EmitULEB128IntValue
(
item
.
Tag
,
0
)
;
switch
(
item
.
Type
)
{
default
:
llvm_unreachable
(
"Invalid attribute type"
)
;
case
AttributeItemType
::
NumericAttribute
:
Streamer
.
EmitULEB128IntValue
(
item
.
IntValue
,
0
)
;
break
;
case
AttributeItemType
::
TextAttribute
:
Streamer
.
EmitBytes
(
item
.
StringValue
.
upper
(
)
,
0
)
;
Streamer
.
EmitIntValue
(
0
,
1
)
;
break
;
}
}
Contents
.
clear
(
)
;
}
</s>


<s> bool ARMAsmPrinter :: runOnMachineFunction ( MachineFunction & MF ) { AFI = MF . getInfo < ARMFunctionInfo > ( ) ; MCP = MF . getConstantPool ( ) ; return AsmPrinter :: runOnMachineFunction ( MF ) ; } </s>


<s> bool ARMAsmPrinter :: runOnMachineFunction ( MachineFunction & MF ) { AFI = MF . getInfo < ARMFunctionInfo > ( ) ; MCP = MF . getConstantPool ( ) ; Subtarget = & MF . getSubtarget < ARMSubtarget > ( ) ; SetupMachineFunction ( MF ) ; const Function & F = MF . getFunction ( ) ; const TargetMachine & TM = MF . getTarget ( ) ; for ( auto * GV : AFI -> getGlobalsPromotedToConstantPool ( ) ) PromotedGlobals . insert ( GV ) ; unsigned OptimizationGoal ; if ( F . hasOptNone ( ) ) OptimizationGoal = 6 ; else if ( F . hasMinSize ( ) ) OptimizationGoal = 4 ; else if ( F . hasOptSize ( ) ) OptimizationGoal = 3 ; else if ( TM . getOptLevel ( ) == CodeGenOpt :: Aggressive ) OptimizationGoal = 2 ; else if ( TM . getOptLevel ( ) > CodeGenOpt :: None ) OptimizationGoal = 1 ; else OptimizationGoal = 5 ; if ( OptimizationGoals == - 1 ) OptimizationGoals = OptimizationGoal ; else if ( OptimizationGoals != ( int ) OptimizationGoal ) OptimizationGoals = 0 ; if ( Subtarget -> isTargetCOFF ( ) ) { bool Internal = F . hasInternalLinkage ( ) ; COFF :: SymbolStorageClass Scl = Internal ? COFF :: IMAGE_SYM_CLASS_STATIC : COFF :: IMAGE_SYM_CLASS_EXTERNAL ; int Type = COFF :: IMAGE_SYM_DTYPE_FUNCTION << COFF :: SCT_COMPLEX_TYPE_SHIFT ; OutStreamer -> BeginCOFFSymbolDef ( CurrentFnSym ) ; OutStreamer -> EmitCOFFSymbolStorageClass ( Scl ) ; OutStreamer -> EmitCOFFSymbolType ( Type ) ; OutStreamer -> EndCOFFSymbolDef ( ) ; } EmitFunctionBody ( ) ; emitXRayTable ( ) ; if ( ! ThumbIndirectPads . empty ( ) ) { OutStreamer -> EmitAssemblerFlag ( MCAF_Code16 ) ; EmitAlignment ( Align ( 2 ) ) ; for ( std :: pair < unsigned , MCSymbol * > & TIP : ThumbIndirectPads ) { OutStreamer -> EmitLabel ( TIP . second ) ; EmitToStreamer ( * OutStreamer , MCInstBuilder ( ARM :: tBX ) . addReg ( TIP . first ) . addImm ( ARMCC :: AL ) . addReg ( 0 ) ) ; } ThumbIndirectPads . clear ( ) ; } return false ; } </s>


<s> void ARMAsmPrinter :: EmitInstruction ( const MachineInstr * MI ) { if ( EnableMCInst ) { printInstructionThroughMCStreamer ( MI ) ; return ; } if ( MI -> getOpcode ( ) == ARM :: CONSTPOOL_ENTRY ) EmitAlignment ( 2 ) ; SmallString < 128 > Str ; raw_svector_ostream OS ( Str ) ; printInstruction ( MI , OS ) ; OutStreamer . EmitRawText ( OS . str ( ) ) ; if ( MI -> getOpcode ( ) == ARM :: t2TBB ) EmitAlignment ( 1 ) ; } </s>


<s>
bool
ARMAsmPrinter
::
PrintAsmMemoryOperand
(
const
MachineInstr
*
MI
,
unsigned
OpNum
,
unsigned
AsmVariant
,
const
char
*
ExtraCode
,
raw_ostream
&
O
)
{
if
(
ExtraCode
&&
ExtraCode
[
0
]
)
return
true
;
const
MachineOperand
&
MO
=
MI
->
getOperand
(
OpNum
)
;
assert
(
MO
.
isReg
(
)
&&
"unexpected inline asm memory operand"
)
;
O
<<
"["
<<
getRegisterName
(
MO
.
getReg
(
)
)
<<
"]"
;
return
false
;
}
</s>


<s> bool ARMAsmPrinter :: PrintAsmOperand ( const MachineInstr * MI , unsigned OpNum , unsigned AsmVariant , const char * ExtraCode , raw_ostream & O ) { if ( ExtraCode && ExtraCode [ 0 ] ) { if ( ExtraCode [ 1 ] != 0 ) return true ; switch ( ExtraCode [ 0 ] ) { default : return true ; case 'a' : if ( MI -> getOperand ( OpNum ) . isReg ( ) ) { O << "[" << getRegisterName ( MI -> getOperand ( OpNum ) . getReg ( ) ) << "]" ; return false ; } case 'c' : if ( ! MI -> getOperand ( OpNum ) . isImm ( ) ) return true ; printNoHashImmediate ( MI , OpNum , O ) ; return false ; case 'P' : case 'q' : printOperand ( MI , OpNum , O ) ; return false ; case 'Q' : if ( TM . getTargetData ( ) -> isLittleEndian ( ) ) break ; case 'R' : if ( TM . getTargetData ( ) -> isBigEndian ( ) ) break ; case 'H' : if ( ! MI -> getOperand ( OpNum ) . isReg ( ) || OpNum + 1 == MI -> getNumOperands ( ) || ! MI -> getOperand ( OpNum + 1 ) . isReg ( ) ) return true ; ++ OpNum ; } } printOperand ( MI , OpNum , O ) ; return false ; } </s>


<s> virtual unsigned getISAEncoding ( ) { if ( ! Subtarget -> isTargetDarwin ( ) ) return 0 ; return Subtarget -> isThumb ( ) ? ARM :: DW_ISA_ARM_thumb : ARM :: DW_ISA_ARM_arm ; } </s>

Get the value for DW_AT_APPLE_isa . Zero if no isa encoding specified .


<s>
void
Finish
(
)
{
const
size_t
VendorHeaderSize
=
4
+
CurrentVendor
.
size
(
)
+
1
;
const
size_t
TagHeaderSize
=
1
+
4
;
Streamer
.
EmitIntValue
(
VendorHeaderSize
+
TagHeaderSize
+
ContentsSize
,
4
)
;
Streamer
.
EmitBytes
(
CurrentVendor
,
0
)
;
Streamer
.
EmitIntValue
(
0
,
1
)
;
Streamer
.
EmitIntValue
(
ARMBuildAttrs
::
File
,
1
)
;
Streamer
.
EmitIntValue
(
TagHeaderSize
+
ContentsSize
,
4
)
;
for
(
unsigned
int
i
=
0
;
i
<
Contents
.
size
(
)
;
++
i
)
{
AttributeItemType
item
=
Contents
[
i
]
;
Streamer
.
EmitULEB128IntValue
(
item
.
Tag
,
0
)
;
switch
(
item
.
Type
)
{
case
AttributeItemType
::
NumericAttribute
:
Streamer
.
EmitULEB128IntValue
(
item
.
IntValue
,
0
)
;
break
;
case
AttributeItemType
::
TextAttribute
:
Streamer
.
EmitBytes
(
item
.
StringValue
.
upper
(
)
,
0
)
;
Streamer
.
EmitIntValue
(
0
,
1
)
;
break
;
default
:
assert
(
0
&&
"Invalid attribute type"
)
;
}
}
Contents
.
clear
(
)
;
}
</s>


<s> virtual unsigned getISAEncoding ( ) { if ( ! Subtarget -> isTargetDarwin ( ) ) return 0 ; return Subtarget -> isThumb ( ) ? llvm :: ARM :: DW_ISA_ARM_thumb : llvm :: ARM :: DW_ISA_ARM_arm ; } </s>


<s> virtual unsigned getISAEncoding ( ) LLVM_OVERRIDE { if ( ! Subtarget -> isTargetDarwin ( ) ) return 0 ; return Subtarget -> isThumb ( ) ? ARM :: DW_ISA_ARM_thumb : ARM :: DW_ISA_ARM_arm ; } </s>


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


<s> void emitConstantPool ( ) override { } </s>

Print to the current output stream assembly representations of the constants in the constant pool MCP .


<s> bool ARMAsmPrinter :: runOnMachineFunction ( MachineFunction & MF ) { AFI = MF . getInfo < ARMFunctionInfo > ( ) ; MCP = MF . getConstantPool ( ) ; Subtarget = & MF . getSubtarget < ARMSubtarget > ( ) ; SetupMachineFunction ( MF ) ; if ( Subtarget -> isTargetCOFF ( ) ) { bool Internal = MF . getFunction ( ) -> hasInternalLinkage ( ) ; COFF :: SymbolStorageClass Scl = Internal ? COFF :: IMAGE_SYM_CLASS_STATIC : COFF :: IMAGE_SYM_CLASS_EXTERNAL ; int Type = COFF :: IMAGE_SYM_DTYPE_FUNCTION << COFF :: SCT_COMPLEX_TYPE_SHIFT ; OutStreamer -> BeginCOFFSymbolDef ( CurrentFnSym ) ; OutStreamer -> EmitCOFFSymbolStorageClass ( Scl ) ; OutStreamer -> EmitCOFFSymbolType ( Type ) ; OutStreamer -> EndCOFFSymbolDef ( ) ; } EmitFunctionBody ( ) ; if ( ! ThumbIndirectPads . empty ( ) ) { OutStreamer -> EmitAssemblerFlag ( MCAF_Code16 ) ; EmitAlignment ( 1 ) ; for ( unsigned i = 0 , e = ThumbIndirectPads . size ( ) ; i < e ; i ++ ) { OutStreamer -> EmitLabel ( ThumbIndirectPads [ i ] . second ) ; EmitToStreamer ( * OutStreamer , MCInstBuilder ( ARM :: tBX ) . addReg ( ThumbIndirectPads [ i ] . first ) . addImm ( ARMCC :: AL ) . addReg ( 0 ) ) ; } ThumbIndirectPads . clear ( ) ; } return false ; } </s>

ARM ARM ARM ARM 1 0 ARM::tBX ARMCC::AL 0


<s> void ARMAsmPrinter :: emitInlineAsmEnd ( const MCSubtargetInfo & StartInfo , const MCSubtargetInfo * EndInfo ) const { const bool WasThumb = isThumb ( StartInfo ) ; if ( ! EndInfo || WasThumb != isThumb ( * EndInfo ) ) { OutStreamer . EmitAssemblerFlag ( WasThumb ? MCAF_Code16 : MCAF_Code32 ) ; } } </s>


<s>
const
char
*
getPassName
(
)
const
override
{
return
"ARM Assembly / Object Emitter"
;
}
</s>


<s> static bool isThumb ( const MCSubtargetInfo & STI ) { return ( STI . getFeatureBits ( ) & ARM :: ModeThumb ) != 0 ; } </s>


<s> bool ARMAsmPrinter :: runOnMachineFunction ( MachineFunction & MF ) { AFI = MF . getInfo < ARMFunctionInfo > ( ) ; MCP = MF . getConstantPool ( ) ; SetupMachineFunction ( MF ) ; if ( Subtarget -> isTargetCOFF ( ) ) { bool Internal = MF . getFunction ( ) -> hasInternalLinkage ( ) ; COFF :: SymbolStorageClass Scl = Internal ? COFF :: IMAGE_SYM_CLASS_STATIC : COFF :: IMAGE_SYM_CLASS_EXTERNAL ; int Type = COFF :: IMAGE_SYM_DTYPE_FUNCTION << COFF :: SCT_COMPLEX_TYPE_SHIFT ; OutStreamer . BeginCOFFSymbolDef ( CurrentFnSym ) ; OutStreamer . EmitCOFFSymbolStorageClass ( Scl ) ; OutStreamer . EmitCOFFSymbolType ( Type ) ; OutStreamer . EndCOFFSymbolDef ( ) ; } EmitFunctionHeader ( ) ; EmitFunctionBody ( ) ; return false ; } </s>


<s>
bool
ARMAsmPrinter
::
doFinalization
(
Module
&
M
)
{
if
(
Subtarget
->
isTargetDarwin
(
)
)
{
TargetLoweringObjectFileMachO
&
TLOFMacho
=
static_cast
<
TargetLoweringObjectFileMachO
&
>
(
getObjFileLowering
(
)
)
;
O
<<
'\n'
;
if
(
!
GVNonLazyPtrs
.
empty
(
)
)
{
OutStreamer
.
SwitchSection
(
TLOFMacho
.
getNonLazySymbolPointerSection
(
)
)
;
EmitAlignment
(
2
)
;
for
(
StringMap
<
std
::
string
>
::
iterator
I
=
GVNonLazyPtrs
.
begin
(
)
,
E
=
GVNonLazyPtrs
.
end
(
)
;
I
!=
E
;
++
I
)
{
O
<<
I
->
second
<<
":\n"
;
O
<<
"\t.indirect_symbol "
<<
I
->
getKeyData
(
)
<<
"\n"
;
O
<<
"\t.long\t0\n"
;
}
}
if
(
!
HiddenGVNonLazyPtrs
.
empty
(
)
)
{
OutStreamer
.
SwitchSection
(
getObjFileLowering
(
)
.
getDataSection
(
)
)
;
EmitAlignment
(
2
)
;
for
(
StringMap
<
std
::
string
>
::
iterator
I
=
HiddenGVNonLazyPtrs
.
begin
(
)
,
E
=
HiddenGVNonLazyPtrs
.
end
(
)
;
I
!=
E
;
++
I
)
{
O
<<
I
->
second
<<
":\n"
;
O
<<
"\t.long "
<<
I
->
getKeyData
(
)
<<
"\n"
;
}
}
O
<<
"\t.subsections_via_symbols\n"
;
}
return
AsmPrinter
::
doFinalization
(
M
)
;
}
</s>

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

ARM
ARM
2
":\n"
"\t.indirect_symbol "
"\n"
"\t.long\t0\n"
2
":\n"
"\t.long "
"\n"
"\t.subsections_via_symbols\n"


<s>
bool
ARMAsmPrinter
::
doInitialization
(
Module
&
M
)
{
bool
Result
=
AsmPrinter
::
doInitialization
(
M
)
;
DW
=
getAnalysisIfAvailable
<
DwarfWriter
>
(
)
;
if
(
Subtarget
->
isThumb
(
)
)
O
<<
"\t.syntax unified\n"
;
if
(
Subtarget
->
isTargetELF
(
)
)
{
std
::
string
CPUString
=
Subtarget
->
getCPUString
(
)
;
if
(
CPUString
!=
"generic"
)
O
<<
"\t.cpu "
<<
CPUString
<<
'\n'
;
if
(
Subtarget
->
hasVFP2
(
)
)
O
<<
"\t.eabi_attribute "
<<
ARMBuildAttrs
::
VFP_arch
<<
", 2\n"
;
if
(
!
UnsafeFPMath
)
O
<<
"\t.eabi_attribute "
<<
ARMBuildAttrs
::
ABI_FP_denormal
<<
", 1\n"
<<
"\t.eabi_attribute "
<<
ARMBuildAttrs
::
ABI_FP_exceptions
<<
", 1\n"
;
if
(
FiniteOnlyFPMath
(
)
)
O
<<
"\t.eabi_attribute "
<<
ARMBuildAttrs
::
ABI_FP_number_model
<<
", 1\n"
;
else
O
<<
"\t.eabi_attribute "
<<
ARMBuildAttrs
::
ABI_FP_number_model
<<
", 3\n"
;
O
<<
"\t.eabi_attribute "
<<
ARMBuildAttrs
::
ABI_align8_needed
<<
", 1\n"
<<
"\t.eabi_attribute "
<<
ARMBuildAttrs
::
ABI_align8_preserved
<<
", 1\n"
;
if
(
Subtarget
->
isAAPCS_ABI
(
)
&&
FloatABIType
==
FloatABI
::
Hard
)
O
<<
"\t.eabi_attribute "
<<
ARMBuildAttrs
::
ABI_HardFP_use
<<
", 3\n"
<<
"\t.eabi_attribute "
<<
ARMBuildAttrs
::
ABI_VFP_args
<<
", 1\n"
;
}
return
Result
;
}
</s>

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

ARM
ARM
"\t.syntax unified\n"
"generic"
"\t.cpu "
"\t.eabi_attribute "
ARMBuildAttrs::VFP_arch
", 2\n"
"\t.eabi_attribute "
ARMBuildAttrs::ABI_FP_denormal
", 1\n"
"\t.eabi_attribute "
ARMBuildAttrs::ABI_FP_exceptions
", 1\n"
"\t.eabi_attribute "
ARMBuildAttrs::ABI_FP_number_model
", 1\n"
"\t.eabi_attribute "
ARMBuildAttrs::ABI_FP_number_model
", 3\n"
"\t.eabi_attribute "
ARMBuildAttrs::ABI_align8_needed
", 1\n"
"\t.eabi_attribute "
ARMBuildAttrs::ABI_align8_preserved
", 1\n"
"\t.eabi_attribute "
ARMBuildAttrs::ABI_HardFP_use
", 3\n"
"\t.eabi_attribute "
ARMBuildAttrs::ABI_VFP_args
", 1\n"


<s> bool ARMAsmPrinter :: PrintAsmMemoryOperand ( const MachineInstr * MI , unsigned OpNum , unsigned AsmVariant , const char * ExtraCode ) { if ( ExtraCode && ExtraCode [ 0 ] ) return true ; printAddrMode2Operand ( MI , OpNum ) ; return false ; } </s>


<s> bool ARMAsmPrinter :: PrintAsmOperand ( const MachineInstr * MI , unsigned OpNum , unsigned AsmVariant , const char * ExtraCode ) { if ( ExtraCode && ExtraCode [ 0 ] ) { if ( ExtraCode [ 1 ] != 0 ) return true ; switch ( ExtraCode [ 0 ] ) { default : return true ; case 'a' : if ( MI -> getOperand ( OpNum ) . isReg ( ) ) { O << "[" << TRI -> getAsmName ( MI -> getOperand ( OpNum ) . getReg ( ) ) << "]" ; return false ; } case 'c' : if ( ! MI -> getOperand ( OpNum ) . isImm ( ) ) return true ; printNoHashImmediate ( MI , OpNum ) ; return false ; case 'P' : printOperand ( MI , OpNum ) ; return false ; case 'Q' : if ( TM . getTargetData ( ) -> isLittleEndian ( ) ) break ; case 'R' : if ( TM . getTargetData ( ) -> isBigEndian ( ) ) break ; case 'H' : if ( ! MI -> getOperand ( OpNum ) . isReg ( ) || OpNum + 1 == MI -> getNumOperands ( ) || ! MI -> getOperand ( OpNum + 1 ) . isReg ( ) ) return true ; ++ OpNum ; } } printOperand ( MI , OpNum ) ; return false ; } </s>


<s>
bool
ARMAsmPrinter
::
runOnMachineFunction
(
MachineFunction
&
MF
)
{
this
->
MF
=
&
MF
;
AFI
=
MF
.
getInfo
<
ARMFunctionInfo
>
(
)
;
MCP
=
MF
.
getConstantPool
(
)
;
SetupMachineFunction
(
MF
)
;
O
<<
"\n"
;
O
<<
'\n'
;
const
Function
*
F
=
MF
.
getFunction
(
)
;
OutStreamer
.
SwitchSection
(
getObjFileLowering
(
)
.
SectionForGlobal
(
F
,
Mang
,
TM
)
)
;
switch
(
F
->
getLinkage
(
)
)
{
default
:
llvm_unreachable
(
"Unknown linkage type!"
)
;
case
Function
::
PrivateLinkage
:
case
Function
::
LinkerPrivateLinkage
:
case
Function
::
InternalLinkage
:
break
;
case
Function
::
ExternalLinkage
:
O
<<
"\t.globl\t"
<<
CurrentFnName
<<
"\n"
;
break
;
case
Function
::
WeakAnyLinkage
:
case
Function
::
WeakODRLinkage
:
case
Function
::
LinkOnceAnyLinkage
:
case
Function
::
LinkOnceODRLinkage
:
if
(
Subtarget
->
isTargetDarwin
(
)
)
{
O
<<
"\t.globl\t"
<<
CurrentFnName
<<
"\n"
;
O
<<
"\t.weak_definition\t"
<<
CurrentFnName
<<
"\n"
;
}
else
{
O
<<
TAI
->
getWeakRefDirective
(
)
<<
CurrentFnName
<<
"\n"
;
}
break
;
}
printVisibility
(
CurrentFnName
,
F
->
getVisibility
(
)
)
;
if
(
AFI
->
isThumbFunction
(
)
)
{
EmitAlignment
(
MF
.
getAlignment
(
)
,
F
,
AFI
->
getAlign
(
)
)
;
O
<<
"\t.code\t16\n"
;
O
<<
"\t.thumb_func"
;
if
(
Subtarget
->
isTargetDarwin
(
)
)
O
<<
"\t"
<<
CurrentFnName
;
O
<<
"\n"
;
InCPMode
=
false
;
}
else
{
EmitAlignment
(
MF
.
getAlignment
(
)
,
F
)
;
}
O
<<
CurrentFnName
<<
":\n"
;
DW
->
BeginFunction
(
&
MF
)
;
if
(
Subtarget
->
isTargetDarwin
(
)
)
{
MachineFunction
::
iterator
I
=
MF
.
begin
(
)
;
if
(
++
I
==
MF
.
end
(
)
&&
MF
.
front
(
)
.
empty
(
)
)
O
<<
"\tnop\n"
;
}
for
(
MachineFunction
::
const_iterator
I
=
MF
.
begin
(
)
,
E
=
MF
.
end
(
)
;
I
!=
E
;
++
I
)
{
if
(
I
!=
MF
.
begin
(
)
)
{
printBasicBlockLabel
(
I
,
true
,
true
,
VerboseAsm
)
;
O
<<
'\n'
;
}
for
(
MachineBasicBlock
::
const_iterator
II
=
I
->
begin
(
)
,
E
=
I
->
end
(
)
;
II
!=
E
;
++
II
)
{
printMachineInstruction
(
II
)
;
}
}
if
(
TAI
->
hasDotTypeDotSizeDirective
(
)
)
O
<<
"\t.size "
<<
CurrentFnName
<<
", .-"
<<
CurrentFnName
<<
"\n"
;
DW
->
EndFunction
(
&
MF
)
;
return
false
;
}
</s>

ARM
ARM
ARM
"\n"
"Unknown linkage type!"
"\t.globl\t"
"\n"
"\t.globl\t"
"\n"
"\t.weak_definition\t"
"\n"
"\n"
"\t.code\t16\n"
"\t.thumb_func"
"\t"
"\n"
":\n"
"\tnop\n"
"\t.size "
", .-"
"\n"


<s>
virtual
const
char
*
getPassName
(
)
const
LLVM_OVERRIDE
{
return
"ARM Assembly / Object Emitter"
;
}
</s>


<s> bool ARMAsmPrinter :: runOnMachineFunction ( MachineFunction & MF ) { AFI = MF . getInfo < ARMFunctionInfo > ( ) ; MCP = MF . getConstantPool ( ) ; Subtarget = & MF . getSubtarget < ARMSubtarget > ( ) ; if ( Subtarget -> isTargetNaCl ( ) ) { NaClAlignAllJumpTargetsAndConstantPools ( MF ) ; } SetupMachineFunction ( MF ) ; if ( Subtarget -> isTargetCOFF ( ) ) { bool Internal = MF . getFunction ( ) -> hasInternalLinkage ( ) ; COFF :: SymbolStorageClass Scl = Internal ? COFF :: IMAGE_SYM_CLASS_STATIC : COFF :: IMAGE_SYM_CLASS_EXTERNAL ; int Type = COFF :: IMAGE_SYM_DTYPE_FUNCTION << COFF :: SCT_COMPLEX_TYPE_SHIFT ; OutStreamer . BeginCOFFSymbolDef ( CurrentFnSym ) ; OutStreamer . EmitCOFFSymbolStorageClass ( Scl ) ; OutStreamer . EmitCOFFSymbolType ( Type ) ; OutStreamer . EndCOFFSymbolDef ( ) ; } EmitFunctionBody ( ) ; if ( ! ThumbIndirectPads . empty ( ) ) { OutStreamer . EmitAssemblerFlag ( MCAF_Code16 ) ; EmitAlignment ( 1 ) ; for ( unsigned i = 0 , e = ThumbIndirectPads . size ( ) ; i < e ; i ++ ) { OutStreamer . EmitLabel ( ThumbIndirectPads [ i ] . second ) ; EmitToStreamer ( OutStreamer , MCInstBuilder ( ARM :: tBX ) . addReg ( ThumbIndirectPads [ i ] . first ) . addImm ( ARMCC :: AL ) . addReg ( 0 ) ) ; } ThumbIndirectPads . clear ( ) ; } return false ; } </s>


<s> bool ARMAsmPrinter :: runOnMachineFunction ( MachineFunction & MF ) { AFI = MF . getInfo < ARMFunctionInfo > ( ) ; MCP = MF . getConstantPool ( ) ; Subtarget = & MF . getSubtarget < ARMSubtarget > ( ) ; SetupMachineFunction ( MF ) ; const Function * F = MF . getFunction ( ) ; const TargetMachine & TM = MF . getTarget ( ) ; for ( auto * GV : AFI -> getGlobalsPromotedToConstantPool ( ) ) PromotedGlobals . insert ( GV ) ; unsigned OptimizationGoal ; if ( F -> hasFnAttribute ( Attribute :: OptimizeNone ) ) OptimizationGoal = 6 ; else if ( F -> optForMinSize ( ) ) OptimizationGoal = 4 ; else if ( F -> optForSize ( ) ) OptimizationGoal = 3 ; else if ( TM . getOptLevel ( ) == CodeGenOpt :: Aggressive ) OptimizationGoal = 2 ; else if ( TM . getOptLevel ( ) > CodeGenOpt :: None ) OptimizationGoal = 1 ; else OptimizationGoal = 5 ; if ( OptimizationGoals == - 1 ) OptimizationGoals = OptimizationGoal ; else if ( OptimizationGoals != ( int ) OptimizationGoal ) OptimizationGoals = 0 ; if ( Subtarget -> isTargetCOFF ( ) ) { bool Internal = F -> hasInternalLinkage ( ) ; COFF :: SymbolStorageClass Scl = Internal ? COFF :: IMAGE_SYM_CLASS_STATIC : COFF :: IMAGE_SYM_CLASS_EXTERNAL ; int Type = COFF :: IMAGE_SYM_DTYPE_FUNCTION << COFF :: SCT_COMPLEX_TYPE_SHIFT ; OutStreamer -> BeginCOFFSymbolDef ( CurrentFnSym ) ; OutStreamer -> EmitCOFFSymbolStorageClass ( Scl ) ; OutStreamer -> EmitCOFFSymbolType ( Type ) ; OutStreamer -> EndCOFFSymbolDef ( ) ; } EmitFunctionBody ( ) ; emitXRayTable ( ) ; if ( ! ThumbIndirectPads . empty ( ) ) { OutStreamer -> EmitAssemblerFlag ( MCAF_Code16 ) ; EmitAlignment ( 1 ) ; for ( std :: pair < unsigned , MCSymbol * > & TIP : ThumbIndirectPads ) { OutStreamer -> EmitLabel ( TIP . second ) ; EmitToStreamer ( * OutStreamer , MCInstBuilder ( ARM :: tBX ) . addReg ( TIP . first ) . addImm ( ARMCC :: AL ) . addReg ( 0 ) ) ; } ThumbIndirectPads . clear ( ) ; } return false ; } </s>


<s>
void
ARMAsmPrinter
::
EmitInstruction
(
const
MachineInstr
*
MI
)
{
if
(
EnableMCInst
)
{
printInstructionThroughMCStreamer
(
MI
)
;
return
;
}
if
(
MI
->
getOpcode
(
)
==
ARM
::
CONSTPOOL_ENTRY
)
EmitAlignment
(
2
)
;
SmallString
<
128
>
Str
;
raw_svector_ostream
OS
(
Str
)
;
if
(
MI
->
getOpcode
(
)
==
ARM
::
DBG_VALUE
)
{
unsigned
NOps
=
MI
->
getNumOperands
(
)
;
assert
(
NOps
==
4
)
;
OS
<<
'\t'
<<
MAI
->
getCommentString
(
)
<<
"DEBUG_VALUE: "
;
DIVariable
V
(
const_cast
<
MDNode
*
>
(
MI
->
getOperand
(
NOps
1
)
.
getMetadata
(
)
)
)
;
OS
<<
V
.
getName
(
)
;
OS
<<
" <- "
;
assert
(
MI
->
getOperand
(
0
)
.
isReg
(
)
&&
MI
->
getOperand
(
1
)
.
isImm
(
)
)
;
OS
<<
'['
;
printOperand
(
MI
,
0
,
OS
)
;
OS
<<
'+'
;
printOperand
(
MI
,
1
,
OS
)
;
OS
<<
']'
;
OS
<<
"+"
;
printOperand
(
MI
,
NOps
2
,
OS
)
;
OutStreamer
.
EmitRawText
(
OS
.
str
(
)
)
;
return
;
}
printInstruction
(
MI
,
OS
)
;
OutStreamer
.
EmitRawText
(
OS
.
str
(
)
)
;
if
(
MI
->
getOpcode
(
)
==
ARM
::
t2TBB
)
EmitAlignment
(
1
)
;
}
</s>


"llvm does not support 'Q', 'R', and 'H' modifiers!"


<s> bool ARMAsmPrinter :: runOnMachineFunction ( MachineFunction & MF ) { AFI = MF . getInfo < ARMFunctionInfo > ( ) ; MCP = MF . getConstantPool ( ) ; SetupMachineFunction ( MF ) ; if ( Subtarget -> isTargetCOFF ( ) ) { bool Internal = MF . getFunction ( ) -> hasInternalLinkage ( ) ; COFF :: SymbolStorageClass Scl = Internal ? COFF :: IMAGE_SYM_CLASS_STATIC : COFF :: IMAGE_SYM_CLASS_EXTERNAL ; int Type = COFF :: IMAGE_SYM_DTYPE_FUNCTION << COFF :: SCT_COMPLEX_TYPE_SHIFT ; OutStreamer . BeginCOFFSymbolDef ( CurrentFnSym ) ; OutStreamer . EmitCOFFSymbolStorageClass ( Scl ) ; OutStreamer . EmitCOFFSymbolType ( Type ) ; OutStreamer . EndCOFFSymbolDef ( ) ; } EmitFunctionHeader ( ) ; EmitFunctionBody ( ) ; if ( ! ThumbIndirectPads . empty ( ) ) { OutStreamer . EmitAssemblerFlag ( MCAF_Code16 ) ; EmitAlignment ( 1 ) ; for ( unsigned i = 0 , e = ThumbIndirectPads . size ( ) ; i < e ; i ++ ) { OutStreamer . EmitLabel ( ThumbIndirectPads [ i ] . second ) ; EmitToStreamer ( OutStreamer , MCInstBuilder ( ARM :: tBX ) . addReg ( ThumbIndirectPads [ i ] . first ) . addImm ( ARMCC :: AL ) . addReg ( 0 ) ) ; } ThumbIndirectPads . clear ( ) ; } return false ; } </s>


<s>
bool
ARMAsmPrinter
::
doInitialization
(
Module
&
M
)
{
bool
Result
=
AsmPrinter
::
doInitialization
(
M
)
;
MMI
=
getAnalysisIfAvailable
<
MachineModuleInfo
>
(
)
;
assert
(
MMI
)
;
DW
=
getAnalysisIfAvailable
<
DwarfWriter
>
(
)
;
assert
(
DW
&&
"Dwarf Writer is not available"
)
;
DW
->
BeginModule
(
&
M
,
MMI
,
O
,
this
,
TAI
)
;
if
(
Subtarget
->
isTargetDarwin
(
)
)
Mang
->
setUseQuotes
(
true
)
;
if
(
Subtarget
->
isTargetELF
(
)
)
{
std
::
string
CPUString
=
Subtarget
->
getCPUString
(
)
;
if
(
CPUString
!=
"generic"
)
O
<<
"\t.cpu "
<<
CPUString
<<
'\n'
;
if
(
Subtarget
->
hasVFP2
(
)
)
O
<<
"\t.eabi_attribute "
<<
ARMBuildAttrs
::
VFP_arch
<<
", 2\n"
;
if
(
!
UnsafeFPMath
)
O
<<
"\t.eabi_attribute "
<<
ARMBuildAttrs
::
ABI_FP_denormal
<<
", 1\n"
<<
"\t.eabi_attribute "
<<
ARMBuildAttrs
::
ABI_FP_exceptions
<<
", 1\n"
;
if
(
FiniteOnlyFPMath
(
)
)
O
<<
"\t.eabi_attribute "
<<
ARMBuildAttrs
::
ABI_FP_number_model
<<
", 1\n"
;
else
O
<<
"\t.eabi_attribute "
<<
ARMBuildAttrs
::
ABI_FP_number_model
<<
", 3\n"
;
O
<<
"\t.eabi_attribute "
<<
ARMBuildAttrs
::
ABI_align8_needed
<<
", 1\n"
<<
"\t.eabi_attribute "
<<
ARMBuildAttrs
::
ABI_align8_preserved
<<
", 1\n"
;
}
return
Result
;
}
</s>

ARM
ARM
"Dwarf Writer is not available"
"generic"
"\t.cpu "
"\t.eabi_attribute "
ARMBuildAttrs::VFP_arch
", 2\n"
"\t.eabi_attribute "
ARMBuildAttrs::ABI_FP_denormal
", 1\n"
"\t.eabi_attribute "
ARMBuildAttrs::ABI_FP_exceptions
", 1\n"
"\t.eabi_attribute "
ARMBuildAttrs::ABI_FP_number_model
", 1\n"
"\t.eabi_attribute "
ARMBuildAttrs::ABI_FP_number_model
", 3\n"
"\t.eabi_attribute "
ARMBuildAttrs::ABI_align8_needed
", 1\n"
"\t.eabi_attribute "
ARMBuildAttrs::ABI_align8_preserved
", 1\n"


<s> bool ARMAsmPrinter :: PrintAsmMemoryOperand ( const MachineInstr * MI , unsigned OpNo , unsigned AsmVariant , const char * ExtraCode ) { if ( ExtraCode && ExtraCode [ 0 ] ) return true ; printAddrMode2Operand ( MI , OpNo ) ; return false ; } </s>


<s> bool ARMAsmPrinter :: PrintAsmOperand ( const MachineInstr * MI , unsigned OpNo , unsigned AsmVariant , const char * ExtraCode ) { if ( ExtraCode && ExtraCode [ 0 ] ) { if ( ExtraCode [ 1 ] != 0 ) return true ; switch ( ExtraCode [ 0 ] ) { default : return true ; case 'a' : case 'c' : printOperand ( MI , OpNo , "no_hash" ) ; return false ; case 'P' : printOperand ( MI , OpNo ) ; return false ; case 'Q' : if ( TM . getTargetData ( ) -> isLittleEndian ( ) ) break ; case 'R' : if ( TM . getTargetData ( ) -> isBigEndian ( ) ) break ; case 'H' : if ( ! MI -> getOperand ( OpNo ) . isReg ( ) || OpNo + 1 == MI -> getNumOperands ( ) || ! MI -> getOperand ( OpNo + 1 ) . isReg ( ) ) return true ; ++ OpNo ; } } printOperand ( MI , OpNo ) ; return false ; } </s>


<s> Register ( ) { ARMTargetMachine :: registerAsmPrinter ( createARMCodePrinterPass ) ; } </s>


<s> void Finish ( ) { const size_t ContentsSize = Contents . size ( ) ; const size_t VendorHeaderSize = 4 + CurrentVendor . size ( ) + 1 ; const size_t TagHeaderSize = 1 + 4 ; Streamer . EmitIntValue ( VendorHeaderSize + TagHeaderSize + ContentsSize , 4 ) ; Streamer . EmitBytes ( CurrentVendor , 0 ) ; Streamer . EmitIntValue ( 0 , 1 ) ; Streamer . EmitIntValue ( ARMBuildAttrs :: File , 1 ) ; Streamer . EmitIntValue ( TagHeaderSize + ContentsSize , 4 ) ; Streamer . EmitBytes ( Contents , 0 ) ; Contents . clear ( ) ; } </s>


<s>
bool
ARMAsmPrinter
::
PrintAsmMemoryOperand
(
const
MachineInstr
*
MI
,
unsigned
OpNum
,
unsigned
AsmVariant
,
const
char
*
ExtraCode
,
raw_ostream
&
O
)
{
if
(
ExtraCode
&&
ExtraCode
[
0
]
)
return
true
;
const
MachineOperand
&
MO
=
MI
->
getOperand
(
OpNum
)
;
assert
(
MO
.
isReg
(
)
&&
"unexpected inline asm memory operand"
)
;
O
<<
"["
<<
ARMInstPrinter
::
getRegisterName
(
MO
.
getReg
(
)
)
<<
"]"
;
return
false
;
}
</s>

ARM
ARM
0
"unexpected inline asm memory operand"
"["
ARM
"]"


<s> bool ARMAsmPrinter :: PrintAsmOperand ( const MachineInstr * MI , unsigned OpNum , unsigned AsmVariant , const char * ExtraCode , raw_ostream & O ) { if ( ExtraCode && ExtraCode [ 0 ] ) { if ( ExtraCode [ 1 ] != 0 ) return true ; switch ( ExtraCode [ 0 ] ) { default : return true ; case 'a' : if ( MI -> getOperand ( OpNum ) . isReg ( ) ) { O << "[" << ARMInstPrinter :: getRegisterName ( MI -> getOperand ( OpNum ) . getReg ( ) ) << "]" ; return false ; } case 'c' : if ( ! MI -> getOperand ( OpNum ) . isImm ( ) ) return true ; O << MI -> getOperand ( OpNum ) . getImm ( ) ; return false ; case 'P' : case 'q' : printOperand ( MI , OpNum , O ) ; return false ; case 'Q' : case 'R' : case 'H' : return true ; } } printOperand ( MI , OpNum , O ) ; return false ; } </s>


<s> void ARMAsmPrinter :: emitInlineAsmEnd ( const MCSubtargetInfo & StartInfo , const MCSubtargetInfo * EndInfo ) const { const bool WasThumb = isThumb ( StartInfo ) ; if ( EndInfo == NULL || WasThumb != isThumb ( * EndInfo ) ) { OutStreamer . EmitAssemblerFlag ( WasThumb ? MCAF_Code16 : MCAF_Code32 ) ; } } </s>


<s>
void
ARMAsmPrinter
::
emitMachineConstantPoolValue
(
MachineConstantPoolValue
*
MCPV
)
{
const
DataLayout
&
DL
=
getDataLayout
(
)
;
int
Size
=
DL
.
getTypeAllocSize
(
MCPV
->
getType
(
)
)
;
ARMConstantPoolValue
*
ACPV
=
static_cast
<
ARMConstantPoolValue
*
>
(
MCPV
)
;
if
(
ACPV
->
isPromotedGlobal
(
)
)
{
auto
*
ACPC
=
cast
<
ARMConstantPoolConstant
>
(
ACPV
)
;
for
(
const
auto
*
GV
:
ACPC
->
promotedGlobals
(
)
)
{
if
(
!
EmittedPromotedGlobalLabels
.
count
(
GV
)
)
{
MCSymbol
*
GVSym
=
getSymbol
(
GV
)
;
OutStreamer
->
emitLabel
(
GVSym
)
;
EmittedPromotedGlobalLabels
.
insert
(
GV
)
;
}
}
return
emitGlobalConstant
(
DL
,
ACPC
->
getPromotedGlobalInit
(
)
)
;
}
MCSymbol
*
MCSym
;
if
(
ACPV
->
isLSDA
(
)
)
{
MCSym
=
getCurExceptionSym
(
)
;
}
else
if
(
ACPV
->
isBlockAddress
(
)
)
{
const
BlockAddress
*
BA
=
cast
<
ARMConstantPoolConstant
>
(
ACPV
)
->
getBlockAddress
(
)
;
MCSym
=
GetBlockAddressSymbol
(
BA
)
;
}
else
if
(
ACPV
->
isGlobalValue
(
)
)
{
const
GlobalValue
*
GV
=
cast
<
ARMConstantPoolConstant
>
(
ACPV
)
->
getGV
(
)
;
unsigned
char
TF
=
Subtarget
->
isTargetMachO
(
)
ARMII
::
MO_NONLAZY
:
0
;
MCSym
=
GetARMGVSymbol
(
GV
,
TF
)
;
}
else
if
(
ACPV
->
isMachineBasicBlock
(
)
)
{
const
MachineBasicBlock
*
MBB
=
cast
<
ARMConstantPoolMBB
>
(
ACPV
)
->
getMBB
(
)
;
MCSym
=
MBB
->
getSymbol
(
)
;
}
else
{
assert
(
ACPV
->
isExtSymbol
(
)
&&
"unrecognized constant pool value"
)
;
auto
Sym
=
cast
<
ARMConstantPoolSymbol
>
(
ACPV
)
->
getSymbol
(
)
;
MCSym
=
GetExternalSymbolSymbol
(
Sym
)
;
}
const
MCExpr
*
Expr
=
MCSymbolRefExpr
::
create
(
MCSym
,
getModifierVariantKind
(
ACPV
->
getModifier
(
)
)
,
OutContext
)
;
if
(
ACPV
->
getPCAdjustment
(
)
)
{
MCSymbol
*
PCLabel
=
getPICLabel
(
DL
.
getPrivateGlobalPrefix
(
)
,
getFunctionNumber
(
)
,
ACPV
->
getLabelId
(
)
,
OutContext
)
;
const
MCExpr
*
PCRelExpr
=
MCSymbolRefExpr
::
create
(
PCLabel
,
OutContext
)
;
PCRelExpr
=
MCBinaryExpr
::
createAdd
(
PCRelExpr
,
MCConstantExpr
::
create
(
ACPV
->
getPCAdjustment
(
)
,
OutContext
)
,
OutContext
)
;
if
(
ACPV
->
mustAddCurrentAddress
(
)
)
{
MCSymbol
*
DotSym
=
OutContext
.
createTempSymbol
(
)
;
OutStreamer
->
emitLabel
(
DotSym
)
;
const
MCExpr
*
DotExpr
=
MCSymbolRefExpr
::
create
(
DotSym
,
OutContext
)
;
PCRelExpr
=
MCBinaryExpr
::
createSub
(
PCRelExpr
,
DotExpr
,
OutContext
)
;
}
Expr
=
MCBinaryExpr
::
createSub
(
Expr
,
PCRelExpr
,
OutContext
)
;
}
OutStreamer
->
emitValue
(
Expr
,
Size
)
;
}
</s>

EmitMachineConstantPoolValue - Print a machine constantpool value to the .s file .

ARM
ARM
ARM
ARM
ARM
ARM
ARM
ARMII::MO_NONLAZY
0
ARM
ARM
"unrecognized constant pool value"
ARM


<s> bool ARMAsmPrinter :: runOnMachineFunction ( MachineFunction & MF ) { AFI = MF . getInfo < ARMFunctionInfo > ( ) ; MCP = MF . getConstantPool ( ) ; if ( FlagSfiBranch ) { NaclAlignAllJumpTargetsAndConstantPools ( MF ) ; } return AsmPrinter :: runOnMachineFunction ( MF ) ; } </s>


<s> bool ARMAsmPrinter :: runOnMachineFunction ( MachineFunction & MF ) { AFI = MF . getInfo < ARMFunctionInfo > ( ) ; MCP = MF . getConstantPool ( ) ; Subtarget = & MF . getSubtarget < ARMSubtarget > ( ) ; SetupMachineFunction ( MF ) ; const Function & F = MF . getFunction ( ) ; const TargetMachine & TM = MF . getTarget ( ) ; for ( auto * GV : AFI -> getGlobalsPromotedToConstantPool ( ) ) PromotedGlobals . insert ( GV ) ; unsigned OptimizationGoal ; if ( F . hasOptNone ( ) ) OptimizationGoal = 6 ; else if ( F . hasMinSize ( ) ) OptimizationGoal = 4 ; else if ( F . hasOptSize ( ) ) OptimizationGoal = 3 ; else if ( TM . getOptLevel ( ) == CodeGenOpt :: Aggressive ) OptimizationGoal = 2 ; else if ( TM . getOptLevel ( ) > CodeGenOpt :: None ) OptimizationGoal = 1 ; else OptimizationGoal = 5 ; if ( OptimizationGoals == - 1 ) OptimizationGoals = OptimizationGoal ; else if ( OptimizationGoals != ( int ) OptimizationGoal ) OptimizationGoals = 0 ; if ( Subtarget -> isTargetCOFF ( ) ) { bool Internal = F . hasInternalLinkage ( ) ; COFF :: SymbolStorageClass Scl = Internal ? COFF :: IMAGE_SYM_CLASS_STATIC : COFF :: IMAGE_SYM_CLASS_EXTERNAL ; int Type = COFF :: IMAGE_SYM_DTYPE_FUNCTION << COFF :: SCT_COMPLEX_TYPE_SHIFT ; OutStreamer -> BeginCOFFSymbolDef ( CurrentFnSym ) ; OutStreamer -> emitCOFFSymbolStorageClass ( Scl ) ; OutStreamer -> emitCOFFSymbolType ( Type ) ; OutStreamer -> EndCOFFSymbolDef ( ) ; } emitFunctionBody ( ) ; emitXRayTable ( ) ; if ( ! ThumbIndirectPads . empty ( ) ) { OutStreamer -> emitAssemblerFlag ( MCAF_Code16 ) ; emitAlignment ( Align ( 2 ) ) ; for ( std :: pair < unsigned , MCSymbol * > & TIP : ThumbIndirectPads ) { OutStreamer -> emitLabel ( TIP . second ) ; EmitToStreamer ( * OutStreamer , MCInstBuilder ( ARM :: tBX ) . addReg ( TIP . first ) . addImm ( ARMCC :: AL ) . addReg ( 0 ) ) ; } ThumbIndirectPads . clear ( ) ; } return false ; } </s>


<s>
void
ARMAsmPrinter
::
emitMachineConstantPoolValue
(
MachineConstantPoolValue
*
MCPV
)
{
const
DataLayout
&
DL
=
getDataLayout
(
)
;
int
Size
=
DL
.
getTypeAllocSize
(
MCPV
->
getType
(
)
)
;
ARMConstantPoolValue
*
ACPV
=
static_cast
<
ARMConstantPoolValue
*
>
(
MCPV
)
;
if
(
ACPV
->
isPromotedGlobal
(
)
)
{
auto
*
ACPC
=
cast
<
ARMConstantPoolConstant
>
(
ACPV
)
;
for
(
const
auto
*
GV
:
ACPC
->
promotedGlobals
(
)
)
{
if
(
!
EmittedPromotedGlobalLabels
.
count
(
GV
)
)
{
MCSymbol
*
GVSym
=
getSymbol
(
GV
)
;
OutStreamer
->
emitLabel
(
GVSym
)
;
EmittedPromotedGlobalLabels
.
insert
(
GV
)
;
}
}
return
emitGlobalConstant
(
DL
,
ACPC
->
getPromotedGlobalInit
(
)
,
0
)
;
}
MCSymbol
*
MCSym
;
if
(
ACPV
->
isLSDA
(
)
)
{
MCSym
=
getMBBExceptionSym
(
MF
->
front
(
)
)
;
}
else
if
(
ACPV
->
isBlockAddress
(
)
)
{
const
BlockAddress
*
BA
=
cast
<
ARMConstantPoolConstant
>
(
ACPV
)
->
getBlockAddress
(
)
;
MCSym
=
GetBlockAddressSymbol
(
BA
)
;
}
else
if
(
ACPV
->
isGlobalValue
(
)
)
{
const
GlobalValue
*
GV
=
cast
<
ARMConstantPoolConstant
>
(
ACPV
)
->
getGV
(
)
;
unsigned
char
TF
=
Subtarget
->
isTargetMachO
(
)
ARMII
::
MO_NONLAZY
:
0
;
MCSym
=
GetARMGVSymbol
(
GV
,
TF
)
;
}
else
if
(
ACPV
->
isMachineBasicBlock
(
)
)
{
const
MachineBasicBlock
*
MBB
=
cast
<
ARMConstantPoolMBB
>
(
ACPV
)
->
getMBB
(
)
;
MCSym
=
MBB
->
getSymbol
(
)
;
}
else
{
assert
(
ACPV
->
isExtSymbol
(
)
&&
"unrecognized constant pool value"
)
;
auto
Sym
=
cast
<
ARMConstantPoolSymbol
>
(
ACPV
)
->
getSymbol
(
)
;
MCSym
=
GetExternalSymbolSymbol
(
Sym
)
;
}
const
MCExpr
*
Expr
=
MCSymbolRefExpr
::
create
(
MCSym
,
getModifierVariantKind
(
ACPV
->
getModifier
(
)
)
,
OutContext
)
;
if
(
ACPV
->
getPCAdjustment
(
)
)
{
MCSymbol
*
PCLabel
=
getPICLabel
(
DL
.
getPrivateGlobalPrefix
(
)
,
getFunctionNumber
(
)
,
ACPV
->
getLabelId
(
)
,
OutContext
)
;
const
MCExpr
*
PCRelExpr
=
MCSymbolRefExpr
::
create
(
PCLabel
,
OutContext
)
;
PCRelExpr
=
MCBinaryExpr
::
createAdd
(
PCRelExpr
,
MCConstantExpr
::
create
(
ACPV
->
getPCAdjustment
(
)
,
OutContext
)
,
OutContext
)
;
if
(
ACPV
->
mustAddCurrentAddress
(
)
)
{
MCSymbol
*
DotSym
=
OutContext
.
createTempSymbol
(
)
;
OutStreamer
->
emitLabel
(
DotSym
)
;
const
MCExpr
*
DotExpr
=
MCSymbolRefExpr
::
create
(
DotSym
,
OutContext
)
;
PCRelExpr
=
MCBinaryExpr
::
createSub
(
PCRelExpr
,
DotExpr
,
OutContext
)
;
}
Expr
=
MCBinaryExpr
::
createSub
(
Expr
,
PCRelExpr
,
OutContext
)
;
}
OutStreamer
->
emitValue
(
Expr
,
Size
)
;
}
</s>

ARM
ARM
ARM
ARM
ARM
0
ARM
ARM
ARMII::MO_NONLAZY
0
ARM
ARM
"unrecognized constant pool value"
ARM


"C++ constructor pointer had zero size!"

"C++ constructor pointer was not a GlobalValue!"

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


<s> void ARMAsmPrinter :: emitFunctionEntryLabel ( ) { if ( AFI -> isThumbFunction ( ) ) { OutStreamer -> emitAssemblerFlag ( MCAF_Code16 ) ; OutStreamer -> emitThumbFunc ( CurrentFnSym ) ; } else { OutStreamer -> emitAssemblerFlag ( MCAF_Code32 ) ; } OutStreamer -> emitLabel ( CurrentFnSym ) ; } </s>

EmitFunctionEntryLabel - Emit the label that is the entrypoint for the function .


<s> bool ARMAsmPrinter :: runOnMachineFunction ( MachineFunction & MF ) { AFI = MF . getInfo < ARMFunctionInfo > ( ) ; MCP = MF . getConstantPool ( ) ; Subtarget = & MF . getSubtarget < ARMSubtarget > ( ) ; SetupMachineFunction ( MF ) ; if ( Subtarget -> isTargetCOFF ( ) ) { bool Internal = MF . getFunction ( ) -> hasInternalLinkage ( ) ; COFF :: SymbolStorageClass Scl = Internal ? COFF :: IMAGE_SYM_CLASS_STATIC : COFF :: IMAGE_SYM_CLASS_EXTERNAL ; int Type = COFF :: IMAGE_SYM_DTYPE_FUNCTION << COFF :: SCT_COMPLEX_TYPE_SHIFT ; OutStreamer . BeginCOFFSymbolDef ( CurrentFnSym ) ; OutStreamer . EmitCOFFSymbolStorageClass ( Scl ) ; OutStreamer . EmitCOFFSymbolType ( Type ) ; OutStreamer . EndCOFFSymbolDef ( ) ; } EmitFunctionBody ( ) ; if ( ! ThumbIndirectPads . empty ( ) ) { OutStreamer . EmitAssemblerFlag ( MCAF_Code16 ) ; EmitAlignment ( 1 ) ; for ( unsigned i = 0 , e = ThumbIndirectPads . size ( ) ; i < e ; i ++ ) { OutStreamer . EmitLabel ( ThumbIndirectPads [ i ] . second ) ; EmitToStreamer ( OutStreamer , MCInstBuilder ( ARM :: tBX ) . addReg ( ThumbIndirectPads [ i ] . first ) . addImm ( ARMCC :: AL ) . addReg ( 0 ) ) ; } ThumbIndirectPads . clear ( ) ; } return false ; } </s>


<s>
bool
ARMAsmPrinter
::
doInitialization
(
Module
&
M
)
{
bool
Result
=
AsmPrinter
::
doInitialization
(
M
)
;
MMI
=
getAnalysisIfAvailable
<
MachineModuleInfo
>
(
)
;
assert
(
MMI
)
;
DW
=
getAnalysisIfAvailable
<
DwarfWriter
>
(
)
;
assert
(
DW
&&
"Dwarf Writer is not available"
)
;
DW
->
BeginModule
(
&
M
,
MMI
,
O
,
this
,
TAI
)
;
if
(
Subtarget
->
isTargetDarwin
(
)
)
Mang
->
setUseQuotes
(
true
)
;
return
Result
;
}
</s>


<s> bool ARMAsmPrinter :: PrintAsmOperand ( const MachineInstr * MI , unsigned OpNo , unsigned AsmVariant , const char * ExtraCode ) { if ( ExtraCode && ExtraCode [ 0 ] ) { if ( ExtraCode [ 1 ] != 0 ) return true ; switch ( ExtraCode [ 0 ] ) { default : return true ; case 'c' : case 'P' : printOperand ( MI , OpNo ) ; return false ; case 'Q' : if ( TM . getTargetData ( ) -> isLittleEndian ( ) ) break ; case 'R' : if ( TM . getTargetData ( ) -> isBigEndian ( ) ) break ; case 'H' : if ( ! MI -> getOperand ( OpNo ) . isReg ( ) || OpNo + 1 == MI -> getNumOperands ( ) || ! MI -> getOperand ( OpNo + 1 ) . isReg ( ) ) return true ; ++ OpNo ; } } printOperand ( MI , OpNo ) ; return false ; } </s>


<s>
void
Finish
(
)
{
const
size_t
VendorHeaderSize
=
4
+
CurrentVendor
.
size
(
)
+
1
;
const
size_t
TagHeaderSize
=
1
+
4
;
Streamer
.
EmitIntValue
(
VendorHeaderSize
+
TagHeaderSize
+
ContentsSize
,
4
)
;
Streamer
.
EmitBytes
(
CurrentVendor
,
0
)
;
Streamer
.
EmitIntValue
(
0
,
1
)
;
Streamer
.
EmitIntValue
(
ARMBuildAttrs
::
File
,
1
)
;
Streamer
.
EmitIntValue
(
TagHeaderSize
+
ContentsSize
,
4
)
;
for
(
unsigned
int
i
=
0
;
i
<
Contents
.
size
(
)
;
++
i
)
{
AttributeItemType
item
=
Contents
[
i
]
;
Streamer
.
EmitULEB128IntValue
(
item
.
Tag
,
0
)
;
switch
(
item
.
Type
)
{
case
AttributeItemType
::
NumericAttribute
:
Streamer
.
EmitULEB128IntValue
(
item
.
IntValue
,
0
)
;
break
;
case
AttributeItemType
::
TextAttribute
:
Streamer
.
EmitBytes
(
UppercaseString
(
item
.
StringValue
)
,
0
)
;
Streamer
.
EmitIntValue
(
0
,
1
)
;
break
;
default
:
assert
(
0
&&
"Invalid attribute type"
)
;
}
}
Contents
.
clear
(
)
;
}
</s>


<s> bool ARMAsmPrinter :: runOnMachineFunction ( MachineFunction & MF ) { AFI = MF . getInfo < ARMFunctionInfo > ( ) ; MCP = MF . getConstantPool ( ) ; if ( Subtarget -> isTargetNaCl ( ) ) { NaClAlignAllJumpTargetsAndConstantPools ( MF ) ; } return AsmPrinter :: runOnMachineFunction ( MF ) ; } </s>


<s> void ARMAsmPrinter :: emitEndOfAsmFile ( Module & M ) { const Triple & TT = TM . getTargetTriple ( ) ; if ( TT . isOSBinFormatMachO ( ) ) { const TargetLoweringObjectFileMachO & TLOFMacho = static_cast < const TargetLoweringObjectFileMachO & > ( getObjFileLowering ( ) ) ; MachineModuleInfoMachO & MMIMacho = MMI -> getObjFileInfo < MachineModuleInfoMachO > ( ) ; MachineModuleInfoMachO :: SymbolListTy Stubs = MMIMacho . GetGVStubList ( ) ; if ( ! Stubs . empty ( ) ) { OutStreamer -> SwitchSection ( TLOFMacho . getNonLazySymbolPointerSection ( ) ) ; emitAlignment ( Align ( 4 ) ) ; for ( auto & Stub : Stubs ) emitNonLazySymbolPointer ( * OutStreamer , Stub . first , Stub . second ) ; Stubs . clear ( ) ; OutStreamer -> AddBlankLine ( ) ; } Stubs = MMIMacho . GetThreadLocalGVStubList ( ) ; if ( ! Stubs . empty ( ) ) { OutStreamer -> SwitchSection ( TLOFMacho . getThreadLocalPointerSection ( ) ) ; emitAlignment ( Align ( 4 ) ) ; for ( auto & Stub : Stubs ) emitNonLazySymbolPointer ( * OutStreamer , Stub . first , Stub . second ) ; Stubs . clear ( ) ; OutStreamer -> AddBlankLine ( ) ; } OutStreamer -> emitAssemblerFlag ( MCAF_SubsectionsViaSymbols ) ; } MCTargetStreamer & TS = * OutStreamer -> getTargetStreamer ( ) ; ARMTargetStreamer & ATS = static_cast < ARMTargetStreamer & > ( TS ) ; if ( OptimizationGoals > 0 && ( Subtarget -> isTargetAEABI ( ) || Subtarget -> isTargetGNUAEABI ( ) || Subtarget -> isTargetMuslAEABI ( ) ) ) ATS . emitAttribute ( ARMBuildAttrs :: ABI_optimization_goals , OptimizationGoals ) ; OptimizationGoals = - 1 ; ATS . finishAttributeSection ( ) ; } </s>

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


<s> void ARMAsmPrinter :: emitFunctionBodyEnd ( ) { if ( ! InConstantPool ) return ; InConstantPool = false ; OutStreamer -> emitDataRegion ( MCDR_DataRegionEnd ) ; } </s>

Targets can override this to emit stuff after the last basic block in the function .


<s> void ARMAsmPrinter :: emitFunctionEntryLabel ( ) { if ( AFI -> isThumbFunction ( ) ) { OutStreamer -> emitAssemblerFlag ( MCAF_Code16 ) ; OutStreamer -> emitThumbFunc ( CurrentFnSym ) ; } else { OutStreamer -> emitAssemblerFlag ( MCAF_Code32 ) ; } if ( AFI -> isCmseNSEntryFunction ( ) ) { MCSymbol * S = OutContext . getOrCreateSymbol ( "__acle_se_" + CurrentFnSym -> getName ( ) ) ; emitLinkage ( & MF -> getFunction ( ) , S ) ; OutStreamer -> emitSymbolAttribute ( S , MCSA_ELF_TypeFunction ) ; OutStreamer -> emitLabel ( S ) ; } OutStreamer -> emitLabel ( CurrentFnSym ) ; } </s>


<s> void ARMAsmPrinter :: emitGlobalVariable ( const GlobalVariable * GV ) { if ( PromotedGlobals . count ( GV ) ) return ; AsmPrinter :: emitGlobalVariable ( GV ) ; } </s>

Emit the specified global variable to the .s file .


<s> void ARMAsmPrinter :: emitInlineAsmEnd ( const MCSubtargetInfo & StartInfo , const MCSubtargetInfo * EndInfo ) const { const bool WasThumb = isThumb ( StartInfo ) ; if ( ! EndInfo || WasThumb != isThumb ( * EndInfo ) ) { OutStreamer -> emitAssemblerFlag ( WasThumb ? MCAF_Code16 : MCAF_Code32 ) ; } } </s>

Let the target do anything it needs to do after emitting inlineasm .


<s>
void
ARMAsmPrinter
::
emitMachineConstantPoolValue
(
MachineConstantPoolValue
*
MCPV
)
{
const
DataLayout
&
DL
=
getDataLayout
(
)
;
int
Size
=
DL
.
getTypeAllocSize
(
MCPV
->
getType
(
)
)
;
ARMConstantPoolValue
*
ACPV
=
static_cast
<
ARMConstantPoolValue
*
>
(
MCPV
)
;
if
(
ACPV
->
isPromotedGlobal
(
)
)
{
auto
*
ACPC
=
cast
<
ARMConstantPoolConstant
>
(
ACPV
)
;
for
(
const
auto
*
GV
:
ACPC
->
promotedGlobals
(
)
)
{
if
(
!
EmittedPromotedGlobalLabels
.
count
(
GV
)
)
{
MCSymbol
*
GVSym
=
getSymbol
(
GV
)
;
OutStreamer
->
emitLabel
(
GVSym
)
;
EmittedPromotedGlobalLabels
.
insert
(
GV
)
;
}
}
return
emitGlobalConstant
(
DL
,
ACPC
->
getPromotedGlobalInit
(
)
)
;
}
MCSymbol
*
MCSym
;
if
(
ACPV
->
isLSDA
(
)
)
{
MCSym
=
getMBBExceptionSym
(
MF
->
front
(
)
)
;
}
else
if
(
ACPV
->
isBlockAddress
(
)
)
{
const
BlockAddress
*
BA
=
cast
<
ARMConstantPoolConstant
>
(
ACPV
)
->
getBlockAddress
(
)
;
MCSym
=
GetBlockAddressSymbol
(
BA
)
;
}
else
if
(
ACPV
->
isGlobalValue
(
)
)
{
const
GlobalValue
*
GV
=
cast
<
ARMConstantPoolConstant
>
(
ACPV
)
->
getGV
(
)
;
unsigned
char
TF
=
Subtarget
->
isTargetMachO
(
)
ARMII
::
MO_NONLAZY
:
0
;
MCSym
=
GetARMGVSymbol
(
GV
,
TF
)
;
}
else
if
(
ACPV
->
isMachineBasicBlock
(
)
)
{
const
MachineBasicBlock
*
MBB
=
cast
<
ARMConstantPoolMBB
>
(
ACPV
)
->
getMBB
(
)
;
MCSym
=
MBB
->
getSymbol
(
)
;
}
else
{
assert
(
ACPV
->
isExtSymbol
(
)
&&
"unrecognized constant pool value"
)
;
auto
Sym
=
cast
<
ARMConstantPoolSymbol
>
(
ACPV
)
->
getSymbol
(
)
;
MCSym
=
GetExternalSymbolSymbol
(
Sym
)
;
}
const
MCExpr
*
Expr
=
MCSymbolRefExpr
::
create
(
MCSym
,
getModifierVariantKind
(
ACPV
->
getModifier
(
)
)
,
OutContext
)
;
if
(
ACPV
->
getPCAdjustment
(
)
)
{
MCSymbol
*
PCLabel
=
getPICLabel
(
DL
.
getPrivateGlobalPrefix
(
)
,
getFunctionNumber
(
)
,
ACPV
->
getLabelId
(
)
,
OutContext
)
;
const
MCExpr
*
PCRelExpr
=
MCSymbolRefExpr
::
create
(
PCLabel
,
OutContext
)
;
PCRelExpr
=
MCBinaryExpr
::
createAdd
(
PCRelExpr
,
MCConstantExpr
::
create
(
ACPV
->
getPCAdjustment
(
)
,
OutContext
)
,
OutContext
)
;
if
(
ACPV
->
mustAddCurrentAddress
(
)
)
{
MCSymbol
*
DotSym
=
OutContext
.
createTempSymbol
(
)
;
OutStreamer
->
emitLabel
(
DotSym
)
;
const
MCExpr
*
DotExpr
=
MCSymbolRefExpr
::
create
(
DotSym
,
OutContext
)
;
PCRelExpr
=
MCBinaryExpr
::
createSub
(
PCRelExpr
,
DotExpr
,
OutContext
)
;
}
Expr
=
MCBinaryExpr
::
createSub
(
Expr
,
PCRelExpr
,
OutContext
)
;
}
OutStreamer
->
emitValue
(
Expr
,
Size
)
;
}
</s>


<s> void ARMAsmPrinter :: emitStartOfAsmFile ( Module & M ) { const Triple & TT = TM . getTargetTriple ( ) ; OutStreamer -> emitAssemblerFlag ( MCAF_SyntaxUnified ) ; if ( TT . isOSBinFormatELF ( ) ) emitAttributes ( ) ; if ( ! M . getModuleInlineAsm ( ) . empty ( ) && TT . isThumb ( ) ) OutStreamer -> emitAssemblerFlag ( MCAF_Code16 ) ; } </s>

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


<s> MCSymbol * ARMAsmPrinter :: GetCPISymbol ( unsigned CPID ) const { const DataLayout & DL = getDataLayout ( ) ; return OutContext . getOrCreateSymbol ( Twine ( DL . getPrivateGlobalPrefix ( ) ) + "CPI" + Twine ( getFunctionNumber ( ) ) + "_" + Twine ( CPID ) ) ; } </s>

Return the symbol for the specified constant pool entry .


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


<s>
bool
ARMAsmPrinter
::
PrintAsmMemoryOperand
(
const
MachineInstr
*
MI
,
unsigned
OpNum
,
const
char
*
ExtraCode
,
raw_ostream
&
O
)
{
if
(
ExtraCode
&&
ExtraCode
[
0
]
)
{
if
(
ExtraCode
[
1
]
!=
0
)
return
true
;
switch
(
ExtraCode
[
0
]
)
{
case
'A'
:
default
:
return
true
;
case
'm'
:
if
(
!
MI
->
getOperand
(
OpNum
)
.
isReg
(
)
)
return
true
;
O
<<
ARMInstPrinter
::
getRegisterName
(
MI
->
getOperand
(
OpNum
)
.
getReg
(
)
)
;
return
false
;
}
}
const
MachineOperand
&
MO
=
MI
->
getOperand
(
OpNum
)
;
assert
(
MO
.
isReg
(
)
&&
"unexpected inline asm memory operand"
)
;
O
<<
"["
<<
ARMInstPrinter
::
getRegisterName
(
MO
.
getReg
(
)
)
<<
"]"
;
return
false
;
}
</s>

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


<s>
void
ARMAsmPrinter
::
PrintSymbolOperand
(
const
MachineOperand
&
MO
,
raw_ostream
&
O
)
{
assert
(
MO
.
isGlobal
(
)
&&
"caller should check MO.isGlobal"
)
;
unsigned
TF
=
MO
.
getTargetFlags
(
)
;
if
(
TF
&
ARMII
::
MO_LO16
)
O
<<
":lower16:"
;
else
if
(
TF
&
ARMII
::
MO_HI16
)
O
<<
":upper16:"
;
GetARMGVSymbol
(
MO
.
getGlobal
(
)
,
TF
)
->
print
(
O
,
MAI
)
;
printOffset
(
MO
.
getOffset
(
)
,
O
)
;
}
</s>


<s> bool ARMAsmPrinter :: runOnMachineFunction ( MachineFunction & MF ) { AFI = MF . getInfo < ARMFunctionInfo > ( ) ; MCP = MF . getConstantPool ( ) ; Subtarget = & MF . getSubtarget < ARMSubtarget > ( ) ; SetupMachineFunction ( MF ) ; const Function & F = MF . getFunction ( ) ; const TargetMachine & TM = MF . getTarget ( ) ; for ( auto * GV : AFI -> getGlobalsPromotedToConstantPool ( ) ) PromotedGlobals . insert ( GV ) ; unsigned OptimizationGoal ; if ( F . hasOptNone ( ) ) OptimizationGoal = 6 ; else if ( F . hasMinSize ( ) ) OptimizationGoal = 4 ; else if ( F . hasOptSize ( ) ) OptimizationGoal = 3 ; else if ( TM . getOptLevel ( ) == CodeGenOpt :: Aggressive ) OptimizationGoal = 2 ; else if ( TM . getOptLevel ( ) > CodeGenOpt :: None ) OptimizationGoal = 1 ; else OptimizationGoal = 5 ; if ( OptimizationGoals == - 1 ) OptimizationGoals = OptimizationGoal ; else if ( OptimizationGoals != ( int ) OptimizationGoal ) OptimizationGoals = 0 ; if ( Subtarget -> isTargetCOFF ( ) ) { bool Internal = F . hasInternalLinkage ( ) ; COFF :: SymbolStorageClass Scl = Internal ? COFF :: IMAGE_SYM_CLASS_STATIC : COFF :: IMAGE_SYM_CLASS_EXTERNAL ; int Type = COFF :: IMAGE_SYM_DTYPE_FUNCTION << COFF :: SCT_COMPLEX_TYPE_SHIFT ; OutStreamer -> BeginCOFFSymbolDef ( CurrentFnSym ) ; OutStreamer -> EmitCOFFSymbolStorageClass ( Scl ) ; OutStreamer -> EmitCOFFSymbolType ( Type ) ; OutStreamer -> EndCOFFSymbolDef ( ) ; } emitFunctionBody ( ) ; emitXRayTable ( ) ; if ( ! ThumbIndirectPads . empty ( ) ) { OutStreamer -> emitAssemblerFlag ( MCAF_Code16 ) ; emitAlignment ( Align ( 2 ) ) ; for ( std :: pair < unsigned , MCSymbol * > & TIP : ThumbIndirectPads ) { OutStreamer -> emitLabel ( TIP . second ) ; EmitToStreamer ( * OutStreamer , MCInstBuilder ( ARM :: tBX ) . addReg ( TIP . first ) . addImm ( ARMCC :: AL ) . addReg ( 0 ) ) ; } ThumbIndirectPads . clear ( ) ; } return false ; } </s>

runOnMachineFunction - Emit the function body .


<s> bool ARMBaseInstrInfo :: areLoadsFromSameBasePtr ( SDNode * Load1 , SDNode * Load2 , int64_t & Offset1 , int64_t & Offset2 ) const { if ( Subtarget . isThumb1Only ( ) ) return false ; if ( ! Load1 -> isMachineOpcode ( ) || ! Load2 -> isMachineOpcode ( ) ) return false ; switch ( Load1 -> getMachineOpcode ( ) ) { default : return false ; case ARM :: LDRi12 : case ARM :: LDRBi12 : case ARM :: LDRD : case ARM :: LDRH : case ARM :: LDRSB : case ARM :: LDRSH : case ARM :: VLDRD : case ARM :: VLDRS : case ARM :: t2LDRi8 : case ARM :: t2LDRDi8 : case ARM :: t2LDRSHi8 : case ARM :: t2LDRi12 : case ARM :: t2LDRSHi12 : break ; } switch ( Load2 -> getMachineOpcode ( ) ) { default : return false ; case ARM :: LDRi12 : case ARM :: LDRBi12 : case ARM :: LDRD : case ARM :: LDRH : case ARM :: LDRSB : case ARM :: LDRSH : case ARM :: VLDRD : case ARM :: VLDRS : case ARM :: t2LDRi8 : case ARM :: t2LDRSHi8 : case ARM :: t2LDRi12 : case ARM :: t2LDRSHi12 : break ; } if ( Load1 -> getOperand ( 0 ) != Load2 -> getOperand ( 0 ) || Load1 -> getOperand ( 4 ) != Load2 -> getOperand ( 4 ) ) return false ; if ( Load1 -> getOperand ( 3 ) != Load2 -> getOperand ( 3 ) ) return false ; if ( isa < ConstantSDNode > ( Load1 -> getOperand ( 1 ) ) && isa < ConstantSDNode > ( Load2 -> getOperand ( 1 ) ) ) { Offset1 = cast < ConstantSDNode > ( Load1 -> getOperand ( 1 ) ) -> getSExtValue ( ) ; Offset2 = cast < ConstantSDNode > ( Load2 -> getOperand ( 1 ) ) -> getSExtValue ( ) ; return true ; } return false ; } </s>

areLoadsFromSameBasePtr - This is used by the pre-regalloc scheduler to determine if two loads are loading from the same base address .


<s> bool canCauseFpMLxStall ( unsigned Opcode ) const { return MLxHazardOpcodes . count ( Opcode ) ; } </s>

canCauseFpMLxStall - Return true if an instruction of the specified opcode will cause stalls when scheduled after ( within 4-cycle window ) a fp MLA / MLS instruction .


<s> ARMCC :: CondCodes getPredicate ( const MachineInstr * MI ) const { int PIdx = MI -> findFirstPredOperandIdx ( ) ; return PIdx != - 1 ? ( ARMCC :: CondCodes ) MI -> getOperand ( PIdx ) . getImm ( ) : ARMCC :: AL ; } </s>

Returns the comparison predicate underlying the intrinsic .

ARM ARMCC::CondCodes 1 ARMCC::CondCodes ARMCC::AL


<s> const ARMSubtarget & getSubtarget ( ) const { return Subtarget ; } </s>

getSubtarget - Return the subtarget for which this machine code is being compiled .


<s> bool isFpMLxInstruction ( unsigned Opcode ) const { return MLxEntryMap . count ( Opcode ) ; } </s>

isFpMLxInstruction - This version also returns the multiply opcode and the addition / subtraction opcode to expand to .


<s> bool ARMBaseInstrInfo :: isPredicable ( MachineInstr * MI ) const { if ( ! MI -> isPredicable ( ) ) return false ; if ( ( MI -> getDesc ( ) . TSFlags & ARMII :: DomainMask ) == ARMII :: DomainNEON ) { ARMFunctionInfo * AFI = MI -> getParent ( ) -> getParent ( ) -> getInfo < ARMFunctionInfo > ( ) ; return AFI -> isThumb2Function ( ) ; } return true ; } </s>

Return true if the specified instruction can be predicated .

ARM ARM ARMII::DomainMask ARMII::DomainNEON ARM ARM


<s> bool isProfitableToDupForIfCvt ( MachineBasicBlock & MBB , unsigned NumCycles , BranchProbability Probability ) const override { return NumCycles == 1 ; } </s>

Return true if it 's profitable for if-converter to duplicate instructions of specified accumulated instruction latencies in the specified MBB to enable if-conversion .


<s> bool ARMBaseInstrInfo :: isSchedulingBoundary ( const MachineInstr * MI , const MachineBasicBlock * MBB , const MachineFunction & MF ) const { if ( MI -> isDebugValue ( ) ) return false ; if ( MI -> isTerminator ( ) || MI -> isLabel ( ) ) return true ; MachineBasicBlock :: const_iterator I = MI ; while ( ++ I != MBB -> end ( ) && I -> isDebugValue ( ) ) ; if ( I != MBB -> end ( ) && I -> getOpcode ( ) == ARM :: t2IT ) return true ; if ( ! MI -> isCall ( ) && MI -> definesRegister ( ARM :: SP ) ) return true ; return false ; } </s>

isSchedulingBoundary - Overrides the isSchedulingBoundary from Codegen/TargetInstrInfo.cpp to make it capable of identifying ENDBR intructions and prevent it from being re-scheduled .


<s>
MachineInstr
*
ARMBaseInstrInfo
::
optimizeSelect
(
MachineInstr
*
MI
,
bool
PreferFalse
)
const
{
assert
(
(
MI
->
getOpcode
(
)
==
ARM
::
MOVCCr
||
MI
->
getOpcode
(
)
==
ARM
::
t2MOVCCr
)
&&
"Unknown select instruction"
)
;
const
MachineRegisterInfo
&
MRI
=
MI
->
getParent
(
)
->
getParent
(
)
->
getRegInfo
(
)
;
MachineInstr
*
DefMI
=
canFoldIntoMOVCC
(
MI
->
getOperand
(
2
)
.
getReg
(
)
,
MRI
,
this
)
;
bool
Invert
=
!
DefMI
;
if
(
!
DefMI
)
DefMI
=
canFoldIntoMOVCC
(
MI
->
getOperand
(
1
)
.
getReg
(
)
,
MRI
,
this
)
;
if
(
!
DefMI
)
return
0
;
MachineInstrBuilder
NewMI
=
BuildMI
(
*
MI
->
getParent
(
)
,
MI
,
MI
->
getDebugLoc
(
)
,
DefMI
->
getDesc
(
)
,
MI
->
getOperand
(
0
)
.
getReg
(
)
)
;
const
MCInstrDesc
&
DefDesc
=
DefMI
->
getDesc
(
)
;
for
(
unsigned
i
=
1
,
e
=
DefDesc
.
getNumOperands
(
)
;
i
!=
e
&&
!
DefDesc
.
OpInfo
[
i
]
.
isPredicate
(
)
;
++
i
)
NewMI
.
addOperand
(
DefMI
->
getOperand
(
i
)
)
;
unsigned
CondCode
=
MI
->
getOperand
(
3
)
.
getImm
(
)
;
if
(
Invert
)
NewMI
.
addImm
(
ARMCC
::
getOppositeCondition
(
ARMCC
::
CondCodes
(
CondCode
)
)
)
;
else
NewMI
.
addImm
(
CondCode
)
;
NewMI
.
addOperand
(
MI
->
getOperand
(
4
)
)
;
if
(
NewMI
->
hasOptionalDef
(
)
)
AddDefaultCC
(
NewMI
)
;
MachineOperand
FalseReg
=
MI
->
getOperand
(
Invert
2
:
1
)
;
FalseReg
.
setImplicit
(
)
;
NewMI
.
addOperand
(
FalseReg
)
;
NewMI
->
tieOperands
(
0
,
NewMI
->
getNumOperands
(
)
1
)
;
DefMI
->
eraseFromParent
(
)
;
return
NewMI
;
}
</s>

Given a select instruction that was understood by analyzeSelect and returned Optimizable = true , attempt to optimize MI by merging it with one of its operands .


<s> bool ARMBaseInstrInfo :: shouldScheduleLoadsNear ( SDNode * Load1 , SDNode * Load2 , int64_t Offset1 , int64_t Offset2 , unsigned NumLoads ) const { if ( Subtarget . isThumb1Only ( ) ) return false ; assert ( Offset2 > Offset1 ) ; if ( ( Offset2 - Offset1 ) / 8 > 64 ) return false ; if ( Load1 -> getMachineOpcode ( ) != Load2 -> getMachineOpcode ( ) ) return false ; if ( NumLoads >= 3 ) return false ; return true ; } </s>

shouldScheduleLoadsNear - This is a used by the pre-regalloc scheduler to determine ( in conjunction with areLoadsFromSameBasePtr ) if two loads should be scheduled togther .


<s>
bool
ARMBaseInstrInfo
::
analyzeBranch
(
MachineBasicBlock
&
MBB
,
MachineBasicBlock
*
&
TBB
,
MachineBasicBlock
*
&
FBB
,
SmallVectorImpl
<
MachineOperand
>
&
Cond
,
bool
AllowModify
)
const
{
TBB
=
nullptr
;
FBB
=
nullptr
;
MachineBasicBlock
::
iterator
I
=
MBB
.
end
(
)
;
if
(
I
==
MBB
.
begin
(
)
)
return
false
;
I
;
while
(
isPredicated
(
*
I
)
||
I
->
isTerminator
(
)
||
I
->
isDebugValue
(
)
)
{
bool
CantAnalyze
=
false
;
while
(
I
->
isDebugValue
(
)
||
!
I
->
isTerminator
(
)
)
{
if
(
I
==
MBB
.
begin
(
)
)
return
false
;
I
;
}
if
(
isIndirectBranchOpcode
(
I
->
getOpcode
(
)
)
||
isJumpTableBranchOpcode
(
I
->
getOpcode
(
)
)
)
{
CantAnalyze
=
true
;
}
else
if
(
isUncondBranchOpcode
(
I
->
getOpcode
(
)
)
)
{
TBB
=
I
->
getOperand
(
0
)
.
getMBB
(
)
;
}
else
if
(
isCondBranchOpcode
(
I
->
getOpcode
(
)
)
)
{
if
(
!
Cond
.
empty
(
)
)
return
true
;
assert
(
!
FBB
&&
"FBB should have been null."
)
;
FBB
=
TBB
;
TBB
=
I
->
getOperand
(
0
)
.
getMBB
(
)
;
Cond
.
push_back
(
I
->
getOperand
(
1
)
)
;
Cond
.
push_back
(
I
->
getOperand
(
2
)
)
;
}
else
if
(
I
->
isReturn
(
)
)
{
CantAnalyze
=
!
isPredicated
(
*
I
)
;
}
else
{
return
true
;
}
if
(
!
isPredicated
(
*
I
)
&&
(
isUncondBranchOpcode
(
I
->
getOpcode
(
)
)
||
isIndirectBranchOpcode
(
I
->
getOpcode
(
)
)
||
isJumpTableBranchOpcode
(
I
->
getOpcode
(
)
)
||
I
->
isReturn
(
)
)
)
{
Cond
.
clear
(
)
;
FBB
=
nullptr
;
if
(
AllowModify
)
{
MachineBasicBlock
::
iterator
DI
=
std
::
next
(
I
)
;
while
(
DI
!=
MBB
.
end
(
)
)
{
MachineInstr
&
InstToDelete
=
*
DI
;
++
DI
;
InstToDelete
.
eraseFromParent
(
)
;
}
}
}
if
(
CantAnalyze
)
return
true
;
if
(
I
==
MBB
.
begin
(
)
)
return
false
;
I
;
}
return
false
;
}
</s>

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


<s> bool ARMBaseInstrInfo :: analyzeCompare ( const MachineInstr & MI , unsigned & SrcReg , unsigned & SrcReg2 , int & CmpMask , int & CmpValue ) const { switch ( MI . getOpcode ( ) ) { default : break ; case ARM :: CMPri : case ARM :: t2CMPri : SrcReg = MI . getOperand ( 0 ) . getReg ( ) ; SrcReg2 = 0 ; CmpMask = ~ 0 ; CmpValue = MI . getOperand ( 1 ) . getImm ( ) ; return true ; case ARM :: CMPrr : case ARM :: t2CMPrr : SrcReg = MI . getOperand ( 0 ) . getReg ( ) ; SrcReg2 = MI . getOperand ( 1 ) . getReg ( ) ; CmpMask = ~ 0 ; CmpValue = 0 ; return true ; case ARM :: TSTri : case ARM :: t2TSTri : SrcReg = MI . getOperand ( 0 ) . getReg ( ) ; SrcReg2 = 0 ; CmpMask = MI . getOperand ( 1 ) . getImm ( ) ; CmpValue = 0 ; return true ; } return false ; } </s>

analyzeCompare - For a comparison instruction , return the source registers in SrcReg and SrcReg2 if having two register operands , and the value it compares against in CmpValue .


<s>
bool
ARMBaseInstrInfo
::
analyzeSelect
(
const
MachineInstr
&
MI
,
SmallVectorImpl
<
MachineOperand
>
&
Cond
,
unsigned
&
TrueOp
,
unsigned
&
FalseOp
,
bool
&
Optimizable
)
const
{
assert
(
(
MI
.
getOpcode
(
)
==
ARM
::
MOVCCr
||
MI
.
getOpcode
(
)
==
ARM
::
t2MOVCCr
)
&&
"Unknown select instruction"
)
;
TrueOp
=
1
;
FalseOp
=
2
;
Cond
.
push_back
(
MI
.
getOperand
(
3
)
)
;
Cond
.
push_back
(
MI
.
getOperand
(
4
)
)
;
Optimizable
=
true
;
return
false
;
}
</s>

Analyze the given select instruction , returning true if it can not be understood .


"Can't break virtual register dependencies."

Insert a dependency-breaking instruction before MI to eliminate an unwanted dependency on OpNum .


<s> MachineInstr * ARMBaseInstrInfo :: commuteInstructionImpl ( MachineInstr & MI , bool NewMI , unsigned OpIdx1 , unsigned OpIdx2 ) const { switch ( MI . getOpcode ( ) ) { case ARM :: MOVCCr : case ARM :: t2MOVCCr : { unsigned PredReg = 0 ; ARMCC :: CondCodes CC = getInstrPredicate ( MI , PredReg ) ; if ( CC == ARMCC :: AL || PredReg != ARM :: CPSR ) return nullptr ; MachineInstr * CommutedMI = TargetInstrInfo :: commuteInstructionImpl ( MI , NewMI , OpIdx1 , OpIdx2 ) ; if ( ! CommutedMI ) return nullptr ; CommutedMI -> getOperand ( CommutedMI -> findFirstPredOperandIdx ( ) ) . setImm ( ARMCC :: getOppositeCondition ( CC ) ) ; return CommutedMI ; } } return TargetInstrInfo :: commuteInstructionImpl ( MI , NewMI , OpIdx1 , OpIdx2 ) ; } </s>

Commutes the operands in the given instruction by changing the operands order and/or changing the instruction 's opcode and/or the immediate value operand .

ARM ARM ARM::MOVCCr ARM::t2MOVCCr 0 ARMCC::CondCodes ARMCC::AL ARM::CPSR ARMCC::getOppositeCondition


<s> ScheduleHazardRecognizer * ARMBaseInstrInfo :: CreateTargetHazardRecognizer ( const TargetSubtargetInfo * STI , const ScheduleDAG * DAG ) const { if ( usePreRAHazardRecognizer ( ) ) { const InstrItineraryData * II = static_cast < const ARMSubtarget * > ( STI ) -> getInstrItineraryData ( ) ; return new ScoreboardHazardRecognizer ( II , DAG , "pre-RA-sched" ) ; } return TargetInstrInfo :: CreateTargetHazardRecognizer ( STI , DAG ) ; } </s>

Allocate and return a hazard recognizer to use for this target when scheduling the machine instructions before register allocation .


<s> MachineInstr * ARMBaseInstrInfo :: duplicate ( MachineInstr & Orig , MachineFunction & MF ) const { MachineInstr * MI = TargetInstrInfo :: duplicate ( Orig , MF ) ; switch ( Orig . getOpcode ( ) ) { case ARM :: tLDRpci_pic : case ARM :: t2LDRpci_pic : { unsigned CPI = Orig . getOperand ( 1 ) . getIndex ( ) ; unsigned PCLabelId = duplicateCPV ( MF , CPI ) ; Orig . getOperand ( 1 ) . setIndex ( CPI ) ; Orig . getOperand ( 2 ) . setImm ( PCLabelId ) ; break ; } } return MI ; } </s>

Clones instruction or the whole instruction bundle Orig and insert into MBB before InsertBefore .


"LOAD_STACK_GUARD currently supported only for MachO."

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


<s> std :: pair < uint16_t , uint16_t > ARMBaseInstrInfo :: getExecutionDomain ( const MachineInstr & MI ) const { if ( Subtarget . hasNEON ( ) ) { if ( MI . getOpcode ( ) == ARM :: VMOVD && ! isPredicated ( MI ) ) return std :: make_pair ( ExeVFP , ( 1 << ExeVFP ) | ( 1 << ExeNEON ) ) ; if ( Subtarget . useNEONForFPMovs ( ) && ! isPredicated ( MI ) && ( MI . getOpcode ( ) == ARM :: VMOVRS || MI . getOpcode ( ) == ARM :: VMOVSR || MI . getOpcode ( ) == ARM :: VMOVS ) ) return std :: make_pair ( ExeVFP , ( 1 << ExeVFP ) | ( 1 << ExeNEON ) ) ; } unsigned Domain = MI . getDesc ( ) . TSFlags & ARMII :: DomainMask ; if ( Domain & ARMII :: DomainNEON ) return std :: make_pair ( ExeNEON , 0 ) ; if ( ( Domain & ARMII :: DomainNEONA8 ) && Subtarget . isCortexA8 ( ) ) return std :: make_pair ( ExeNEON , 0 ) ; if ( Domain & ARMII :: DomainVFP ) return std :: make_pair ( ExeVFP , 0 ) ; return std :: make_pair ( ExeGeneric , 0 ) ; } </s>

Return the current execution domain and bit mask of possible domains for instruction .


<s>
bool
ARMBaseInstrInfo
::
getExtractSubregLikeInputs
(
const
MachineInstr
&
MI
,
unsigned
DefIdx
,
RegSubRegPairAndIdx
&
InputReg
)
const
{
assert
(
DefIdx
<
MI
.
getDesc
(
)
.
getNumDefs
(
)
&&
"Invalid definition index"
)
;
assert
(
MI
.
isExtractSubregLike
(
)
&&
"Invalid kind of instruction"
)
;
switch
(
MI
.
getOpcode
(
)
)
{
case
ARM
::
VMOVRRD
:
const
MachineOperand
&
MOReg
=
MI
.
getOperand
(
2
)
;
InputReg
.
Reg
=
MOReg
.
getReg
(
)
;
InputReg
.
SubReg
=
MOReg
.
getSubReg
(
)
;
InputReg
.
SubIdx
=
DefIdx
==
0
ARM
::
ssub_0
:
ARM
::
ssub_1
;
return
true
;
}
llvm_unreachable
(
"Target dependent opcode missing"
)
;
}
</s>

Target-dependent implementation of getExtractSubregInputs .


<s> unsigned getFramePred ( const MachineInstr & MI ) const { assert ( isFrameInstr ( MI ) ) ; return MI . getOperand ( 3 ) . getReg ( ) ; } </s>

Returns predicate register associated with the given frame instruction .


<s>
bool
ARMBaseInstrInfo
::
getInsertSubregLikeInputs
(
const
MachineInstr
&
MI
,
unsigned
DefIdx
,
RegSubRegPair
&
BaseReg
,
RegSubRegPairAndIdx
&
InsertedReg
)
const
{
assert
(
DefIdx
<
MI
.
getDesc
(
)
.
getNumDefs
(
)
&&
"Invalid definition index"
)
;
assert
(
MI
.
isInsertSubregLike
(
)
&&
"Invalid kind of instruction"
)
;
switch
(
MI
.
getOpcode
(
)
)
{
case
ARM
::
VSETLNi32
:
const
MachineOperand
&
MOBaseReg
=
MI
.
getOperand
(
1
)
;
const
MachineOperand
&
MOInsertedReg
=
MI
.
getOperand
(
2
)
;
const
MachineOperand
&
MOIndex
=
MI
.
getOperand
(
3
)
;
BaseReg
.
Reg
=
MOBaseReg
.
getReg
(
)
;
BaseReg
.
SubReg
=
MOBaseReg
.
getSubReg
(
)
;
InsertedReg
.
Reg
=
MOInsertedReg
.
getReg
(
)
;
InsertedReg
.
SubReg
=
MOInsertedReg
.
getSubReg
(
)
;
InsertedReg
.
SubIdx
=
MOIndex
.
getImm
(
)
==
0
ARM
::
ssub_0
:
ARM
::
ssub_1
;
return
true
;
}
llvm_unreachable
(
"Target dependent opcode missing"
)
;
}
</s>

Target-dependent implementation of getInsertSubregInputs .


<s> unsigned ARMBaseInstrInfo :: getInstrLatency ( const InstrItineraryData * ItinData , const MachineInstr & MI , unsigned * PredCost ) const { if ( MI . isCopyLike ( ) || MI . isInsertSubreg ( ) || MI . isRegSequence ( ) || MI . isImplicitDef ( ) ) return 1 ; if ( MI . isBundle ( ) ) { unsigned Latency = 0 ; MachineBasicBlock :: const_instr_iterator I = MI . getIterator ( ) ; MachineBasicBlock :: const_instr_iterator E = MI . getParent ( ) -> instr_end ( ) ; while ( ++ I != E && I -> isInsideBundle ( ) ) { if ( I -> getOpcode ( ) != ARM :: t2IT ) Latency += getInstrLatency ( ItinData , * I , PredCost ) ; } return Latency ; } const MCInstrDesc & MCID = MI . getDesc ( ) ; if ( PredCost && ( MCID . isCall ( ) || MCID . hasImplicitDefOfPhysReg ( ARM :: CPSR ) ) ) { * PredCost = 1 ; } if ( ! ItinData ) return MI . mayLoad ( ) ? 3 : 1 ; unsigned Class = MCID . getSchedClass ( ) ; if ( ! ItinData -> isEmpty ( ) && ItinData -> getNumMicroOps ( Class ) < 0 ) return getNumMicroOps ( ItinData , MI ) ; unsigned Latency = ItinData -> getStageLatency ( Class ) ; unsigned DefAlign = MI . hasOneMemOperand ( ) ? ( * MI . memoperands_begin ( ) ) -> getAlignment ( ) : 0 ; int Adj = adjustDefLatency ( Subtarget , MI , MCID , DefAlign ) ; if ( Adj >= 0 || ( int ) Latency > - Adj ) { return Latency + Adj ; } return Latency ; } </s>

Compute the instruction latency of a given instruction .


<s> unsigned ARMBaseInstrInfo :: getNumLDMAddresses ( const MachineInstr & MI ) const { unsigned Size = 0 ; for ( MachineInstr :: mmo_iterator I = MI . memoperands_begin ( ) , E = MI . memoperands_end ( ) ; I != E ; ++ I ) { Size += ( * I ) -> getSize ( ) ; } return Size / 4 ; } </s>

Get the number of addresses by LDM or VLDM or zero for unknown .


<s>
unsigned
ARMBaseInstrInfo
::
getPartialRegUpdateClearance
(
const
MachineInstr
&
MI
,
unsigned
OpNum
,
const
TargetRegisterInfo
*
TRI
)
const
{
auto
PartialUpdateClearance
=
Subtarget
.
getPartialUpdateClearance
(
)
;
if
(
!
PartialUpdateClearance
)
return
0
;
assert
(
TRI
&&
"Need TRI instance"
)
;
const
MachineOperand
&
MO
=
MI
.
getOperand
(
OpNum
)
;
if
(
MO
.
readsReg
(
)
)
return
0
;
unsigned
Reg
=
MO
.
getReg
(
)
;
int
UseOp
=
1
;
switch
(
MI
.
getOpcode
(
)
)
{
case
ARM
::
VLDRS
:
case
ARM
::
FCONSTS
:
case
ARM
::
VMOVSR
:
case
ARM
::
VMOVv8i8
:
case
ARM
::
VMOVv4i16
:
case
ARM
::
VMOVv2i32
:
case
ARM
::
VMOVv2f32
:
case
ARM
::
VMOVv1i64
:
UseOp
=
MI
.
findRegisterUseOperandIdx
(
Reg
,
false
,
TRI
)
;
break
;
case
ARM
::
VLD1LNd32
:
UseOp
=
3
;
break
;
default
:
return
0
;
}
if
(
UseOp
!=
1
&&
MI
.
getOperand
(
UseOp
)
.
readsReg
(
)
)
return
0
;
if
(
TargetRegisterInfo
::
isVirtualRegister
(
Reg
)
)
{
if
(
!
MO
.
getSubReg
(
)
||
MI
.
readsVirtualRegister
(
Reg
)
)
return
0
;
}
else
if
(
ARM
::
SPRRegClass
.
contains
(
Reg
)
)
{
unsigned
DReg
=
TRI
->
getMatchingSuperReg
(
Reg
,
ARM
::
ssub_0
,
&
ARM
::
DPRRegClass
)
;
if
(
!
DReg
||
!
MI
.
definesRegister
(
DReg
,
TRI
)
)
return
0
;
}
return
PartialUpdateClearance
;
}
</s>

Inform the BreakFalseDeps pass how many idle instructions we would like before a partial register update .


<s> ARMCC :: CondCodes getPredicate ( const MachineInstr & MI ) const { int PIdx = MI . findFirstPredOperandIdx ( ) ; return PIdx != - 1 ? ( ARMCC :: CondCodes ) MI . getOperand ( PIdx ) . getImm ( ) : ARMCC :: AL ; } </s>

Returns the comparison predicate underlying the intrinsic .


<s>
bool
ARMBaseInstrInfo
::
getRegSequenceLikeInputs
(
const
MachineInstr
&
MI
,
unsigned
DefIdx
,
SmallVectorImpl
<
RegSubRegPairAndIdx
>
&
InputRegs
)
const
{
assert
(
DefIdx
<
MI
.
getDesc
(
)
.
getNumDefs
(
)
&&
"Invalid definition index"
)
;
assert
(
MI
.
isRegSequenceLike
(
)
&&
"Invalid kind of instruction"
)
;
switch
(
MI
.
getOpcode
(
)
)
{
case
ARM
::
VMOVDRR
:
const
MachineOperand
*
MOReg
=
&
MI
.
getOperand
(
1
)
;
InputRegs
.
push_back
(
RegSubRegPairAndIdx
(
MOReg
->
getReg
(
)
,
MOReg
->
getSubReg
(
)
,
ARM
::
ssub_0
)
)
;
MOReg
=
&
MI
.
getOperand
(
2
)
;
InputRegs
.
push_back
(
RegSubRegPairAndIdx
(
MOReg
->
getReg
(
)
,
MOReg
->
getSubReg
(
)
,
ARM
::
ssub_1
)
)
;
return
true
;
}
llvm_unreachable
(
"Target dependent opcode missing"
)
;
}
</s>

Target-dependent implementation of getRegSequenceInputs .