<s> bool ARMCallLowering :: lowerFormalArguments ( MachineIRBuilder & MIRBuilder , const Function & F , ArrayRef < unsigned > VRegs ) const { auto & TLI = * getTLI < ARMTargetLowering > ( ) ; auto Subtarget = TLI . getSubtarget ( ) ; if ( Subtarget -> isThumb1Only ( ) ) return false ; if ( F . arg_empty ( ) ) return true ; if ( F . isVarArg ( ) ) return false ; auto & MF = MIRBuilder . getMF ( ) ; auto & MBB = MIRBuilder . getMBB ( ) ; auto DL = MF . getDataLayout ( ) ; for ( auto & Arg : F . args ( ) ) { if ( ! isSupportedType ( DL , TLI , Arg . getType ( ) ) ) return false ; if ( Arg . hasByValOrInAllocaAttr ( ) ) return false ; } CCAssignFn * AssignFn = TLI . CCAssignFnForCall ( F . getCallingConv ( ) , F . isVarArg ( ) ) ; FormalArgHandler ArgHandler ( MIRBuilder , MIRBuilder . getMF ( ) . getRegInfo ( ) , AssignFn ) ; SmallVector < ArgInfo , 8 > ArgInfos ; SmallVector < unsigned , 4 > SplitRegs ; unsigned Idx = 0 ; for ( auto & Arg : F . args ( ) ) { ArgInfo AInfo ( VRegs [ Idx ] , Arg . getType ( ) ) ; setArgFlags ( AInfo , Idx + AttributeList :: FirstArgIndex , DL , F ) ; SplitRegs . clear ( ) ; splitToValueTypes ( AInfo , ArgInfos , MF , [ & ] ( unsigned Reg , uint64_t Offset ) { SplitRegs . push_back ( Reg ) ; } ) ; if ( ! SplitRegs . empty ( ) ) MIRBuilder . buildMerge ( VRegs [ Idx ] , SplitRegs ) ; Idx ++ ; } if ( ! MBB . empty ( ) ) MIRBuilder . setInstr ( * MBB . begin ( ) ) ; if ( ! handleAssignments ( MIRBuilder , ArgInfos , ArgHandler ) ) return false ; MIRBuilder . setMBB ( MBB ) ; return true ; } </s>

This hook must be implemented to lower the incoming ( formal ) arguments , described by VRegs , for GlobalISel .


<s>
bool
ARMCallLowering
::
lowerReturn
(
MachineIRBuilder
&
MIRBuilder
,
const
Value
*
Val
,
ArrayRef
<
unsigned
>
VRegs
)
const
{
assert
(
!
Val
==
VRegs
.
empty
(
)
&&
"Return value without a vreg"
)
;
auto
const
&
ST
=
MIRBuilder
.
getMF
(
)
.
getSubtarget
<
ARMSubtarget
>
(
)
;
unsigned
Opcode
=
ST
.
getReturnOpcode
(
)
;
auto
Ret
=
MIRBuilder
.
buildInstrNoInsert
(
Opcode
)
.
add
(
predOps
(
ARMCC
::
AL
)
)
;
if
(
!
lowerReturnVal
(
MIRBuilder
,
Val
,
VRegs
,
Ret
)
)
return
false
;
MIRBuilder
.
insertInstr
(
Ret
)
;
return
true
;
}
</s>

This hook behaves as the extended lowerReturn function , but for targets that do not support swifterror value promotion .

ARM
ARM
"Return value without a vreg"
ARM
ARMCC::AL


Break OrigArgInfo into one or more pieces the calling convention can process , returned in SplitArgs .


<s>
void
assignValueToAddress
(
unsigned
ValVReg
,
unsigned
Addr
,
uint64_t
Size
,
MachinePointerInfo
&
MPO
,
CCValAssign
&
VA
)
override
{
assert
(
(
Size
==
1
||
Size
==
2
||
Size
==
4
)
&&
"Unsupported size"
)
;
if
(
VA
.
getLocInfo
(
)
==
CCValAssign
::
SExt
||
VA
.
getLocInfo
(
)
==
CCValAssign
::
ZExt
)
{
Size
=
4
;
assert
(
MRI
.
getType
(
ValVReg
)
.
isScalar
(
)
&&
"Only scalars supported atm"
)
;
MRI
.
setType
(
ValVReg
,
LLT
::
scalar
(
32
)
)
;
}
auto
MMO
=
MIRBuilder
.
getMF
(
)
.
getMachineMemOperand
(
MPO
,
MachineMemOperand
::
MOLoad
,
Size
,
0
)
;
MIRBuilder
.
buildLoad
(
ValVReg
,
Addr
,
*
MMO
)
;
}
</s>

An overload which takes an ArgInfo if additional information about the arg is needed .


<s>
void
assignValueToReg
(
unsigned
ValVReg
,
unsigned
PhysReg
,
CCValAssign
&
VA
)
override
{
assert
(
VA
.
isRegLoc
(
)
&&
"Value shouldn't be assigned to reg"
)
;
assert
(
VA
.
getLocReg
(
)
==
PhysReg
&&
"Assigning to the wrong reg?"
)
;
assert
(
VA
.
getValVT
(
)
.
getSizeInBits
(
)
<=
32
&&
"Unsupported value size"
)
;
assert
(
VA
.
getLocVT
(
)
.
getSizeInBits
(
)
==
32
&&
"Unsupported location size"
)
;
MIRBuilder
.
getMBB
(
)
.
addLiveIn
(
PhysReg
)
;
MIRBuilder
.
buildCopy
(
ValVReg
,
PhysReg
)
;
}
</s>

The specified value has been assigned to a physical register , handle the appropriate COPY ( either to or from ) and mark any relevant uses/defines as needed .

ARM
"Value shouldn't be assigned to reg"
"Assigning to the wrong reg?"
32
"Unsupported value size"
32
"Unsupported location size"


<s>
unsigned
getStackAddress
(
uint64_t
Size
,
int64_t
Offset
,
MachinePointerInfo
&
MPO
)
override
{
assert
(
(
Size
==
1
||
Size
==
2
||
Size
==
4
)
&&
"Unsupported size"
)
;
auto
&
MFI
=
MIRBuilder
.
getMF
(
)
.
getFrameInfo
(
)
;
int
FI
=
MFI
.
CreateFixedObject
(
Size
,
Offset
,
true
)
;
MPO
=
MachinePointerInfo
::
getFixedStack
(
MIRBuilder
.
getMF
(
)
,
FI
)
;
unsigned
AddrReg
=
MRI
.
createGenericVirtualRegister
(
LLT
::
pointer
(
MPO
.
getAddrSpace
(
)
,
32
)
)
;
MIRBuilder
.
buildFrameIndex
(
AddrReg
,
FI
)
;
return
AddrReg
;
}
</s>

Materialize a VReg containing the address of the specified stack-based object .


<s> bool ARMCallLowering :: lowerFormalArguments ( MachineIRBuilder & MIRBuilder , const Function & F , ArrayRef < unsigned > VRegs ) const { if ( F . arg_empty ( ) ) return true ; if ( F . isVarArg ( ) ) return false ; auto DL = MIRBuilder . getMF ( ) . getDataLayout ( ) ; auto & TLI = * getTLI < ARMTargetLowering > ( ) ; if ( TLI . getSubtarget ( ) -> isThumb ( ) ) return false ; auto & Args = F . getArgumentList ( ) ; for ( auto & Arg : Args ) if ( ! isSupportedType ( DL , TLI , Arg . getType ( ) ) ) return false ; CCAssignFn * AssignFn = TLI . CCAssignFnForCall ( F . getCallingConv ( ) , F . isVarArg ( ) ) ; SmallVector < ArgInfo , 8 > ArgInfos ; unsigned Idx = 0 ; for ( auto & Arg : Args ) { ArgInfo AInfo ( VRegs [ Idx ] , Arg . getType ( ) ) ; setArgFlags ( AInfo , Idx + 1 , DL , F ) ; ArgInfos . push_back ( AInfo ) ; Idx ++ ; } FormalArgHandler ArgHandler ( MIRBuilder , MIRBuilder . getMF ( ) . getRegInfo ( ) , AssignFn ) ; return handleAssignments ( MIRBuilder , ArgInfos , ArgHandler ) ; } </s>


<s>
bool
ARMCallLowering
::
lowerReturn
(
MachineIRBuilder
&
MIRBuilder
,
const
Value
*
Val
,
unsigned
VReg
)
const
{
assert
(
!
Val
==
!
VReg
&&
"Return value without a vreg"
)
;
auto
Ret
=
MIRBuilder
.
buildInstrNoInsert
(
ARM
::
BX_RET
)
.
add
(
predOps
(
ARMCC
::
AL
)
)
;
if
(
!
lowerReturnVal
(
MIRBuilder
,
Val
,
VReg
,
Ret
)
)
return
false
;
MIRBuilder
.
insertInstr
(
Ret
)
;
return
true
;
}
</s>

ARM
ARM
"Return value without a vreg"
ARM::BX_RET
ARMCC::AL


<s>
void
assignValueToAddress
(
unsigned
ValVReg
,
unsigned
Addr
,
uint64_t
Size
,
MachinePointerInfo
&
MPO
,
CCValAssign
&
VA
)
override
{
assert
(
Size
==
4
&&
"Unsupported size"
)
;
auto
MMO
=
MIRBuilder
.
getMF
(
)
.
getMachineMemOperand
(
MPO
,
MachineMemOperand
::
MOLoad
,
Size
,
0
)
;
MIRBuilder
.
buildLoad
(
ValVReg
,
Addr
,
*
MMO
)
;
}
</s>


<s>
void
assignValueToReg
(
unsigned
ValVReg
,
unsigned
PhysReg
,
CCValAssign
&
VA
)
override
{
assert
(
VA
.
isRegLoc
(
)
&&
"Value shouldn't be assigned to reg"
)
;
assert
(
VA
.
getLocReg
(
)
==
PhysReg
&&
"Assigning to the wrong reg?"
)
;
assert
(
VA
.
getValVT
(
)
.
getSizeInBits
(
)
<=
32
&&
"Unsupported value size"
)
;
assert
(
VA
.
getLocVT
(
)
.
getSizeInBits
(
)
==
32
&&
"Unsupported location size"
)
;
assert
(
VA
.
getLocInfo
(
)
!=
CCValAssign
::
SExt
&&
VA
.
getLocInfo
(
)
!=
CCValAssign
::
ZExt
&&
"ABI extensions not supported yet"
)
;
MIRBuilder
.
buildCopy
(
PhysReg
,
ValVReg
)
;
MIB
.
addUse
(
PhysReg
,
RegState
::
Implicit
)
;
}
</s>

ARM
"Value shouldn't be assigned to reg"
"Assigning to the wrong reg?"
32
"Unsupported value size"
32
"Unsupported location size"
"ABI extensions not supported yet"


<s>
unsigned
getStackAddress
(
uint64_t
Size
,
int64_t
Offset
,
MachinePointerInfo
&
MPO
)
override
{
assert
(
Size
==
4
&&
"Unsupported size"
)
;
auto
&
MFI
=
MIRBuilder
.
getMF
(
)
.
getFrameInfo
(
)
;
int
FI
=
MFI
.
CreateFixedObject
(
Size
,
Offset
,
true
)
;
MPO
=
MachinePointerInfo
::
getFixedStack
(
MIRBuilder
.
getMF
(
)
,
FI
)
;
unsigned
AddrReg
=
MRI
.
createGenericVirtualRegister
(
LLT
::
pointer
(
MPO
.
getAddrSpace
(
)
,
32
)
)
;
MIRBuilder
.
buildFrameIndex
(
AddrReg
,
FI
)
;
return
AddrReg
;
}
</s>


<s> bool ARMCallLowering :: lowerFormalArguments ( MachineIRBuilder & MIRBuilder , const Function & F , ArrayRef < unsigned > VRegs ) const { if ( F . arg_empty ( ) ) return true ; if ( F . isVarArg ( ) ) return false ; auto DL = MIRBuilder . getMF ( ) . getDataLayout ( ) ; auto & TLI = * getTLI < ARMTargetLowering > ( ) ; auto & Args = F . getArgumentList ( ) ; unsigned ArgIdx = 0 ; for ( auto & Arg : Args ) { ArgIdx ++ ; if ( ! isSupportedType ( DL , TLI , Arg . getType ( ) ) ) return false ; if ( ArgIdx > 4 && Arg . getType ( ) -> getIntegerBitWidth ( ) != 32 ) return false ; } CCAssignFn * AssignFn = TLI . CCAssignFnForCall ( F . getCallingConv ( ) , F . isVarArg ( ) ) ; SmallVector < ArgInfo , 8 > ArgInfos ; unsigned Idx = 0 ; for ( auto & Arg : Args ) { ArgInfo AInfo ( VRegs [ Idx ] , Arg . getType ( ) ) ; setArgFlags ( AInfo , Idx + 1 , DL , F ) ; ArgInfos . push_back ( AInfo ) ; Idx ++ ; } FormalArgHandler ArgHandler ( MIRBuilder , MIRBuilder . getMF ( ) . getRegInfo ( ) ) ; return handleAssignments ( MIRBuilder , AssignFn , ArgInfos , ArgHandler ) ; } </s>


<s>
bool
ARMCallLowering
::
lowerReturn
(
MachineIRBuilder
&
MIRBuilder
,
const
Value
*
Val
,
unsigned
VReg
)
const
{
assert
(
!
Val
==
!
VReg
&&
"Return value without a vreg"
)
;
auto
Ret
=
AddDefaultPred
(
MIRBuilder
.
buildInstrNoInsert
(
ARM
::
BX_RET
)
)
;
if
(
!
lowerReturnVal
(
MIRBuilder
,
Val
,
VReg
,
Ret
)
)
return
false
;
MIRBuilder
.
insertInstr
(
Ret
)
;
return
true
;
}
</s>

ARM
ARM
"Return value without a vreg"
ARM::BX_RET


<s> bool ARMCallLowering :: lowerFormalArguments ( MachineIRBuilder & MIRBuilder , const Function & F , ArrayRef < unsigned > VRegs ) const { auto & TLI = * getTLI < ARMTargetLowering > ( ) ; auto Subtarget = TLI . getSubtarget ( ) ; if ( Subtarget -> isThumb ( ) ) return false ; if ( F . arg_empty ( ) ) return true ; if ( F . isVarArg ( ) ) return false ; auto & MF = MIRBuilder . getMF ( ) ; auto & MBB = MIRBuilder . getMBB ( ) ; auto DL = MF . getDataLayout ( ) ; for ( auto & Arg : F . args ( ) ) { if ( ! isSupportedType ( DL , TLI , Arg . getType ( ) ) ) return false ; if ( Arg . hasByValOrInAllocaAttr ( ) ) return false ; } CCAssignFn * AssignFn = TLI . CCAssignFnForCall ( F . getCallingConv ( ) , F . isVarArg ( ) ) ; FormalArgHandler ArgHandler ( MIRBuilder , MIRBuilder . getMF ( ) . getRegInfo ( ) , AssignFn ) ; SmallVector < ArgInfo , 8 > ArgInfos ; SmallVector < unsigned , 4 > SplitRegs ; unsigned Idx = 0 ; for ( auto & Arg : F . args ( ) ) { ArgInfo AInfo ( VRegs [ Idx ] , Arg . getType ( ) ) ; setArgFlags ( AInfo , Idx + AttributeList :: FirstArgIndex , DL , F ) ; SplitRegs . clear ( ) ; splitToValueTypes ( AInfo , ArgInfos , MF , [ & ] ( unsigned Reg , uint64_t Offset ) { SplitRegs . push_back ( Reg ) ; } ) ; if ( ! SplitRegs . empty ( ) ) MIRBuilder . buildMerge ( VRegs [ Idx ] , SplitRegs ) ; Idx ++ ; } if ( ! MBB . empty ( ) ) MIRBuilder . setInstr ( * MBB . begin ( ) ) ; return handleAssignments ( MIRBuilder , ArgInfos , ArgHandler ) ; } </s>


<s>
bool
ARMCallLowering
::
lowerReturn
(
MachineIRBuilder
&
MIRBuilder
,
const
Value
*
Val
,
unsigned
VReg
)
const
{
assert
(
!
Val
==
!
VReg
&&
"Return value without a vreg"
)
;
auto
const
&
ST
=
MIRBuilder
.
getMF
(
)
.
getSubtarget
<
ARMSubtarget
>
(
)
;
unsigned
Opcode
=
ST
.
getReturnOpcode
(
)
;
auto
Ret
=
MIRBuilder
.
buildInstrNoInsert
(
Opcode
)
.
add
(
predOps
(
ARMCC
::
AL
)
)
;
if
(
!
lowerReturnVal
(
MIRBuilder
,
Val
,
VReg
,
Ret
)
)
return
false
;
MIRBuilder
.
insertInstr
(
Ret
)
;
return
true
;
}
</s>


<s>
unsigned
assignCustomValue
(
ARMCallLowering
::
ArgInfo
&
Arg
,
ArrayRef
<
CCValAssign
>
VAs
,
std
::
function
<
void
(
)
>
*
Thunk
)
override
{
assert
(
Arg
.
Regs
.
size
(
)
==
1
&&
"Can't handle multple regs yet"
)
;
CCValAssign
VA
=
VAs
[
0
]
;
assert
(
VA
.
needsCustom
(
)
&&
"Value doesn't need custom handling"
)
;
if
(
VA
.
getValVT
(
)
!=
MVT
::
f64
)
return
0
;
CCValAssign
NextVA
=
VAs
[
1
]
;
assert
(
NextVA
.
needsCustom
(
)
&&
"Value doesn't need custom handling"
)
;
assert
(
NextVA
.
getValVT
(
)
==
MVT
::
f64
&&
"Unsupported type"
)
;
assert
(
VA
.
getValNo
(
)
==
NextVA
.
getValNo
(
)
&&
"Values belong to different arguments"
)
;
assert
(
VA
.
isRegLoc
(
)
&&
"Value should be in reg"
)
;
assert
(
NextVA
.
isRegLoc
(
)
&&
"Value should be in reg"
)
;
Register
NewRegs
[
]
=
{
MRI
.
createGenericVirtualRegister
(
LLT
::
scalar
(
32
)
)
,
MRI
.
createGenericVirtualRegister
(
LLT
::
scalar
(
32
)
)
}
;
assignValueToReg
(
NewRegs
[
0
]
,
VA
.
getLocReg
(
)
,
VA
)
;
assignValueToReg
(
NewRegs
[
1
]
,
NextVA
.
getLocReg
(
)
,
NextVA
)
;
bool
IsLittle
=
MIRBuilder
.
getMF
(
)
.
getSubtarget
<
ARMSubtarget
>
(
)
.
isLittle
(
)
;
if
(
!
IsLittle
)
std
::
swap
(
NewRegs
[
0
]
,
NewRegs
[
1
]
)
;
MIRBuilder
.
buildMerge
(
Arg
.
Regs
[
0
]
,
NewRegs
)
;
return
1
;
}
</s>

Handle custom values , which may be passed into one or more of VAs .


<s>
void
assignValueToAddress
(
Register
ValVReg
,
Register
Addr
,
LLT
MemTy
,
MachinePointerInfo
&
MPO
,
CCValAssign
&
VA
)
override
{
if
(
VA
.
getLocInfo
(
)
==
CCValAssign
::
SExt
||
VA
.
getLocInfo
(
)
==
CCValAssign
::
ZExt
)
{
MemTy
=
LLT
::
scalar
(
32
)
;
assert
(
MRI
.
getType
(
ValVReg
)
.
isScalar
(
)
&&
"Only scalars supported atm"
)
;
auto
LoadVReg
=
buildLoad
(
LLT
::
scalar
(
32
)
,
Addr
,
MemTy
,
MPO
)
;
MIRBuilder
.
buildTrunc
(
ValVReg
,
LoadVReg
)
;
}
else
{
buildLoad
(
ValVReg
,
Addr
,
MemTy
,
MPO
)
;
}
}
</s>


<s>
void
assignValueToReg
(
Register
ValVReg
,
Register
PhysReg
,
CCValAssign
VA
)
override
{
assert
(
VA
.
isRegLoc
(
)
&&
"Value shouldn't be assigned to reg"
)
;
assert
(
VA
.
getLocReg
(
)
==
PhysReg
&&
"Assigning to the wrong reg?"
)
;
uint64_t
ValSize
=
VA
.
getValVT
(
)
.
getFixedSizeInBits
(
)
;
uint64_t
LocSize
=
VA
.
getLocVT
(
)
.
getFixedSizeInBits
(
)
;
assert
(
ValSize
<=
64
&&
"Unsupported value size"
)
;
assert
(
LocSize
<=
64
&&
"Unsupported location size"
)
;
markPhysRegUsed
(
PhysReg
)
;
if
(
ValSize
==
LocSize
)
{
MIRBuilder
.
buildCopy
(
ValVReg
,
PhysReg
)
;
}
else
{
assert
(
ValSize
<
LocSize
&&
"Extensions not supported"
)
;
auto
PhysRegToVReg
=
MIRBuilder
.
buildCopy
(
LLT
::
scalar
(
LocSize
)
,
PhysReg
)
;
MIRBuilder
.
buildTrunc
(
ValVReg
,
PhysRegToVReg
)
;
}
}
</s>

ARM
"Value shouldn't be assigned to reg"
"Assigning to the wrong reg?"
64
"Unsupported value size"
64
"Unsupported location size"
"Extensions not supported"


<s> MachineInstrBuilder buildLoad ( const DstOp & Res , Register Addr , LLT MemTy , MachinePointerInfo & MPO ) { MachineFunction & MF = MIRBuilder . getMF ( ) ; auto MMO = MF . getMachineMemOperand ( MPO , MachineMemOperand :: MOLoad , MemTy , inferAlignFromPtrInfo ( MF , MPO ) ) ; return MIRBuilder . buildLoad ( Res , Addr , * MMO ) ; } </s>

Build and insert a G_LOAD instruction , while constructing the MachineMemOperand .


<s>
Register
getStackAddress
(
uint64_t
Size
,
int64_t
Offset
,
MachinePointerInfo
&
MPO
,
ISD
::
ArgFlagsTy
Flags
)
override
{
assert
(
(
Size
==
1
||
Size
==
2
||
Size
==
4
||
Size
==
8
)
&&
"Unsupported size"
)
;
auto
&
MFI
=
MIRBuilder
.
getMF
(
)
.
getFrameInfo
(
)
;
const
bool
IsImmutable
=
!
Flags
.
isByVal
(
)
;
int
FI
=
MFI
.
CreateFixedObject
(
Size
,
Offset
,
IsImmutable
)
;
MPO
=
MachinePointerInfo
::
getFixedStack
(
MIRBuilder
.
getMF
(
)
,
FI
)
;
return
MIRBuilder
.
buildFrameIndex
(
LLT
::
pointer
(
MPO
.
getAddrSpace
(
)
,
32
)
,
FI
)
.
getReg
(
0
)
;
}
</s>


<s> bool ARMCallLowering :: lowerFormalArguments ( MachineIRBuilder & MIRBuilder , const Function & F , ArrayRef < ArrayRef < Register >> VRegs , FunctionLoweringInfo & FLI ) const { auto & TLI = * getTLI < ARMTargetLowering > ( ) ; auto Subtarget = TLI . getSubtarget ( ) ; if ( Subtarget -> isThumb1Only ( ) ) return false ; if ( F . arg_empty ( ) ) return true ; if ( F . isVarArg ( ) ) return false ; auto & MF = MIRBuilder . getMF ( ) ; auto & MBB = MIRBuilder . getMBB ( ) ; const auto & DL = MF . getDataLayout ( ) ; for ( auto & Arg : F . args ( ) ) { if ( ! isSupportedType ( DL , TLI , Arg . getType ( ) ) ) return false ; if ( Arg . hasPassPointeeByValueCopyAttr ( ) ) return false ; } CCAssignFn * AssignFn = TLI . CCAssignFnForCall ( F . getCallingConv ( ) , F . isVarArg ( ) ) ; OutgoingValueAssigner ArgAssigner ( AssignFn ) ; FormalArgHandler ArgHandler ( MIRBuilder , MIRBuilder . getMF ( ) . getRegInfo ( ) ) ; SmallVector < ArgInfo , 8 > SplitArgInfos ; unsigned Idx = 0 ; for ( auto & Arg : F . args ( ) ) { ArgInfo OrigArgInfo ( VRegs [ Idx ] , Arg . getType ( ) , Idx ) ; setArgFlags ( OrigArgInfo , Idx + AttributeList :: FirstArgIndex , DL , F ) ; splitToValueTypes ( OrigArgInfo , SplitArgInfos , DL , F . getCallingConv ( ) ) ; Idx ++ ; } if ( ! MBB . empty ( ) ) MIRBuilder . setInstr ( * MBB . begin ( ) ) ; if ( ! determineAndHandleAssignments ( ArgHandler , ArgAssigner , SplitArgInfos , MIRBuilder , F . getCallingConv ( ) , F . isVarArg ( ) ) ) return false ; MIRBuilder . setMBB ( MBB ) ; return true ; } </s>


<s>
bool
ARMCallLowering
::
lowerReturn
(
MachineIRBuilder
&
MIRBuilder
,
const
Value
*
Val
,
ArrayRef
<
Register
>
VRegs
,
FunctionLoweringInfo
&
FLI
)
const
{
assert
(
!
Val
==
VRegs
.
empty
(
)
&&
"Return value without a vreg"
)
;
auto
const
&
ST
=
MIRBuilder
.
getMF
(
)
.
getSubtarget
<
ARMSubtarget
>
(
)
;
unsigned
Opcode
=
ST
.
getReturnOpcode
(
)
;
auto
Ret
=
MIRBuilder
.
buildInstrNoInsert
(
Opcode
)
.
add
(
predOps
(
ARMCC
::
AL
)
)
;
if
(
!
lowerReturnVal
(
MIRBuilder
,
Val
,
VRegs
,
Ret
)
)
return
false
;
MIRBuilder
.
insertInstr
(
Ret
)
;
return
true
;
}
</s>


<s>
unsigned
assignCustomValue
(
ARMCallLowering
::
ArgInfo
&
Arg
,
ArrayRef
<
CCValAssign
>
VAs
)
override
{
assert
(
Arg
.
Regs
.
size
(
)
==
1
&&
"Can't handle multple regs yet"
)
;
CCValAssign
VA
=
VAs
[
0
]
;
assert
(
VA
.
needsCustom
(
)
&&
"Value doesn't need custom handling"
)
;
if
(
VA
.
getValVT
(
)
!=
MVT
::
f64
)
return
0
;
CCValAssign
NextVA
=
VAs
[
1
]
;
assert
(
NextVA
.
needsCustom
(
)
&&
"Value doesn't need custom handling"
)
;
assert
(
NextVA
.
getValVT
(
)
==
MVT
::
f64
&&
"Unsupported type"
)
;
assert
(
VA
.
getValNo
(
)
==
NextVA
.
getValNo
(
)
&&
"Values belong to different arguments"
)
;
assert
(
VA
.
isRegLoc
(
)
&&
"Value should be in reg"
)
;
assert
(
NextVA
.
isRegLoc
(
)
&&
"Value should be in reg"
)
;
Register
NewRegs
[
]
=
{
MRI
.
createGenericVirtualRegister
(
LLT
::
scalar
(
32
)
)
,
MRI
.
createGenericVirtualRegister
(
LLT
::
scalar
(
32
)
)
}
;
assignValueToReg
(
NewRegs
[
0
]
,
VA
.
getLocReg
(
)
,
VA
)
;
assignValueToReg
(
NewRegs
[
1
]
,
NextVA
.
getLocReg
(
)
,
NextVA
)
;
bool
IsLittle
=
MIRBuilder
.
getMF
(
)
.
getSubtarget
<
ARMSubtarget
>
(
)
.
isLittle
(
)
;
if
(
!
IsLittle
)
std
::
swap
(
NewRegs
[
0
]
,
NewRegs
[
1
]
)
;
MIRBuilder
.
buildMerge
(
Arg
.
Regs
[
0
]
,
NewRegs
)
;
return
1
;
}
</s>


<s>
void
assignValueToReg
(
Register
ValVReg
,
Register
PhysReg
,
CCValAssign
&
VA
)
override
{
assert
(
VA
.
isRegLoc
(
)
&&
"Value shouldn't be assigned to reg"
)
;
assert
(
VA
.
getLocReg
(
)
==
PhysReg
&&
"Assigning to the wrong reg?"
)
;
uint64_t
ValSize
=
VA
.
getValVT
(
)
.
getFixedSizeInBits
(
)
;
uint64_t
LocSize
=
VA
.
getLocVT
(
)
.
getFixedSizeInBits
(
)
;
assert
(
ValSize
<=
64
&&
"Unsupported value size"
)
;
assert
(
LocSize
<=
64
&&
"Unsupported location size"
)
;
markPhysRegUsed
(
PhysReg
)
;
if
(
ValSize
==
LocSize
)
{
MIRBuilder
.
buildCopy
(
ValVReg
,
PhysReg
)
;
}
else
{
assert
(
ValSize
<
LocSize
&&
"Extensions not supported"
)
;
auto
PhysRegToVReg
=
MIRBuilder
.
buildCopy
(
LLT
::
scalar
(
LocSize
)
,
PhysReg
)
;
MIRBuilder
.
buildTrunc
(
ValVReg
,
PhysRegToVReg
)
;
}
}
</s>


<s>
bool
ARMCallLowering
::
lowerFormalArguments
(
MachineIRBuilder
&
MIRBuilder
,
const
Function
&
F
,
ArrayRef
<
ArrayRef
<
Register
>>
VRegs
)
const
{
auto
&
TLI
=
*
getTLI
<
ARMTargetLowering
>
(
)
;
auto
Subtarget
=
TLI
.
getSubtarget
(
)
;
if
(
Subtarget
->
isThumb1Only
(
)
)
return
false
;
if
(
F
.
arg_empty
(
)
)
return
true
;
if
(
F
.
isVarArg
(
)
)
return
false
;
auto
&
MF
=
MIRBuilder
.
getMF
(
)
;
auto
&
MBB
=
MIRBuilder
.
getMBB
(
)
;
auto
DL
=
MF
.
getDataLayout
(
)
;
for
(
auto
&
Arg
:
F
.
args
(
)
)
{
if
(
!
isSupportedType
(
DL
,
TLI
,
Arg
.
getType
(
)
)
)
return
false
;
if
(
Arg
.
hasByValOrInAllocaAttr
(
)
)
return
false
;
}
CCAssignFn
*
AssignFn
=
TLI
.
CCAssignFnForCall
(
F
.
getCallingConv
(
)
,
F
.
isVarArg
(
)
)
;
FormalArgHandler
ArgHandler
(
MIRBuilder
,
MIRBuilder
.
getMF
(
)
.
getRegInfo
(
)
,
AssignFn
)
;
SmallVector
<
ArgInfo
,
8
>
SplitArgInfos
;
unsigned
Idx
=
0
;
for
(
auto
&
Arg
:
F
.
args
(
)
)
{
ArgInfo
OrigArgInfo
(
VRegs
[
Idx
]
,
Arg
.
getType
(
)
)
;
setArgFlags
(
OrigArgInfo
,
Idx
+
AttributeList
::
FirstArgIndex
,
DL
,
F
)
;
splitToValueTypes
(
OrigArgInfo
,
SplitArgInfos
,
MF
,
[
&
]
(
Register
Reg
)
{
llvm_unreachable
(
"Args should already be split"
)
;
}
)
;
Idx
++
;
}
if
(
!
MBB
.
empty
(
)
)
MIRBuilder
.
setInstr
(
*
MBB
.
begin
(
)
)
;
if
(
!
handleAssignments
(
MIRBuilder
,
SplitArgInfos
,
ArgHandler
)
)
return
false
;
MIRBuilder
.
setMBB
(
MBB
)
;
return
true
;
}
</s>

ARM
ARM
ARM
8
0
"Args should already be split"


<s> bool ARMCallLowering :: lowerFormalArguments ( MachineIRBuilder & MIRBuilder , const Function & F , ArrayRef < unsigned > VRegs ) const { auto & TLI = * getTLI < ARMTargetLowering > ( ) ; auto Subtarget = TLI . getSubtarget ( ) ; if ( Subtarget -> isThumb ( ) ) return false ; if ( F . arg_empty ( ) ) return true ; if ( F . isVarArg ( ) ) return false ; auto & MF = MIRBuilder . getMF ( ) ; auto & MBB = MIRBuilder . getMBB ( ) ; auto DL = MF . getDataLayout ( ) ; for ( auto & Arg : F . args ( ) ) { if ( ! isSupportedType ( DL , TLI , Arg . getType ( ) ) ) return false ; if ( Arg . hasByValOrInAllocaAttr ( ) ) return false ; } CCAssignFn * AssignFn = TLI . CCAssignFnForCall ( F . getCallingConv ( ) , F . isVarArg ( ) ) ; FormalArgHandler ArgHandler ( MIRBuilder , MIRBuilder . getMF ( ) . getRegInfo ( ) , AssignFn ) ; SmallVector < ArgInfo , 8 > ArgInfos ; SmallVector < unsigned , 4 > SplitRegs ; unsigned Idx = 0 ; for ( auto & Arg : F . args ( ) ) { ArgInfo AInfo ( VRegs [ Idx ] , Arg . getType ( ) ) ; setArgFlags ( AInfo , Idx + AttributeList :: FirstArgIndex , DL , F ) ; SplitRegs . clear ( ) ; splitToValueTypes ( AInfo , ArgInfos , MF , [ & ] ( unsigned Reg , uint64_t Offset ) { SplitRegs . push_back ( Reg ) ; } ) ; if ( ! SplitRegs . empty ( ) ) MIRBuilder . buildMerge ( VRegs [ Idx ] , SplitRegs ) ; Idx ++ ; } if ( ! MBB . empty ( ) ) MIRBuilder . setInstr ( * MBB . begin ( ) ) ; if ( ! handleAssignments ( MIRBuilder , ArgInfos , ArgHandler ) ) return false ; MIRBuilder . setMBB ( MBB ) ; return true ; } </s>


<s>
unsigned
assignCustomValue
(
const
ARMCallLowering
::
ArgInfo
&
Arg
,
ArrayRef
<
CCValAssign
>
VAs
)
override
{
CCValAssign
VA
=
VAs
[
0
]
;
assert
(
VA
.
needsCustom
(
)
&&
"Value doesn't need custom handling"
)
;
assert
(
VA
.
getValVT
(
)
==
MVT
::
f64
&&
"Unsupported type"
)
;
CCValAssign
NextVA
=
VAs
[
1
]
;
assert
(
NextVA
.
needsCustom
(
)
&&
"Value doesn't need custom handling"
)
;
assert
(
NextVA
.
getValVT
(
)
==
MVT
::
f64
&&
"Unsupported type"
)
;
assert
(
VA
.
getValNo
(
)
==
NextVA
.
getValNo
(
)
&&
"Values belong to different arguments"
)
;
assert
(
VA
.
isRegLoc
(
)
&&
"Value should be in reg"
)
;
assert
(
NextVA
.
isRegLoc
(
)
&&
"Value should be in reg"
)
;
unsigned
NewRegs
[
]
=
{
MRI
.
createGenericVirtualRegister
(
LLT
::
scalar
(
32
)
)
,
MRI
.
createGenericVirtualRegister
(
LLT
::
scalar
(
32
)
)
}
;
assignValueToReg
(
NewRegs
[
0
]
,
VA
.
getLocReg
(
)
,
VA
)
;
assignValueToReg
(
NewRegs
[
1
]
,
NextVA
.
getLocReg
(
)
,
NextVA
)
;
bool
IsLittle
=
MIRBuilder
.
getMF
(
)
.
getSubtarget
<
ARMSubtarget
>
(
)
.
isLittle
(
)
;
if
(
!
IsLittle
)
std
::
swap
(
NewRegs
[
0
]
,
NewRegs
[
1
]
)
;
MIRBuilder
.
buildSequence
(
Arg
.
Reg
,
NewRegs
,
{
0
,
32
}
)
;
return
1
;
}
</s>


<s>
void
assignValueToAddress
(
unsigned
ValVReg
,
unsigned
Addr
,
uint64_t
Size
,
MachinePointerInfo
&
MPO
,
CCValAssign
&
VA
)
override
{
assert
(
(
Size
==
1
||
Size
==
2
||
Size
==
4
||
Size
==
8
)
&&
"Unsupported size"
)
;
if
(
VA
.
getLocInfo
(
)
==
CCValAssign
::
SExt
||
VA
.
getLocInfo
(
)
==
CCValAssign
::
ZExt
)
{
Size
=
4
;
assert
(
MRI
.
getType
(
ValVReg
)
.
isScalar
(
)
&&
"Only scalars supported atm"
)
;
MRI
.
setType
(
ValVReg
,
LLT
::
scalar
(
32
)
)
;
}
auto
MMO
=
MIRBuilder
.
getMF
(
)
.
getMachineMemOperand
(
MPO
,
MachineMemOperand
::
MOLoad
,
Size
,
0
)
;
MIRBuilder
.
buildLoad
(
ValVReg
,
Addr
,
*
MMO
)
;
}
</s>


<s>
void
assignValueToReg
(
unsigned
ValVReg
,
unsigned
PhysReg
,
CCValAssign
&
VA
)
override
{
assert
(
VA
.
isRegLoc
(
)
&&
"Value shouldn't be assigned to reg"
)
;
assert
(
VA
.
getLocReg
(
)
==
PhysReg
&&
"Assigning to the wrong reg?"
)
;
assert
(
VA
.
getValVT
(
)
.
getSizeInBits
(
)
<=
64
&&
"Unsupported value size"
)
;
assert
(
VA
.
getLocVT
(
)
.
getSizeInBits
(
)
<=
64
&&
"Unsupported location size"
)
;
markPhysRegUsed
(
PhysReg
)
;
MIRBuilder
.
buildCopy
(
ValVReg
,
PhysReg
)
;
}
</s>

ARM
"Value shouldn't be assigned to reg"
"Assigning to the wrong reg?"
64
"Unsupported value size"
64
"Unsupported location size"


<s> bool ARMCallLowering :: lowerCall ( MachineIRBuilder & MIRBuilder , const MachineOperand & Callee , const ArgInfo & OrigRet , ArrayRef < ArgInfo > OrigArgs ) const { MachineFunction & MF = MIRBuilder . getMF ( ) ; const auto & TLI = * getTLI < ARMTargetLowering > ( ) ; const auto & DL = MF . getDataLayout ( ) ; const TargetRegisterInfo * TRI = MF . getSubtarget ( ) . getRegisterInfo ( ) ; MachineRegisterInfo & MRI = MF . getRegInfo ( ) ; if ( MF . getSubtarget < ARMSubtarget > ( ) . genLongCalls ( ) ) return false ; MIRBuilder . buildInstr ( ARM :: ADJCALLSTACKDOWN ) . addImm ( 0 ) . add ( predOps ( ARMCC :: AL ) ) ; auto CallConv = MF . getFunction ( ) -> getCallingConv ( ) ; auto MIB = MIRBuilder . buildInstrNoInsert ( ARM :: BLX ) . add ( Callee ) . addRegMask ( TRI -> getCallPreservedMask ( MF , CallConv ) ) ; SmallVector < ArgInfo , 8 > ArgInfos ; for ( auto Arg : OrigArgs ) { if ( ! isSupportedType ( DL , TLI , Arg . Ty ) ) return false ; if ( ! Arg . IsFixed ) return false ; splitToValueTypes ( Arg , ArgInfos , DL , MRI ) ; } auto ArgAssignFn = TLI . CCAssignFnForCall ( CallConv , false ) ; OutgoingValueHandler ArgHandler ( MIRBuilder , MRI , MIB , ArgAssignFn ) ; if ( ! handleAssignments ( MIRBuilder , ArgInfos , ArgHandler ) ) return false ; MIRBuilder . insertInstr ( MIB ) ; if ( ! OrigRet . Ty -> isVoidTy ( ) ) { if ( ! isSupportedType ( DL , TLI , OrigRet . Ty ) ) return false ; ArgInfos . clear ( ) ; splitToValueTypes ( OrigRet , ArgInfos , DL , MRI ) ; auto RetAssignFn = TLI . CCAssignFnForReturn ( CallConv , false ) ; CallReturnHandler RetHandler ( MIRBuilder , MRI , MIB , RetAssignFn ) ; if ( ! handleAssignments ( MIRBuilder , ArgInfos , RetHandler ) ) return false ; } MIRBuilder . buildInstr ( ARM :: ADJCALLSTACKUP ) . addImm ( 0 ) . addImm ( 0 ) . add ( predOps ( ARMCC :: AL ) ) ; return true ; } </s>

This hook must be implemented to lower the given call instruction , including argument and return value marshalling .

ARM ARM ARM ARM ARM::ADJCALLSTACKDOWN 0 ARMCC::AL ARM::BLX 8 ARM::ADJCALLSTACKUP 0 0 ARMCC::AL


<s> bool ARMCallLowering :: lowerFormalArguments ( MachineIRBuilder & MIRBuilder , const Function & F , ArrayRef < unsigned > VRegs ) const { if ( F . arg_empty ( ) ) return true ; if ( F . isVarArg ( ) ) return false ; auto & MF = MIRBuilder . getMF ( ) ; auto DL = MF . getDataLayout ( ) ; auto & TLI = * getTLI < ARMTargetLowering > ( ) ; auto Subtarget = TLI . getSubtarget ( ) ; if ( Subtarget -> isThumb ( ) ) return false ; if ( Subtarget -> useSoftFloat ( ) || ! Subtarget -> hasVFP2 ( ) ) return false ; auto & Args = F . getArgumentList ( ) ; for ( auto & Arg : Args ) if ( ! isSupportedType ( DL , TLI , Arg . getType ( ) ) ) return false ; CCAssignFn * AssignFn = TLI . CCAssignFnForCall ( F . getCallingConv ( ) , F . isVarArg ( ) ) ; SmallVector < ArgInfo , 8 > ArgInfos ; unsigned Idx = 0 ; for ( auto & Arg : Args ) { ArgInfo AInfo ( VRegs [ Idx ] , Arg . getType ( ) ) ; setArgFlags ( AInfo , Idx + 1 , DL , F ) ; splitToValueTypes ( AInfo , ArgInfos , DL , MF . getRegInfo ( ) ) ; Idx ++ ; } FormalArgHandler ArgHandler ( MIRBuilder , MIRBuilder . getMF ( ) . getRegInfo ( ) , AssignFn ) ; return handleAssignments ( MIRBuilder , ArgInfos , ArgHandler ) ; } </s>


<s>
void
ARMCallLowering
::
splitToValueTypes
(
const
ArgInfo
&
OrigArg
,
SmallVectorImpl
<
ArgInfo
>
&
SplitArgs
,
const
DataLayout
&
DL
,
MachineRegisterInfo
&
MRI
)
const
{
const
ARMTargetLowering
&
TLI
=
*
getTLI
<
ARMTargetLowering
>
(
)
;
LLVMContext
&
Ctx
=
OrigArg
.
Ty
->
getContext
(
)
;
SmallVector
<
EVT
,
4
>
SplitVTs
;
SmallVector
<
uint64_t
,
4
>
Offsets
;
ComputeValueVTs
(
TLI
,
DL
,
OrigArg
.
Ty
,
SplitVTs
,
&
Offsets
,
0
)
;
assert
(
SplitVTs
.
size
(
)
==
1
&&
"Unsupported type"
)
;
SplitArgs
.
emplace_back
(
OrigArg
.
Reg
,
SplitVTs
[
0
]
.
getTypeForEVT
(
Ctx
)
,
OrigArg
.
Flags
,
OrigArg
.
IsFixed
)
;
}
</s>


<s> bool ARMCallLowering :: lowerFormalArguments ( MachineIRBuilder & MIRBuilder , const Function & F , ArrayRef < ArrayRef < Register >> VRegs ) const { auto & TLI = * getTLI < ARMTargetLowering > ( ) ; auto Subtarget = TLI . getSubtarget ( ) ; if ( Subtarget -> isThumb1Only ( ) ) return false ; if ( F . arg_empty ( ) ) return true ; if ( F . isVarArg ( ) ) return false ; auto & MF = MIRBuilder . getMF ( ) ; auto & MBB = MIRBuilder . getMBB ( ) ; auto DL = MF . getDataLayout ( ) ; for ( auto & Arg : F . args ( ) ) { if ( ! isSupportedType ( DL , TLI , Arg . getType ( ) ) ) return false ; if ( Arg . hasPassPointeeByValueCopyAttr ( ) ) return false ; } CCAssignFn * AssignFn = TLI . CCAssignFnForCall ( F . getCallingConv ( ) , F . isVarArg ( ) ) ; FormalArgHandler ArgHandler ( MIRBuilder , MIRBuilder . getMF ( ) . getRegInfo ( ) , AssignFn ) ; SmallVector < ArgInfo , 8 > SplitArgInfos ; unsigned Idx = 0 ; for ( auto & Arg : F . args ( ) ) { ArgInfo OrigArgInfo ( VRegs [ Idx ] , Arg . getType ( ) ) ; setArgFlags ( OrigArgInfo , Idx + AttributeList :: FirstArgIndex , DL , F ) ; splitToValueTypes ( OrigArgInfo , SplitArgInfos , MF ) ; Idx ++ ; } if ( ! MBB . empty ( ) ) MIRBuilder . setInstr ( * MBB . begin ( ) ) ; if ( ! handleAssignments ( MIRBuilder , SplitArgInfos , ArgHandler ) ) return false ; MIRBuilder . setMBB ( MBB ) ; return true ; } </s>


<s>
unsigned
assignCustomValue
(
const
ARMCallLowering
::
ArgInfo
&
Arg
,
ArrayRef
<
CCValAssign
>
VAs
)
override
{
assert
(
Arg
.
Regs
.
size
(
)
==
1
&&
"Can't handle multple regs yet"
)
;
CCValAssign
VA
=
VAs
[
0
]
;
assert
(
VA
.
needsCustom
(
)
&&
"Value doesn't need custom handling"
)
;
assert
(
VA
.
getValVT
(
)
==
MVT
::
f64
&&
"Unsupported type"
)
;
CCValAssign
NextVA
=
VAs
[
1
]
;
assert
(
NextVA
.
needsCustom
(
)
&&
"Value doesn't need custom handling"
)
;
assert
(
NextVA
.
getValVT
(
)
==
MVT
::
f64
&&
"Unsupported type"
)
;
assert
(
VA
.
getValNo
(
)
==
NextVA
.
getValNo
(
)
&&
"Values belong to different arguments"
)
;
assert
(
VA
.
isRegLoc
(
)
&&
"Value should be in reg"
)
;
assert
(
NextVA
.
isRegLoc
(
)
&&
"Value should be in reg"
)
;
Register
NewRegs
[
]
=
{
MRI
.
createGenericVirtualRegister
(
LLT
::
scalar
(
32
)
)
,
MRI
.
createGenericVirtualRegister
(
LLT
::
scalar
(
32
)
)
}
;
assignValueToReg
(
NewRegs
[
0
]
,
VA
.
getLocReg
(
)
,
VA
)
;
assignValueToReg
(
NewRegs
[
1
]
,
NextVA
.
getLocReg
(
)
,
NextVA
)
;
bool
IsLittle
=
MIRBuilder
.
getMF
(
)
.
getSubtarget
<
ARMSubtarget
>
(
)
.
isLittle
(
)
;
if
(
!
IsLittle
)
std
::
swap
(
NewRegs
[
0
]
,
NewRegs
[
1
]
)
;
MIRBuilder
.
buildMerge
(
Arg
.
Regs
[
0
]
,
NewRegs
)
;
return
1
;
}
</s>


<s>
void
assignValueToAddress
(
Register
ValVReg
,
Register
Addr
,
uint64_t
Size
,
MachinePointerInfo
&
MPO
,
CCValAssign
&
VA
)
override
{
assert
(
(
Size
==
1
||
Size
==
2
||
Size
==
4
||
Size
==
8
)
&&
"Unsupported size"
)
;
if
(
VA
.
getLocInfo
(
)
==
CCValAssign
::
SExt
||
VA
.
getLocInfo
(
)
==
CCValAssign
::
ZExt
)
{
Size
=
4
;
assert
(
MRI
.
getType
(
ValVReg
)
.
isScalar
(
)
&&
"Only scalars supported atm"
)
;
auto
LoadVReg
=
MRI
.
createGenericVirtualRegister
(
LLT
::
scalar
(
32
)
)
;
buildLoad
(
LoadVReg
,
Addr
,
Size
,
1
,
MPO
)
;
MIRBuilder
.
buildTrunc
(
ValVReg
,
LoadVReg
)
;
}
else
{
buildLoad
(
ValVReg
,
Addr
,
Size
,
1
,
MPO
)
;
}
}
</s>


<s>
void
assignValueToReg
(
Register
ValVReg
,
Register
PhysReg
,
CCValAssign
&
VA
)
override
{
assert
(
VA
.
isRegLoc
(
)
&&
"Value shouldn't be assigned to reg"
)
;
assert
(
VA
.
getLocReg
(
)
==
PhysReg
&&
"Assigning to the wrong reg?"
)
;
auto
ValSize
=
VA
.
getValVT
(
)
.
getSizeInBits
(
)
;
auto
LocSize
=
VA
.
getLocVT
(
)
.
getSizeInBits
(
)
;
assert
(
ValSize
<=
64
&&
"Unsupported value size"
)
;
assert
(
LocSize
<=
64
&&
"Unsupported location size"
)
;
markPhysRegUsed
(
PhysReg
)
;
if
(
ValSize
==
LocSize
)
{
MIRBuilder
.
buildCopy
(
ValVReg
,
PhysReg
)
;
}
else
{
assert
(
ValSize
<
LocSize
&&
"Extensions not supported"
)
;
auto
PhysRegToVReg
=
MRI
.
createGenericVirtualRegister
(
LLT
::
scalar
(
LocSize
)
)
;
MIRBuilder
.
buildCopy
(
PhysRegToVReg
,
PhysReg
)
;
MIRBuilder
.
buildTrunc
(
ValVReg
,
PhysRegToVReg
)
;
}
}
</s>


<s> void buildLoad ( Register Val , Register Addr , uint64_t Size , unsigned Alignment , MachinePointerInfo & MPO ) { auto MMO = MIRBuilder . getMF ( ) . getMachineMemOperand ( MPO , MachineMemOperand :: MOLoad , Size , Alignment ) ; MIRBuilder . buildLoad ( Val , Addr , * MMO ) ; } </s>


<s>
Register
getStackAddress
(
uint64_t
Size
,
int64_t
Offset
,
MachinePointerInfo
&
MPO
)
override
{
assert
(
(
Size
==
1
||
Size
==
2
||
Size
==
4
||
Size
==
8
)
&&
"Unsupported size"
)
;
auto
&
MFI
=
MIRBuilder
.
getMF
(
)
.
getFrameInfo
(
)
;
int
FI
=
MFI
.
CreateFixedObject
(
Size
,
Offset
,
true
)
;
MPO
=
MachinePointerInfo
::
getFixedStack
(
MIRBuilder
.
getMF
(
)
,
FI
)
;
unsigned
AddrReg
=
MRI
.
createGenericVirtualRegister
(
LLT
::
pointer
(
MPO
.
getAddrSpace
(
)
,
32
)
)
;
MIRBuilder
.
buildFrameIndex
(
AddrReg
,
FI
)
;
return
AddrReg
;
}
</s>


<s> bool ARMCallLowering :: lowerFormalArguments ( MachineIRBuilder & MIRBuilder , const Function & F , ArrayRef < ArrayRef < Register >> VRegs ) const { auto & TLI = * getTLI < ARMTargetLowering > ( ) ; auto Subtarget = TLI . getSubtarget ( ) ; if ( Subtarget -> isThumb1Only ( ) ) return false ; if ( F . arg_empty ( ) ) return true ; if ( F . isVarArg ( ) ) return false ; auto & MF = MIRBuilder . getMF ( ) ; auto & MBB = MIRBuilder . getMBB ( ) ; auto DL = MF . getDataLayout ( ) ; for ( auto & Arg : F . args ( ) ) { if ( ! isSupportedType ( DL , TLI , Arg . getType ( ) ) ) return false ; if ( Arg . hasByValOrInAllocaAttr ( ) ) return false ; } CCAssignFn * AssignFn = TLI . CCAssignFnForCall ( F . getCallingConv ( ) , F . isVarArg ( ) ) ; FormalArgHandler ArgHandler ( MIRBuilder , MIRBuilder . getMF ( ) . getRegInfo ( ) , AssignFn ) ; SmallVector < ArgInfo , 8 > SplitArgInfos ; unsigned Idx = 0 ; for ( auto & Arg : F . args ( ) ) { ArgInfo OrigArgInfo ( VRegs [ Idx ] , Arg . getType ( ) ) ; setArgFlags ( OrigArgInfo , Idx + AttributeList :: FirstArgIndex , DL , F ) ; splitToValueTypes ( OrigArgInfo , SplitArgInfos , MF ) ; Idx ++ ; } if ( ! MBB . empty ( ) ) MIRBuilder . setInstr ( * MBB . begin ( ) ) ; if ( ! handleAssignments ( MIRBuilder , SplitArgInfos , ArgHandler ) ) return false ; MIRBuilder . setMBB ( MBB ) ; return true ; } </s>


<s> MachineInstrBuilder buildLoad ( const DstOp & Res , Register Addr , uint64_t Size , MachinePointerInfo & MPO ) { MachineFunction & MF = MIRBuilder . getMF ( ) ; unsigned Alignment = inferAlignmentFromPtrInfo ( MF , MPO ) ; auto MMO = MF . getMachineMemOperand ( MPO , MachineMemOperand :: MOLoad , Size , Alignment ) ; return MIRBuilder . buildLoad ( Res , Addr , * MMO ) ; } </s>


<s>
void
assignValueToAddress
(
Register
ValVReg
,
Register
Addr
,
uint64_t
Size
,
MachinePointerInfo
&
MPO
,
CCValAssign
&
VA
)
override
{
assert
(
(
Size
==
1
||
Size
==
2
||
Size
==
4
||
Size
==
8
)
&&
"Unsupported size"
)
;
if
(
VA
.
getLocInfo
(
)
==
CCValAssign
::
SExt
||
VA
.
getLocInfo
(
)
==
CCValAssign
::
ZExt
)
{
Size
=
4
;
assert
(
MRI
.
getType
(
ValVReg
)
.
isScalar
(
)
&&
"Only scalars supported atm"
)
;
auto
LoadVReg
=
buildLoad
(
LLT
::
scalar
(
32
)
,
Addr
,
Size
,
1
,
MPO
)
;
MIRBuilder
.
buildTrunc
(
ValVReg
,
LoadVReg
)
;
}
else
{
buildLoad
(
ValVReg
,
Addr
,
Size
,
1
,
MPO
)
;
}
}
</s>


<s> MachineInstrBuilder buildLoad ( const DstOp & Res , Register Addr , uint64_t Size , unsigned Alignment , MachinePointerInfo & MPO ) { auto MMO = MIRBuilder . getMF ( ) . getMachineMemOperand ( MPO , MachineMemOperand :: MOLoad , Size , Alignment ) ; return MIRBuilder . buildLoad ( Res , Addr , * MMO ) ; } </s>


<s>
Register
getStackAddress
(
uint64_t
Size
,
int64_t
Offset
,
MachinePointerInfo
&
MPO
)
override
{
assert
(
(
Size
==
1
||
Size
==
2
||
Size
==
4
||
Size
==
8
)
&&
"Unsupported size"
)
;
auto
&
MFI
=
MIRBuilder
.
getMF
(
)
.
getFrameInfo
(
)
;
int
FI
=
MFI
.
CreateFixedObject
(
Size
,
Offset
,
true
)
;
MPO
=
MachinePointerInfo
::
getFixedStack
(
MIRBuilder
.
getMF
(
)
,
FI
)
;
Register
AddrReg
=
MRI
.
createGenericVirtualRegister
(
LLT
::
pointer
(
MPO
.
getAddrSpace
(
)
,
32
)
)
;
MIRBuilder
.
buildFrameIndex
(
AddrReg
,
FI
)
;
return
AddrReg
;
}
</s>


<s> bool ARMCallLowering :: lowerFormalArguments ( MachineIRBuilder & MIRBuilder , const Function & F , ArrayRef < unsigned > VRegs ) const { auto & TLI = * getTLI < ARMTargetLowering > ( ) ; auto Subtarget = TLI . getSubtarget ( ) ; if ( Subtarget -> isThumb ( ) ) return false ; if ( F . arg_empty ( ) ) return true ; if ( F . isVarArg ( ) ) return false ; auto & MF = MIRBuilder . getMF ( ) ; auto & MBB = MIRBuilder . getMBB ( ) ; auto DL = MF . getDataLayout ( ) ; for ( auto & Arg : F . args ( ) ) if ( ! isSupportedType ( DL , TLI , Arg . getType ( ) ) ) return false ; CCAssignFn * AssignFn = TLI . CCAssignFnForCall ( F . getCallingConv ( ) , F . isVarArg ( ) ) ; FormalArgHandler ArgHandler ( MIRBuilder , MIRBuilder . getMF ( ) . getRegInfo ( ) , AssignFn ) ; SmallVector < ArgInfo , 8 > ArgInfos ; SmallVector < unsigned , 4 > SplitRegs ; unsigned Idx = 0 ; for ( auto & Arg : F . args ( ) ) { ArgInfo AInfo ( VRegs [ Idx ] , Arg . getType ( ) ) ; setArgFlags ( AInfo , Idx + AttributeList :: FirstArgIndex , DL , F ) ; SplitRegs . clear ( ) ; splitToValueTypes ( AInfo , ArgInfos , MF , [ & ] ( unsigned Reg , uint64_t Offset ) { SplitRegs . push_back ( Reg ) ; } ) ; if ( ! SplitRegs . empty ( ) ) MIRBuilder . buildMerge ( VRegs [ Idx ] , SplitRegs ) ; Idx ++ ; } if ( ! MBB . empty ( ) ) MIRBuilder . setInstr ( * MBB . begin ( ) ) ; return handleAssignments ( MIRBuilder , ArgInfos , ArgHandler ) ; } </s>


<s> bool ARMCallLowering :: lowerFormalArguments ( MachineIRBuilder & MIRBuilder , const Function & F , ArrayRef < ArrayRef < Register >> VRegs , FunctionLoweringInfo & FLI ) const { auto & TLI = * getTLI < ARMTargetLowering > ( ) ; auto Subtarget = TLI . getSubtarget ( ) ; if ( Subtarget -> isThumb1Only ( ) ) return false ; if ( F . arg_empty ( ) ) return true ; if ( F . isVarArg ( ) ) return false ; auto & MF = MIRBuilder . getMF ( ) ; auto & MBB = MIRBuilder . getMBB ( ) ; const auto & DL = MF . getDataLayout ( ) ; for ( auto & Arg : F . args ( ) ) { if ( ! isSupportedType ( DL , TLI , Arg . getType ( ) ) ) return false ; if ( Arg . hasPassPointeeByValueCopyAttr ( ) ) return false ; } CCAssignFn * AssignFn = TLI . CCAssignFnForCall ( F . getCallingConv ( ) , F . isVarArg ( ) ) ; OutgoingValueAssigner ArgAssigner ( AssignFn ) ; FormalArgHandler ArgHandler ( MIRBuilder , MIRBuilder . getMF ( ) . getRegInfo ( ) ) ; SmallVector < ArgInfo , 8 > SplitArgInfos ; unsigned Idx = 0 ; for ( auto & Arg : F . args ( ) ) { ArgInfo OrigArgInfo ( VRegs [ Idx ] , Arg . getType ( ) ) ; setArgFlags ( OrigArgInfo , Idx + AttributeList :: FirstArgIndex , DL , F ) ; splitToValueTypes ( OrigArgInfo , SplitArgInfos , DL , F . getCallingConv ( ) ) ; Idx ++ ; } if ( ! MBB . empty ( ) ) MIRBuilder . setInstr ( * MBB . begin ( ) ) ; if ( ! determineAndHandleAssignments ( ArgHandler , ArgAssigner , SplitArgInfos , MIRBuilder , F . getCallingConv ( ) , F . isVarArg ( ) ) ) return false ; MIRBuilder . setMBB ( MBB ) ; return true ; } </s>


<s> bool ARMCallLowering :: lowerFormalArguments ( MachineIRBuilder & MIRBuilder , const Function & F , ArrayRef < ArrayRef < Register >> VRegs , FunctionLoweringInfo & FLI ) const { auto & TLI = * getTLI < ARMTargetLowering > ( ) ; auto Subtarget = TLI . getSubtarget ( ) ; if ( Subtarget -> isThumb1Only ( ) ) return false ; if ( F . arg_empty ( ) ) return true ; if ( F . isVarArg ( ) ) return false ; auto & MF = MIRBuilder . getMF ( ) ; auto & MBB = MIRBuilder . getMBB ( ) ; auto DL = MF . getDataLayout ( ) ; for ( auto & Arg : F . args ( ) ) { if ( ! isSupportedType ( DL , TLI , Arg . getType ( ) ) ) return false ; if ( Arg . hasPassPointeeByValueCopyAttr ( ) ) return false ; } CCAssignFn * AssignFn = TLI . CCAssignFnForCall ( F . getCallingConv ( ) , F . isVarArg ( ) ) ; FormalArgHandler ArgHandler ( MIRBuilder , MIRBuilder . getMF ( ) . getRegInfo ( ) , AssignFn ) ; SmallVector < ArgInfo , 8 > SplitArgInfos ; unsigned Idx = 0 ; for ( auto & Arg : F . args ( ) ) { ArgInfo OrigArgInfo ( VRegs [ Idx ] , Arg . getType ( ) ) ; setArgFlags ( OrigArgInfo , Idx + AttributeList :: FirstArgIndex , DL , F ) ; splitToValueTypes ( OrigArgInfo , SplitArgInfos , MF ) ; Idx ++ ; } if ( ! MBB . empty ( ) ) MIRBuilder . setInstr ( * MBB . begin ( ) ) ; if ( ! handleAssignments ( MIRBuilder , SplitArgInfos , ArgHandler ) ) return false ; MIRBuilder . setMBB ( MBB ) ; return true ; } </s>


<s>
Register
getStackAddress
(
uint64_t
Size
,
int64_t
Offset
,
MachinePointerInfo
&
MPO
)
override
{
assert
(
(
Size
==
1
||
Size
==
2
||
Size
==
4
||
Size
==
8
)
&&
"Unsupported size"
)
;
LLT
p0
=
LLT
::
pointer
(
0
,
32
)
;
LLT
s32
=
LLT
::
scalar
(
32
)
;
Register
SPReg
=
MRI
.
createGenericVirtualRegister
(
p0
)
;
MIRBuilder
.
buildCopy
(
SPReg
,
Register
(
ARM
::
SP
)
)
;
Register
OffsetReg
=
MRI
.
createGenericVirtualRegister
(
s32
)
;
MIRBuilder
.
buildConstant
(
OffsetReg
,
Offset
)
;
Register
AddrReg
=
MRI
.
createGenericVirtualRegister
(
p0
)
;
MIRBuilder
.
buildPtrAdd
(
AddrReg
,
SPReg
,
OffsetReg
)
;
MPO
=
MachinePointerInfo
::
getStack
(
MIRBuilder
.
getMF
(
)
,
Offset
)
;
return
AddrReg
;
}
</s>


<s>
void
assignValueToAddress
(
unsigned
ValVReg
,
unsigned
Addr
,
uint64_t
Size
,
MachinePointerInfo
&
MPO
,
CCValAssign
&
VA
)
override
{
assert
(
(
Size
==
1
||
Size
==
2
||
Size
==
4
||
Size
==
8
)
&&
"Unsupported size"
)
;
if
(
VA
.
getLocInfo
(
)
==
CCValAssign
::
SExt
||
VA
.
getLocInfo
(
)
==
CCValAssign
::
ZExt
)
{
Size
=
4
;
assert
(
MRI
.
getType
(
ValVReg
)
.
isScalar
(
)
&&
"Only scalars supported atm"
)
;
auto
LoadVReg
=
MRI
.
createGenericVirtualRegister
(
LLT
::
scalar
(
32
)
)
;
buildLoad
(
LoadVReg
,
Addr
,
Size
,
1
,
MPO
)
;
MIRBuilder
.
buildTrunc
(
ValVReg
,
LoadVReg
)
;
}
else
{
buildLoad
(
ValVReg
,
Addr
,
Size
,
1
,
MPO
)
;
}
}
</s>


<s> bool ARMCallLowering :: lowerFormalArguments ( MachineIRBuilder & MIRBuilder , const Function & F , ArrayRef < unsigned > VRegs ) const { auto & TLI = * getTLI < ARMTargetLowering > ( ) ; auto Subtarget = TLI . getSubtarget ( ) ; if ( Subtarget -> isThumb1Only ( ) ) return false ; if ( F . arg_empty ( ) ) return true ; if ( F . isVarArg ( ) ) return false ; auto & MF = MIRBuilder . getMF ( ) ; auto & MBB = MIRBuilder . getMBB ( ) ; auto DL = MF . getDataLayout ( ) ; for ( auto & Arg : F . args ( ) ) { if ( ! isSupportedType ( DL , TLI , Arg . getType ( ) ) ) return false ; if ( Arg . hasByValOrInAllocaAttr ( ) ) return false ; } CCAssignFn * AssignFn = TLI . CCAssignFnForCall ( F . getCallingConv ( ) , F . isVarArg ( ) ) ; FormalArgHandler ArgHandler ( MIRBuilder , MIRBuilder . getMF ( ) . getRegInfo ( ) , AssignFn ) ; SmallVector < ArgInfo , 8 > ArgInfos ; SmallVector < unsigned , 4 > SplitRegs ; unsigned Idx = 0 ; for ( auto & Arg : F . args ( ) ) { ArgInfo AInfo ( VRegs [ Idx ] , Arg . getType ( ) ) ; setArgFlags ( AInfo , Idx + AttributeList :: FirstArgIndex , DL , F ) ; SplitRegs . clear ( ) ; splitToValueTypes ( AInfo , ArgInfos , MF , [ & ] ( unsigned Reg ) { SplitRegs . push_back ( Reg ) ; } ) ; if ( ! SplitRegs . empty ( ) ) MIRBuilder . buildMerge ( VRegs [ Idx ] , SplitRegs ) ; Idx ++ ; } if ( ! MBB . empty ( ) ) MIRBuilder . setInstr ( * MBB . begin ( ) ) ; if ( ! handleAssignments ( MIRBuilder , ArgInfos , ArgHandler ) ) return false ; MIRBuilder . setMBB ( MBB ) ; return true ; } </s>


<s>
unsigned
assignCustomValue
(
const
CallLowering
::
ArgInfo
&
Arg
,
ArrayRef
<
CCValAssign
>
VAs
)
override
{
CCValAssign
VA
=
VAs
[
0
]
;
assert
(
VA
.
needsCustom
(
)
&&
"Value doesn't need custom handling"
)
;
assert
(
VA
.
getValVT
(
)
==
MVT
::
f64
&&
"Unsupported type"
)
;
CCValAssign
NextVA
=
VAs
[
1
]
;
assert
(
NextVA
.
needsCustom
(
)
&&
"Value doesn't need custom handling"
)
;
assert
(
NextVA
.
getValVT
(
)
==
MVT
::
f64
&&
"Unsupported type"
)
;
assert
(
VA
.
getValNo
(
)
==
NextVA
.
getValNo
(
)
&&
"Values belong to different arguments"
)
;
assert
(
VA
.
isRegLoc
(
)
&&
"Value should be in reg"
)
;
assert
(
NextVA
.
isRegLoc
(
)
&&
"Value should be in reg"
)
;
unsigned
NewRegs
[
]
=
{
MRI
.
createGenericVirtualRegister
(
LLT
::
scalar
(
32
)
)
,
MRI
.
createGenericVirtualRegister
(
LLT
::
scalar
(
32
)
)
}
;
MIRBuilder
.
buildExtract
(
NewRegs
[
0
]
,
Arg
.
Reg
,
0
)
;
MIRBuilder
.
buildExtract
(
NewRegs
[
1
]
,
Arg
.
Reg
,
32
)
;
bool
IsLittle
=
MIRBuilder
.
getMF
(
)
.
getSubtarget
<
ARMSubtarget
>
(
)
.
isLittle
(
)
;
if
(
!
IsLittle
)
std
::
swap
(
NewRegs
[
0
]
,
NewRegs
[
1
]
)
;
assignValueToReg
(
NewRegs
[
0
]
,
VA
.
getLocReg
(
)
,
VA
)
;
assignValueToReg
(
NewRegs
[
1
]
,
NextVA
.
getLocReg
(
)
,
NextVA
)
;
return
1
;
}
</s>


<s> bool ARMCallLowering :: lowerCall ( MachineIRBuilder & MIRBuilder , CallingConv :: ID CallConv , const MachineOperand & Callee , const ArgInfo & OrigRet , ArrayRef < ArgInfo > OrigArgs ) const { MachineFunction & MF = MIRBuilder . getMF ( ) ; const auto & TLI = * getTLI < ARMTargetLowering > ( ) ; const auto & DL = MF . getDataLayout ( ) ; const TargetRegisterInfo * TRI = MF . getSubtarget ( ) . getRegisterInfo ( ) ; MachineRegisterInfo & MRI = MF . getRegInfo ( ) ; if ( MF . getSubtarget < ARMSubtarget > ( ) . genLongCalls ( ) ) return false ; auto CallSeqStart = MIRBuilder . buildInstr ( ARM :: ADJCALLSTACKDOWN ) ; auto MIB = MIRBuilder . buildInstrNoInsert ( ARM :: BLX ) . add ( Callee ) . addRegMask ( TRI -> getCallPreservedMask ( MF , CallConv ) ) ; SmallVector < ArgInfo , 8 > ArgInfos ; for ( auto Arg : OrigArgs ) { if ( ! isSupportedType ( DL , TLI , Arg . Ty ) ) return false ; if ( ! Arg . IsFixed ) return false ; splitToValueTypes ( Arg , ArgInfos , DL , MRI ) ; } auto ArgAssignFn = TLI . CCAssignFnForCall ( CallConv , false ) ; OutgoingValueHandler ArgHandler ( MIRBuilder , MRI , MIB , ArgAssignFn ) ; if ( ! handleAssignments ( MIRBuilder , ArgInfos , ArgHandler ) ) return false ; MIRBuilder . insertInstr ( MIB ) ; if ( ! OrigRet . Ty -> isVoidTy ( ) ) { if ( ! isSupportedType ( DL , TLI , OrigRet . Ty ) ) return false ; ArgInfos . clear ( ) ; splitToValueTypes ( OrigRet , ArgInfos , DL , MRI ) ; auto RetAssignFn = TLI . CCAssignFnForReturn ( CallConv , false ) ; CallReturnHandler RetHandler ( MIRBuilder , MRI , MIB , RetAssignFn ) ; if ( ! handleAssignments ( MIRBuilder , ArgInfos , RetHandler ) ) return false ; } CallSeqStart . addImm ( ArgHandler . StackSize ) . add ( predOps ( ARMCC :: AL ) ) ; MIRBuilder . buildInstr ( ARM :: ADJCALLSTACKUP ) . addImm ( ArgHandler . StackSize ) . addImm ( 0 ) . add ( predOps ( ARMCC :: AL ) ) ; return true ; } </s>

ARM ARM ARM ARM ARM::ADJCALLSTACKDOWN ARM::BLX 8 ARMCC::AL ARM::ADJCALLSTACKUP 0 ARMCC::AL


<s> bool ARMCallLowering :: lowerFormalArguments ( MachineIRBuilder & MIRBuilder , const Function & F , ArrayRef < unsigned > VRegs ) const { if ( F . arg_empty ( ) ) return true ; if ( F . isVarArg ( ) ) return false ; auto & MF = MIRBuilder . getMF ( ) ; auto DL = MF . getDataLayout ( ) ; auto & TLI = * getTLI < ARMTargetLowering > ( ) ; auto Subtarget = TLI . getSubtarget ( ) ; if ( Subtarget -> isThumb ( ) ) return false ; for ( auto & Arg : F . args ( ) ) if ( ! isSupportedType ( DL , TLI , Arg . getType ( ) ) ) return false ; CCAssignFn * AssignFn = TLI . CCAssignFnForCall ( F . getCallingConv ( ) , F . isVarArg ( ) ) ; SmallVector < ArgInfo , 8 > ArgInfos ; unsigned Idx = 0 ; for ( auto & Arg : F . args ( ) ) { ArgInfo AInfo ( VRegs [ Idx ] , Arg . getType ( ) ) ; setArgFlags ( AInfo , Idx + 1 , DL , F ) ; splitToValueTypes ( AInfo , ArgInfos , DL , MF . getRegInfo ( ) ) ; Idx ++ ; } FormalArgHandler ArgHandler ( MIRBuilder , MIRBuilder . getMF ( ) . getRegInfo ( ) , AssignFn ) ; return handleAssignments ( MIRBuilder , ArgInfos , ArgHandler ) ; } </s>


<s> bool ARMCallLowering :: lowerFormalArguments ( MachineIRBuilder & MIRBuilder , const Function & F , ArrayRef < unsigned > VRegs ) const { if ( F . arg_empty ( ) ) return true ; if ( F . isVarArg ( ) ) return false ; auto & MF = MIRBuilder . getMF ( ) ; auto & MBB = MIRBuilder . getMBB ( ) ; auto DL = MF . getDataLayout ( ) ; auto & TLI = * getTLI < ARMTargetLowering > ( ) ; auto Subtarget = TLI . getSubtarget ( ) ; if ( Subtarget -> isThumb ( ) ) return false ; for ( auto & Arg : F . args ( ) ) if ( ! isSupportedType ( DL , TLI , Arg . getType ( ) ) ) return false ; CCAssignFn * AssignFn = TLI . CCAssignFnForCall ( F . getCallingConv ( ) , F . isVarArg ( ) ) ; FormalArgHandler ArgHandler ( MIRBuilder , MIRBuilder . getMF ( ) . getRegInfo ( ) , AssignFn ) ; SmallVector < ArgInfo , 8 > ArgInfos ; SmallVector < unsigned , 4 > SplitRegs ; unsigned Idx = 0 ; for ( auto & Arg : F . args ( ) ) { ArgInfo AInfo ( VRegs [ Idx ] , Arg . getType ( ) ) ; setArgFlags ( AInfo , Idx + AttributeList :: FirstArgIndex , DL , F ) ; SplitRegs . clear ( ) ; splitToValueTypes ( AInfo , ArgInfos , MF , [ & ] ( unsigned Reg , uint64_t Offset ) { SplitRegs . push_back ( Reg ) ; } ) ; if ( ! SplitRegs . empty ( ) ) MIRBuilder . buildMerge ( VRegs [ Idx ] , SplitRegs ) ; Idx ++ ; } if ( ! MBB . empty ( ) ) MIRBuilder . setInstr ( * MBB . begin ( ) ) ; return handleAssignments ( MIRBuilder , ArgInfos , ArgHandler ) ; } </s>


<s> bool ARMCallLowering :: lowerFormalArguments ( MachineIRBuilder & MIRBuilder , const Function & F , ArrayRef < unsigned > VRegs ) const { if ( F . arg_empty ( ) ) return true ; if ( F . isVarArg ( ) ) return false ; auto & MF = MIRBuilder . getMF ( ) ; auto DL = MF . getDataLayout ( ) ; auto & TLI = * getTLI < ARMTargetLowering > ( ) ; auto Subtarget = TLI . getSubtarget ( ) ; if ( Subtarget -> isThumb ( ) ) return false ; if ( Subtarget -> useSoftFloat ( ) || ! Subtarget -> hasVFP2 ( ) ) return false ; for ( auto & Arg : F . args ( ) ) if ( ! isSupportedType ( DL , TLI , Arg . getType ( ) ) ) return false ; CCAssignFn * AssignFn = TLI . CCAssignFnForCall ( F . getCallingConv ( ) , F . isVarArg ( ) ) ; SmallVector < ArgInfo , 8 > ArgInfos ; unsigned Idx = 0 ; for ( auto & Arg : F . args ( ) ) { ArgInfo AInfo ( VRegs [ Idx ] , Arg . getType ( ) ) ; setArgFlags ( AInfo , Idx + 1 , DL , F ) ; splitToValueTypes ( AInfo , ArgInfos , DL , MF . getRegInfo ( ) ) ; Idx ++ ; } FormalArgHandler ArgHandler ( MIRBuilder , MIRBuilder . getMF ( ) . getRegInfo ( ) , AssignFn ) ; return handleAssignments ( MIRBuilder , ArgInfos , ArgHandler ) ; } </s>


<s>
unsigned
assignCustomValue
(
const
llvm
::
ARMCallLowering
::
ArgInfo
&
Arg
,
ArrayRef
<
CCValAssign
>
VAs
)
override
{
CCValAssign
VA
=
VAs
[
0
]
;
assert
(
VA
.
needsCustom
(
)
&&
"Value doesn't need custom handling"
)
;
assert
(
VA
.
getValVT
(
)
==
MVT
::
f64
&&
"Unsupported type"
)
;
CCValAssign
NextVA
=
VAs
[
1
]
;
assert
(
NextVA
.
needsCustom
(
)
&&
"Value doesn't need custom handling"
)
;
assert
(
NextVA
.
getValVT
(
)
==
MVT
::
f64
&&
"Unsupported type"
)
;
assert
(
VA
.
getValNo
(
)
==
NextVA
.
getValNo
(
)
&&
"Values belong to different arguments"
)
;
assert
(
VA
.
isRegLoc
(
)
&&
"Value should be in reg"
)
;
assert
(
NextVA
.
isRegLoc
(
)
&&
"Value should be in reg"
)
;
unsigned
NewRegs
[
]
=
{
MRI
.
createGenericVirtualRegister
(
LLT
::
scalar
(
32
)
)
,
MRI
.
createGenericVirtualRegister
(
LLT
::
scalar
(
32
)
)
}
;
assignValueToReg
(
NewRegs
[
0
]
,
VA
.
getLocReg
(
)
,
VA
)
;
assignValueToReg
(
NewRegs
[
1
]
,
NextVA
.
getLocReg
(
)
,
NextVA
)
;
bool
IsLittle
=
MIRBuilder
.
getMF
(
)
.
getSubtarget
<
ARMSubtarget
>
(
)
.
isLittle
(
)
;
if
(
!
IsLittle
)
std
::
swap
(
NewRegs
[
0
]
,
NewRegs
[
1
]
)
;
MIRBuilder
.
buildSequence
(
Arg
.
Reg
,
NewRegs
,
{
0
,
32
}
)
;
return
1
;
}
</s>


<s>
void
assignValueToReg
(
unsigned
ValVReg
,
unsigned
PhysReg
,
CCValAssign
&
VA
)
override
{
assert
(
VA
.
isRegLoc
(
)
&&
"Value shouldn't be assigned to reg"
)
;
assert
(
VA
.
getLocReg
(
)
==
PhysReg
&&
"Assigning to the wrong reg?"
)
;
assert
(
VA
.
getValVT
(
)
.
getSizeInBits
(
)
<=
64
&&
"Unsupported value size"
)
;
assert
(
VA
.
getLocVT
(
)
.
getSizeInBits
(
)
<=
64
&&
"Unsupported location size"
)
;
MIRBuilder
.
getMBB
(
)
.
addLiveIn
(
PhysReg
)
;
MIRBuilder
.
buildCopy
(
ValVReg
,
PhysReg
)
;
}
</s>


<s>
unsigned
assignCustomValue
(
const
ARMCallLowering
::
ArgInfo
&
Arg
,
ArrayRef
<
CCValAssign
>
VAs
)
override
{
assert
(
Arg
.
Regs
.
size
(
)
==
1
&&
"Can't handle multple regs yet"
)
;
CCValAssign
VA
=
VAs
[
0
]
;
assert
(
VA
.
needsCustom
(
)
&&
"Value doesn't need custom handling"
)
;
if
(
VA
.
getValVT
(
)
!=
MVT
::
f64
)
return
0
;
CCValAssign
NextVA
=
VAs
[
1
]
;
assert
(
NextVA
.
needsCustom
(
)
&&
"Value doesn't need custom handling"
)
;
assert
(
NextVA
.
getValVT
(
)
==
MVT
::
f64
&&
"Unsupported type"
)
;
assert
(
VA
.
getValNo
(
)
==
NextVA
.
getValNo
(
)
&&
"Values belong to different arguments"
)
;
assert
(
VA
.
isRegLoc
(
)
&&
"Value should be in reg"
)
;
assert
(
NextVA
.
isRegLoc
(
)
&&
"Value should be in reg"
)
;
Register
NewRegs
[
]
=
{
MRI
.
createGenericVirtualRegister
(
LLT
::
scalar
(
32
)
)
,
MRI
.
createGenericVirtualRegister
(
LLT
::
scalar
(
32
)
)
}
;
assignValueToReg
(
NewRegs
[
0
]
,
VA
.
getLocReg
(
)
,
VA
)
;
assignValueToReg
(
NewRegs
[
1
]
,
NextVA
.
getLocReg
(
)
,
NextVA
)
;
bool
IsLittle
=
MIRBuilder
.
getMF
(
)
.
getSubtarget
<
ARMSubtarget
>
(
)
.
isLittle
(
)
;
if
(
!
IsLittle
)
std
::
swap
(
NewRegs
[
0
]
,
NewRegs
[
1
]
)
;
MIRBuilder
.
buildMerge
(
Arg
.
Regs
[
0
]
,
NewRegs
)
;
return
1
;
}
</s>


<s>
void
assignValueToAddress
(
Register
ValVReg
,
Register
Addr
,
uint64_t
Size
,
MachinePointerInfo
&
MPO
,
CCValAssign
&
VA
)
override
{
assert
(
(
Size
==
1
||
Size
==
2
||
Size
==
4
||
Size
==
8
)
&&
"Unsupported size"
)
;
if
(
VA
.
getLocInfo
(
)
==
CCValAssign
::
SExt
||
VA
.
getLocInfo
(
)
==
CCValAssign
::
ZExt
)
{
Size
=
4
;
assert
(
MRI
.
getType
(
ValVReg
)
.
isScalar
(
)
&&
"Only scalars supported atm"
)
;
auto
LoadVReg
=
buildLoad
(
LLT
::
scalar
(
32
)
,
Addr
,
Size
,
MPO
)
;
MIRBuilder
.
buildTrunc
(
ValVReg
,
LoadVReg
)
;
}
else
{
buildLoad
(
ValVReg
,
Addr
,
Size
,
MPO
)
;
}
}
</s>


<s>
void
assignValueToReg
(
Register
ValVReg
,
Register
PhysReg
,
CCValAssign
&
VA
)
override
{
assert
(
VA
.
isRegLoc
(
)
&&
"Value shouldn't be assigned to reg"
)
;
assert
(
VA
.
getLocReg
(
)
==
PhysReg
&&
"Assigning to the wrong reg?"
)
;
auto
ValSize
=
VA
.
getValVT
(
)
.
getSizeInBits
(
)
;
auto
LocSize
=
VA
.
getLocVT
(
)
.
getSizeInBits
(
)
;
assert
(
ValSize
<=
64
&&
"Unsupported value size"
)
;
assert
(
LocSize
<=
64
&&
"Unsupported location size"
)
;
markPhysRegUsed
(
PhysReg
)
;
if
(
ValSize
==
LocSize
)
{
MIRBuilder
.
buildCopy
(
ValVReg
,
PhysReg
)
;
}
else
{
assert
(
ValSize
<
LocSize
&&
"Extensions not supported"
)
;
auto
PhysRegToVReg
=
MIRBuilder
.
buildCopy
(
LLT
::
scalar
(
LocSize
)
,
PhysReg
)
;
MIRBuilder
.
buildTrunc
(
ValVReg
,
PhysRegToVReg
)
;
}
}
</s>


<s> MachineInstrBuilder buildLoad ( const DstOp & Res , Register Addr , uint64_t Size , MachinePointerInfo & MPO ) { MachineFunction & MF = MIRBuilder . getMF ( ) ; auto MMO = MF . getMachineMemOperand ( MPO , MachineMemOperand :: MOLoad , Size , inferAlignFromPtrInfo ( MF , MPO ) ) ; return MIRBuilder . buildLoad ( Res , Addr , * MMO ) ; } </s>


<s>
Register
getStackAddress
(
uint64_t
Size
,
int64_t
Offset
,
MachinePointerInfo
&
MPO
)
override
{
assert
(
(
Size
==
1
||
Size
==
2
||
Size
==
4
||
Size
==
8
)
&&
"Unsupported size"
)
;
auto
&
MFI
=
MIRBuilder
.
getMF
(
)
.
getFrameInfo
(
)
;
int
FI
=
MFI
.
CreateFixedObject
(
Size
,
Offset
,
true
)
;
MPO
=
MachinePointerInfo
::
getFixedStack
(
MIRBuilder
.
getMF
(
)
,
FI
)
;
return
MIRBuilder
.
buildFrameIndex
(
LLT
::
pointer
(
MPO
.
getAddrSpace
(
)
,
32
)
,
FI
)
.
getReg
(
0
)
;
}
</s>


<s> bool isIncomingArgumentHandler ( ) const override { return true ; } </s>

Returns true if the handler is dealing with incoming arguments , i.e .


<s> bool ARMCallLowering :: lowerFormalArguments ( MachineIRBuilder & MIRBuilder , const Function & F , ArrayRef < ArrayRef < Register >> VRegs ) const { auto & TLI = * getTLI < ARMTargetLowering > ( ) ; auto Subtarget = TLI . getSubtarget ( ) ; if ( Subtarget -> isThumb1Only ( ) ) return false ; if ( F . arg_empty ( ) ) return true ; if ( F . isVarArg ( ) ) return false ; auto & MF = MIRBuilder . getMF ( ) ; auto & MBB = MIRBuilder . getMBB ( ) ; auto DL = MF . getDataLayout ( ) ; for ( auto & Arg : F . args ( ) ) { if ( ! isSupportedType ( DL , TLI , Arg . getType ( ) ) ) return false ; if ( Arg . hasPassPointeeByValueAttr ( ) ) return false ; } CCAssignFn * AssignFn = TLI . CCAssignFnForCall ( F . getCallingConv ( ) , F . isVarArg ( ) ) ; FormalArgHandler ArgHandler ( MIRBuilder , MIRBuilder . getMF ( ) . getRegInfo ( ) , AssignFn ) ; SmallVector < ArgInfo , 8 > SplitArgInfos ; unsigned Idx = 0 ; for ( auto & Arg : F . args ( ) ) { ArgInfo OrigArgInfo ( VRegs [ Idx ] , Arg . getType ( ) ) ; setArgFlags ( OrigArgInfo , Idx + AttributeList :: FirstArgIndex , DL , F ) ; splitToValueTypes ( OrigArgInfo , SplitArgInfos , MF ) ; Idx ++ ; } if ( ! MBB . empty ( ) ) MIRBuilder . setInstr ( * MBB . begin ( ) ) ; if ( ! handleAssignments ( MIRBuilder , SplitArgInfos , ArgHandler ) ) return false ; MIRBuilder . setMBB ( MBB ) ; return true ; } </s>


<s>
bool
ARMCallLowering
::
lowerReturn
(
MachineIRBuilder
&
MIRBuilder
,
const
Value
*
Val
,
ArrayRef
<
Register
>
VRegs
)
const
{
assert
(
!
Val
==
VRegs
.
empty
(
)
&&
"Return value without a vreg"
)
;
auto
const
&
ST
=
MIRBuilder
.
getMF
(
)
.
getSubtarget
<
ARMSubtarget
>
(
)
;
unsigned
Opcode
=
ST
.
getReturnOpcode
(
)
;
auto
Ret
=
MIRBuilder
.
buildInstrNoInsert
(
Opcode
)
.
add
(
predOps
(
ARMCC
::
AL
)
)
;
if
(
!
lowerReturnVal
(
MIRBuilder
,
Val
,
VRegs
,
Ret
)
)
return
false
;
MIRBuilder
.
insertInstr
(
Ret
)
;
return
true
;
}
</s>


"Unhandled instruction encoding format!"

Targets should implement this to emit instructions .


<s>
unsigned
ARMCodeEmitter
::
getMachineOpValue
(
const
MachineInstr
&
MI
,
const
MachineOperand
&
MO
)
const
{
if
(
MO
.
isReg
(
)
)
return
getARMRegisterNumbering
(
MO
.
getReg
(
)
)
;
else
if
(
MO
.
isImm
(
)
)
return
static_cast
<
unsigned
>
(
MO
.
getImm
(
)
)
;
else
if
(
MO
.
isGlobal
(
)
)
emitGlobalAddress
(
MO
.
getGlobal
(
)
,
ARM
::
reloc_arm_branch
,
true
,
false
)
;
else
if
(
MO
.
isSymbol
(
)
)
emitExternalSymbolAddress
(
MO
.
getSymbolName
(
)
,
ARM
::
reloc_arm_branch
)
;
else
if
(
MO
.
isCPI
(
)
)
{
const
TargetInstrDesc
&
TID
=
MI
.
getDesc
(
)
;
unsigned
Reloc
=
(
(
TID
.
TSFlags
&
ARMII
::
FormMask
)
==
ARMII
::
VFPLdStFrm
)
ARM
::
reloc_arm_vfp_cp_entry
:
ARM
::
reloc_arm_cp_entry
;
emitConstPoolAddress
(
MO
.
getIndex
(
)
,
Reloc
)
;
}
else
if
(
MO
.
isJTI
(
)
)
emitJumpTableAddress
(
MO
.
getIndex
(
)
,
ARM
::
reloc_arm_relative
)
;
else
if
(
MO
.
isMBB
(
)
)
emitMachineBasicBlock
(
MO
.
getMBB
(
)
,
ARM
::
reloc_arm_branch
)
;
else
llvm_unreachable
(
"Unable to encode MachineOperand!"
)
;
return
0
;
}
</s>

getMachineOpValue - Return binary encoding of operand .


"JIT relocation model must be set to static or default!"

runOnMachineFunction - Emit the function body .


<s> unsigned Emitter < CodeEmitter > :: getMachineOpValue ( const MachineInstr & MI , const MachineOperand & MO ) { if ( MO . isReg ( ) ) return ARMRegisterInfo :: getRegisterNumbering ( MO . getReg ( ) ) ; else if ( MO . isImm ( ) ) return static_cast < unsigned > ( MO . getImm ( ) ) ; else if ( MO . isGlobal ( ) ) emitGlobalAddress ( MO . getGlobal ( ) , ARM :: reloc_arm_branch , true , false ) ; else if ( MO . isSymbol ( ) ) emitExternalSymbolAddress ( MO . getSymbolName ( ) , ARM :: reloc_arm_branch ) ; else if ( MO . isCPI ( ) ) { const TargetInstrDesc & TID = MI . getDesc ( ) ; unsigned Reloc = ( ( TID . TSFlags & ARMII :: FormMask ) == ARMII :: VFPLdStFrm ) ? ARM :: reloc_arm_vfp_cp_entry : ARM :: reloc_arm_cp_entry ; emitConstPoolAddress ( MO . getIndex ( ) , Reloc ) ; } else if ( MO . isJTI ( ) ) emitJumpTableAddress ( MO . getIndex ( ) , ARM :: reloc_arm_relative ) ; else if ( MO . isMBB ( ) ) emitMachineBasicBlock ( MO . getMBB ( ) , ARM :: reloc_arm_branch ) ; else { cerr << MO ; llvm_unreachable ( 0 ) ; } return 0 ; } </s>


<s>
unsigned
ARMCodeEmitter
::
getMachineOpValue
(
const
MachineInstr
&
MI
,
const
MachineOperand
&
MO
)
const
{
if
(
MO
.
isReg
(
)
)
return
getARMRegisterNumbering
(
MO
.
getReg
(
)
)
;
else
if
(
MO
.
isImm
(
)
)
return
static_cast
<
unsigned
>
(
MO
.
getImm
(
)
)
;
else
if
(
MO
.
isGlobal
(
)
)
emitGlobalAddress
(
MO
.
getGlobal
(
)
,
ARM
::
reloc_arm_branch
,
true
,
false
)
;
else
if
(
MO
.
isSymbol
(
)
)
emitExternalSymbolAddress
(
MO
.
getSymbolName
(
)
,
ARM
::
reloc_arm_branch
)
;
else
if
(
MO
.
isCPI
(
)
)
{
const
MCInstrDesc
&
MCID
=
MI
.
getDesc
(
)
;
unsigned
Reloc
=
(
(
MCID
.
TSFlags
&
ARMII
::
FormMask
)
==
ARMII
::
VFPLdStFrm
)
ARM
::
reloc_arm_vfp_cp_entry
:
ARM
::
reloc_arm_cp_entry
;
emitConstPoolAddress
(
MO
.
getIndex
(
)
,
Reloc
)
;
}
else
if
(
MO
.
isJTI
(
)
)
emitJumpTableAddress
(
MO
.
getIndex
(
)
,
ARM
::
reloc_arm_relative
)
;
else
if
(
MO
.
isMBB
(
)
)
emitMachineBasicBlock
(
MO
.
getMBB
(
)
,
ARM
::
reloc_arm_branch
)
;
else
llvm_unreachable
(
"Unable to encode MachineOperand!"
)
;
return
0
;
}
</s>


<s>
unsigned
ARMCodeEmitter
::
getMachineOpValue
(
const
MachineInstr
&
MI
,
const
MachineOperand
&
MO
)
const
{
if
(
MO
.
isReg
(
)
)
return
II
->
getRegisterInfo
(
)
.
getEncodingValue
(
MO
.
getReg
(
)
)
;
else
if
(
MO
.
isImm
(
)
)
return
static_cast
<
unsigned
>
(
MO
.
getImm
(
)
)
;
else
if
(
MO
.
isGlobal
(
)
)
emitGlobalAddress
(
MO
.
getGlobal
(
)
,
ARM
::
reloc_arm_branch
,
true
,
false
)
;
else
if
(
MO
.
isSymbol
(
)
)
emitExternalSymbolAddress
(
MO
.
getSymbolName
(
)
,
ARM
::
reloc_arm_branch
)
;
else
if
(
MO
.
isCPI
(
)
)
{
const
MCInstrDesc
&
MCID
=
MI
.
getDesc
(
)
;
unsigned
Reloc
=
(
(
MCID
.
TSFlags
&
ARMII
::
FormMask
)
==
ARMII
::
VFPLdStFrm
)
ARM
::
reloc_arm_vfp_cp_entry
:
ARM
::
reloc_arm_cp_entry
;
emitConstPoolAddress
(
MO
.
getIndex
(
)
,
Reloc
)
;
}
else
if
(
MO
.
isJTI
(
)
)
emitJumpTableAddress
(
MO
.
getIndex
(
)
,
ARM
::
reloc_arm_relative
)
;
else
if
(
MO
.
isMBB
(
)
)
emitMachineBasicBlock
(
MO
.
getMBB
(
)
,
ARM
::
reloc_arm_branch
)
;
else
llvm_unreachable
(
"Unable to encode MachineOperand!"
)
;
return
0
;
}
</s>


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

getAnalysisUsage - Subclasses that override getAnalysisUsage must call this .


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

getPassName - Return a nice clean name for a pass .


"ERROR: Unknown type of MachineOperand: "


<s> unsigned ARMCodeEmitter :: getMachineOpValue ( const MachineInstr & MI , const MachineOperand & MO ) { if ( MO . isReg ( ) ) return ARMRegisterInfo :: getRegisterNumbering ( MO . getReg ( ) ) ; else if ( MO . isImm ( ) ) return static_cast < unsigned > ( MO . getImm ( ) ) ; else if ( MO . isGlobal ( ) ) emitGlobalAddress ( MO . getGlobal ( ) , ARM :: reloc_arm_branch , true , false ) ; else if ( MO . isSymbol ( ) ) emitExternalSymbolAddress ( MO . getSymbolName ( ) , ARM :: reloc_arm_branch ) ; else if ( MO . isCPI ( ) ) { const TargetInstrDesc & TID = MI . getDesc ( ) ; unsigned Reloc = ( ( TID . TSFlags & ARMII :: FormMask ) == ARMII :: VFPLdStFrm ) ? ARM :: reloc_arm_vfp_cp_entry : ARM :: reloc_arm_cp_entry ; emitConstPoolAddress ( MO . getIndex ( ) , Reloc ) ; } else if ( MO . isJTI ( ) ) emitJumpTableAddress ( MO . getIndex ( ) , ARM :: reloc_arm_relative ) ; else if ( MO . isMBB ( ) ) emitMachineBasicBlock ( MO . getMBB ( ) , ARM :: reloc_arm_branch ) ; else { errs ( ) << MO ; llvm_unreachable ( 0 ) ; } return 0 ; } </s>


<s>
unsigned
ARMCodeEmitter
::
getMachineOpValue
(
const
MachineInstr
&
MI
,
const
MachineOperand
&
MO
)
const
{
if
(
MO
.
isReg
(
)
)
return
getARMRegisterNumbering
(
MO
.
getReg
(
)
)
;
else
if
(
MO
.
isImm
(
)
)
return
static_cast
<
unsigned
>
(
MO
.
getImm
(
)
)
;
else
if
(
MO
.
isFPImm
(
)
)
return
static_cast
<
unsigned
>
(
MO
.
getFPImm
(
)
->
getValueAPF
(
)
.
bitcastToAPInt
(
)
.
getHiBits
(
32
)
.
getLimitedValue
(
)
)
;
else
if
(
MO
.
isGlobal
(
)
)
emitGlobalAddress
(
MO
.
getGlobal
(
)
,
ARM
::
reloc_arm_branch
,
true
,
false
)
;
else
if
(
MO
.
isSymbol
(
)
)
emitExternalSymbolAddress
(
MO
.
getSymbolName
(
)
,
ARM
::
reloc_arm_branch
)
;
else
if
(
MO
.
isCPI
(
)
)
{
const
MCInstrDesc
&
MCID
=
MI
.
getDesc
(
)
;
unsigned
Reloc
=
(
(
MCID
.
TSFlags
&
ARMII
::
FormMask
)
==
ARMII
::
VFPLdStFrm
)
ARM
::
reloc_arm_vfp_cp_entry
:
ARM
::
reloc_arm_cp_entry
;
emitConstPoolAddress
(
MO
.
getIndex
(
)
,
Reloc
)
;
}
else
if
(
MO
.
isJTI
(
)
)
emitJumpTableAddress
(
MO
.
getIndex
(
)
,
ARM
::
reloc_arm_relative
)
;
else
if
(
MO
.
isMBB
(
)
)
emitMachineBasicBlock
(
MO
.
getMBB
(
)
,
ARM
::
reloc_arm_branch
)
;
else
llvm_unreachable
(
"Unable to encode MachineOperand!"
)
;
return
0
;
}
</s>


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


<s> unsigned getBranchTargetOpValue ( const MachineInstr & MI , unsigned Op ) const { return 0 ; } </s>

getBranchTargetOpValue - Return binary encoding of the branch target operand .


<s>
unsigned
ARMCodeEmitter
::
getMachineOpValue
(
const
MachineInstr
&
MI
,
const
MachineOperand
&
MO
)
const
{
if
(
MO
.
isReg
(
)
)
return
II
->
getRegisterInfo
(
)
.
getEncodingValue
(
MO
.
getReg
(
)
)
;
else
if
(
MO
.
isImm
(
)
)
return
static_cast
<
unsigned
>
(
MO
.
getImm
(
)
)
;
else
if
(
MO
.
isFPImm
(
)
)
return
static_cast
<
unsigned
>
(
MO
.
getFPImm
(
)
->
getValueAPF
(
)
.
bitcastToAPInt
(
)
.
getHiBits
(
32
)
.
getLimitedValue
(
)
)
;
else
if
(
MO
.
isGlobal
(
)
)
emitGlobalAddress
(
MO
.
getGlobal
(
)
,
ARM
::
reloc_arm_branch
,
true
,
false
)
;
else
if
(
MO
.
isSymbol
(
)
)
emitExternalSymbolAddress
(
MO
.
getSymbolName
(
)
,
ARM
::
reloc_arm_branch
)
;
else
if
(
MO
.
isCPI
(
)
)
{
const
MCInstrDesc
&
MCID
=
MI
.
getDesc
(
)
;
unsigned
Reloc
=
(
(
MCID
.
TSFlags
&
ARMII
::
FormMask
)
==
ARMII
::
VFPLdStFrm
)
ARM
::
reloc_arm_vfp_cp_entry
:
ARM
::
reloc_arm_cp_entry
;
emitConstPoolAddress
(
MO
.
getIndex
(
)
,
Reloc
)
;
}
else
if
(
MO
.
isJTI
(
)
)
emitJumpTableAddress
(
MO
.
getIndex
(
)
,
ARM
::
reloc_arm_relative
)
;
else
if
(
MO
.
isMBB
(
)
)
emitMachineBasicBlock
(
MO
.
getMBB
(
)
,
ARM
::
reloc_arm_branch
)
;
else
llvm_unreachable
(
"Unable to encode MachineOperand!"
)
;
return
0
;
}
</s>


<s>
virtual
const
char
*
getPassName
(
)
const
{
return
"ARM Machine Code Emitter"
;
}
</s>


<s>
bool
ARMCodeGenPrepare
::
runOnFunction
(
Function
&
F
)
{
if
(
skipFunction
(
F
)
||
DisableCGP
)
return
false
;
auto
*
TPC
=
&
getAnalysis
<
TargetPassConfig
>
(
)
;
if
(
!
TPC
)
return
false
;
const
TargetMachine
&
TM
=
TPC
->
getTM
<
TargetMachine
>
(
)
;
ST
=
&
TM
.
getSubtarget
<
ARMSubtarget
>
(
F
)
;
bool
MadeChange
=
false
;
LLVM_DEBUG
(
dbgs
(
)
<<
"ARM CGP: Running on "
<<
F
.
getName
(
)
<<
"\n"
)
;
for
(
BasicBlock
&
BB
:
F
)
{
auto
&
Insts
=
BB
.
getInstList
(
)
;
for
(
auto
&
I
:
Insts
)
{
if
(
AllVisited
.
count
(
&
I
)
)
continue
;
if
(
isa
<
ICmpInst
>
(
I
)
)
{
auto
&
CI
=
cast
<
ICmpInst
>
(
I
)
;
if
(
CI
.
isSigned
(
)
||
!
isa
<
IntegerType
>
(
CI
.
getOperand
(
0
)
->
getType
(
)
)
)
continue
;
LLVM_DEBUG
(
dbgs
(
)
<<
"ARM CGP: Searching from: "
<<
CI
<<
"\n"
)
;
for
(
auto
&
Op
:
CI
.
operands
(
)
)
{
if
(
auto
*
I
=
dyn_cast
<
Instruction
>
(
Op
)
)
MadeChange
|=
TryToPromote
(
I
)
;
}
}
}
LLVM_DEBUG
(
if
(
verifyFunction
(
F
,
&
dbgs
(
)
)
)
{
dbgs
(
)
<<
F
;
report_fatal_error
(
"Broken function after type promotion"
)
;
}
)
;
}
if
(
MadeChange
)
LLVM_DEBUG
(
dbgs
(
)
<<
"After ARMCodeGenPrepare: "
<<
F
<<
"\n"
)
;
return
MadeChange
;
}
</s>

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

ARM
ARM
ARM
"ARM CGP: Running on "
"\n"
0
"ARM CGP: Searching from: "
"\n"
"Broken function after type promotion"
"After ARMCodeGenPrepare: "
"\n"


<s>
bool
ARMCodeGenPrepare
::
runOnFunction
(
Function
&
F
)
{
if
(
skipFunction
(
F
)
||
DisableCGP
)
return
false
;
auto
*
TPC
=
&
getAnalysis
<
TargetPassConfig
>
(
)
;
if
(
!
TPC
)
return
false
;
const
TargetMachine
&
TM
=
TPC
->
getTM
<
TargetMachine
>
(
)
;
ST
=
&
TM
.
getSubtarget
<
ARMSubtarget
>
(
F
)
;
bool
MadeChange
=
false
;
LLVM_DEBUG
(
dbgs
(
)
<<
"ARM CGP: Running on "
<<
F
.
getName
(
)
<<
"\n"
)
;
for
(
BasicBlock
&
BB
:
F
)
{
auto
&
Insts
=
BB
.
getInstList
(
)
;
for
(
auto
&
I
:
Insts
)
{
if
(
AllVisited
.
count
(
&
I
)
)
continue
;
if
(
isa
<
ICmpInst
>
(
I
)
)
{
auto
&
CI
=
cast
<
ICmpInst
>
(
I
)
;
if
(
CI
.
isSigned
(
)
||
!
isa
<
IntegerType
>
(
CI
.
getOperand
(
0
)
->
getType
(
)
)
)
continue
;
for
(
auto
&
Op
:
CI
.
operands
(
)
)
{
if
(
auto
*
I
=
dyn_cast
<
Instruction
>
(
Op
)
)
MadeChange
|=
TryToPromote
(
I
)
;
}
}
}
Promoter
->
Cleanup
(
)
;
LLVM_DEBUG
(
if
(
verifyFunction
(
F
,
&
dbgs
(
)
)
)
{
dbgs
(
)
;
report_fatal_error
(
"Broken function after type promotion"
)
;
}
)
;
}
if
(
MadeChange
)
LLVM_DEBUG
(
dbgs
(
)
<<
"After ARMCodeGenPrepare: "
<<
F
<<
"\n"
)
;
return
MadeChange
;
}
</s>

ARM
ARM
ARM
"ARM CGP: Running on "
"\n"
0
"Broken function after type promotion"
"After ARMCodeGenPrepare: "
"\n"


<s> static bool isSigned ( Value * V ) { if ( ! isa < Instruction > ( V ) ) return false ; unsigned Opc = cast < Instruction > ( V ) -> getOpcode ( ) ; return Opc == Instruction :: AShr || Opc == Instruction :: SDiv || Opc == Instruction :: SRem ; } </s>

Returns true if all source operands of the recurrence are SExtInsts .


<s>
bool
ARMCodeGenPrepare
::
runOnFunction
(
Function
&
F
)
{
if
(
skipFunction
(
F
)
||
DisableCGP
)
return
false
;
auto
*
TPC
=
&
getAnalysis
<
TargetPassConfig
>
(
)
;
if
(
!
TPC
)
return
false
;
const
TargetMachine
&
TM
=
TPC
->
getTM
<
TargetMachine
>
(
)
;
ST
=
&
TM
.
getSubtarget
<
ARMSubtarget
>
(
F
)
;
bool
MadeChange
=
false
;
LLVM_DEBUG
(
dbgs
(
)
<<
"ARM CGP: Running on "
<<
F
.
getName
(
)
<<
"\n"
)
;
for
(
BasicBlock
&
BB
:
F
)
{
auto
&
Insts
=
BB
.
getInstList
(
)
;
for
(
auto
&
I
:
Insts
)
{
if
(
AllVisited
.
count
(
&
I
)
)
continue
;
if
(
isa
<
ICmpInst
>
(
I
)
)
{
auto
&
CI
=
cast
<
ICmpInst
>
(
I
)
;
if
(
CI
.
isSigned
(
)
||
!
isa
<
IntegerType
>
(
CI
.
getOperand
(
0
)
->
getType
(
)
)
)
continue
;
LLVM_DEBUG
(
dbgs
(
)
<<
"ARM CGP: Searching from: "
<<
CI
<<
"\n"
)
;
for
(
auto
&
Op
:
CI
.
operands
(
)
)
{
if
(
auto
*
I
=
dyn_cast
<
Instruction
>
(
Op
)
)
{
if
(
isa
<
ZExtInst
>
(
I
)
)
MadeChange
|=
TryToPromote
(
I
->
getOperand
(
0
)
)
;
else
MadeChange
|=
TryToPromote
(
I
)
;
}
}
}
}
Promoter
->
Cleanup
(
)
;
LLVM_DEBUG
(
if
(
verifyFunction
(
F
,
&
dbgs
(
)
)
)
{
dbgs
(
)
;
report_fatal_error
(
"Broken function after type promotion"
)
;
}
)
;
}
if
(
MadeChange
)
LLVM_DEBUG
(
dbgs
(
)
<<
"After ARMCodeGenPrepare: "
<<
F
<<
"\n"
)
;
return
MadeChange
;
}
</s>

ARM
ARM
ARM
"ARM CGP: Running on "
"\n"
0
"ARM CGP: Searching from: "
"\n"
0
"Broken function after type promotion"
"After ARMCodeGenPrepare: "
"\n"


<s> bool ARMCodeGenPrepare :: doFinalization ( Module & M ) { delete Promoter ; return false ; } </s>

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


<s> bool ARMCodeGenPrepare :: doInitialization ( Module & M ) { Promoter = new IRPromoter ( & M ) ; return false ; } </s>

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


<s> void getAnalysisUsage ( AnalysisUsage & AU ) const override { AU . addRequired < TargetPassConfig > ( ) ; } </s>


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


<s>
bool
ARMCodeGenPrepare
::
runOnFunction
(
Function
&
F
)
{
if
(
skipFunction
(
F
)
||
DisableCGP
)
return
false
;
auto
*
TPC
=
&
getAnalysis
<
TargetPassConfig
>
(
)
;
if
(
!
TPC
)
return
false
;
const
TargetMachine
&
TM
=
TPC
->
getTM
<
TargetMachine
>
(
)
;
ST
=
&
TM
.
getSubtarget
<
ARMSubtarget
>
(
F
)
;
bool
MadeChange
=
false
;
LLVM_DEBUG
(
dbgs
(
)
<<
"ARM CGP: Running on "
<<
F
.
getName
(
)
<<
"\n"
)
;
for
(
BasicBlock
&
BB
:
F
)
{
auto
&
Insts
=
BB
.
getInstList
(
)
;
for
(
auto
&
I
:
Insts
)
{
if
(
AllVisited
.
count
(
&
I
)
)
continue
;
if
(
isa
<
ICmpInst
>
(
I
)
)
{
auto
&
CI
=
cast
<
ICmpInst
>
(
I
)
;
if
(
CI
.
isSigned
(
)
||
!
isa
<
IntegerType
>
(
CI
.
getOperand
(
0
)
->
getType
(
)
)
)
continue
;
LLVM_DEBUG
(
dbgs
(
)
<<
"ARM CGP: Searching from: "
<<
CI
<<
"\n"
)
;
for
(
auto
&
Op
:
CI
.
operands
(
)
)
{
if
(
auto
*
I
=
dyn_cast
<
Instruction
>
(
Op
)
)
MadeChange
|=
TryToPromote
(
I
)
;
}
}
}
Promoter
->
Cleanup
(
)
;
LLVM_DEBUG
(
if
(
verifyFunction
(
F
,
&
dbgs
(
)
)
)
{
dbgs
(
)
;
report_fatal_error
(
"Broken function after type promotion"
)
;
}
)
;
}
if
(
MadeChange
)
LLVM_DEBUG
(
dbgs
(
)
<<
"After ARMCodeGenPrepare: "
<<
F
<<
"\n"
)
;
return
MadeChange
;
}
</s>


"Didn't find MI in its own basic block?"

getOffsetOf - Return the current offset of the specified machine instruction from the start of the function .


"ARM constant island placement and branch shortening pass"


<s>
bool
ARMConstantIslands
::
isBBInRange
(
MachineInstr
*
MI
,
MachineBasicBlock
*
DestBB
,
unsigned
MaxDisp
)
{
unsigned
PCAdj
=
isThumb
4
:
8
;
unsigned
BrOffset
=
getOffsetOf
(
MI
)
+
PCAdj
;
unsigned
DestOffset
=
BBInfo
[
DestBB
->
getNumber
(
)
]
.
Offset
;
DEBUG
(
dbgs
(
)
<<
"Branch of destination BB#"
<<
DestBB
->
getNumber
(
)
<<
" from BB#"
<<
MI
->
getParent
(
)
->
getNumber
(
)
<<
" max delta="
<<
MaxDisp
<<
" from "
<<
getOffsetOf
(
MI
)
<<
" to "
<<
DestOffset
<<
" offset "
<<
int
(
DestOffset
BrOffset
)
<<
"\t"
<<
*
MI
)
;
if
(
BrOffset
<=
DestOffset
)
{
if
(
DestOffset
BrOffset
<=
MaxDisp
)
return
true
;
}
else
{
if
(
BrOffset
DestOffset
<=
MaxDisp
)
return
true
;
}
return
false
;
}
</s>

isBBInRange - Returns true if the distance between specific MI and specific BB can fit in MI 's displacement field .

ARM
ARM
4
8
"Branch of destination BB#"
" from BB#"
" max delta="
" from "
" to "
" offset "
"\t"


<s>
void
ARMConstantIslands
::
verify
(
)
{
for
(
MachineFunction
::
iterator
MBBI
=
MF
->
begin
(
)
,
E
=
MF
->
end
(
)
;
MBBI
!=
E
;
++
MBBI
)
{
MachineBasicBlock
*
MBB
=
&
*
MBBI
;
unsigned
MBBId
=
MBB
->
getNumber
(
)
;
assert
(
!
MBBId
||
BBInfo
[
MBBId
1
]
.
postOffset
(
)
<=
BBInfo
[
MBBId
]
.
Offset
)
;
}
DEBUG
(
dbgs
(
)
<<
"Verifying "
<<
CPUsers
.
size
(
)
<<
" CP users.\n"
)
;
for
(
unsigned
i
=
0
,
e
=
CPUsers
.
size
(
)
;
i
!=
e
;
++
i
)
{
CPUser
&
U
=
CPUsers
[
i
]
;
unsigned
UserOffset
=
getUserOffset
(
U
)
;
if
(
isCPEntryInRange
(
U
.
MI
,
UserOffset
,
U
.
CPEMI
,
U
.
getMaxDisp
(
)
+
2
,
U
.
NegOk
,
true
)
)
{
DEBUG
(
dbgs
(
)
<<
"OK\n"
)
;
continue
;
}
DEBUG
(
dbgs
(
)
<<
"Out of range.\n"
)
;
dumpBBs
(
)
;
DEBUG
(
MF
->
dump
(
)
)
;
llvm_unreachable
(
"Constant pool entry out of range!"
)
;
}
}
</s>

ARM
ARM
1
"Verifying "
" CP users.\n"
0
2
"OK\n"
"Out of range.\n"
"Constant pool entry out of range!"


<s> unsigned internalKnownBits ( ) const { return Unalign ? Unalign : KnownBits ; } </s>

Compute the number of known offset bits internally to this block .


<s> unsigned postOffset ( unsigned LogAlign = 0 ) const { unsigned PO = Offset + Size ; unsigned LA = std :: max ( unsigned ( PostAlign ) , LogAlign ) ; if ( ! LA ) return PO ; return WorstCaseAlign ( PO , LA , internalKnownBits ( ) ) ; } </s>

Compute the offset immediately following this block .


<s>
void
ARMConstantIslands
::
verify
(
)
{
for
(
MachineFunction
::
iterator
MBBI
=
MF
->
begin
(
)
,
E
=
MF
->
end
(
)
;
MBBI
!=
E
;
++
MBBI
)
{
MachineBasicBlock
*
MBB
=
MBBI
;
unsigned
Align
=
MBB
->
getAlignment
(
)
;
unsigned
MBBId
=
MBB
->
getNumber
(
)
;
assert
(
BBInfo
[
MBBId
]
.
Offset
%
(
1u
<<
Align
)
==
0
)
;
assert
(
!
MBBId
||
BBInfo
[
MBBId
1
]
.
postOffset
(
)
<=
BBInfo
[
MBBId
]
.
Offset
)
;
}
DEBUG
(
dbgs
(
)
<<
"Verifying "
<<
CPUsers
.
size
(
)
<<
" CP users.\n"
)
;
for
(
unsigned
i
=
0
,
e
=
CPUsers
.
size
(
)
;
i
!=
e
;
++
i
)
{
CPUser
&
U
=
CPUsers
[
i
]
;
unsigned
UserOffset
=
getUserOffset
(
U
)
;
if
(
isCPEntryInRange
(
U
.
MI
,
UserOffset
,
U
.
CPEMI
,
U
.
getMaxDisp
(
)
+
2
,
U
.
NegOk
,
true
)
)
{
DEBUG
(
dbgs
(
)
<<
"OK\n"
)
;
continue
;
}
DEBUG
(
dbgs
(
)
<<
"Out of range.\n"
)
;
dumpBBs
(
)
;
DEBUG
(
MF
->
dump
(
)
)
;
llvm_unreachable
(
"Constant pool entry out of range!"
)
;
}
}
</s>


"Constant Island pass failed to converge!"

"Branch Fix Up pass failed to converge!"


<s> void ARMConstantIslands :: verify ( MachineFunction & MF ) { assert ( BBOffsets . size ( ) == BBSizes . size ( ) ) ; for ( unsigned i = 1 , e = BBOffsets . size ( ) ; i != e ; ++ i ) assert ( BBOffsets [ i - 1 ] + BBSizes [ i - 1 ] == BBOffsets [ i ] ) ; if ( ! isThumb ) return ; for ( MachineFunction :: iterator MBBI = MF . begin ( ) , E = MF . end ( ) ; MBBI != E ; ++ MBBI ) { MachineBasicBlock * MBB = MBBI ; if ( ! MBB -> empty ( ) && MBB -> begin ( ) -> getOpcode ( ) == ARM :: CONSTPOOL_ENTRY ) { unsigned MBBId = MBB -> getNumber ( ) ; assert ( ( BBOffsets [ MBBId ] % 4 == 0 && BBSizes [ MBBId ] % 4 == 0 ) || ( BBOffsets [ MBBId ] % 4 != 0 && BBSizes [ MBBId ] % 4 != 0 ) ) ; } } } </s>


<s> unsigned internalKnownBits ( ) const { unsigned Bits = Unalign ? Unalign : KnownBits ; if ( Size & ( ( 1u << Bits ) - 1 ) ) Bits = CountTrailingZeros_32 ( Size ) ; return Bits ; } </s>


<s>
void
ARMConstantIslands
::
verify
(
)
{
for
(
MachineFunction
::
iterator
MBBI
=
MF
->
begin
(
)
,
E
=
MF
->
end
(
)
;
MBBI
!=
E
;
++
MBBI
)
{
MachineBasicBlock
*
MBB
=
MBBI
;
unsigned
MBBId
=
MBB
->
getNumber
(
)
;
assert
(
!
MBBId
||
BBInfo
[
MBBId
1
]
.
postOffset
(
)
<=
BBInfo
[
MBBId
]
.
Offset
)
;
}
DEBUG
(
dbgs
(
)
<<
"Verifying "
<<
CPUsers
.
size
(
)
<<
" CP users.\n"
)
;
for
(
unsigned
i
=
0
,
e
=
CPUsers
.
size
(
)
;
i
!=
e
;
++
i
)
{
CPUser
&
U
=
CPUsers
[
i
]
;
unsigned
UserOffset
=
getUserOffset
(
U
)
;
if
(
isCPEntryInRange
(
U
.
MI
,
UserOffset
,
U
.
CPEMI
,
U
.
getMaxDisp
(
)
+
2
,
U
.
NegOk
,
true
)
)
{
DEBUG
(
dbgs
(
)
<<
"OK\n"
)
;
continue
;
}
DEBUG
(
dbgs
(
)
<<
"Out of range.\n"
)
;
dumpBBs
(
)
;
DEBUG
(
MF
->
dump
(
)
)
;
llvm_unreachable
(
"Constant pool entry out of range!"
)
;
}
}
</s>


<s>
void
ARMConstantIslands
::
verify
(
MachineFunction
&
MF
)
{
assert
(
BBOffsets
.
size
(
)
==
BBSizes
.
size
(
)
)
;
for
(
unsigned
i
=
1
,
e
=
BBOffsets
.
size
(
)
;
i
!=
e
;
++
i
)
assert
(
BBOffsets
[
i
1
]
+
BBSizes
[
i
1
]
==
BBOffsets
[
i
]
)
;
if
(
!
isThumb
)
return
;
for
(
MachineFunction
::
iterator
MBBI
=
MF
.
begin
(
)
,
E
=
MF
.
end
(
)
;
MBBI
!=
E
;
++
MBBI
)
{
MachineBasicBlock
*
MBB
=
MBBI
;
if
(
!
MBB
->
empty
(
)
&&
MBB
->
begin
(
)
->
getOpcode
(
)
==
ARM
::
CONSTPOOL_ENTRY
)
{
unsigned
MBBId
=
MBB
->
getNumber
(
)
;
assert
(
HasInlineAsm
||
(
BBOffsets
[
MBBId
]
%
4
==
0
&&
BBSizes
[
MBBId
]
%
4
==
0
)
||
(
BBOffsets
[
MBBId
]
%
4
!=
0
&&
BBSizes
[
MBBId
]
%
4
!=
0
)
)
;
}
}
for
(
unsigned
i
=
0
,
e
=
CPUsers
.
size
(
)
;
i
!=
e
;
++
i
)
{
CPUser
&
U
=
CPUsers
[
i
]
;
unsigned
UserOffset
=
GetOffsetOf
(
U
.
MI
)
+
(
isThumb
4
:
8
)
;
unsigned
CPEOffset
=
GetOffsetOf
(
U
.
CPEMI
)
;
unsigned
Disp
=
UserOffset
<
CPEOffset
CPEOffset
UserOffset
:
UserOffset
CPEOffset
;
assert
(
Disp
<=
U
.
MaxDisp
||
"Constant pool entry out of range!"
)
;
}
}
</s>


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


<s>
void
ARMConstantIslands
::
verify
(
)
{
BBInfoVector
&
BBInfo
=
BBUtils
->
getBBInfo
(
)
;
assert
(
is_sorted
(
*
MF
,
[
&
BBInfo
]
(
const
MachineBasicBlock
&
LHS
,
const
MachineBasicBlock
&
RHS
)
{
return
BBInfo
[
LHS
.
getNumber
(
)
]
.
postOffset
(
)
<
BBInfo
[
RHS
.
getNumber
(
)
]
.
postOffset
(
)
;
}
)
)
;
LLVM_DEBUG
(
dbgs
(
)
<<
"Verifying "
<<
CPUsers
.
size
(
)
<<
" CP users.\n"
)
;
for
(
unsigned
i
=
0
,
e
=
CPUsers
.
size
(
)
;
i
!=
e
;
++
i
)
{
CPUser
&
U
=
CPUsers
[
i
]
;
unsigned
UserOffset
=
getUserOffset
(
U
)
;
if
(
isCPEntryInRange
(
U
.
MI
,
UserOffset
,
U
.
CPEMI
,
U
.
getMaxDisp
(
)
+
2
,
U
.
NegOk
,
true
)
)
{
LLVM_DEBUG
(
dbgs
(
)
<<
"OK\n"
)
;
continue
;
}
LLVM_DEBUG
(
dbgs
(
)
<<
"Out of range.\n"
)
;
dumpBBs
(
)
;
LLVM_DEBUG
(
MF
->
dump
(
)
)
;
llvm_unreachable
(
"Constant pool entry out of range!"
)
;
}
}
</s>

ARM
ARM
"Verifying "
" CP users.\n"
0
2
"OK\n"
"Out of range.\n"
"Constant pool entry out of range!"


<s>
void
ARMConstantIslands
::
verify
(
)
{
assert
(
std
::
is_sorted
(
MF
->
begin
(
)
,
MF
->
end
(
)
,
[
this
]
(
const
MachineBasicBlock
&
LHS
,
const
MachineBasicBlock
&
RHS
)
{
return
BBInfo
[
LHS
.
getNumber
(
)
]
.
postOffset
(
)
<
BBInfo
[
RHS
.
getNumber
(
)
]
.
postOffset
(
)
;
}
)
)
;
DEBUG
(
dbgs
(
)
<<
"Verifying "
<<
CPUsers
.
size
(
)
<<
" CP users.\n"
)
;
for
(
unsigned
i
=
0
,
e
=
CPUsers
.
size
(
)
;
i
!=
e
;
++
i
)
{
CPUser
&
U
=
CPUsers
[
i
]
;
unsigned
UserOffset
=
getUserOffset
(
U
)
;
if
(
isCPEntryInRange
(
U
.
MI
,
UserOffset
,
U
.
CPEMI
,
U
.
getMaxDisp
(
)
+
2
,
U
.
NegOk
,
true
)
)
{
DEBUG
(
dbgs
(
)
<<
"OK\n"
)
;
continue
;
}
DEBUG
(
dbgs
(
)
<<
"Out of range.\n"
)
;
dumpBBs
(
)
;
DEBUG
(
MF
->
dump
(
)
)
;
llvm_unreachable
(
"Constant pool entry out of range!"
)
;
}
}
</s>


<s> bool ARMConstantIslands :: runOnMachineFunction ( MachineFunction & Fn ) { MachineConstantPool & MCP = * Fn . getConstantPool ( ) ; TII = Fn . getTarget ( ) . getInstrInfo ( ) ; AFI = Fn . getInfo < ARMFunctionInfo > ( ) ; isThumb = AFI -> isThumbFunction ( ) ; HasFarJump = false ; Fn . RenumberBlocks ( ) ; AFI -> setAlign ( isThumb ? 1U : 2U ) ; std :: vector < MachineInstr * > CPEMIs ; if ( ! MCP . isEmpty ( ) ) { DoInitialPlacement ( Fn , CPEMIs ) ; if ( isThumb ) AFI -> setAlign ( 2U ) ; } AFI -> initConstPoolEntryUId ( CPEMIs . size ( ) ) ; InitialFunctionScan ( Fn , CPEMIs ) ; CPEMIs . clear ( ) ; RemoveUnusedCPEntries ( ) ; bool MadeChange = false ; while ( true ) { bool Change = false ; for ( unsigned i = 0 , e = CPUsers . size ( ) ; i != e ; ++ i ) Change |= HandleConstantPoolUser ( Fn , i ) ; DEBUG ( dumpBBs ( ) ) ; for ( unsigned i = 0 , e = ImmBranches . size ( ) ; i != e ; ++ i ) Change |= FixUpImmediateBr ( Fn , ImmBranches [ i ] ) ; DEBUG ( dumpBBs ( ) ) ; if ( ! Change ) break ; MadeChange = true ; } verify ( Fn ) ; if ( ! HasFarJump && AFI -> isLRSpilledForFarJump ( ) && isThumb ) MadeChange |= UndoLRSpillRestore ( ) ; BBSizes . clear ( ) ; BBOffsets . clear ( ) ; WaterList . clear ( ) ; CPUsers . clear ( ) ; CPEntries . clear ( ) ; ImmBranches . clear ( ) ; PushPopMIs . clear ( ) ; return MadeChange ; } </s>


<s> void ARMConstantIslands :: verify ( MachineFunction & Fn ) { assert ( BBOffsets . size ( ) == BBSizes . size ( ) ) ; for ( unsigned i = 1 , e = BBOffsets . size ( ) ; i != e ; ++ i ) assert ( BBOffsets [ i - 1 ] + BBSizes [ i - 1 ] == BBOffsets [ i ] ) ; if ( isThumb ) { for ( MachineFunction :: iterator MBBI = Fn . begin ( ) , E = Fn . end ( ) ; MBBI != E ; ++ MBBI ) { MachineBasicBlock * MBB = MBBI ; if ( ! MBB -> empty ( ) && MBB -> begin ( ) -> getOpcode ( ) == ARM :: CONSTPOOL_ENTRY ) assert ( ( BBOffsets [ MBB -> getNumber ( ) ] % 4 == 0 && BBSizes [ MBB -> getNumber ( ) ] % 4 == 0 ) || ( BBOffsets [ MBB -> getNumber ( ) ] % 4 != 0 && BBSizes [ MBB -> getNumber ( ) ] % 4 != 0 ) ) ; } } } </s>


<s>
bool
ARMConstantIslands
::
isBBInRange
(
MachineInstr
*
MI
,
MachineBasicBlock
*
DestBB
,
unsigned
MaxDisp
)
{
unsigned
PCAdj
=
isThumb
4
:
8
;
unsigned
BrOffset
=
getOffsetOf
(
MI
)
+
PCAdj
;
unsigned
DestOffset
=
BBInfo
[
DestBB
->
getNumber
(
)
]
.
Offset
;
DEBUG
(
dbgs
(
)
<<
"Branch of destination "
<<
printMBBReference
(
*
DestBB
)
<<
" from "
<<
printMBBReference
(
*
MI
->
getParent
(
)
)
<<
" max delta="
<<
MaxDisp
<<
" from "
<<
getOffsetOf
(
MI
)
<<
" to "
<<
DestOffset
<<
" offset "
<<
int
(
DestOffset
BrOffset
)
<<
"\t"
<<
*
MI
)
;
if
(
BrOffset
<=
DestOffset
)
{
if
(
DestOffset
BrOffset
<=
MaxDisp
)
return
true
;
}
else
{
if
(
BrOffset
DestOffset
<=
MaxDisp
)
return
true
;
}
return
false
;
}
</s>

ARM
ARM
4
8
"Branch of destination "
" from "
" max delta="
" from "
" to "
" offset "
"\t"


"ARM constant island placement and branch shortening pass"


<s>
void
ARMConstantIslands
::
verify
(
)
{
BBInfoVector
&
BBInfo
=
BBUtils
->
getBBInfo
(
)
;
assert
(
std
::
is_sorted
(
MF
->
begin
(
)
,
MF
->
end
(
)
,
[
&
BBInfo
]
(
const
MachineBasicBlock
&
LHS
,
const
MachineBasicBlock
&
RHS
)
{
return
BBInfo
[
LHS
.
getNumber
(
)
]
.
postOffset
(
)
<
BBInfo
[
RHS
.
getNumber
(
)
]
.
postOffset
(
)
;
}
)
)
;
LLVM_DEBUG
(
dbgs
(
)
<<
"Verifying "
<<
CPUsers
.
size
(
)
<<
" CP users.\n"
)
;
for
(
unsigned
i
=
0
,
e
=
CPUsers
.
size
(
)
;
i
!=
e
;
++
i
)
{
CPUser
&
U
=
CPUsers
[
i
]
;
unsigned
UserOffset
=
getUserOffset
(
U
)
;
if
(
isCPEntryInRange
(
U
.
MI
,
UserOffset
,
U
.
CPEMI
,
U
.
getMaxDisp
(
)
+
2
,
U
.
NegOk
,
true
)
)
{
LLVM_DEBUG
(
dbgs
(
)
<<
"OK\n"
)
;
continue
;
}
LLVM_DEBUG
(
dbgs
(
)
<<
"Out of range.\n"
)
;
dumpBBs
(
)
;
LLVM_DEBUG
(
MF
->
dump
(
)
)
;
llvm_unreachable
(
"Constant pool entry out of range!"
)
;
}
}
</s>


<s>
void
ARMConstantIslands
::
verify
(
)
{
BBInfoVector
&
BBInfo
=
BBUtils
->
getBBInfo
(
)
;
assert
(
is_sorted
(
*
MF
,
[
&
BBInfo
]
(
const
MachineBasicBlock
&
LHS
,
const
MachineBasicBlock
&
RHS
)
{
return
BBInfo
[
LHS
.
getNumber
(
)
]
.
postOffset
(
)
<
BBInfo
[
RHS
.
getNumber
(
)
]
.
postOffset
(
)
;
}
)
)
;
LLVM_DEBUG
(
dbgs
(
)
<<
"Verifying "
<<
CPUsers
.
size
(
)
<<
" CP users.\n"
)
;
for
(
CPUser
&
U
:
CPUsers
)
{
unsigned
UserOffset
=
getUserOffset
(
U
)
;
if
(
isCPEntryInRange
(
U
.
MI
,
UserOffset
,
U
.
CPEMI
,
U
.
getMaxDisp
(
)
+
2
,
U
.
NegOk
,
true
)
)
{
LLVM_DEBUG
(
dbgs
(
)
<<
"OK\n"
)
;
continue
;
}
LLVM_DEBUG
(
dbgs
(
)
<<
"Out of range.\n"
)
;
dumpBBs
(
)
;
LLVM_DEBUG
(
MF
->
dump
(
)
)
;
llvm_unreachable
(
"Constant pool entry out of range!"
)
;
}
}
</s>

ARM
ARM
"Verifying "
" CP users.\n"
2
"OK\n"
"Out of range.\n"
"Constant pool entry out of range!"


"Didn't find MI in its own basic block?"


<s>
void
ARMConstantIslands
::
verify
(
)
{
for
(
MachineFunction
::
iterator
MBBI
=
MF
->
begin
(
)
,
E
=
MF
->
end
(
)
;
MBBI
!=
E
;
++
MBBI
)
{
MachineBasicBlock
*
MBB
=
MBBI
;
unsigned
Align
=
MBB
->
getAlignment
(
)
;
unsigned
MBBId
=
MBB
->
getNumber
(
)
;
assert
(
BBInfo
[
MBBId
]
.
Offset
%
(
1u
<<
Align
)
==
0
)
;
assert
(
!
MBBId
||
BBInfo
[
MBBId
1
]
.
postOffset
(
)
<=
BBInfo
[
MBBId
]
.
Offset
)
;
}
for
(
unsigned
i
=
0
,
e
=
CPUsers
.
size
(
)
;
i
!=
e
;
++
i
)
{
CPUser
&
U
=
CPUsers
[
i
]
;
unsigned
UserOffset
=
GetUserOffset
(
U
)
;
assert
(
CPEIsInRange
(
U
.
MI
,
UserOffset
,
U
.
CPEMI
,
U
.
getMaxDisp
(
)
,
U
.
NegOk
)
&&
"Constant pool entry out of range!"
)
;
}
}
</s>


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


<s>
bool
ARMConstantIslands
::
isBBInRange
(
MachineInstr
*
MI
,
MachineBasicBlock
*
DestBB
,
unsigned
MaxDisp
)
{
unsigned
PCAdj
=
isThumb
4
:
8
;
unsigned
BrOffset
=
getOffsetOf
(
MI
)
+
PCAdj
;
unsigned
DestOffset
=
BBInfo
[
DestBB
->
getNumber
(
)
]
.
Offset
;
LLVM_DEBUG
(
dbgs
(
)
<<
"Branch of destination "
<<
printMBBReference
(
*
DestBB
)
<<
" from "
<<
printMBBReference
(
*
MI
->
getParent
(
)
)
<<
" max delta="
<<
MaxDisp
<<
" from "
<<
getOffsetOf
(
MI
)
<<
" to "
<<
DestOffset
<<
" offset "
<<
int
(
DestOffset
BrOffset
)
<<
"\t"
<<
*
MI
)
;
if
(
BrOffset
<=
DestOffset
)
{
if
(
DestOffset
BrOffset
<=
MaxDisp
)
return
true
;
}
else
{
if
(
BrOffset
DestOffset
<=
MaxDisp
)
return
true
;
}
return
false
;
}
</s>


<s>
void
ARMConstantIslands
::
verify
(
)
{
assert
(
std
::
is_sorted
(
MF
->
begin
(
)
,
MF
->
end
(
)
,
[
this
]
(
const
MachineBasicBlock
&
LHS
,
const
MachineBasicBlock
&
RHS
)
{
return
BBInfo
[
LHS
.
getNumber
(
)
]
.
postOffset
(
)
<
BBInfo
[
RHS
.
getNumber
(
)
]
.
postOffset
(
)
;
}
)
)
;
LLVM_DEBUG
(
dbgs
(
)
<<
"Verifying "
<<
CPUsers
.
size
(
)
<<
" CP users.\n"
)
;
for
(
unsigned
i
=
0
,
e
=
CPUsers
.
size
(
)
;
i
!=
e
;
++
i
)
{
CPUser
&
U
=
CPUsers
[
i
]
;
unsigned
UserOffset
=
getUserOffset
(
U
)
;
if
(
isCPEntryInRange
(
U
.
MI
,
UserOffset
,
U
.
CPEMI
,
U
.
getMaxDisp
(
)
+
2
,
U
.
NegOk
,
true
)
)
{
LLVM_DEBUG
(
dbgs
(
)
<<
"OK\n"
)
;
continue
;
}
LLVM_DEBUG
(
dbgs
(
)
<<
"Out of range.\n"
)
;
dumpBBs
(
)
;
LLVM_DEBUG
(
MF
->
dump
(
)
)
;
llvm_unreachable
(
"Constant pool entry out of range!"
)
;
}
}
</s>


<s> ARMConstantPoolMBB * ARMConstantPoolMBB :: Create ( LLVMContext & C , const MachineBasicBlock * mbb , unsigned ID , unsigned char PCAdj ) { return new ARMConstantPoolMBB ( C , mbb , ID , PCAdj , ARMCP :: no_modifier , false ) ; } </s>

Construct a unary instruction , given the opcode and an operand .


<s>
void
ARMConstantPoolValue
::
dump
(
)
const
{
errs
(
)
<<
"  "
<<
*
this
;
}
</s>

Dump the plan to stderr ( for debugging ) .


<s> bool ARMConstantPoolMBB :: hasSameValue ( ARMConstantPoolValue * ACPV ) { const ARMConstantPoolMBB * ACPMBB = dyn_cast < ARMConstantPoolMBB > ( ACPV ) ; return ACPMBB && ACPMBB -> MBB == MBB && ARMConstantPoolValue :: hasSameValue ( ACPV ) ; } </s>

hasSameValue - Return true if this ARM constpool value can share the same constantpool entry as another ARM constpool value .


<s> void ARMConstantPoolMBB :: print ( raw_ostream & O ) const { O << "BB#" << MBB -> getNumber ( ) ; ARMConstantPoolValue :: print ( O ) ; } </s>

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


<s> const char * getSymbol ( ) const { return S ; } </s>

Get the target address and flags for the named symbol .


<s> bool ARMConstantPoolValue :: hasSameValue ( ARMConstantPoolValue * ACPV ) { if ( ACPV -> Kind == Kind && ACPV -> CVal == CVal && ACPV -> PCAdjust == PCAdjust && CPV_streq ( ACPV -> S , S ) && ACPV -> Modifier == Modifier ) { if ( ACPV -> LabelId == LabelId ) return true ; if ( Kind == ARMCP :: CPValue || Kind == ARMCP :: CPExtSymbol ) return true ; } return false ; } </s>

ARM ARM ARM ARMCP::CPValue ARMCP::CPExtSymbol


<s> bool isBlockAddress ( ) { return Kind == ARMCP :: CPBlockAddress ; } </s>

isBlockAddress - Tests if this is a MO_BlockAddress operand .


<s> void ARMConstantPoolValue :: print ( raw_ostream & O ) const { if ( CVal ) O << CVal -> getName ( ) ; else O << S ; if ( Modifier ) O << "(" << getModifierText ( ) << ")" ; if ( PCAdjust != 0 ) { O << "-(LPC" << LabelId << "+" << ( unsigned ) PCAdjust ; if ( AddCurrentAddress ) O << "-." ; O << ")" ; } } </s>


<s> ARMConstantPoolSymbol * ARMConstantPoolSymbol :: Create ( LLVMContext & C , StringRef s , unsigned ID , unsigned char PCAdj ) { return new ARMConstantPoolSymbol ( C , s , ID , PCAdj , ARMCP :: no_modifier , false ) ; } </s>


<s> void print ( std :: ostream * O ) const { if ( O ) print ( * O ) ; } </s>


<s> static bool classof ( const ARMConstantPoolValue * APV ) { return APV -> isGlobalValue ( ) || APV -> isBlockAddress ( ) || APV -> isLSDA ( ) || APV -> isPromotedGlobal ( ) ; } </s>

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


<s> ARMConstantPoolSymbol * ARMConstantPoolSymbol :: Create ( LLVMContext & C , StringRef s , ARMCP :: ARMCPModifier Modifier ) { return new ARMConstantPoolSymbol ( C , s , 0 , 0 , Modifier , false ) ; } </s>

ARM ARM ARM ARMCP::ARMCPModifier ARM 0 0


<s>
LLVM_DUMP_METHOD
void
ARMConstantPoolValue
::
dump
(
)
const
{
errs
(
)
<<
"  "
<<
*
this
;
}
</s>


<s> StringRef getSymbol ( ) const { return S ; } </s>


<s> bool ARMConstantPoolValue :: hasSameValue ( ARMConstantPoolValue * ACPV ) { if ( ACPV -> Kind == Kind && ACPV -> PCAdjust == PCAdjust && ACPV -> Modifier == Modifier && ACPV -> LabelId == LabelId && ACPV -> AddCurrentAddress == AddCurrentAddress ) { if ( Kind == ARMCP :: CPValue || Kind == ARMCP :: CPExtSymbol ) return true ; } return false ; } </s>


<s> void ARMConstantPoolMBB :: print ( raw_ostream & O ) const { O << printMBBReference ( * MBB ) ; ARMConstantPoolValue :: print ( O ) ; } </s>


<s> bool ARMConstantPoolSymbol :: hasSameValue ( ARMConstantPoolValue * ACPV ) { const ARMConstantPoolSymbol * ACPS = dyn_cast < ARMConstantPoolSymbol > ( ACPV ) ; return ACPS && CPV_streq ( ACPS -> S , S ) && ARMConstantPoolValue :: hasSameValue ( ACPV ) ; } </s>


<s>
void
ARMConstantPoolValue
::
dump
(
)
const
{
cerr
<<
"  "
<<
*
this
;
}
</s>


<s> void ARMConstantPoolValue :: print ( raw_ostream & O ) const { if ( GV ) O << GV -> getName ( ) ; else O << S ; if ( isNonLazyPointer ( ) ) O << "$non_lazy_ptr" ; else if ( isStub ( ) ) O << "$stub" ; if ( Modifier ) O << "(" << Modifier << ")" ; if ( PCAdjust != 0 ) { O << "-(LPC" << LabelId << "+" << ( unsigned ) PCAdjust ; if ( AddCurrentAddress ) O << "-." ; O << ")" ; } } </s>


<s> static bool classof ( const ARMConstantPoolMBB * ) { return true ; } </s>


<s> void ARMConstantPoolMBB :: print ( raw_ostream & O ) const { ARMConstantPoolValue :: print ( O ) ; } </s>


<s> bool ARMConstantPoolValue :: hasSameValue ( ARMConstantPoolValue * ACPV ) { if ( ACPV -> Kind == Kind && ACPV -> CVal == CVal && ACPV -> PCAdjust == PCAdjust && ( ACPV -> S == S || strcmp ( ACPV -> S , S ) == 0 ) && ( ACPV -> Modifier == Modifier || strcmp ( ACPV -> Modifier , Modifier ) == 0 ) ) { if ( ACPV -> LabelId == LabelId ) return true ; if ( Kind == ARMCP :: CPValue || Kind == ARMCP :: CPExtSymbol ) return true ; } return false ; } </s>

ARM ARM ARM 0 0 ARMCP::CPValue ARMCP::CPExtSymbol


<s> void ARMConstantPoolValue :: print ( raw_ostream & O ) const { if ( CVal ) O << CVal -> getName ( ) ; else O << S ; if ( Modifier ) O << "(" << Modifier << ")" ; if ( PCAdjust != 0 ) { O << "-(LPC" << LabelId << "+" << ( unsigned ) PCAdjust ; if ( AddCurrentAddress ) O << "-." ; O << ")" ; } } </s>


<s> void ARMConstantPoolValue :: print ( raw_ostream & O ) const { if ( GV ) O << GV -> getName ( ) ; else O << S ; if ( Modifier ) O << "(" << Modifier << ")" ; if ( PCAdjust != 0 ) { O << "-(LPC" << LabelId << "+" << ( unsigned ) PCAdjust ; if ( AddCurrentAddress ) O << "-." ; O << ")" ; } } </s>


<s> static bool classof ( const ARMConstantPoolValue * ACPV ) { return ACPV -> isMachineBasicBlock ( ) ; } </s>


<s> bool equals ( const ARMConstantPoolMBB * A ) const { return MBB == A -> MBB && ARMConstantPoolValue :: equals ( A ) ; } </s>

equals - Check for string equality , this is more efficient than compare ( ) when the relative ordering of inequal strings is n't needed .


<s> const MachineBasicBlock * getMBB ( ) const { return MBB ; } </s>

Return a reference to the basic block containing this bundle .


<s> const char * getSymbol ( ) const { return S . c_str ( ) ; } </s>


<s> bool isBlockAddress ( ) const { return Kind == ARMCP :: CPBlockAddress ; } </s>


<s> void print ( raw_ostream * O ) const { if ( O ) print ( * O ) ; } </s>


<s>
static
bool
Check
(
DecodeStatus
&
Out
,
DecodeStatus
In
)
{
switch
(
In
)
{
case
MCDisassembler
::
Success
:
return
true
;
case
MCDisassembler
::
SoftFail
:
Out
=
In
;
return
true
;
case
MCDisassembler
::
Fail
:
Out
=
In
;
return
false
;
}
llvm_unreachable
(
"Invalid DecodeStatus!"
)
;
}
</s>

Matches check string and its `` not strings '' and/or `` dag strings '' .


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

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


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

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


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

Returns the disassembly of a single instruction .


<s> static bool Check ( DecodeStatus & Out , DecodeStatus In ) { switch ( In ) { case MCDisassembler :: Success : return true ; case MCDisassembler :: SoftFail : Out = In ; return true ; case MCDisassembler :: Fail : Out = In ; return false ; } return false ; } </s>


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