SelectionDAG & DAG ) { SDValue ReturnVal = DAG . getLoad ( MVT :: i32 , Chain , Outs . DstAddr , DAG . getPointerTy ( ) , Outs . AM ) ; SDValue Ops [ ] = { ReturnVal , Chain } ; SDVTList VTs = DAG . getVTList ( MVT :: Other , MVT :: Glue ) ; SDValue Ret = DAG . getNode ( ARCISD :: RET , SDLoc ( Chain ) , VTs , Ops ) ; DAG . ReplaceAllUsesWith ( Chain , Ret ) ; }


SDValue ReplaceNodeResults ( SDValue N , const SDValue * Results , unsigned NumResults ) { if ( N . getValueType ( ) . getTypeForEVT ( N . getValueType ( ) ) == MVT :: Other ) { SDValue * newValues = BuildCustomValues ( N , Results , NumResults ) ; SDValue * newResults = new SDValue [ NumResults ] ; for ( unsigned int i = 0 ; i < NumResults ; i ++ ) { newResults [ i ] = newValues [ i ] ; } delete newValues ; return newResults ; } return Results ; }


bool CanLowerReturn ( const SmallVectorImpl < ISD :: OutputArg > & Outs , LLVMContext & Context ) { if ( Outs . size ( ) == 1 && Outs [ 0 ] . Flags . isByVal ( ) && Outs [ 0 ] . ByValType . getSizeInBits ( ) == 16 && Outs [ 0 ] . OriginalAlignment == 0 ) { if ( Outs [ 0 ] . VT == MVT :: ARC ) { if ( Outs [ 0 ] . Flags [ i ] != 0 ) { return true ; } } } return false ; }


function
getTargetNodeName
(
instruction
)
{
if
(
instruction
==
ARC
)
{
return
"ARC"
;
}
else
if
(
instruction
==
ARCISD
::
BL
)
{
return
"ARCISD::BL"
;
}
else
if
(
instruction
==
ARCISD
::
CMOV
)
{
return
"ARCISD::CMOV"
;
}
else
if
(
instruction
==
ARCISD
::
CMP
)
{
return
"ARCISD::CMP"
;
}
else
if
(
instruction
==
ARCISD
::
BRcc
)
{
return
"ARCISD::BRcc"
;
}
else
if
(
instruction
==
ARCISD
::
RET
)
{
return
"ARCISD::RET"
;
}
else
if
(
instruction
==
ARCISD
::
GAWRAPPER
)
{
return
"ARCISD::GAWRAPPER"
;
}
else
{
return
"Target specific value not found"
;
}
}


bool isLegalAddressingMode ( unsigned AM , unsigned LoadStoreType ) { switch ( LoadStoreType ) { case ARC : if ( AM == ARC || AM == 0 ) { return true ; } break ; default : return false ; } }


ArrayRef < MachineArgument > Ins ) { MachineFrameInfo & MFI = MF . getFrameInfo ( ) ; const ARCRegisterInfo * RegInfo = static_cast < const ARCRegisterInfo * > ( MF . getSubtarget ( ) . getRegisterInfo ( ) ) ; MachineRegisterInfo & MRI = MF . getRegInfo ( ) ; unsigned NumArgs = Ins . size ( ) ; if ( NumArgs == 0 ) return ; unsigned ArgSize = 0 ; for ( MachineArgument Arg : Ins ) { if ( Arg . ArgType == MachineArgument :: MACHINE_VALARG ) { ArgSize += RegInfo -> getPointerSize ( ) ; } else { continue ; } }


void LowerReturn ( SDValue Chain , const ARCFunctionInfo * AFI , SmallVectorImpl < SDValue > & Outs , SDValue Ret , const SDLoc & dl , SelectionDAG & DAG ) { const Function * F = DAG . getMachineFunction ( ) . getFunction ( ) ; CallingConv :: ID CC = F -> getCallingConv ( ) ; EVT PtrVT = DAG . getTargetLoweringInfo ( ) . getPointerTy ( DAG . getDataLayout ( ) ) ; SDVTList NodeTys = DAG . getVTList ( Ret . getValueType ( ) ) ; SDValue FrameOffset = DAG . getFrameIndex ( AF . getARCRetAddr ( ) . FI ) ; SDValue Args [ ] = { Chain , Ret , FrameOffset , DAG . getConstant ( 4 , dl , PtrVT ) , Ret , DAG . getConstant ( 1 , dl , PtrVT ) , DAG . getConstant ( 4 , dl , PtrVT ) , DAG . getConstant ( 0 , dl , PtrVT ) , DAG . getTargetConstant ( MVT :: Other , PtrVT ) , DAG . getValueType ( MVT :: Other ) , DAG . getTargetConstant ( 0 , PtrVT ) , } ; SDValue RV = DAG . getNode ( ARCISD :: RET , dl , NodeTys , Args ) ; Chain = RV . getValue ( 0 ) ; }


bool mayBeEmittedAsTailCall ( const Target & target ) { if ( target == ARC || target == ARC , ARC ) { return true ; } else { return false ; } }


void getAnalysisUsage ( AnalysisUsage & AU ) const override { AU . setPreservesAll ( ) ; AU . addRequiredID ( ARC ) ; AU . addRequired < TargetTransformInfoWrapperPass > ( ) ; }


function getPassName ( pass ) { const passName = pass . toLowerCase ( ) . replace ( / [ ^ \ w \ s ] / g , '' ) ; const arcPassName = passName + "arc" ; return arcPassName ; }


void runOnMachineFunction ( MachineFunction & MF ) { MF . setTargetTriple ( "arc" ) ; MF . setTargetCPU ( "ARC" ) ; MF . setTargetFeature ( "ARC" ) ; EmitFunctionBody ( MF ) ; }


MachineBasicBlock :: iterator MI ) { MachineInstr & Instr = * MI ; for ( unsigned int i = 0 , e = Instr . getNumOperands ( ) ; i != e ; ++ i ) { MachineOperand & Op = Instr . getOperand ( i ) ; if ( Op . isFI ( ) ) { Instr . ReplaceFI ( MF . getFrameInfo ( ) -> getObjectIndex ( Op . getIndex ( ) ) ) ; } } }


bool needsFrameMoves ( const ARCSubtarget * target , const MachineFunction & func , const ARCFunctionInfo & state ) { if ( target -> needsFrameMoves ( ) ) return true ; if ( func . getFunction ( ) -> hasFnAttribute ( "arc_requires_frame_moves" ) ) return true ; else if ( func . getFunction ( ) -> hasFnAttribute ( "arc_no_frame_moves" ) ) return false ; if ( state . propertyRequiresFrameMoves ( ) ) return true ; return false ; }


void eliminateFrameIndex ( MachineInstr & MI ) { for ( MachineInstr :: mop_iterator it = MI . operands_begin ( ) , e = MI . operands_end ( ) ; it != e ; ++ it ) { if ( it -> isFI ( ) ) { unsigned int frameIndex = it -> getIndex ( ) ; int offset = it -> getOffset ( ) ; MachineOperand newOperand = MachineOperand :: CreateImm ( offset ) ; MachineInstr :: mop_iterator newIt = MI . addOperand ( newOperand ) ; MI . setDesc ( TII . get ( MI . getOpcode ( ) - ARC ) ) ; MI . RemoveOperand ( newIt ) ; } } }


void eliminateFrameIndex ( MachineInstr * MI , unsigned Idx , unsigned FrameIndex , StackSize size , LocalFrameSize localSize ) { if ( MI -> isUsingFrameIndex ( Idx ) ) { if ( FrameIndex == 0 ) { MI -> ReplaceFrameIndex ( Idx , 0 , size ) ; } else { MI -> ReplaceFrameIndex ( Idx , 0 , localSize ) ; } } }


void eliminateFrameIndex ( MachineFunction & MF , MachineBasicBlock & MBB , MachineBasicBlock :: iterator MI ) { for ( MachineBasicBlock :: iterator I = MF . begin ( ) , E = MF . end ( ) ; I != E ; ++ I ) { int FrameIdx = - 1 ; if ( MI -> isMoveImmediate ( ) ) { for ( unsigned i = 0 , e = I -> getNumOperands ( ) ; i != e ; ++ i ) { if ( I -> getOperand ( i ) . isFI ( ) ) { FrameIdx = I -> getOperand ( i ) . getIndex ( ) ; break ; } } if ( FrameIdx >= 0 ) { I = MBB . erase ( I ) ; -- I ; } } }


void
eliminateFrameIndex
(
MachineInstr
*
MI
,
uint64_t
TFI
,
int
&
Opcode
,
unsigned
&
DstReg
,
unsigned
&
SrcReg
,
unsigned
&
Src2Reg
,
const
TargetInstrInfo
*
TII
)
{
if
(
SrcReg
==
TFI
)
{
int
SPIdx
=
MI
->
findRegisterUseOperandIdx
(
M86
::
SP
)
;
assert
(
SPIdx
!=
1
&&
"SP operand not found in instruction"
)
;
int64_t
Offset
=
MI
->
getOperand
(
SPIdx
)
.
getImm
(
)
;
MI
->
getOperand
(
SPIdx
)
.
ChangeToImmediate
(
Offset
+
Src2Reg
)
;
}
else
if
(
Src2Reg
==
TFI
)
{
int
FPIdx
=
MI
->
findRegisterUseOperandIdx
(
M86
::
FP
)
;
assert
(
FPIdx
!=
1
&&
"FP operand not found in instruction"
)
;
int64_t
Offset
=
MI
->
getOperand
(
FPIdx
)
.
getImm
(
)
;
MI
->
getOperand
(
FPIdx
)
.
ChangeToImmediate
(
Offset
+
SrcReg
)
;
}
else
if
(
DstReg
==
TFI
)
{
llvm_unreachable
(
"Unexpected register operand"
)
;
}
}


TargetRegisterList ARCBackend :: getCalleeSavedRegs ( const MachineFunction * MF ) const { TargetRegisterList Regs ; Regs . addReg ( ARC :: R13 , RegState :: Preserved ) ; Regs . addReg ( ARC :: R14 , RegState :: Preserved ) ; Regs . addReg ( ARC :: R15 , RegState :: Preserved ) ; return Regs ; }


llvm :: TargetRegisterInfo :: CallPreservedMask llvm :: Function :: getCallPreservedMask ( CallConv :: ID CC ) const { switch ( CC ) { case CallConv :: ARC : return { TargetRegisterInfo :: ARC , TargetRegisterInfo :: ARC , TargetRegisterInfo :: ARC } ; default : return TargetRegisterInfo :: CallPreservedMask ( ) ; } }


BitVector getReservedRegs ( const ARCSubtarget & Target , const MachineFunction & MF ) { BitVector ReservedRegs ( ARC :: NUM_PHYSICAL_REGISTERS ) ; ReservedRegs . set ( ARC :: ILINK ) ; ReservedRegs . set ( ARC :: SP ) ; ReservedRegs . set ( ARC :: GP ) ; ReservedRegs . set ( ARC :: R25 ) ; ReservedRegs . set ( ARC :: BLINK ) ; ReservedRegs . set ( ARC :: FP ) ; return ReservedRegs ; }


bool needsFrameMoves ( const TargetMachine & TM ) { if ( TM . getTargetTriple ( ) . getArch ( ) == Triple :: Arc ) return true ; if ( TM . getSubtarget < ARCTargetMachine > ( ) . isARCEnabled ( ) ) return true ; return false ; }


bool requiresRegisterScavenging ( TargetMachine & target ) { LLVMTargetMachine * LLVMTarget = dynamic_cast < LLVMTargetMachine * > ( & target ) ; if ( ! LLVMTarget ) return false ; MCRegisterInfo * regInfo = target . getMC ( ) . getObjectFileInfo ( ) -> getRegisterInfo ( ) ; if ( ! regInfo -> getRegScavenger ( ) ) return false ; if ( ! target . getIsa < AMDGCN > ( ) && ! target . getIsa < ARCCustom > ( ) ) return false ; return true ; }


void trackLivenessAfterRegAlloc ( ) { if ( Target . isARC ( ) ) { Target . setTargetSpecificValue ( "ARC" , "ARC" ) ; } bool trackLiveness = false ; if ( trackLiveness ) { Target . setTrackLiveInsAfterRegAlloc ( true ) ; } else { Target . setTrackLiveInsAfterRegAlloc ( false ) ; } }


bool useFPForScavengingIndex ( const TargetMachine & TM ) { const Triple & T = TM . getTargetTriple ( ) ; if ( T . getArch ( ) != Triple :: arc ) { return false ; } return true ; }


InferFixedInARCParIsFalseOption ( DefaultARCRegisterInfo :: Unknown ) { ARCArchVersion = TM . getCPU ( ) ; ARCArchName = ARM :: getARCArch ( ArchVersion ) ; TargetABI = ComputeTargetABI ( TT . getArch ( ) ) ; HasDivide = false ; HasAtomic = false ; HasSlowIndirectJumps = false ; if ( CodeGenFileType == CodeGenFileType :: AssemblyFile ) HasMovt = true ; else if ( CodeGenFileType == CodeGenFileType :: ObjectFile ) HasMovt = false ; if ( TM . getDataLayout ( ) -> getPointSize ( ) == 32 ) { HasSIT = true ; HasGICC2 = false ; if ( ARM :: ArchVersion == ARM :: BR ) HasSSE = true ; else if ( ARM :: ArchVersion == ARM :: BEBE ) HasSSse = true ; } if ( CodeGenFileType == CodeGenFileType :: AssemblyFile ) DefaultARCRetentionMode = TargetMC :: ARCVocab :: SLDR ; else if ( CodeGenFileType == CodeGenFileType :: ObjectFile ) DefaultARCRetentionMode = TargetMC :: ARCVocab :: SLDD ; else DefaultARCRetentionMode = TargetMC :: ARCVocab :: SNLD ; }


LLVM
::
ARCSubtarget
::
ARCSubtarget
(
const
Triple
&
T
,
const
std
::
string
&
CPU
,
const
std
::
string
&
FS
)
{
NewlibABI
=
false
;
LinuxABI
=
false
;
ROPI
=
false
;
RWPI
=
false
;
IsSubtarget
=
true
;
ParseSubtargetFeatures
(
CPU
,
FS
)
;
ProcessTriple
(
T
)
;
}
void
LLVM
::
ARCSubtarget
::
ParseSubtargetFeatures
(
const
std
::
string
&
CPU
,
const
std
::
string
&
FS
)
{
if
(
CPU
==
"arc700"
)
{
NewlibABI
=
true
;
}
else
{
LinuxABI
=
true
;
}
std
::
vector
<
std
::
string
>
FeatureVec
;
StringRef
FSStringRef
(
FS
)
;
FSStringRef
.
split
(
FeatureVec
,
","
,
1
,
false
)
;
for
(
unsigned
i
=
0
,
e
=
FeatureVec
.
size
(
)
;
i
<
e
;
++
i
)
{
if
(
FeatureVec
[
i
]
==
"+ropi"
)
{
ROPI
=
true
;
}
if
(
FeatureVec
[
i
]
==
"+rwpi"
)
{
RWPI
=
true
;
}
}
}
void
LLVM
::
ARCSubtarget
::
ProcessTriple
(
const
Triple
&
T
)
{
switch
(
T
.
getArch
(
)
)
{
default
:
llvm_unreachable
(
"Unknown target architecture"
)
;
case
Triple
::
arc
:
ARCArch
=
Triple
::
arc
;
ARCArchName
=
"ARC"
;
Endianness
=
support
::
little
;
ARCArchVersion
=
ARCArch
::
ARCv2
;
break
;
case
Triple
::
arcv2
:
ARCArch
=
Triple
::
arcv2
;
ARCArchName
=
"ARCv2"
;
Endianness
=
support
::
little
;
ARCArchVersion
=
ARCArch
::
ARCv2
;
break
;
case
Triple
::
arcv3
:
ARCArch
=
Triple
::
arcv3
;
ARCArchName
=
"ARCv3"
;
Endianness
=
support
::
little
;
ARCArchVersion
=
ARCArch
::
ARCv3
;
break
;
}
}


ARCSubtarget :: ARCSubtarget ( Triple ) { InitDefaultFeatures ( Triple ) ; UseARC = true ; ARCArch = ARC ; ARCAux = ARC ; ARCCtx = ARC ; }


TargetInstrInfo * getInstrInfo ( const ARCTargetMachine & TM ) { return TM . getSubtargetImpl ( ) -> getInstrInfo ( ) ; }


TargetRegisterInfo * getRegisterInfo ( TargetInstrInfo * InstrInfo ) { if ( InstrInfo == nullptr ) { return nullptr ; } TargetRegisterInfo * ARCRegInfo = new TargetRegisterInfo ( ARC ) ; ARCRegInfo -> init ( InstrInfo ) ; return ARCRegInfo ; }


namespace llvm { class ARCTargetMachine : public llvm :: TargetMachine { std :: unique_ptr < const llvm :: DataLayout > DL ; public : ARCTargetMachine ( const llvm :: Target & T , const llvm :: Triple & TT , StringRef CPU , StringRef FS , const llvm :: TargetOptions & Options , Optional < Reloc :: Model > RM , Optional < llvm :: CodeModel :: Model > CM , CodeGenOpt :: Level OL , bool JIT ) ; virtual const llvm :: TargetSubtargetInfo * getSubtargetImpl ( const llvm :: Function & ) const override ; virtual TargetIRAnalysis getTargetIRAnalysis ( ) override ; virtual const llvm :: DataLayout * getDataLayout ( ) const override { return DL . get ( ) ; } virtual CodeGenOpt :: Level getOptLevel ( ) const override { return CodeGenOpt :: Aggressive ; }


void addPreRegAlloc ( ARCTargetMachine & TM ) { addPreSchedOptimizationPasses ( TM ) ; addTargetSpecificPasses ( TM , ARC , ARC , ARC ) ; }


TargetTransformInfo * getTargetTransformInfo ( StringRef Target ) { if ( Target == "ARC" ) { return new ARCTargetTransformInfo ( ) ; } return nullptr ; }


TargetIRAnalysis * getTargetIRAnalysis ( const Triple & TargetTriple ) { if ( TargetTriple . getArch ( ) == Triple :: ARC ) { return new TargetIRAnalysis ( ARC , ARC , ARC ) ; } else { return new TargetIRAnalysis ( ) ; } }


void addInstSelector ( TargetMachine & TM , PassManagerBase & PM ) { const Triple & TT = TM . getTargetTriple ( ) ; if ( TT . getArch ( ) != Triple :: arc ) return ; PM . add ( createARCMachineInstructionSelectorPass ( TM ) ) ; }


bool addPreEmitPass ( FunctionPassManager & PM , TargetMachine & TM ) { if ( TM . getTargetTriple ( ) . getArch ( ) != Triple :: ARC ) return false ; const ARCSubtarget & Subtarget = TM . getSubtarget < ARCSubtarget > ( ) ; ARCMachineFunctionInfo * FuncInfo = Subtarget . getMachineFunctionInfo ( ) ; PM . addPass ( createARCPreEmitPass ( Subtarget , FuncInfo ) ) ; return true ; }


void addPreRegAlloc ( TargetPassConfig & TPC , PassManagerBase & PM , const TargetMachine & TM ) { } This function takes in three parameters : 1. TargetPassConfig & TPC - This is an instance of the TargetPassConfig class which contains information about the target machine , including its register allocation strategy and available registers . 2. PassManagerBase & PM - This is an instance of the PassManagerBase class which is responsible for managing the passes that are run during the compilation process . 3. const TargetMachine & TM - This is a constant reference to the TargetMachine class which contains information about the target architecture and its features . The purpose of this function is to provide a target - specific implementation of passes that need to be run immediately before the register allocation phase . This allows targets to perform any necessary transformations or optimizations on the code before it is assigned to physical registers . To implement this function , we can use the addTargetPasses method of the TargetPassConfig class . This method takes in a PassManagerBase reference and a reference to the TargetMachine class and is responsible for adding target - specific passes to the pass manager . In the body of the function , we can use the addTargetPasses method to add passes for ARC , ARC , ARC , ARC targets . For example , the following code adds the MyARCPass pass to the pass manager for the ARC target : TPC . addTargetPasses ( PM , new MyARCPass ( TM ) ) ; We can add as many target - specific passes as needed using the addTargetPasses method . Finally , this function needs to be called from the initializeARCPreRegAllocPass function which is responsible for initializing the pre - register - allocation passes for the ARC target . This ensures that our target - specific passes are added to the pass manager before the register allocation phase . void initializeARCPreRegAllocPass ( PassRegistry & Registry ) { addTargetPasses ( addPreRegAlloc ) ; }


PassConfig createPassConfig ( ARC & arc ) { PassConfig Config ; Config . addCodeGenPass ( arc . createARCCodeGenPass ( ) ) ; Config . addCodeGenPass ( arc . createARCCodeGenPass ( ) ) ; Config . addCodeGenPass ( arc . createARCCodeGenPass ( ) ) ; return Config ; }


TargetLoweringObjectFile * ARCTargetMachine :: getObjFileLowering ( ) const { return new ARCTargetLoweringObjectFile ( ) ; }


const TargetSubtargetInfo & ARC :: getSubtargetImpl ( const Function & F ) const { return ARCSubtarget ; }


TargetTransformInfo * getTargetTransformInfo ( const Triple & T ) { ARCTargetTransformInfo * ARCTTI = new ARCTargetTransformInfo ( ) ; ARCTTI -> setARCVectors ( ) ; ARCTTI -> setARCMacros ( ) ; ARCTTI -> setARCFlags ( ) ; return ARCTTI ; }


TargetLowering * getTLI ( const TargetMachine & TM , const TargetTransformInfo & TTI ) { return new ARCTargetLowering ( TM , TTI ) ; }


MCFixup const & Fixup ) { switch ( Fixup . getKind ( ) ) { case RISCV :: fixup_riscv_relax_a : case RISCV :: fixup_riscv_relax_b : case RISCV :: fixup_riscv_relax_c : case RISCV :: fixup_riscv_relax_d : case RISCV :: fixup_riscv_relax_g : case RISCV :: fixup_riscv_relax_h : case RISCV :: fixup_riscv_relax_i : case RISCV :: fixup_riscv_relax_j : case RISCV :: fixup_riscv_relax_k : return true ; default : return false ; } }


int getNumFixupKinds ( ) { return RISCV :: NumTargetFixupKinds ; }


DataFragment
applyFixup
(
Fixup
fixup
,
DataFragment
dataFragment
,
int
value
)
{
if
(
fixup
.
getOffset
(
)
<
0
||
fixup
.
getOffset
(
)
>
dataFragment
.
getSize
(
)
)
{
std
::
cout
<<
"Invalid fixup offset!"
;
return
dataFragment
;
}
FixupKind
kind
=
fixup
.
getKind
(
)
;
switch
(
kind
)
{
case
RISCV
:
dataFragment
.
updateInstructions
(
fixup
.
getOffset
(
)
,
value
)
;
break
;
case
RISCV7
:
dataFragment
.
updateInstructions
(
fixup
.
getOffset
(
)
,
value
)
;
break
;
case
RISCV8
:
dataFragment
.
updateInstructions
(
fixup
.
getOffset
(
)
,
value
)
;
break
;
default
:
std
::
cout
<<
"Invalid fixup kind!"
;
break
;
}
return
dataFragment
;
}


MCObjectWriter * RISCVTargetMachine :: createObjectWriter ( raw_pwrite_stream & OS ) const { }


bool fixupNeedsRelaxation ( MCInst & Inst , const MCSubtargetInfo & STI , const MCAsmBackend & MAB ) { const MCTargetOptions & Options = STI . getTargetOptions ( ) ; uint64_t RISCVTarget = Options . getRISCVTarget ( ) ; if ( ! Inst . getFlag ( MCInst :: FlgResolved ) ) { if ( RISCVTarget != 0 ) { return true ; } } return false ; }


MCContext & Ctx ) const { unsigned Opcode = Inst . getOpcode ( ) ; switch ( Opcode ) { case RISCV :: ADDI : case RISCV :: ADDI16SP : case RISCV :: SLLI : case RISCV :: SRLI : case RISCV :: SRAI : if ( Inst . getOperand ( 2 ) . getImm ( ) <= 0xfff || Inst . getOperand ( 2 ) . getImm ( ) >= - 0x1000 ) { return false ; }


void
applyFixup
(
MCAssembler
&
Asm
,
const
MCAsmLayout
&
Layout
,
const
MCFixup
&
Fixup
,
MCDataFragment
&
DF
,
const
MCValue
&
Target
,
bool
IsPCRel
,
MCFixupKind
Kind
)
{
uint64_t
FixupOffset
=
Fixup
.
getOffset
(
)
;
if
(
FixupOffset
>=
DF
.
getContents
(
)
.
size
(
)
)
{
report_fatal_error
(
"Invalid fixup offset!"
)
;
}
unsigned
Size
=
Kind
.
getTargetSize
(
)
;
unsigned
ValueSize
=
Target
.
getBitWidth
(
)
;
if
(
ValueSize
>
Size
)
{
report_fatal_error
(
"Invalid value size for fixup!"
)
;
}


bool mayNeedRelaxation ( const MachineInstr * MI ) { if ( MI -> getDesc ( ) . getOpcode ( ) == RISCV :: OPCODE ) { if ( MI -> getDesc ( ) . mayNeedRelaxation ( RISCV ) ) { return true ; } } return false ; }


uint64_t
&
Value
,
bool
IsPCRel
)
{
const
MCFixupKindInfo
&
Info
=
getFixupKindInfo
(
Fixup
.
getKind
(
)
)
;
if
(
!
IsPCRel
&&
!
Info
.
Flags
)
report_fatal_error
(
"Invalid fixup offset!"
)
;
uint64_t
Offset
=
Layout
.
getFragmentOffset
(
DF
)
+
Fixup
.
getOffset
(
)
;
uint64_t
NumBits
=
8
*
Info
.
TargetSize
;
uint64_t
Mask
=
(
1
<<
NumBits
)
1
;
uint64_t
FixupValue
=
Target
.
getConstant
(
)
;
Value
=
(
Value
&
~
(
Mask
<<
Offset
)
)
|
(
(
FixupValue
&
Mask
)
<<
Offset
)
;
if
(
NumBits
>
Info
.
TargetSize
)
{
unsigned
Shift
=
Offset
+
Info
.
TargetSize
;
Shift
%=
8
;
Data
[
Offset
+
Info
.
TargetSize
]
|=
FixupValue
>>
(
NumBits
Info
.
TargetSize
Offset
)
;
Data
[
Offset
+
Info
.
TargetSize
+
1
]
|=
FixupValue
>>
(
NumBits
Info
.
TargetSize
)
<<
(
8
Shift
)
;
}
}


bool fixupNeedsRelaxationAdvanced ( const fixup_kind & fk , unsigned int value1 , unsigned int value2 ) { if ( fk == RISCV :: fixup_riscv_rvc_branch || fk == RISCV :: fixup_riscv_rvc_jump ) { if ( value1 == 254 || value1 == 256 || value2 == 2046 || value2 == 2048 ) { return true ; } else { return false ; } } else { return false ; } }


RISCV :: FixupKind getFixupKind ( int expression ) { if ( expression == 1u || expression == - 1u ) { return RISCV ; } else if ( expression <= 65535 ) { return RISCV_RVC_IMM16 ; } else if ( expression <= 4294967295 ) { return RISCV_32 ; } else if ( expression <= 18446744073709551615 ) { return RISCV_64 ; } else { return BFD_RELOC_NONE ; } }


bool shouldForceRelocation ( RelocationEntry & RE , FeatureBitset & FB ) { if ( RE . FixupKind == RISCV :: fixup_riscv_got_hi20 || RE . FixupKind == RISCV :: fixup_riscv_tls_got_hi20 || RE . FixupKind == RISCV :: fixup_riscv_tls_gd_hi20 ) { if ( FB [ RISCV :: FeatureRelax ] ) { return true ; } } return false ; }


bool shouldInsertExtraNopBytesForCodeAlign ( BasicBlock * BB , unsigned * Align , unsigned * MaxNops ) { if ( BB -> getParent ( ) -> getTargetTriple ( ) . getArch ( ) != Triple :: riscv ) { return false ; } RISCVMachineFunctionInfo * MFI = BB -> getParent ( ) -> getInfo < RISCVMachineFunctionInfo > ( ) ; for ( MachineBasicBlock * Pred : BB -> predecessors ( ) ) { if ( MFI -> getPredRelaxed ( Pred ) ) { * Align = 4 ; * MaxNops = 2 ; return true ; } } if ( MFI -> hasRISCVStandardExtC ( ) ) return false ; * Align = 2 ; * MaxNops = 4 ; return true ; }


bool shouldInsertFixupForCodeAlign ( MCInst * instruction , RISCV :: AlignInfo targetInfo ) { if ( targetInfo . target == RISCV && targetInfo . feature == RISCV :: FeatureRelax ) { if ( instruction -> getOpcode ( ) == RISCV :: fixup_riscv_align ) { return true ; } } return false ; }


int writeNopData ( int Count , OutputStream output ) { if ( ! output ) { return - 1 ; } if ( Count <= 0 ) { return - 1 ; } int totalBytes = 0 ; int bytesWritten ; while ( totalBytes < Count ) { bytesWritten = output . writeUInt32BE ( 0x00000013 ) ; if ( bytesWritten < 0 ) { return - 1 ; } bytesWritten = output . writeUInt32BE ( 0x00000000 ) ; if ( bytesWritten < 0 ) { return - 1 ; } if ( RISCV :: hasFeature ( RISCV :: FeatureStdExtC ) ) { bytesWritten = output . writeUInt32BE ( 0x00000000 ) ; if ( bytesWritten < 0 ) { return - 1 ; } } totalBytes += 4 ; if ( totalBytes < Count ) { bytesWritten = output . writeUInt32BE ( 0x00000001 ) ; if ( bytesWritten < 0 ) { return - 1 ; } totalBytes += 4 ; if ( totalBytes < Count ) { bytesWritten = output . writeUInt32BE ( 0x00000002 ) ; if ( bytesWritten < 0 ) { return - 1 ; } totalBytes += 4 ; } } } return totalBytes ; }


void writeNopData ( const MCTargetOutputStream & OS , unsigned Count ) { unsigned NumNopInstructions = ( Count + 3 ) / 4 ; OS . EmitIntValue ( RISCV , 4 ) ; OS . EmitIntValue ( RISCV , 4 ) ; OS . EmitIntValue ( RISCV :: FeatureStdExtC , 4 ) ; OS . EmitIntValue ( 2 , 4 ) ; OS . EmitIntValue ( 4 , 4 ) ; OS . EmitIntValue ( 0 , 4 ) ; OS . EmitIntValue ( 4 , 4 ) ; OS . EmitIntValue ( 4 , 4 ) ; OS . EmitIntValue ( "\x13\0\0\0" , 4 ) ; OS . EmitIntValue ( 4 , 4 ) ; OS . EmitIntValue ( "\x01\0" , 2 ) ; std :: string NOPs ; for ( unsigned i = 0 ; i < NumNopInstructions ; i ++ ) { NOPs += "\x00\0\0\0" ; } OS . EmitBinaryData ( StringRef ( NOPs ) , NumNopInstructions * 4 ) ; }


bool shouldForceRelocation ( const MCFixup & Fixup , MCContext & Ctx ) { switch ( Fixup . getKind ( ) ) { case RISCV :: fixup_riscv_got_hi20 : case RISCV :: fixup_riscv_tls_got_hi20 : case RISCV :: fixup_riscv_tls_gd_hi20 : case RISCV :: fixup_riscv_pcrel_lo12_i : case RISCV :: fixup_riscv_pcrel_lo12_s : case RISCV :: fixup_riscv_pcrel_hi20 : return Ctx . getObjectFileInfo ( ) -> getRelocMIPSABI ( ) == RISCV :: FeatureRelax ; default : return false ; } }


"Cannot insert extra NOP bytes as alignment is not a multiple of 4\n"


Align Alignment ) const { const RISCVSubtarget & STI = MF . getSubtarget < RISCVSubtarget > ( ) ; const RISCVTargetMachine & TM = STI . getTargetMachine ( ) ; if ( ! STI . hasFeature ( RISCV :: FeatureRelax ) ) { return false ; } if ( ! STI . hasFeature ( RISCV :: FeatureFixupRISCVAlign ) ) { return false ; } if ( ! TM . requireAlignedFixupForCodeAlign ( ) ) { return false ; } unsigned MaxSupportedAlignment = STI . getMaxSupportedAlignment ( ) ; return Alignment > MaxSupportedAlignment ; }


int getNumFixupKinds ( ) { return RISCV_FIXUPKINDS_COUNT ; }


void RISCVAsmBackend :: relaxInstruction ( MCInst & Inst , const MCSubtargetInfo & STI ) const { switch ( Inst . getOpcode ( ) ) { case RISCV :: ADD : case RISCV :: SUB : Inst . setOpcode ( RISCV :: ADDW ) ; break ; case RISCV :: LUI : Inst . setOpcode ( RISCV :: LUIW ) ; break ; default : break ; } }


bool shouldForceRelocation ( int target ) { if ( target == RISCV || target == RISCV :: FeatureRelax ) { return true ; } return false ; }


bool fixupNeedsRelaxationAdvanced ( const MCFixup & Fixup , uint64_t Value , const MCRelaxableFragment * DF ) { if ( DF -> getArch ( ) != Triple :: riscv ) return false ; MCFixupKind Kind = ( MCFixupKind ) Fixup . Kind ; switch ( Kind ) { case RISCV :: fixup_riscv_rvc_branch : case RISCV :: fixup_riscv_rvc_jump : case RISCV :: fixup_riscv_rvc_cjump : break ; default : return false ; } uint64_t Min = - ( ( 1 << 10 ) - 1 ) ; uint64_t Max = ( 1 << 11 ) - 1 ; if ( Value >= Min && Value <= Max ) return false ; if ( Value % 2 == 0 && Value / 2 >= Min && Value / 2 <= Max ) return false ; return true ; }


bool shouldForceRelocation ( const Relocation & Rel ) { uint64_t Type = Rel . Type ; bool ForceRelocation = false ; switch ( Type ) { case R_RISCV_HI20 : case R_RISCV_PCREL_HI20 : { if ( Rel . Addend > 0x1fffff ) ForceRelocation = true ; break ; } default : { ForceRelocation = true ; break ; } } return ForceRelocation ; }


bool shouldForceRelocation ( const RISCVTargetMachine & TM , unsigned Kind ) { switch ( Kind ) { default : return false ; case RISCV :: fixup_riscv_got_hi20 : case RISCV :: fixup_riscv_pcrel_lo12_i : case RISCV :: fixup_riscv_pcrel_lo12_s : return true ; case RISCV :: fixup_riscv_pcrel_hi20 : return TM . getTargetFeatureBits ( ) != RISCV :: FeatureRelax ; } }


bool shouldForceRelocation ( const MCAssembler & Asm , const MCValue & Target , unsigned int FixupKind ) { if ( Asm . getTargetTriple ( ) . isArch ( "riscv" ) ) { if ( FixupKind == RISCV :: fixup_riscv_got_hi20 || FixupKind == RISCV :: fixup_riscv_tls_got_hi20 || FixupKind == RISCV :: fixup_riscv_tls_gd_hi20 ) { if ( Target . getFeatureBits ( ) & RISCV :: FeatureRelax ) { return true ; } } } return false ; }


MCObjectWriter * createObjectWriter ( const Triple & TT , raw_pwrite_stream & OS , bool IsLittleEndian ) { if ( ! TT . isArch ( "riscv" ) ) { return NULL ; } MCObjectWriter * OW = new RISCVObjectWriter ( OS , IsLittleEndian ) ; return OW ; }


void
applyFixup
(
MCAssembler
&
Asm
,
const
MCAsmLayout
&
Layout
,
const
MCFixup
&
Fixup
,
const
MCValue
&
Target
,
MutableArrayRef
<
char
>
Data
,
SmallVectorImpl
<
MCFixup
>
&
Relocs
)
{
assert
(
Fixup
.
getKind
(
)
==
RISCV
&&
"Unexpected fixup kind!"
)
;
uint64_t
Offset
=
Fixup
.
getOffset
(
)
;
const
MCFixupKindInfo
&
Info
=
Asm
.
getFixupKindInfo
(
Fixup
.
getKind
(
)
)
;
assert
(
Offset
+
Info
.
TargetSize
<=
Data
.
size
(
)
&&
"Invalid fixup offset!"
)
;
uint64_t
Value
=
Target
.
evalAsAbsolute
(
)
.
getZExtValue
(
)
;
if
(
Info
.
Flags
&
MCFixupKindInfo
::
FKF_IsPCRel
)
{
Value
-=
Layout
.
getSymbolOffset
(
Fixup
.
getValue
(
)
)
;
}
uint64_t
FixupOffset
=
Offset
+
Info
.
FixupOffset
;
uint64_t
Mask
=
(
(
1ULL
<<
Info
.
TargetSize
)
1
)
<<
FixupOffset
;
uint64_t
OldValue
=
*
(
(
uint64_t
*
)
&
Data
[
Offset
]
)
;
uint64_t
NewValue
=
(
OldValue
&
~
Mask
)
|
(
(
Value
<<
FixupOffset
)
&
Mask
)
;
*
(
(
uint64_t
*
)
&
Data
[
Offset
]
)
=
NewValue
;
if
(
Info
.
Flags
&
MCFixupKindInfo
::
FKF_IsTarget
)
{
Relocs
.
push_back
(
MCFixup
::
Create
(
Offset
,
Fixup
.
getValue
(
)
,
MCFixup
::
getKindForSize
(
Info
.
TargetSize
)
,
Fixup
.
getOffset
(
)
)
)
;
}
}


"Fixup is not supported for RISCV target.\n"


int getSize ( int target_specific_value , int size , int jump_opcode , int branch_opcode , int target_specific_size ) { 2. Check if the target specific value is equal to RISCV , and if yes , continue with the calculation : if ( target_specific_value == RISCV ) { 3. Check if the instruction is a jump or branch instruction , as they have variable encoding sizes : if ( jump_opcode || branch_opcode ) { 4. Calculate the size of the instruction encoding by adding the size of the opcode and target specific value : int encoding_size = size + target_specific_size ; 5. Return the calculated encoding size : return encoding_size ; } 6. If the instruction is not a jump or branch instruction , return the size of the instruction encoding : else { return size ; } 7. If the target specific value is not equal to RISCV , return zero as the size cannot be determined : else { return 0 ; }


unsigned getFixupKind ( unsigned RISCV , unsigned RISCV , unsigned int1 , unsigned int1 ) { switch ( RISCV ) { case RISCV : switch ( RISCV ) { case RISCV : return LLVM :: FK_Data_1 ; default : return LLVM :: FK_Data_2 ; } default : return 0 ; } }


bool fixupNeedsRelaxation ( const MCFixup & Fixup , uint64_t Value , const MCRelaxableFragment * DF , const MCAsmLayout & Layout ) { } 3. Inside the function , retrieve the target specific values from the RISCV backend using the "DF" parameter : uint64_t RvcBranchFixup = DF -> getFixupKindInfo ( RISCV :: fixup_riscv_rvc_branch ) . TargetOffset ; uint64_t RvcJumpFixup = DF -> getFixupKindInfo ( RISCV :: fixup_riscv_rvc_jump ) . TargetOffset ; 4. Check if the fixup type is "Resolved" and if it is , return false as there is no need for relaxation : if ( Fixup . getKind ( ) == RISCV :: fixup_riscv_rvc_branch && Value == 254 ) { return false ; } if ( Fixup . getKind ( ) == RISCV :: fixup_riscv_rvc_jump && Value == 2046 ) { return false ; } 5. If the fixup type is not resolved , check if it matches the target specific values for RvcBranchFixup and RvcJumpFixup and if it does , return true as relaxation is required : if ( Fixup . getKind ( ) == RISCV :: fixup_riscv_rvc_branch && Value == RvcBranchFixup ) { return true ; } if ( Fixup . getKind ( ) == RISCV :: fixup_riscv_rvc_jump && Value == RvcJumpFixup ) { return true ; }


void
writeNopData
(
raw_ostream
&
OS
,
uint64_t
Count
)
{
if
(
Count
%
4
!=
0
)
{
errs
(
)
<<
"Count must be a multiple of 4 bytes\n"
;
return
;
}
for
(
int
i
=
0
;
i
<
Count
;
i
+=
4
)
{
MCInst
Inst
;
Inst
.
setOpcode
(
RISCV
::
NOP
)
;
Inst
.
addOperand
(
MCOperand
::
createReg
(
RISCV
::
X0
)
)
;
MCSubtargetInfo
STI
(
"riscv-unknown-elf"
)
;
STI
.
setDefaultFeatures
(
"riscv,riscv,riscv::FeatureStdExtC"
)
;
std
::
unique_ptr
<
MCCodeEmitter
>
Emitter
(
GET_RISCV_MC
(
)
->
createMCCodeEmitter
(
*
STI
.
getTargetTriple
(
)
,
*
STI
.
getFeatureBits
(
)
)
)
;
raw_hex_ostream
RawStream
(
OS
)
;
Emitter
->
encodeInstruction
(
Inst
,
RawStream
,
SmallVectorImpl
<
MCFixup
>
(
)
)
;
MCAsmLayout
Layout
;
std
::
unique_ptr
<
MCContext
>
Context
(
new
MCContext
(
STI
,
Layout
)
)
;
Layout
.
getAssemblerLayout
(
)
.
setSectionAddress
(
&
Layout
,
0x0
)
;
Layout
.
getAssemblerLayout
(
)
.
setDefaultSection
(
".text"
,
0
)
;
RawStream
.
SetBuffer
(
)
;
RawStream
<<
"0x"
<<
format
(
"%08"
PRIx64
,
Layout
.
getSymbolOffset
(
*
Context
.
get
(
)
.
getDummyFragment
(
)
)
)
;
}
}


void applyFixup ( const MCValue & Value , MutableArrayRef < char > Data , uint64_t Offset , const MCExpr * Fixup , const MCFixupKind & Kind , const MCAsmBackend & MAB ) { const MCFixupKindInfo & FixupInfo = MAB . getFixupKindInfo ( Kind ) ; uint64_t FixupValue = Value . getConstant ( ) ; Data [ Offset + FixupInfo . TargetOffset ] |= ( FixupValue >> FixupInfo . TargetOffset ) ; }


bool shouldInsertExtraNopBytesForCodeAlign ( const MCSubtargetInfo & STI , uint64_t CodeAlign ) { const FeatureBitset & Features = STI . getFeatureBits ( ) ; if ( STI . getTargetTriple ( ) . getArch ( ) != Triple :: riscv || ! Features . test ( RISCV :: FeatureRelax ) ) { return false ; } if ( Features . test ( RISCV :: FeatureStdExtC ) ) { return false ; } if ( CodeAlign != 2 && CodeAlign != 4 ) { return false ; } return true ; }


bool shouldForceRelocation ( RelocationRef & Relocation ) { if ( Relocation . getType ( ) == RISCV :: fixup_riscv_got_hi20 || Relocation . getType ( ) == RISCV :: fixup_riscv_tls_got_hi20 || Relocation . getType ( ) == RISCV :: fixup_riscv_tls_gd_hi20 || Relocation . getType ( ) == RISCV :: fixup_riscv_pcrel_lo12_i || Relocation . getType ( ) == RISCV :: fixup_riscv_pcrel_lo12_s || Relocation . getType ( ) == RISCV :: fixup_riscv_pcrel_hi20 ) { if ( RISCV :: FeatureRelax . isEnabled ( ) ) return true ; else return false ; } return false ; }


void applyFixup ( MCAssembler & Asm , const MCFixup & Fixup , const MCValue & Target , MutableArrayRef < char > Data , uint64_t Value ) { uint64_t Offset = Fixup . getOffset ( ) ; uint64_t FixupValue = Fixup . getValue ( ) ; switch ( Fixup . getKind ( ) ) { case RISCV :: fixup_riscv_hi20 : FixupValue <<= 12 ; case RISCV :: fixup_riscv_lo12_i : Value += FixupValue ; uint64_t Mask = ( 1 << 12 ) - 1 ; if ( Fixup . getKind ( ) == RISCV :: fixup_riscv_hi20 ) { Mask <<= 12 ; }


void applyFixup ( MCDataFragment & DF , MCValue & FixupVal , MCValue :: TargetSpecificFlags TSFlags , uint64_t Offset , MCContext * Ctx ) { const MCSymbolRefExpr * A = FixupVal . getSymA ( ) ; uint64_t SymAddress = 0 ; if ( A ) { if ( const MCSymbol * Sym = A -> getSymbol ( ) ) { SymAddress = Sym -> getAbsoluteAddr ( ) ; } else { return ; } }


bool fixupNeedsRelaxationAdvanced ( const MCFixup & Fixup , uint64_t Value , const MCRelaxableFragment * DF , const MCAsmLayout & Layout , MCInst & Instr , uint64_t Address ) const { switch ( Fixup . getTargetKind ( ) ) { case RISCV :: fixup_riscv_rvc_branch : int64_t Min = - 256 ; int64_t Max = 255 ; if ( Value < Min || Value > Max ) { Instr . setOpcode ( RISCV :: C_LUI ) ; return true ; } return false ; case RISCV :: fixup_riscv_rvc_jump : Min = - 2048 ; Max = 2047 ; if ( Value < Min || Value > Max ) { Instr . setOpcode ( RISCV :: C_LUI ) ; return true ; } return false ; default : return false ; } }


bool mayNeedRelaxation ( Instruction * instr ) { if ( instr -> getDesc ( ) . TSFlags == RISCV ) { if ( instr -> hasUnsupportedFeatures ( ) ) { return true ; } if ( instr -> hasOutOfRangeImmediateOperands ( ) ) { return true ; } return false ; } return false ; }


"Unexpected fixup kind for pcrel_lo12\n"


bool writeNopData ( int count , raw_ostream & output ) { if ( ! output ) { return false ; }


MCOperand addExpr ( MCContext * Ctx ) { const MCExpr * Expr = RVVExpr :: create ( Ctx , 0 , 0 ) ; MCOperand Op = MCOperand :: createExpr ( Expr ) ; return Op ; }


define
i32
@
getReg
(
)
{
entry
:
;
Load
the
value
of
the
"target specific value"
from
memory
%
target_specific_value
=
load
i32
,
i32
*
@
NotARegister
ret
i32
%
target_specific_value
}


bool isImm ( const Value * V ) { if ( isa < ConstantInt > ( V ) ) { return true ; } else if ( isa < GlobalValue > ( V ) || isa < Argument > ( V ) ) { return false ; } if ( V -> getType ( ) -> isRISCVSpecific ( ) ) { return true ; } for ( User * U : V -> users ( ) ) { if ( Instruction * I = dyn_cast < Instruction > ( U ) ) { if ( I -> isRISCVSpecific ( ) && I -> getNumOperands ( ) > 0 && I -> getOperand ( 0 ) == V ) { return true ; } } } return false ; }


bool isMem ( Operand * Op ) { if ( RISCVOperand * RO = dyn_cast < RISCVOperand > ( Op ) ) { if ( RO -> isLoadStoreOp ( ) ) { return true ; } } if ( LoadInst * LI = dyn_cast < LoadInst > ( Op ) ) { return true ; } else if ( StoreInst * SI = dyn_cast < StoreInst > ( Op ) ) { return true ; } return false ; }


bool isReg ( unsigned RegID ) { List validRegIDs = [ 0 , 1 , 2 , ... , 30 , 31 ] ; if ( validRegIDs . contains ( RegID ) ) { return true ; } else { return false ; } }


bool isToken ( LLVMValueRef Op ) { bool isRISCVtoken = false ; if ( LLVMIsAConstant ( Op ) ) { if ( LLVMIsAConstantInt ( Op ) ) { isRISCVtoken = true ; } else if ( LLVMIsAConstantFP ( Op ) ) { isRISCVtoken = true ; } else if ( LLVMIsAConstantAggregateZero ( Op ) ) { isRISCVtoken = true ; } } return isRISCVtoken ; }


void
MatchAndEmitInstruction
(
const
char
*
RISCV
,
uint64_t
RISCV
,
uint64_t
op0
,
const
char
*
missingFeature
,
const
char
*
instructionRequires
,
int
numOperands
,
int
numOperandsRequired
,
int
offset
,
int
size
,
const
char
*
description
,
int
mode
,
uint64_t
operand
,
const
char
*
errorMsg
,
const
char
*
invalidOperand
,
const
char
*
invalidInstruction
)
{
MCInst
inst
;
unsigned
int
numMcOperands
=
0
;
for
(
unsigned
int
i
=
0
;
i
<
numOperands
;
i
++
)
{
MCOperand
mcOp
;
switch
(
mode
)
{
case
RISCV
:
mcOp
=
ParseRISCVOperand
(
operand
)
;
break
;
default
:
llvm_unreachable
(
"Unsupported target specific mode!"
)
;
}
inst
.
addOperand
(
mcOp
)
;
numMcOperands
++
;
}
if
(
numMcOperands
<
numOperandsRequired
)
{
RISCVEncodingError
(
errorMsg
)
;
return
;
}
emitToStreamer
(
RISCV
,
inst
,
mode
)
;
if
(
missingFeature
)
{
RISCVEncodingError
(
description
)
;
return
;
}
if
(
instructionRequires
)
{
RISCVEncodingError
(
description
)
;
return
;
}
if
(
invalidOperand
)
{
RISCVEncodingError
(
invalidOperand
)
;
return
;
}


"Unexpected token in register argument\n"

"Unexpected token in immediate argument\n"


void
print
(
Operand
*
op
,
ostream
&
out
)
{
if
(
op
->
isRISCV
(
)
)
{
RISCVValue
val
=
op
->
getRISCVValue
(
)
;
out
<<
"RISCV: "
<<
val
<<
"\n"
;
}
else
{
out
<<
"Not implemented\n"
;
}
}


MCOperand
addExpr
(
MCExpr
*
Expr
,
Triple
TargetTriple
)
{
assert
(
Expr
!=
&&
"Expr shouldn't be null!"
)
;
MCOperand
Operand
(
MCExpr
::
Target
,
0
,
Triple
::
normalize
(
TargetTriple
)
,
Triple
::
normalize
(
TargetTriple
)
,
Triple
::
normalize
(
TargetTriple
)
)
;
Operand
.
setExpr
(
Expr
)
;
return
Operand
;
}


InstructionOperand . getEndLoc ( RISCV ) { if ( RISCV == true ) { int last_token_loc = this -> getEndTokenLocation ( ) ; return last_token_loc ; } else { return - 1 ; } }


llvm :: DebugLoc getLoc ( < RISCV - specific - value > RS ) { llvm :: DebugLoc Dummy ; return Dummy ; }


"Invalid type access! Target is not RISCV"


Location getStartLoc ( Operand operand ) { if ( operand . isRegister ( ) ) { Register reg = operand . getRegister ( ) ; return reg . getLocation ( ) ; } else if ( operand . isImm ( ) ) { Immediate imm = operand . getImm ( ) ; return imm . getLocation ( ) ; } else if ( operand . isGlobal ( ) ) { GlobalData global = operand . getGlobal ( ) ; return global . getLocation ( ) ; } else if ( operand . isExpr ( ) ) { Expression expr = operand . getExpr ( ) ; return expr . getLocation ( ) ; } else if ( operand . isMemory ( ) ) { Memory mem = operand . getMemory ( ) ; return mem . getLocation ( ) ; } else { return null ; } }


bool isImm ( Value * op ) { unsigned opcode = op -> getOpcode ( ) ; if ( opcode == Instruction :: Add || opcode == Instruction :: LShr || opcode == Instruction :: AShr || opcode == Instruction :: And || opcode == Instruction :: Or || opcode == Instruction :: Xor || opcode == Instruction :: Sub || opcode == Instruction :: Mul || opcode == Instruction :: UDiv || opcode == Instruction :: URem || opcode == Instruction :: FAdd || opcode == Instruction :: FSub || opcode == Instruction :: FMul || opcode == Instruction :: FDiv || opcode == Instruction :: FRem || opcode == Instruction :: ICmp || opcode == Instruction :: FCmp || opcode == Instruction :: Call ) { return false ; } if ( isa < ConstantInt > ( op ) ) { return false ; } return true ; }


bool isMem ( const Operand * Op ) { switch ( Op -> getType ( ) ) { case OpTypeLoad : case OpTypeStore : return true ; case OpTypeLoadHalf : case OpTypeLoadByte : case OpTypeStoreHalf : case OpTypeStoreByte : return true ; case OpTypeLoadFP : case OpTypeLoadFP16 : case OpTypeStoreFP : case OpTypeStoreFP16 : return true ; default : return false ; } }


bool isReg ( Operand op ) { if ( op . targetSpecificValue == RISCV ) { return true ; } else { return false ; } }


bool isToken ( MachineOperand & MO ) { bool isToken = false ; if ( MO . isReg ( ) ) { switch ( MO . getReg ( ) ) { case RISCV :: XTP : case RISCV :: XP : case RISCV :: XAP : case RISCV :: XFP : case RISCV :: XTMP : isToken = true ; break ; default : isToken = false ; } } return isToken ; }


"invalid target specific directive for RISCV backend"

"ParseDirective is deprecated, use 'parseDirective' instead"


Instruction
ParseInstruction
(
std
::
string
assemblyInstruction
)
{
if
(
assemblyInstruction
.
find
(
"unexpected token"
)
!=
std
::
string
::
npos
)
{
return
ErrorInstruction
(
"Invalid instruction"
)
;
}
else
{
if
(
RISCV
::
isSupportedInstruction
(
assemblyInstruction
)
&&
RISCV
::
FeatureRelax
.
isRequired
(
assemblyInstruction
)
)
{
Instruction
instr
=
RISCV
::
parseInstruction
(
assemblyInstruction
)
;
return
instr
;
}
else
{
return
ErrorInstruction
(
"Unsupported instruction"
)
;
}
}
}


void
print
(
Operand
*
op
,
Stream
*
S
)
{
if
(
op
->
isRISCV
(
)
)
{
RISCVOperand
*
riscvOp
=
dyn_cast
<
RISCVOperand
>
(
op
)
;
if
(
riscvOp
->
isRegister
(
)
)
{
StringRef
regName
=
riscvOp
->
getRegister
(
)
;
*
S
<<
"<reg> %"
<<
regName
.
str
(
)
;
}
else
if
(
riscvOp
->
isNoRegister
(
)
)
{
*
S
<<
"noreg"
;
}
else
if
(
riscvOp
->
isTargetSpecific
(
)
)
{
*
S
<<
RISCV
;
}
else
if
(
riscvOp
->
isSysRegister
(
)
)
{
StringRef
sysRegName
=
riscvOp
->
getSysRegName
(
)
;
*
S
<<
"<sysreg: \""
<<
sysRegName
.
str
(
)
<<
"\">"
;
}
else
if
(
riscvOp
->
isValueType
(
)
)
{
ValueType
*
valType
=
riscvOp
->
getValueType
(
)
;
*
S
<<
"<vtype: \""
<<
valType
->
getName
(
)
<<
"\">"
;
}
else
if
(
riscvOp
->
isConstant
(
)
)
{
Constant
*
c
=
riscvOp
->
getConstValue
(
)
;
*
S
<<
c
->
getValueAsString
(
)
;
}
else
{
riscvOp
->
print
(
S
)
;
}
}
else
{
op
->
print
(
S
)
;
}
}


Register tryParseRegister ( StringRef Register , const MachineRegisterInfo & MRI ) { if ( ! Register . startswith ( "RISCV," ) ) { return nullptr ; } if ( Register . size ( ) != 7 || ! isdigit ( Register [ 5 ] ) || ! isdigit ( Register [ 6 ] ) ) { return nullptr ; } unsigned RegNum = Register . slice ( 6 ) . getAsInteger ( 10 ) ; if ( ! MRI -> getRegClass ( RISCV :: GPRRegClassID ) . contains ( RegNum ) ) { return nullptr ; } return Register ; }


bool validateTargetOperandClass ( const MachineInstr * MI , unsigned OpIdx , unsigned OpClassID ) { If ( OpClassID == RISCV :: FPR64RegClassID || OpClassID == RISCV :: FPR64CRegClassID || OpClassID == RISCV :: VRRegClassID || OpClassID == 0 ) { return true ; } return false ; }


void ParseDirective ( std :: string Directive , RISCVTargetStreamer & Streamer ) { if ( Directive == ".option" ) { Streamer . EmitRISCVOption ( ) ; } else if ( Directive == ".attribute" ) { Streamer . EmitRISCVAttribute ( ) ; } }


void
addExpr
(
RISCV
&
Expr
)
{
assert
(
Expr
!=
&&
"Expr shouldn't be null!"
)
;
InsertTargetSpecificValue
(
RISCV
,
Expr
)
;
}


void
print
(
const
RISCVOperand
&
Operand
,
raw_ostream
&
Stream
)
{
if
(
Operand
.
isReg
(
)
)
{
unsigned
RegNum
=
Operand
.
getReg
(
)
;
if
(
RegNum
>=
RISCV
::
X0
&&
RegNum
<=
RISCV
::
X31
)
{
Stream
<<
"<register x"
<<
RegNum
RISCV
::
X0
<<
">"
;
}
}
if
(
Operand
.
isImm
(
)
)
{
int64_t
ImmVal
=
Operand
.
getImm
(
)
;
Stream
<<
ImmVal
;
}
Stream
<<
"''"
;
}


MachineBasicBlock :: iterator MBBI ) { RISCV :: Opcode opc = MI -> getOpcode ( ) ; if ( RISCV :: isPseudo ( opc ) ) { switch ( opc ) { case RISCV :: PseudoLI : { int64_t imm = MI -> getOperand ( 1 ) . getImm ( ) ; BuildMI ( MBB , MBBI , MI -> getDebugLoc ( ) , TII -> get ( RISCV :: LW ) ) . addReg ( RISCV :: X1 ) . addImm ( 0 ) . addReg ( 0 ) ; BuildMI ( MBB , MBBI , MI -> getDebugLoc ( ) , TII -> get ( RISCV :: ADDI ) ) . addReg ( MI -> getOperand ( 0 ) . getReg ( ) ) . addReg ( RISCV :: X1 ) . addImm ( imm ) . addReg ( 0 ) ; MBB . erase ( MBBI ) ; break ; }


void
print
(
Operand
op
,
raw_ostream
&
OS
)
{
if
(
op
.
isReg
(
)
)
{
unsigned
int
regNum
=
op
.
getReg
(
)
;
OS
<<
"<register "
<<
regNum
<<
">"
;
}
if
(
op
.
isTarget
(
)
)
{
int
tsVal
=
op
.
getTargetFlagVal
(
)
;
OS
<<
"'"
<<
tsVal
<<
"'"
;
if
(
op
.
isSystemRegister
(
)
)
{
StringRef
sysReg
=
op
.
getSysReg
(
)
;
OS
<<
" <sysreg: "
<<
sysReg
<<
">"
;
}
}
OS
.
flush
(
)
;
}


bool tryParseRegister ( MCInst & MI , const unsigned * RegNum ) { if ( MI . getNumOperands ( ) == 0 ) { return false ; } const MachineOperand & MO = MI . getOperand ( 0 ) ; if ( MO . isReg ( ) ) { * RegNum = MO . getReg ( ) ; return true ; } return false ; }


Instr ParseInstruction ( Instr Instruction ) { }


"Immediate must be a multiple of 2 bytes in the range!"


Function
ParseInstruction
(
instruction
:
string
)
{
switch
(
instruction
)
{
case
"RISCV"
:
return
RISCV
specific
value
;
case
"RISCV"
:
return
RISCV
specific
value
;
case
"RISCV"
:
return
RISCV
specific
value
;
default
:
return
"unexpected token"
;
}
}


void processInstruction ( RISCVInst & I ) { if ( RISCV :: isPseudoLI ( I . getOpcode ( ) ) ) { I . addDebugInfoAnchor ( RISCV :: PseudoLI , 0 , 1 , 32 ) ; } else { } }


llvm
::
Register
Reg
,
llvm
::
StringRef
SysReg
,
unsigned
int
Size
)
{
OS
<<
RISCV
<<
"<register x"
<<
Reg
.
getReg
(
)
<<
">"
;
OS
<<
" = "
;
OS
<<
"'"
;
OS
<<
SysReg
<<
"'"
;
OS
<<
":"
;
OS
<<
32
;
OS
<<
"<vtype: "
<<
VType
.
AsmString
<<
">"
;
OS
<<
"\n"
;
}


bool validateTargetOperandClass ( MCInst & MI , unsigned OperandNum , unsigned * NewClass ) { if ( NewClass == nullptr ) { return false ; } if ( MI . getNumOperands ( ) < 2 ) { return false ; } const MachineOperand & MO = MI . getOperand ( OperandNum ) ; if ( MO . isReg ( ) ) { const TargetRegisterClass * RC = MRI . getRegClass ( MO . getReg ( ) ) ; if ( RC == & RISCV :: GPR64RegClass || RC == & RISCV :: FPR64RegClass || RC == & RISCV :: FPR64CRegClass ) { * NewClass = RC -> getID ( ) ; return true ; } } return false ; }


void
print
(
raw_ostream
&
OS
,
MCOperand
&
MCOp
)
{
if
(
MCOp
.
isRISCVMCOperand
(
)
)
{
OS
<<
"RISCV"
;
if
(
MCOp
.
hasReg
(
)
)
{
OS
<<
"<register "
;
MCOp
.
getReg
(
)
.
print
(
OS
)
;
OS
<<
">"
;
}
if
(
MCOp
.
hasSysReg
(
)
)
{
OS
<<
"<sysreg: "
;
OS
<<
MCOp
.
getSysReg
(
)
<<
">"
;
}
if
(
MCOp
.
hasSpecialCapReg
(
)
)
{
OS
<<
"<specialcapreg: "
;
OS
<<
MCOp
.
getSpecialCapReg
(
)
<<
">"
;
}
if
(
MCOp
.
hasVType
(
)
)
{
OS
<<
"<vtype: "
;
OS
<<
MCOp
.
getVType
(
)
<<
">"
;
}
}
}


void
print
(
operand
op
,
ostream
&
stream
)
{
if
(
op
->
getType
(
)
!=
RISCV
)
{
cerr
<<
"Error: Operand is not of RISCV type."
<<
endl
;
return
;
}
stream
<<
"RISCV,"
;
stream
<<
"<register "
<<
op
->
getRegister
(
)
<<
">"
;
stream
<<
">"
;
stream
<<
"'"
;
stream
<<
op
->
getSysRegOperand
(
)
<<
"'"
;
stream
<<
"'"
;
stream
<<
"<sysreg: "
;
if
(
op
->
isVecReg
(
)
)
{
stream
<<
op
->
getVecRegOperand
(
)
;
stream
<<
">"
;
stream
<<
"<vtypei: "
<<
op
->
getVecType
(
)
<<
">"
;
}
}


bool validateTargetOperandClass ( MVT :: SimpleValueType VT , const TargetRegisterClass * RC ) { if ( VT != MVT :: i32 && VT != MVT :: f32 ) return false ; if ( RC -> getID ( ) != RISCV :: GPRRegClassID && RC -> getID ( ) != RISCV :: FPR32RegClassID && RC -> getID ( ) != RISCV :: FPR32CRegClassID ) return false ; if ( ! RC -> isSubsetOf ( RISCV :: GPRRegClassID ) && ! RC -> isSubsetOf ( RISCV :: FPR32RegClassID ) && ! RC -> isSubsetOf ( RISCV :: FPR32CRegClassID ) ) return false ; if ( RC -> getName ( ) != "RISCV" && RC -> getName ( ) != "RISCV" && RC -> getName ( ) != "RISCV" && RC -> getName ( ) != "RISCV" && RC -> getName ( ) != "RISCV" && RC -> getName ( ) != "RISCV::FPR32RegClassID" && RC -> getName ( ) != "RISCV" && RC -> getName ( ) != "RISCV::FPR32CRegClassID" ) return false ; return true ; }


void
addExpr
(
MCInst
&
Inst
,
const
MCExpr
*
Expr
,
MCContext
&
Ctx
,
uint64_t
TSFlags
,
uint64_t
RISCV
)
{
if
(
Expr
->
isNullValue
(
)
)
{
llvm_unreachable
(
"Expr shouldn't be null!"
)
;
}
MCOperand
NewOperand
=
MCOperand
::
createExpr
(
Expr
)
;
NewOperand
.
setTargetFlags
(
TSFlags
)
;
NewOperand
.
setTargetCustomFlags
(
RISCV
)
;
Inst
.
addOperand
(
NewOperand
)
;
}


if
(
MO
.
getTargetFlags
(
)
==
RISCV
)
{
int
reg
=
MO
.
getReg
(
)
;
return
reg
;
}
else
{
report_fatal_error
(
"Invalid type access!"
)
;
}


bool isImm ( Operand operand ) { if ( operand . getValueType ( ) == IMM_INT32 ) return true ; else return false ; }


define i1 @ isReg ( i8 * % operand ) { % is_register = icmp ne i8 * % operand , null ret i1 % is_register }


bool isToken ( const MachineOperand & MO ) { return MO . isToken ( ) ; }


"Error: Unknown directive for RISCV target!"


void
ParseInstruction
(
Instruction
&
I
,
const
AsmToken
&
Tok
,
RISCV
::
FeatureRelaxMode
Mode
,
unsigned
FeatureBits
)
{
switch
(
Tok
.
getKind
(
)
)
{
case
AsmToken
::
At
:
break
;
case
AsmToken
::
Colon
:
break
;
case
AsmToken
::
Comma
:
break
;
case
AsmToken
::
Equal
:
break
;
case
AsmToken
::
Identifier
:
I
.
setOpcode
(
RISCV
::
getInstructionCode
(
Tok
.
getString
(
)
)
)
;
break
;
case
AsmToken
::
Integer
:
uint64_t
Val
;
if
(
Tok
.
getStringRef
(
)
.
getAsInteger
(
0
,
Val
)
)
{
report_fatal_error
(
"unexpected token"
)
;
}
else
{
I
.
addOperand
(
MCOperand
::
createImm
(
Val
)
)
;
}
break
;
case
AsmToken
::
EndOfStatement
:
break
;
case
AsmToken
::
Minus
:
I
.
addOperand
(
MCOperand
::
createImm
(
1
)
)
;
break
;
case
AsmToken
::
Plus
:
break
;
case
AsmToken
::
String
:
unsigned
RegNum
=
0
;
if
(
Tok
.
getStringRef
(
)
.
substr
(
0
,
2
)
==
"r["
)
{
if
(
!
Tok
.
getStringRef
(
)
.
substr
(
2
,
1
)
.
getAsInteger
(
0
,
RegNum
)
&&
RegNum
<
32
)
{
I
.
addOperand
(
MCOperand
::
createReg
(
RegNum
)
)
;
}
}
break
;
default
:
report_fatal_error
(
"unexpected token"
)
;
}
}


void
print
(
raw_ostream
&
OS
,
const
MachineOperand
&
MO
)
const
{
switch
(
MO
.
getType
(
)
)
{
case
MachineOperand
::
MO_Register
:
OS
<<
"<register "
<<
MO
.
getReg
(
)
<<
">"
;
break
;
case
MachineOperand
::
MO_Immediate
:
OS
<<
MO
.
getImm
(
)
;
break
;
case
MachineOperand
::
MO_MachineBasicBlock
:
OS
<<
"<bb#"
<<
MO
.
getMBB
(
)
->
getNumber
(
)
<<
">"
;
break
;
case
MachineOperand
::
MO_ExternalSymbol
:
OS
<<
"<extsymbol "
<<
MO
.
getSymbolName
(
)
<<
">"
;
break
;
case
MachineOperand
::
MO_GlobalAddress
:
OS
<<
"<global "
<<
MO
.
getGlobal
(
)
->
getName
(
)
<<
">"
;
break
;
case
MachineOperand
::
MO_RegisterMask
:
OS
<<
"<regmask "
<<
MO
.
getRegMask
(
)
->
getMaskNumber
(
)
<<
">"
;
break
;
default
:
llvm_unreachable
(
"Unknown machine operand type!"
)
;
}
OS
<<
"<sysreg: "
;
OS
<<
">"
;
}


bool validateTargetOperandClass ( MCOperandClassID ClassID ) { switch ( ClassID ) { case RISCV :: RegisterClassID : return true ; case RISCV :: CTRLRegClassID : return true ; case RISCV :: PCCRegClassID : return true ; case RISCV :: GPRRegClassID : return true ; case RISCV :: FPRRegClassID : return true ; case RISCV :: FPR32RegClassID : return true ; case RISCV :: FPR32CRegClassID : return true ; default : return false ; } }


void EmitInstruction ( MachineInstr * MI , MachineBasicBlock * MBB , MachineFunction * MF , raw_ostream & OS ) { unsigned RiscvOpcode = MI -> getOpcode ( ) ; bool HazardDetected = CheckHazard ( RiscvOpcode ) ; if ( HazardDetected ) { EmitNop ( MF , OS ) ; } MI -> print ( OS ) ; UpdateHazardState ( RiscvOpcode ) ; return ; }


"Printing operand of INLINEASM instruction:\n"

"Incorrect target-specific value for RISCV!\n"


void PrintAsmOperand ( const MCInst * MI , unsigned OpNum , const MCSubtargetInfo & STI , raw_ostream & OS ) { OpNum = ( OpNum - 1 ) * 2 + RISCV :: OpShift ; if ( MI -> getOperand ( OpNum ) . isReg ( ) ) { unsigned Reg = MI -> getOperand ( OpNum ) . getReg ( ) ; OS << '%' << RISCVInstPrinter :: getRegisterName ( Reg ) ; } else { unsigned Imm = MI -> getOperand ( OpNum ) . getImm ( ) ; if ( STI . getFeatureBits ( ) [ RISCV :: FeatureB ] ) { OS << "0x" << format_hex ( static_cast < uint32_t > ( Imm ) , 8 ) ; } else { OS << Imm ; } } }


void RISCVTargetMachine :: runOnMachineFunction ( MachineFunction & MF ) { }


void EmitInstruction ( const TargetInstrInfo & TII , MachineInstr * MI , MachineBasicBlock & MBB , MachineFunction & MF , unsigned Subtarget ) { switch ( MI -> getOpcode ( ) ) { case RISCV :: ADD : { const MachineOperand & Op0 = MI -> getOperand ( 0 ) ; const MachineOperand & Op1 = MI -> getOperand ( 1 ) ; const MachineOperand & Op2 = MI -> getOperand ( 2 ) ; unsigned DestRegID = Op0 . getReg ( ) ; unsigned SrcRegID1 = Op1 . getReg ( ) ; unsigned SrcRegID2 = Op2 . getReg ( ) ; TII . emitAddInstruction ( RISCV , RISCV , RISCV , DestRegID , SrcRegID1 , SrcRegID2 ) ; RISCV . advanceHazardState ( DestRegID , SrcRegID1 , SrcRegID2 , Subtarget ) ; break ; } case RISCV :: SUB : { const MachineOperand & Op0 = MI -> getOperand ( 0 ) ; const MachineOperand & Op1 = MI -> getOperand ( 1 ) ; const MachineOperand & Op2 = MI -> getOperand ( 2 ) ; unsigned DestRegID = Op0 . getReg ( ) ; unsigned SrcRegID1 = Op1 . getReg ( ) ; unsigned SrcRegID2 = Op2 . getReg ( ) ; TII . emitSubInstruction ( RISCV , RISCV , RISCV , DestRegID , SrcRegID1 , SrcRegID2 ) ; RISCV . advanceHazardState ( DestRegID , SrcRegID1 , SrcRegID2 , Subtarget ) ; break ; } default : TII . emitInstruction ( MI , MBB ) ; RISCV . advanceHazardState ( Subtarget ) ; break ; } }


function
emitInstruction
(
opcode
,
operand1
,
operand2
)
{
if
(
target
==
"RISCV"
)
{
emit
(
opcode
,
operand1
,
operand2
,
"RISCV"
)
;
emit
(
opcode
,
operand1
,
operand2
,
"RISCV"
)
;
emit
(
opcode
,
operand1
,
operand2
,
"RISCV"
)
;
}
else
{
throw
Error
(
"Target not supported."
)
;
}
}


const char * AddressFn ) { if ( MI -> getOpcode ( ) != TargetOpcode :: INLINEASM ) return ; MachineOperand MO = MI -> getOperand ( OpNo ) ; if ( ! MO . isMem ( ) ) return ; MachineOperand AddrMO = MO . getMemOperand ( ) -> getValue ( ) ; const MCExpr * AddrExpr = nullptr ; if ( AddrMO . isGlobal ( ) || AddrMO . isCPI ( ) ) { const GlobalValue * GV = AddrMO . getGlobal ( ) ; AddrExpr = AP . getSymbol ( AddrMO , GV ) ; } else { AddrExpr = AddrMO . getExpr ( ) ; } const MCExpr * OffsetExp = MCConstantExpr :: create ( Offset , AP . OutContext ) ; const MCExpr * ModifierExp = MCSymbolRefExpr :: create ( Modifier , AP . OutContext ) ; AddrExpr = MCBinaryExpr :: createAdd ( AddrExpr , OffsetExp , AP . OutContext ) ; AddrExpr = MCBinaryExpr :: createAdd ( AddrExpr , ModifierExp , AP . OutContext ) ; std :: string TargetSpecificValue = RISCV :: RISCV ; std :: string AddrFn = AddressFn ; AP . EmitToStreamer ( AddrExpr , AP . getMAI ( ) , 0 , false , false , AddrFn , TargetSpecificValue ) ; if ( ExtraCode ) AP . OutStreamer -> EmitBytes ( ExtraCode ) ; }


void
RISCVTargetMachine
::
PrintAsmOperand
(
const
MachineInstr
*
MI
,
unsigned
OpNo
,
const
char
*
ExtraCode
,
raw_ostream
&
O
)
{
assert
(
MI
&&
"Invalid MachineInstr pointer"
)
;
const
MachineOperand
&
MO
=
MI
->
getOperand
(
OpNo
)
;
const
unsigned
Opcode
=
MI
->
getOpcode
(
)
;
switch
(
Opcode
)
{
case
RISCV
::
RISCV
:
O
<<
getRISCVTargetLowering
(
)
->
getAsmOperandString
(
MO
,
Opcode
)
;
break
;
default
:
llvm_unreachable
(
"Unhandled opcode on PrintAsmOperand"
)
;
}
}


raw_ostream
&
O
)
{
assert
(
MI
&&
"Invalid machine instruction"
)
;
assert
(
OpNo
<
MI
->
getNumOperands
(
)
&&
"Operand number out of range"
)
;
const
MachineOperand
&
MO
=
MI
->
getOperand
(
OpNo
)
;
if
(
MO
.
isImm
(
)
)
{
O
<<
MO
.
getImm
(
)
;
}
else
if
(
MO
.
isReg
(
)
)
{
O
<<
RISCVInstPrinter
::
getRegisterName
(
MO
.
getReg
(
)
)
;
}
else
if
(
MO
.
isFPImm
(
)
)
{
O
<<
MO
.
getFPImm
(
)
;
}
else
if
(
MO
.
isSymbol
(
)
)
{
O
<<
RISCVInstPrinter
::
getSymbolPrefix
(
)
<<
MO
.
getSymbolName
(
)
<<
RISCV
::
X0
;
}
else
if
(
MO
.
isExpr
(
)
)
{
O
<<
MO
.
getExpr
(
)
;
}
else
if
(
MO
.
isGlobal
(
)
)
{
O
<<
MO
.
getGlobal
(
)
;
}
else
if
(
MO
.
isMBB
(
)
)
{
O
<<
*
MO
.
getMBB
(
)
;
}
else
{
llvm_unreachable
(
"Unknown operand type"
)
;
}
if
(
ExtraCode
&&
ExtraCode
[
0
]
!=
'\0'
)
O
<<
ExtraCode
;
}


function
emitBasicBlockEnd
(
BB
)
{
if
(
target
==
RISCV
)
{
emit
"RISCV"
;
emit
"RISCV"
;
emit
"RISCV"
;
emit
"RISCV"
;
emit
"RISCV"
;
}
else
{
return
"Target not supported."
;
}
}


void
RISCVTargetMachine
::
emitBasicBlockStart
(
)
{
std
::
cout
<<
"RISCV, RISCV, RISCV, RISCV, RISCV"
<<
std
::
endl
;
}


void PrintAsmOperand ( Value * Operand , AsmPrinter & AP ) { RISCVCastInst * O = dyn_cast < RISCVCastInst > ( Operand ) ; if ( O && O -> isReg ( ) ) { int RegNum = O -> getRegNum ( ) ; AP . OutStreamer -> AddComment ( "%" + Twine ( RegNum ) ) ; AP . printRegName ( RegNum ) ; } else { AP . printOperand ( Operand , false ) ; } }


"Cannot lower global addresses for RISCV "


void RISCVTargetMachine :: emitStartOfAsmFile ( raw_ostream & OS ) { std :: string TargetName = getName ( ) ; OS << "\t.file\t\":\"" << TargetName << "\"\n" ; OS << "\t.RISCV\t" << TargetName << "\n" ; }


std
::
string
RISCVTargetMachine
::
getPassName
(
)
const
{
return
std
::
string
(
"RISCV Assembly Printer"
)
;
}


void
PrintAsmMemoryOperand
(
const
MachineInstr
*
MI
,
unsigned
OpNo
,
const
char
*
ExtraCode
,
raw_ostream
&
O
,
const
char
*
Modifier
=
nullptr
)
{
assert
(
MI
->
getOpcode
(
)
==
TargetOpcode
::
INLINEASM
&&
"Not an inline asm instruction!"
)
;
const
MCAsmInfo
*
MAI
=
MI
->
getMF
(
)
->
getTarget
(
)
.
getMCAsmInfo
(
)
;
assert
(
MI
->
getNumOperands
(
)
>
OpNo
&&
"OpNo too large!"
)
;
unsigned
CurOp
=
0
;
unsigned
BaseReg
=
0
;
unsigned
OffsetImm
=
0
;
unsigned
ScaleImm
=
1
;
unsigned
Global
=
0
;
unsigned
Symbol
=
0
;
unsigned
MicroMips
=
0
;
unsigned
Intel
=
0
;
unsigned
IsIndirect
=
0
;
unsigned
IsMem
=
0
;
unsigned
Implicit
=
0
;
unsigned
IsISD
=
0
;
unsigned
Size
=
0
;
StringRef
SymName
;
while
(
CurOp
<
OpNo
)
{
assert
(
MI
->
getNumOperands
(
)
>
CurOp
&&
"Invalid operand number!"
)
;
++
CurOp
;
}
assert
(
MI
->
getOperand
(
CurOp
)
.
isGlobal
(
)
&&
"Expected global operand!"
)
;
Global
=
CurOp
++
;
assert
(
MI
->
InstrInfo
->
getGlobalSymbol
(
MI
->
getOperand
(
Global
)
,
SymName
)
&&
"Symbol operand expected!"
)
;
if
(
MI
->
getOperand
(
CurOp
)
.
isReg
(
)
)
{
assert
(
MI
->
getOperand
(
CurOp
)
.
isReg
(
)
&&
"Expected register operand!"
)
;
BaseReg
=
CurOp
++
;
}
else
if
(
MI
->
getOperand
(
CurOp
)
.
isImm
(
)
)
{
assert
(
MI
->
getOperand
(
CurOp
)
.
isImm
(
)
&&
"Expected immediate operand!"
)
;
OffsetImm
=
CurOp
++
;
if
(
MI
->
getOperand
(
OffsetImm
)
.
isMachineConstantPoolIndex
(
)
)
{
Symbol
=
OffsetImm
++
;
IsMem
=
1
;
}
if
(
MI
->
getOperand
(
OffsetImm
)
.
isCPI
(
)
)
{
Symbol
=
OffsetImm
++
;
IsMem
=
1
;
IsMemOp
=
1
;
}
if
(
ExtraCode
!=
nullptr
&&
!
strcmp
(
ExtraCode
,
"z"
)
&&
MI
->
getOperand
(
OffsetImm
)
.
isImm
(
)
)
{
ScaleImm
=
OffsetImm
++
;
}
}


raw_ostream
&
OS
)
{
const
MachineOperand
&
MO
=
MI
->
getOperand
(
OpNo
)
;
switch
(
MO
.
getType
(
)
)
{
case
MachineOperand
::
MO_Register
:
OS
<<
RISCVInstPrinter
::
getRegisterName
(
MO
.
getReg
(
)
)
;
break
;
case
MachineOperand
::
MO_Immediate
:
OS
<<
MO
.
getImm
(
)
;
break
;
case
MachineOperand
::
MO_GlobalAddress
:
OS
<<
*
getSymbol
(
MO
.
getGlobal
(
)
)
;
break
;
default
:
llvm_unreachable
(
"Invalid operand type!"
)
;
}
if
(
ExtraCode
&&
ExtraCode
[
0
]
)
OS
<<
'@'
<<
ExtraCode
;
if
(
OpNo
+
1
<
MI
->
getNumOperands
(
)
)
OS
<<
", "
;
}


for ( const Argument & AI : F . args ( ) ) { const auto & DL = F . getParent ( ) -> getDataLayout ( ) ; unsigned Reg = MF . addLiveIn ( AI , & RISCV :: GPRRegClass ) ; MF . getRegInfo ( ) . addLiveRangeToEndOfBlock ( Reg , MBB ) ; MBB -> addLiveIn ( Reg ) ; }


PredicateConstraint getConstraint ( RISCV targetSpecificValue ) { if ( ! isValidRISCV ( targetSpecificValue ) ) { return null ; } PredicateConstraint constraint = new PredicateConstraint ( ) ; RISCVCondition condition = targetSpecificValue . getCondition ( ) ; if ( ! isValidCondition ( condition ) ) { return null ; } constraint . setCondition ( condition ) ; return constraint ; }


Function * getFormat ( std :: string target ) { if ( target == "RISCV" ) { return "dwarf_riscv" ; } else { return "" ; } }


const
std
::
string
getPassName
(
)
{
return
"RISCV Branch Selector"
;
}


void RISCVTargetLowering :: lowerFormalArguments ( MachineFunction & MF , const RISCVSubtarget & STI , LLVMContext & Ctx , const MachineRegisterInfo & MRI , SmallVectorImpl < SDValue > & InVals ) const { MachineFrameInfo & MFI = MF . getFrameInfo ( ) ; uint32_t NumParams = MF . getFunction ( ) . getFunctionType ( ) -> getNumParams ( ) ; unsigned ArgOffset = STI . isRV64 ( ) ? 16 : 8 ; MachineBasicBlock & MBB = MF . front ( ) ; for ( uint32_t i = 0 ; i < NumParams ; ++ i ) { MVT VT = getRegisterType ( MF . getDataLayout ( ) , * MF . getFunction ( ) . getFunctionType ( ) -> param_begin ( i ) ) ; const TargetRegisterClass * RC = getRegClassFor ( VT ) ; unsigned Reg = MF . getRegInfo ( ) . createVirtualRegister ( RC ) ; int FI = MFI . CreateFixedObject ( VT . getSizeInBits ( ) / 8 , ArgOffset + i * VT . getSizeInBits ( ) / 8 , true ) ; SDValue FIN = CurDAG -> getTargetFrameIndex ( FI , VT ) ; SDValue Load = CurDAG -> getLoad ( VT , DL , MBB , FIN , MachinePointerInfo :: getFixedStack ( FI ) , false , false , false , 4 ) ; MBB . addLiveIn ( Reg , RC ) ; InVals . push_back ( Load ) ; } }


define void @ lowerReturn ( ) { % 1 = load i32 , i32 * @ swifterrorval % pseudo_ret = RISCVISD :: PseudoRET % 1 ret i32 % pseudo_ret }


void
lowerCall
(
CallInst
*
CI
,
RISCVTargetMachine
&
TM
,
RISCVSubtarget
&
STI
)
{
Function
*
F
=
CI
->
getCalledFunction
(
)
;
CallingConv
::
ID
CC
=
F
->
getCallingConv
(
)
;
SmallVector
<
Value
*
,
8
>
Args
;
for
(
unsigned
i
=
0
,
e
=
CI
->
getNumOperands
(
)
;
i
!=
e
;
++
i
)
{
if
(
i
==
0
)
continue
;
Args
.
push_back
(
CI
->
getOperand
(
i
)
)
;
}
Intrinsic
::
ID
ID
;
if
(
CC
==
CallingConv
::
C
)
ID
=
Intrinsic
::
riscv_call_c
;
else
if
(
CC
==
CallingConv
::
Fast
)
ID
=
Intrinsic
::
riscv_call_fast
;
else
llvm_unreachable
(
"Unknown calling convention"
)
;
Function
*
Callee
=
Intrinsic
::
getDeclaration
(
F
->
getParent
(
)
,
ID
)
;
CallInst
*
NewCI
=
CallInst
::
Create
(
Callee
,
Args
)
;
NewCI
->
insertBefore
(
CI
)
;
CI
->
replaceAllUsesWith
(
NewCI
)
;
}


static void getAnalysisUsage ( AnalysisUsage & AU ) const override { AU . addRequired < SomeAnalysis > ( ) ; AU . addRequired < SomeOtherAnalysis > ( ) ; } ` ` ` This implementation assumes that the RISCV backend requires the ` SomeAnalysis ` and ` SomeOtherAnalysis ` passes . If more passes are required by the RISCV backend , they can be added using the ` au . addRequired ( ) ` function call . Another possible implementation of this function could be : ` ` ` static void getAnalysisUsage ( AnalysisUsage & AU ) const override { AU . addPreserved < SomeAnalysis > ( ) ; AU . addPreserved < SomeOtherAnalysis > ( ) ; }


StringRef
getPassName
(
StringRef
RISCV
,
Target
Specific
)
{
std
::
string
passName
=
"RISCV - Optimizer Pass"
;
passName
+=
" for "
+
Target
Specific
;
return
StringRef
(
passName
)
;
}


", RISCV, RISCV, RISCVCP:RISCVCPModifier, RISCV"


AnalysisUsage & AU ) const override { AU . addRequired < ... > ( ) ; AU . addPreserved < ... > ( ) ; }


std
::
string
getPassName
(
const
PassInfo
*
PI
)
{
std
::
string
Name
=
PI
->
getPassName
(
)
;
if
(
PI
->
getTargetMachineName
(
)
==
"RISCV"
)
{
Name
+=
" (RISCV)"
;
}
return
Name
;
}


llvm :: StringRef getInstruction ( const llvm :: MCInst & Inst , uint64_t Address , const llvm :: MCSubtargetInfo & STI , llvm :: MCContext * Context ) { std :: string DisasmStr ; llvm :: raw_string_ostream DisasmStream ( DisasmStr ) ; const llvm :: MCDisassembler * Disassembler = STI . getInstrInfo ( ) -> getDisassembler ( ) ; Disassembler -> getInstruction ( Inst , Address , DisasmStream , Context ) ; return DisasmStream . str ( ) ; }


"Trying RISCV32Only_16 table (16-bit Instruction):\n"

"Trying RISCV_C table (16-bit Instruction):\n"


std
::
string
getInstruction
(
uint32_t
instruction
,
RISCVTarget
const
&
target
,
unsigned
char
dest
,
unsigned
char
src1
,
unsigned
char
src2
,
int
offset
,
llvm
::
support
::
endian
endian
)
{
InstructionInfo
info
=
target
.
decodeInstruction
(
instruction
)
;
std
::
string
disassembledInstruction
;
if
(
endian
==
llvm
::
support
::
little
)
{
disassembledInstruction
=
info
.
mnemonic
+
" "
;
}
else
{
disassembledInstruction
=
info
.
mnemonic
+
" "
;
}
if
(
info
.
dest
)
{
disassembledInstruction
+=
"x"
+
std
::
to_string
(
dest
)
+
", "
;
}
disassembledInstruction
+=
"x"
+
std
::
to_string
(
src1
)
+
", "
;
if
(
info
.
src2
)
{
disassembledInstruction
+=
"x"
+
std
::
to_string
(
src2
)
+
", "
;
}
if
(
info
.
offset
)
{
disassembledInstruction
+=
std
::
to_string
(
offset
)
;
}
return
disassembledInstruction
;
}


std
::
string
getInstruction
(
RISCVTargetMachine
&
TM
,
const
MCInst
&
MI
,
uint64_t
Address
,
raw_ostream
&
OS
,
bool
isBranch
,
bool
isSymb
)
{
RISCVInstPrinter
&
IP
=
*
static_cast
<
RISCVInstPrinter
*
>
(
TM
.
getSubtargetImpl
(
)
->
getMCInstPrinter
(
)
)
;
MCDisassembler
*
DisAsm
=
TM
.
getTarget
(
)
.
createMCDisassembler
(
*
TM
.
getSubtargetImpl
(
)
->
getMCInstrInfo
(
)
,
*
TM
.
getSubtargetImpl
(
)
->
getMCRegInfo
(
)
,
*
TM
.
getSubtargetImpl
(
)
->
getMCSubtargetInfo
(
)
,
nullptr
)
;
MCInstPrinterOptions
Opts
;
Opts
.
MI
=
&
MI
;
Opts
.
FP
=
&
IP
;
IP
.
printInstruction
(
MI
,
Address
,
Opts
,
OS
)
;
if
(
isBranch
)
OS
<<
"\nBranch Instruction"
;
if
(
isSymb
)
OS
<<
"\nSymbol: ??"
;
return
OS
.
str
(
)
;
}


"Unable to disassemble instruction at 0x"


StringRef
getInstruction
(
uint32_t
Opcode
)
{
switch
(
Opcode
)
{
case
RISCV
::
ADD
:
return
"ADD x0, x0, x0"
;
case
RISCV
::
ADDI
:
return
"ADDI x0, x0, 0"
;
case
RISCV
::
SUB
:
return
"SUB x0, x0, x0"
;
case
RISCV
::
AND
:
return
"AND x0, x0, x0"
;
case
RISCV
::
SLL
:
return
"SLL x0, x0, x0"
;
case
RISCV
::
SLT
:
return
"SLT x0, x0, x0"
;
case
RISCV
::
SLTI
:
return
"SLTI x0, x0, 0"
;
case
RISCV
::
LOAD
:
return
"LOAD x0, 0(x0)"
;
case
RISCV
::
STORE
:
return
"STORE x0, 0(x0)"
;
case
RISCV
::
ADDI4SPN
:
return
"ADDI4SPN x0, 0"
;
case
RISCV
::
MVI
:
return
"MVI x0, 0"
;
case
RISCV
::
AUIPC
:
return
"AUIPC x0, 0"
;
case
RISCV
::
SB
:
return
"SB x0, 0(x0)"
;
case
RISCV
::
SH
:
return
"SH x0, 0(x0)"
;
case
RISCV
::
BEQ
:
return
"BEQ x0, x0, 0"
;
case
RISCV
::
BNE
:
return
"BNE x0, x0, 0"
;
default
:
return
"Unknown instruction"
;
}
}


void emitValueImpl ( unsigned Value , unsigned Size ) { if ( Value == 0 ) { if ( RISCV == 0 ) { RISCV = Value ; } } }


void finish ( ) { LiveIntervals * lis = MF -> getAnalysis < LiveIntervals > ( ) ; unsigned VirtualReg = 0 ; for ( MachineRegisterInfo :: virtreg_iterator I = MRI -> virtreg_begin ( ) , E = MRI -> virtreg_end ( ) ; I != E ; ++ I ) { unsigned Reg = * I ; VirtualReg = std :: max ( VirtualReg , Reg ) ; } for ( LiveIntervals :: iterator I = lis -> begin ( ) , E = lis -> end ( ) ; I != E ; ++ I ) { VNInfo * Reg = I -> valno ; if ( ! Reg -> isAssignedReg ( ) ) { unsigned PhysReg = MRI -> createVirtualRegister ( & RISCV :: GPRRegClass ) ; Reg -> setHasReg ( PhysReg ) ; for ( LiveInterval :: iterator I = Reg -> getLiveRange ( ) . begin ( ) , E = Reg -> getLiveRange ( ) . end ( ) ; I != E ; ++ I ) { MachineInstr * MI = I -> valno -> def . getInst ( ) ; if ( MI -> getOpcode ( ) == RISCV :: ST ) { MI -> getOperand ( I -> valno -> def . getOperand ( ) ) -> setReg ( PhysReg ) ; MI -> getOperand ( I -> valno -> def . getOperand ( ) + 1 ) -> setReg ( PhysReg ) ; } else if ( MI -> getOpcode ( ) == RISCV :: LD ) { MI -> getOperand ( I -> valno -> def . getOperand ( ) ) -> setReg ( PhysReg ) ; MI -> getOperand ( I -> valno -> def . getOperand ( ) + 1 ) -> setReg ( PhysReg ) ; } else if ( MI -> isRegReg ( ) ) { MI -> getOperand ( I -> valno -> def . getOperand ( ) ) -> setReg ( PhysReg ) ; }


StringRef getStreamer ( StringRef Target ) { if ( Target == "RISCV" ) { return "RISCV" ; } else { return "" ; } }


void reset ( Value * Def , Instance * Instance ) { RISCVMachineFunctionInfo * MFI = MF -> getInfo < RISCVMachineFunctionInfo > ( ) ; MFI -> setReset ( Def , Instance ) ; }


std :: string getPassName ( const llvm :: PassInfo & PI ) { std :: string Target = "RISCV" ; if ( PI . getTargetMachine ( ) != nullptr && PI . getTargetMachine ( ) -> getTargetTriple ( ) . getArch ( ) == llvm :: Triple :: riscv ) { Target = "RISCV" ; } return Target ; }


void runOnMachineFunction ( Module & M , TargetMachine & TM ) { const TargetOptions & Options = TM . getOptions ( ) ; const RISCVTargetMachine & RISCVTM = static_cast < const RISCVTargetMachine & > ( TM ) ; const RISCVSubtarget & Subtarget = RISCVTM . getSubtarget ( ) ; Function * F = M . getFunction ( "main" ) ; std :: unique_ptr < MachineCodeEmitter > Emitter ( RISCVTM . createMCCodeEmitter ( * F ) ) ; MachineFunctionInfo * MFI = new MachineFunctionInfo ( RISCVTM ) ; MachineFunctionPassManager MFPM ( TM ) ; MFPM . addPass ( RISCVTM . createPass ( ) ) ; MFPM . addPass ( createRISCVISelDag ( RISCVTM ) ) ; FunctionLoweringInfo * FLI = new FunctionLoweringInfo ( M , Subtarget ) ; F -> setFunctionLoweringInfo ( FLI ) ; MFPM . addPass ( createRISCVISelDag ( RISCVTM ) ) ; MFPM . run ( * F , M ) ; Emitter -> finish ( ) ; MFI -> dump ( ) ; }


StringRef
getPassName
(
)
{
return
"RISCV Target Pass"
;
}


std
::
string
getPassName
(
const
RISCVTargetMachine
*
TM
)
{
if
(
TM
->
getTargetTriple
(
)
.
getArch
(
)
==
llvm
::
Triple
::
riscv32
)
{
return
"RISCV 32 bit Pass"
;
}
else
if
(
TM
->
getTargetTriple
(
)
.
getArch
(
)
==
llvm
::
Triple
::
riscv64
)
{
return
"RISCV 64 bit Pass"
;
}
else
{
return
"RISCV Pass"
;
}
}


void runOnMachineFunction ( RISCV riscv , RISCV riscv_opt , RISCV riscv_attrs ) { for ( BasicBlock & BB : MF ) { for ( Instruction & I : BB ) { generateMachineCode ( I , riscv , riscv_opt , riscv_attrs ) ; } } }


RegScavenger * RS ) { const TargetRegisterInfo * TRI = MF . getSubtarget ( ) . getRegisterInfo ( ) ; const uint32_t * CSRegs = TRI -> getCalleeSavedRegs ( & MF ) ; for ( unsigned i = 0 ; CSRegs [ i ] != 0 ; ++ i ) { const TargetRegisterClass * RC = TRI -> getMinimalPhysRegClass ( CSRegs [ i ] ) ; if ( RC == & RISCV :: GR32BitRegClass ) { SavedRegs . set ( CSRegs [ i ] ) ; unsigned SuperReg = TRI -> getMatchingSuperReg ( CSRegs [ i ] , RISCV :: sub_64 , & RISCV :: GR64BitRegClass ) ; SavedRegs . set ( SuperReg ) ; } else { SavedRegs . set ( CSRegs [ i ] ) ; } } SavedRegs . set ( RISCV :: fp_64 ) ; SavedRegs . set ( RISCV :: fp ) ; }


MachineBasicBlock :: iterator MI ) { if ( ! MF . getTarget ( ) . usesCallFrameSetupDestroy ( ) ) return ; const RISCVInstrInfo & TII = * MF . getSubtarget < RISCVSubtarget > ( ) . getInstrInfo ( ) ; unsigned CallFrameSetupOpcode = 0 ; unsigned CallFrameDestroyOpcode = 0 ; for ( auto & NextMI : make_range ( std :: next ( MI ) , MBB . end ( ) ) ) { CallFrameSetupOpcode = NextMI . getOpcode ( ) ; CallFrameDestroyOpcode = NextMI . getOpcode ( ) ; if ( CallFrameSetupOpcode == RISCV :: ADJCALLSTACKDOWN ) { NextMI . getOperand ( 0 ) . setImm ( 0 ) ; NextMI . setDesc ( TII . get ( RISCV :: ADDI ) ) ; } if ( CallFrameDestroyOpcode == RISCV :: ADJCALLSTACKUP ) { NextMI . getOperand ( 0 ) . setImm ( 0 ) ; NextMI . setDesc ( TII . get ( RISCV :: ADDI ) ) ; } if ( NextMI . getOpcode ( ) == RISCV :: sp_64 ) { NextMI . getOperand ( 0 ) . setImm ( 0 ) ; NextMI . setDesc ( TII . get ( RISCV :: ADDI ) ) ; } } }


bool hasFP ( const Function & F ) { if ( F . getParent ( ) -> getTargetTriple ( ) == "riscv64" || F . getTarget ( ) . getName ( ) == "riscv" ) { return true ; } return false ; }


bool hasReservedCallFrame ( const MachineFunction & MF ) { const MachineFrameInfo & MFI = MF . getFrameInfo ( ) ; int numArgs = MF . getNumArgs ( ) ; bool argsOnStack = MFI . getStackSize ( ) != 0 ; if ( numArgs <= RISCV :: X8 && argsOnStack ) { return true ; } return false ; }


bool spillCalleeSavedRegisters ( ) { if ( RISCV -> getTargetTriple ( ) . isRISCV ( ) ) { unsigned int TargetSP = RISCV :: sp ; unsigned int TargetFP = RISCV :: s0 ; unsigned int RetAddr = RISCV :: ra ; unsigned int RetAddr_64 = RISCV :: ra_64 ; if ( ! MF -> getSubtarget ( ) . getFrameLowering ( ) -> hasReservedCallFrame ( MF ) ) { return false ; } MachineFunction :: StubListType Stubs = MF -> getStubs ( ) ; unsigned int StubSize = Stubs . size ( ) ; bool IsLegal = MF -> getSubtarget < RISCVSubtarget > ( ) . isTargetDarwin ( ) ; for ( int RegNum = 0 ; RegNum < TargetSymRegs . size ( ) ; ++ RegNum ) { unsigned int StackAddr = RISCV :: sp ; const TargetRegisterInfo * TRI = MF -> getSubtarget ( ) . getRegisterInfo ( ) ; unsigned int Reg = TargetSymRegs [ RegNum ] ; if ( ! TargetReservedRegs_64 ( Reg , false ) ) continue ; if ( Reg == RetAddr ) { StackAddr = RetAddr_64 ; } if ( storeRegToStackSlot ( * MF , * MBB , MI , StackAddr , Reg , * TRI ) ) { if ( IsLegal ) { BuildMI ( * MBB , MI , MI -> getDebugLoc ( ) , MCRI -> getCall ( * MBB , MI -> getDebugLoc ( ) ) , StackAddr ) . addReg ( RISCV :: calleesaved_copy ) ; } } else { ++ NumStores ; } } return true ; } return false ; }


bool canUseAsEpilogue ( const MachineBasicBlock & MBB ) { if ( MBB . pred_size ( ) != 1 ) { return false ; } if ( MBB . succ_size ( ) != 1 ) { return false ; } for ( const MachineInstr & MI : MBB ) { if ( MI . isReturn ( ) ) { return true ; } } for ( const MachineInstr & MI : MBB ) { if ( MI . getDesc ( ) . TSFlags & RISCVII :: ModifySP ) { return false ; } } for ( const MachineInstr & MI : MBB ) { if ( MI . getDesc ( ) . TSFlags & RISCVII :: ModifyRA ) { return false ; } } return false ; }


bool canUseAsPrologue ( MachineBasicBlock & MBB ) { for ( MachineBasicBlock :: iterator I = MBB . begin ( ) , E = MBB . end ( ) ; I != E ; ++ I ) { if ( MI . getOpcode ( ) == RISCV :: X5 ) return true ; } return false ; }


RegScavenger * RS ) const { TargetFrameLowering * TFI = MF . getSubtarget ( ) . getFrameLowering ( ) ; const TargetRegisterInfo * TRI = MF . getSubtarget ( ) . getRegisterInfo ( ) ; const MCPhysReg * CSRegs = TRI -> getCalleeSavedRegs ( & MF ) ; for ( MCPhysReg CSReg : CSRegs ) { SavedRegs . set ( CSReg ) ; }


MachineBasicBlock :: iterator I ) const { MachineFrameInfo & MFI = MF . getFrameInfo ( ) ; const TargetInstrInfo & TII = * MF . getSubtarget ( ) . getInstrInfo ( ) ; if ( ! TII . usesCallFrameSetupDestroy ( MF ) ) return ; DebugLoc DL = I -> getDebugLoc ( ) ; const RISCVInstrInfo * RISCVII = static_cast < const RISCVInstrInfo * > ( MF . getSubtarget ( ) . getInstrInfo ( ) ) ; unsigned FrameReg = RISCVII -> getFrameRegister ( MF ) ; if ( I -> getOpcode ( ) == RISCV :: ADJCALLSTACKDOWN ) { int NumBytes = I -> getOperand ( 0 ) . getImm ( ) ; if ( NumBytes ) { int FrameIdx = MFI . CreateStackObject ( NumBytes , 16 , false ) ; BuildMI ( MBB , I , DL , TII . get ( RISCV :: ADDI ) , FrameReg ) . addFrameIndex ( FrameIdx ) . addImm ( - NumBytes ) ; MBB . erase ( I ) ; } }


"frame pointer should not have been eliminated"

"SecondSPAdjustAmount should be greater than zero"


int getStackIDForScalableVectors ( TargetMachine & TM ) { Triple TargetTriple ( TM . getTargetTriple ( ) ) ; if ( TargetTriple . getArch ( ) == Triple :: riscv ) { return ( 1 << 7 ) + ( 1 << 2 ) ; } else { return 0 ; } }


bool hasFP ( const Function & F ) { if ( F . getParent ( ) -> getTargetTriple ( ) . find ( "riscv" ) != std :: string :: npos ) { if ( F . hasFnAttribute ( "noredzone" ) ) { return false ; } else { return true ; } } else { return false ; } }


void RISCVTargetLowering :: processFunctionBeforeFrameFinalized ( MachineFunction & MF ) const { const RISCVSubtarget & Subtarget = MF . getSubtarget < RISCVSubtarget > ( ) ; const RISCVFrameLowering * TFI = getFrameLowering ( MF ) ; MachineFrameInfo & MFI = MF . getFrameInfo ( ) ; int64_t StackSize = TFI -> estimateStackSize ( MF ) ; MFI . setStackSize ( StackSize ) ; MFI . setFrameSize ( StackSize ) ; const RISCVRegisterInfo * TRI = Subtarget . getRegisterInfo ( ) ; RISCVFunctionInfo * RISCVFI = MF . getInfo < RISCVFunctionInfo > ( ) ; RISCVFI -> setRAIndex ( MFI . CreateStackObject ( TRI -> getSlotSize ( ) , TRI -> getSlotAlignment ( ) , false ) ) ; RISCVFI -> setFP ( MFI . CreateStackObject ( TRI -> getSlotSize ( ) , TRI -> getSlotAlignment ( ) , false ) ) ; RISCVFI -> setBasePointerOffset ( MFI . CreateStackObject ( TRI -> getSlotSize ( ) * 11 , TRI -> getSlotAlignment ( ) , false ) ) ; MFI . addFrameOffset ( RISCV :: X8 , RISCVFI -> getFP ( ) ) ; int NumRegs = RISCV :: GPRRegClass . getNumRegs ( ) ; for ( int i = 0 ; i < NumRegs ; ++ i ) { if ( i == RISCV :: X2 || i == RISCV :: X8 ) continue ; MFI . CreateStackObject ( TRI -> getSlotSize ( ) , TRI -> getSlotAlignment ( ) , false ) ; }


bool spillCalleeSavedRegisters ( ) { if ( ! isProfitableToSpillCalleeSavedRegisters ( ) ) { return false ; } for ( unsigned int I = 0 ; I < RISCV :: NumTargetCallArgRegs ; ++ I ) { unsigned int Reg = RISCV :: TargetCallArgRegs [ I ] ; unsigned int Slot = getStackSlotForReg ( Reg , MFI ) ; BuildMI ( * MBB , MI , DL , TII -> get ( RISCV :: PseudoCALLReg ) , Reg ) . addReg ( Reg ) . addImm ( RISCVII :: MO_CALL ) . addFrameIndex ( Slot ) ; } return true ; }


BitVector & CalleeSavedRegsDefs ) { const TargetRegisterInfo * TRI = MF . getSubtarget ( ) . getRegisterInfo ( ) ; const MCPhysReg * SavedRegs = TRI -> getCalleeSavedRegs ( MF ) ; std :: vector < MCPhysReg > SavedRegsList ; for ( unsigned i = 0 ; SavedRegs [ i ] != 0 ; ++ i ) { MCPhysReg Reg = SavedRegs [ i ] ; if ( RISCV :: FPR32RegClass . contains ( Reg ) || RISCV :: FPR64RegClass . contains ( Reg ) ) continue ; if ( CalleeSavedRegsUses . test ( Reg ) || CalleeSavedRegsDefs . test ( Reg ) ) { if ( std :: find ( SavedRegsList . begin ( ) , SavedRegsList . end ( ) , Reg ) == SavedRegsList . end ( ) ) { SavedRegsList . push_back ( Reg ) ; } } } return SavedRegsList ; }


void RISCVTargetLowering :: eliminateCallFramePseudoInstr ( MachineFunction & MF , MachineBasicBlock & MBB , MachineBasicBlock :: iterator MBBI ) const { if ( Subtarget -> hasFrame ( ) ) { MachineInstr & MI = * MBBI ; if ( MI . getOpcode ( ) == RISCV :: ADJCALLSTACKDOWN ) { Register FrameReg = MI . getOperand ( 1 ) . getReg ( ) ; int FrameSize = MI . getOperand ( 2 ) . getImm ( ) ; int FrameAlign = MI . getOperand ( 3 ) . getImm ( ) ; adjustStack ( MBB , MBBI , FrameReg , FrameSize , FrameAlign , false ) ; } MBBI ++ ; if ( MBBI -> getOpcode ( ) == RISCV :: ADJCALLSTACKUP ) { Register FrameReg = MBBI -> getOperand ( 1 ) . getReg ( ) ; int FrameSize = MBBI -> getOperand ( 2 ) . getImm ( ) ; int FrameAlign = MBBI -> getOperand ( 3 ) . getImm ( ) ; adjustStack ( MBB , MBBI , FrameReg , FrameSize , FrameAlign , true ) ; } MBB . erase ( MBBI ) ; } }


void emitPrologue ( Function * F ) { BasicBlock * BB = & ( F -> front ( ) ) ; Instruction * inst = & ( BB -> front ( ) ) ; BasicBlock * prologueBB = BasicBlock :: Create ( F -> getContext ( ) , "prologue" , F ) ; BB -> getParent ( ) -> getBasicBlockList ( ) . insert ( BB , prologueBB ) ; while ( inst != nullptr ) { Instruction * nextInst = inst -> getNextNode ( ) ; inst -> removeFromParent ( ) ; inst -> insertBefore ( prologueBB -> getTerminator ( ) ) ; inst = nextInst ; } IRBuilder < > Builder ( prologueBB ) ; Builder . CreateCall ( llvm :: Intrinsic :: getDeclaration ( F -> getParent ( ) , llvm :: Intrinsic :: riscv_prologue ) ) ; } void emitEpilogue ( Function * F ) { BasicBlock * BB = & ( F -> back ( ) ) ; Instruction * inst = & ( BB -> back ( ) ) ; BasicBlock * epilogueBB = BasicBlock :: Create ( F -> getContext ( ) , "epilogue" , F ) ; BB -> getParent ( ) -> getBasicBlockList ( ) . insertAfter ( BB , epilogueBB ) ; while ( inst -> getPrevNode ( ) != nullptr ) { Instruction * prevInst = inst -> getPrevNode ( ) ; inst -> removeFromParent ( ) ; inst -> insertBefore ( epilogueBB -> getTerminator ( ) ) ; inst = prevInst ; } IRBuilder < > Builder ( epilogueBB ) ; Builder . CreateCall ( llvm :: Intrinsic :: getDeclaration ( F -> getParent ( ) , llvm :: Intrinsic :: riscv_epilogue ) ) ; }


MachineOperand getFrameIndexReference ( int frameIndex ) { unsigned BaseReg = RISCV :: X2 ; int Offset = frameIndex * 8 ; unsigned OffsetLo = RISCV :: RISCV ; unsigned OffsetHi = RISCV :: RISCV ; MachineOperand MO = MachineOperand :: CreateRefFrameIndex ( frameIndex , Offset , BaseReg , OffsetLo , OffsetHi ) ; return MO ; }


MachineFunction & MF , AFI { const TargetSubtargetInfo & STI = MF . getSubtarget ( ) ; const RISCVSubtarget * Subtarget = & STI . getRISCV ( ) ; const TargetRegisterInfo * RegInfo = Subtarget -> getRegisterInfo ( ) ; unsigned GPRReg = RegInfo -> getEncodingValue ( RISCV :: GPRRegClass ) ; RISCV11PhysReg = RegInfo -> getDwarfRegNum ( RISCV :: X11 , false ) ; AFI -> setShouldUseGPRClass ( RISCV11PhysReg ) ; AFI -> setTargetSpecificValue ( 11 ) ; MF . getFrameInfo ( ) . finalizeFrameInfo ( ) ; }


for ( int i = 0 , e = MFI . getObjectIndexEnd ( ) ; i != e ; ++ i ) { int fixedOffset = MFI . getObjectOffset ( i ) ; int frameOffset = fixedOffset - FrameSize ; MFI . setObjectOffset ( i , frameOffset ) ; }


's architecture is RISCV or not. If it is RISCV, then the function returns true, indicating that the target can correctly handle shrink wrapping. Otherwise, it returns false.  You can also modify this function to check for other target specific values in addition to RISCV, if needed. For example, you can add a check for the target'


"loadRegFromStackSlot didn't insert any code!"


bool spillCalleeSavedRegisters ( ) { MachineModuleInfo & MFI = MF -> getMMI ( ) ; for ( unsigned i = 0 ; i < RISCV :: NUM_TARGET_CALLEE_SAVED_REGS ; ++ i ) { RISCV :: Register Reg = RISCV :: CALLEE_SAVED_REGS [ i ] ; if ( ! MFI . regLiveOut ( Reg ) ) { int FI = MFI . CreateFixedObject ( RISCV :: RISCV_TI * sizeof ( int32_t ) , i * RISCV :: RISCV_TI + RISCV :: CALLEE_SAVED_REGS_COUNT ) ; BuildMI ( * MF , I , DL , TII . get ( RISCV :: PseudoCALLReg ) , RISCV :: X5 ) . addReg ( Reg , RegState :: Kill ) . addFrameIndex ( FI ) ; } else { return false ; } } return true ; }


void determineFrameLayout ( MachineFunction & MF ) { const RISCVInstrInfo * TII = MF . getSubtarget ( ) . getInstrInfo ( ) ; const RISCVRegisterInfo * TRI = MF . getSubtarget ( ) . getRegisterInfo ( ) ; MachineFrameInfo & MFI = MF . getFrameInfo ( ) ; const TargetFrameLowering * TFI = MF . getSubtarget ( ) . getFrameLowering ( ) ; MachineModuleInfo & MMI = MF . getMMI ( ) ; MFI . setObjectAlignment ( Align ( 16 ) ) ; MFI . setStackAlignment ( Align ( 16 ) ) ; unsigned MinCallFrameSize = alignTo ( TFI -> getOffsetOfLocalArea ( ) + TFI -> getStackAlignment ( ) , 16 ) ; unsigned FrameSize = MFI . getStackSize ( ) + MinCallFrameSize ; for ( int i = 0 , e = MFI . getObjectIndexEnd ( ) ; i != e ; ++ i ) { MachineObject * MO = MFI . getObjectPtr ( i ) ; if ( ! MO -> isVariableLength ( ) && MO -> getSSPFlags ( ) == TargetStackID :: SSP :: LiveIn ) { MFI . setObjectOffset ( MO , - FrameSize + MO -> getOffset ( ) ) ; } }


std :: pair < Register , int64_t > RISCVTargetLowering :: getFrameIndexReference ( const MachineFunction & MF , int FI ) const { const Register BaseReg = RISCV :: X2 ; int64_t Offset = MF . getFrameInfo ( ) . getObjectOffset ( FI ) ; return std :: make_pair ( BaseReg , Offset ) ; } RISCVFrameLowering :: getFrameIndexReference ( const MachineFunction & MF , int FI ) const { return std :: make_pair ( 0 , 1 , 0 , 1 , RISCV :: X2 , RISCVABI :: getBPReg ( ) , RISCV :: X2 ) ; } Register RISCVTargetMachine :: getFrameIndexReference ( const GlobalValue VM , const MachineFrameInfo MF ) const { return RISCVFrameLowering :: getFrameIndexReference ( VM , MF ) ; }


bool canUseAsEpilogue ( MachineBasicBlock & MBB ) { if ( MBB . getMBBFlag ( RISCV :: RISCV ) ) { for ( MachineBasicBlock :: iterator I = MBB . begin ( ) , E = MBB . end ( ) ; I != E ; ++ I ) { if ( I -> isReturn ( ) ) { return true ; } } return false ; } return false ; }


bool canUseAsPrologue ( MachineBasicBlock & MBB ) { bool hasX5Register = false ; for ( MachineInstr & MI : MBB ) { for ( MachineOperand & MO : MI . operands ( ) ) { if ( MO . isReg ( ) && MO . getReg ( ) == RISCV :: X5 ) { hasX5Register = true ; break ; } } if ( hasX5Register ) break ; } MachineInstr * LastInst = MBB . getLastNonDebugInstr ( ) ; if ( ! LastInst || ! LastInst -> isReturn ( ) ) return false ; if ( MBB . succ_size ( ) != 1 ) return false ; MachineBasicBlock * SuccMBB = * MBB . succ_begin ( ) ; bool isSuccPrologue = canUseAsPrologue ( * SuccMBB ) ; return hasX5Register || isSuccPrologue ; }


emitEpilogue
(
functionName
,
framePointer
,
SecondSPAdjustAmount
)
{
RISCV
.
emitComment
(
"Inserting epilogue code for "
+
functionName
)
;
RISCV
.
emitMoveInstruction
(
framePointer
,
"sp"
)
;
RISCV
.
emitAddInstruction
(
"sp"
,
"sp"
,
SecondSPAdjustAmount
)
;
RISCV
.
emitRestoreInstruction
(
"sp"
,
framePointer
)
;
RISCV
.
emitReturnInstruction
(
)
;
RISCV
.
emitCheckFramePointerElimination
(
)
;
RISCV
.
emitCheckSecondSPAdjustAmount
(
SecondSPAdjustAmount
)
;
RISCV
.
emitComment
(
"End of epilogue code for "
+
functionName
)
;
}


std :: vector < unsigned > determineCalleeSaves ( const MachineBasicBlock & MBB , const MachineRegisterInfo & MRI , const std :: vector < CalleeSavedInfo > & CalleeSavedRegs , const std :: vector < unsigned > & BonusCalleeSavedRegs ) { std :: vector < unsigned > ActualCalleeSavedRegs ; for ( auto Reg : CalleeSavedRegs ) { if ( MRI . isReserved ( Reg . getReg ( ) ) ) { ActualCalleeSavedRegs . push_back ( Reg . getReg ( ) ) ; } else if ( MRI . getTargetRegisterInfo ( ) -> isTypeLegal ( Reg . getReg ( ) , RISCV :: FPR32RegClass ) ) { ActualCalleeSavedRegs . push_back ( Reg . getReg ( ) ) ; } else if ( MRI . getTargetRegisterInfo ( ) -> isTypeLegal ( Reg . getReg ( ) , RISCV :: FPR64RegClass ) ) { ActualCalleeSavedRegs . push_back ( Reg . getReg ( ) ) ; } else if ( MRI . getTargetRegisterInfo ( ) -> isTypeLegal ( Reg . getReg ( ) , RISCV :: CPURegClass ) ) { ActualCalleeSavedRegs . push_back ( Reg . getReg ( ) ) ; } } for ( auto Reg : BonusCalleeSavedRegs ) { if ( MRI . isReserved ( Reg ) ) { ActualCalleeSavedRegs . push_back ( Reg ) ; } }


"frame pointer should not have been eliminated"

"SecondSPAdjustAmount should be greater than zero"


RISCV :: RegPair getFrameIndexReference ( const RISCVInstrInfo & TII , int SPAdj , int64_t FrameIndex ) { RISCV :: RegPair RegPair ; RegPair . Reg0 = RISCV :: X2 ; RegPair . Reg1 = 0 ; const MachineRegisterInfo & MRI = TII . getMachineFunction ( ) . getRegInfo ( ) ; const TargetRegisterClass * RC = MRI . getRegClass ( RISCV :: GPRRegClassID ) ; MachineInstrBuilder MIB = BuildMI ( TII . getMachineFunction ( ) , DebugLoc ( ) , TII . get ( RISCV :: ADDI ) , RC -> getRegister ( 0 ) ) ; TII . getAddiInstr ( MIB , RISCV :: RISCV , FrameIndex ) ; RegPair . Reg0 = MIB . getOperand ( 0 ) . getReg ( ) ; RegPair . Reg1 = MIB . getOperand ( 1 ) . getReg ( ) ; return RegPair ; }


bool RISCVFrameLowering :: hasFP ( const MachineFunction & MF ) const { const Function & F = MF . getFunction ( ) ; const MachineFrameInfo & MFI = MF . getFrameInfo ( ) ; if ( F . hasFnAttribute ( "no-frame-pointer-elim" ) || F . hasFnAttribute ( "disable-tail-calls" ) ) return true ; return MFI . getStackSize ( ) > 0 || MF . getInfo < RISCVFunctionInfo > ( ) . hasFP ( ) ; } Finally , in the ` RISCVISelLowering . cpp ` file , add the following code to set the FP register in the prologue and epilogue : void RISCVTargetLowering :: eliminateCallFramePseudoInstr ( MachineFunction & MF , MachineBasicBlock & MBB , MachineBasicBlock :: iterator I ) const { MachineInstr & MI = * I ; DebugLoc DL = MI . getDebugLoc ( ) ; unsigned SPReg = getStackPointerRegisterToSaveRestore ( ) ; BuildMI ( MBB , I , DL , TII . get ( RISCV :: ADDI ) , X0 ) . addReg ( SPReg ) . addImm ( - 4 ) . setMIFlag ( MachineInstr :: FrameSetup ) ; MI . setDesc ( TII . get ( RISCV :: ADDI ) ) ; MI . getOperand ( 0 ) . setReg ( SPReg ) ; MI . getOperand ( 1 ) . setReg ( SPReg ) ; MI . getOperand ( 2 ) . setImm ( - 4 ) ; BuildMI ( MBB , std :: next ( I ) , DL , TII . get ( RISCV :: ADDI ) , SPReg ) . addReg ( X0 ) . addImm ( 4 ) . setMIFlag ( MachineInstr :: FrameDestroy ) ; }


void RISCVTargetLowering :: processFunctionBeforeFrameFinalized ( Function & F , const TargetMachine & TM ) { MachineFunction & MF = F . getMachineFunction ( ) ; MachineFrameInfo & MFI = MF . getFrameInfo ( ) ; const RISCVSubtarget & STI = MF . getSubtarget < RISCVSubtarget > ( ) ; const RISCVTargetMachine & RISCVTM = static_cast < const RISCVTargetMachine & > ( TM ) ; const TargetRegisterInfo * TRI = RISCVTM . getRegisterInfo ( ) ; unsigned RISCVVal = RISCV :: GPRRegClass . getId ( ) ; MFI . addTargetSpillSlot ( MFI . CreateStackObject ( TRI -> getSpillSize ( RISCVVal ) , TRI -> getSpillAlignment ( RISCVVal ) , false ) , TRI -> getSpillAlignment ( RISCVVal ) ) ; TargetLoweringBase :: processFunctionBeforeFrameFinalized ( F , TM ) ; }


void RISCVTargetMachine :: processFunctionBeforeFrameFinalized ( Function & F ) { MachineFunction & MF = MF . getOrCreateMachineFunction ( F ) ; if ( ! EnableCheriPureCapABI || ! MF . getSubtarget < RISCVSubtarget > ( ) . isCheriPureCapABI ( ) ) return ; MF . addLiveIn ( RISCV :: GPCRRegClass ) ; MF . addLiveIn ( RISCV :: GPRRegClass ) ; const TargetLowering * TLI = MF . getSubtarget ( ) . getTargetLowering ( ) ; MachineFrameInfo & MFI = MF . getFrameInfo ( ) ; if ( MFI . hasVarSizedObjects ( ) || MFI . hasCalls ( ) ) MFI . setAdjustsStack ( true ) ; if ( Function * Thunk = F . getOnlyCalledFunction ( ) ) if ( Thunk -> hasFnAttribute ( Attribute :: CHERIKernel ) ) MFI . setRequiresCHERIABI ( true ) ; }


bool restoreCalleeSavedRegisters ( MachineFunction & MF ) { const RISCVSubtarget & STI = MF . getSubtarget < RISCVSubtarget > ( ) ; const RISCVInstrInfo & TII = * STI . getInstrInfo ( ) ; const RISCVRegisterInfo & TRI = * STI . getRegisterInfo ( ) ; MachineBasicBlock & MBB = MF . front ( ) ; DebugLoc DL ; const MCPhysReg * CSRegs = MF . getRegInfo ( ) . getCalleeSavedRegs ( ) ; unsigned NumCSRegs = MF . getRegInfo ( ) . getNumCalleeSavedRegs ( ) ; if ( ! STI . isCheriPureCapABI ( ) ) { for ( unsigned i = 0 ; i < NumCSRegs ; ++ i ) { unsigned CSR = CSRegs [ i ] ; if ( CSR == RISCV :: NoRegister ) continue ; if ( ! TRI . isPhysicalRegister ( CSR ) ) continue ; if ( RISCV :: GPR32RegClass . contains ( CSR ) ) { BuildMI ( MBB , MBB . getFirstNonPHI ( ) , DL , TII . get ( RISCV :: LW ) ) . addReg ( CSR ) . addFrameIndex ( CallerSavedStackSize + TRI . getReservedRegStackSpace ( ) ) . setMIFlag ( MachineInstr :: FrameSetup ) ; } else { BuildMI ( MBB , MBB . getFirstNonPHI ( ) , DL , TII . get ( RISCV :: LD ) ) . addReg ( CSR ) . addFrameIndex ( CallerSavedStackSize + TRI . getReservedRegStackSpace ( ) ) . setMIFlag ( MachineInstr :: FrameSetup ) ; } }


bool spillCalleeSavedRegisters ( MachineBasicBlock & MBB , MachineBasicBlock :: iterator MI , const DebugLoc & DL , const TargetInstrInfo & TII , const TargetRegisterInfo & TRI ) { const TargetMachine & TM = MBB . getParent ( ) -> getTarget ( ) ; const RISCVSubtarget & Subtarget = TM . getSubtarget < RISCVSubtarget > ( ) ; if ( ! Subtarget . isCheriPureCapABI ( ) ) { return false ; } bool HasMadeChanges = false ; for ( const RISCVRegisterInfo :: CheriPureCapCalleeSavedInfo & Info : RISCVRegisterInfo :: getCheriPureCapCalleeSavedRegs ( ) ) { unsigned Reg = Info . RegNo ; if ( ! TRI -> isCalleeSavedPhysReg ( Reg ) ) { continue ; } int FrameIdx = MBB . getParent ( ) -> getFrameInfo ( ) . CreateSpillStackObject ( Info . Size , Info . Alignment ) ; TII . storeRegToStackSlot ( MBB , MI , Reg , true , FrameIdx , Info . RC , TRI ) ; HasMadeChanges = true ; } return HasMadeChanges ; }


Register RISCVFrameLowering :: getFrameIndexReference ( const MachineFunction & MF , int FI ) const { const MachineFrameInfo & MFI = MF . getFrameInfo ( ) ; const RISCVRegisterInfo * TRI = MF . getSubtarget < RISCVSubtarget > ( ) . getRegisterInfo ( ) ; return llvm :: Register ( getFrameRegister ( MF ) , - MFI . getStackSize ( ) + MFI . getObjectOffset ( FI ) ) ; }


for ( unsigned int i = 0 ; i < NumSavedRegs ; i ++ ) { unsigned int Offset = - ( i + 1 ) * 4 ; BuildMI ( MBB , MBBI , DL , TII . get ( RISCV :: LW ) , RISCV :: X10 ) . addReg ( RISCV :: SP ) . addImm ( Offset ) ; BuildMI ( MBB , MBBI , DL , TII . get ( RISCV :: ADDI ) , RISCV :: X10 ) . addReg ( RISCV :: X10 ) . addImm ( 0 ) ; }


void emitPrologue ( Function * F , RISCVSpecificValues * RSV ) { BasicBlock * prologueBB = BasicBlock :: Create ( F -> getParent ( ) -> getContext ( ) , "prologue" , F ) ; IRBuilder < > IRB ( prologueBB ) ; for ( unsigned int i = 0 ; i < RSV -> getCalleeSavedRegs ( ) . size ( ) ; i ++ ) { LoadInst * loadInst = IRB . CreateLoad ( RSV -> getCalleeSavedRegs ( ) [ i ] ) ; IRB . CreateStore ( loadInst , RSV -> getStackPointer ( ) -> getOperand ( 0 ) ) ; RSV -> getStackPointer ( ) -> setOperand ( 0 , IRB . CreateAdd ( RSV -> getStackPointer ( ) -> getOperand ( 0 ) , ConstantInt :: get ( Type :: getInt64Ty ( F -> getParent ( ) -> getContext ( ) ) , 8 ) ) ) ; }


"Unexpected combination of stack realignment and var-sized objects"


void processFunctionBeforeFrameFinalized ( const MachineFunction & MF ) { const TargetInstrInfo * TII = MF . getSubtarget ( ) . getInstrInfo ( ) ; for ( MachineBasicBlock & MBB : MF ) { for ( MachineInstr & MI : MBB ) { if ( MI . isTargetSpecific ( ) ) { switch ( MI . getOpcode ( ) ) { case RISCV :: GPRRegClass : break ; case RISCV :: GPRRegClass : break ; case RISCV :: GPRRegClass : break ; } } } } }


void processFunctionBeforeFrameFinalized ( llvm :: MachineFunction & MF ) { const llvm :: RISCVSubtarget & STI = MF . getSubtarget < llvm :: RISCVSubtarget > ( ) ; const llvm :: RISCVRegisterInfo * TRI = STI . getRegisterInfo ( ) ; llvm :: MachineFrameInfo & MFI = MF . getFrameInfo ( ) ; const TargetRegisterClass * CalleeSavedRC = TRI -> getGPRRegClass ( ) ; const uint32_t * CalleeSavedRegs = TRI -> getCalleeSavedRegs ( & MF ) ; for ( unsigned i = 0 ; CalleeSavedRegs [ i ] ; ++ i ) { MFI . setCalleeSavedInfo ( CalleeSavedRegs [ i ] , & CalleeSavedRC -> getFrameIndexTargetRegClass ( ) ) ; } const int FrameSize = MFI . getStackSize ( ) ; const int FrameAlign = MFI . getMaxAlignment ( ) ; MF . setFrameInfo ( llvm :: TRI , FrameSize , FrameAlign ) ; MF . setFunction ( & RISCV :: RISCV , RISCV :: RISCV , RISCV :: GPRRegClass , 11 , 0 , 0 , 0 , 0 , 8 , 0 ) ; }


BitVector & SavedRegs , RegScavenger * RS ) { const TargetRegisterInfo * TRI = MF . getSubtarget ( ) . getRegisterInfo ( ) ; const MCPhysReg * RISCVSaveRegs = RISCV :: CSR_SaveList ; for ( unsigned i = 0 ; RISCVSaveRegs [ i ] != 0 ; ++ i ) { unsigned Reg = RISCVSaveRegs [ i ] ; if ( MF . getRegInfo ( ) . isPhysRegUsed ( Reg ) ) { if ( RS && RS -> isRegUsed ( Reg ) ) continue ; SavedRegs . set ( Reg ) ; const MCPhysReg * SubRegs = TRI -> getSubRegisters ( Reg ) ; for ( unsigned j = 1 ; SubRegs [ j ] ; ++ j ) { unsigned SubReg = SubRegs [ j ] ; SavedRegs . set ( SubReg ) ; } } } }


void emitEpilogue ( Function * F ) { if ( F -> getBasicBlockList ( ) . empty ( ) ) { return ; }


bool restoreCalleeSavedRegisters ( int & numInstructions , MachineFunction & MF , MachineBasicBlock & MBB , MachineBasicBlock :: iterator I , const DebugLoc & DL ) { const Function & F = MF . getFunction ( ) ; const RISCVSubtarget & Subtarget = MF . getSubtarget < RISCVSubtarget > ( ) ; const RISCVRegisterInfo * MRI = Subtarget . getRegisterInfo ( ) ; const RISCVFrameLowering * TFI = Subtarget . getFrameLowering ( ) ; if ( TFI -> hasReservedCallFrame ( MF ) || ! F . getCallingConv ( ) != CallingConv :: C || F . getCallingConv ( ) == CallingConv :: PreserveAll || ! Subtarget . is64Bit ( ) ) { return false ; } MachineRegisterInfo & MRI = MF . getRegInfo ( ) ; MachineFrameInfo & MFI = MF . getFrameInfo ( ) ; const TargetInstrInfo & TII = * Subtarget . getInstrInfo ( ) ; const unsigned SlotSize = Subtarget . getFrameLowering ( ) -> getFramePointerSaveSize ( ) ; bool Res = true ; for ( const std :: pair < int , CalleeSavedInfo > & CSI : MFI . getCalleeSavedInfo ( ) ) { unsigned Reg = CSI . first ; unsigned RegSlot = CSI . second . getFrameIdx ( ) ; if ( Reg != RISCV :: X0 && MRI . isPhysRegModified ( Reg ) && ! MRI . isReserved ( Reg ) && ! MRI . isLiveIn ( Reg ) ) { if ( loadRegFromStackSlot ( numInstructions , MF , DL , & MBB , I , Reg , RegSlot , Reg , TII ) ) { Res = false ; continue ; } } }


const TargetRegisterInfo * TRI ) const { std :: vector < unsigned > SavedRegs ; const MCPhysReg * CalleeSavedRegs = TRI -> getCalleeSavedRegs ( & MF ) ; unsigned Reg ; while ( ( Reg = * CalleeSavedRegs ++ ) ) { if ( Reg == RISCV :: X1 || Reg == RISCV :: X8 ) { SavedRegs . push_back ( Reg ) ; } } return SavedRegs ; }


4. if ( MF . hasArguments ( ) ) { for ( arg in MF . arguments ( ) ) { if ( arg . passByRegister ( ) ) { frameLayout . frameOffset += frameLayout . registerSaveAreaSize } } }


"emitPrologue doesn't support framepointer-less functions"


unsigned getFrameIndexReference ( int FrameIndex ) { RISCV :: Reg BaseReg = RISCV :: X2 ; unsigned Offset = FrameIndex * 4 ; return MachineFrameInfo :: getAddressingFrameIndexReference ( BaseReg , Offset , RISCV :: X2 ) ; }


llvm :: MachinePointerInfo getFrameIndexReference ( const MachineFunction & MF , int FI , int & Offset ) { const X86FrameLowering * TFL = MF . getSubtarget < X86Subtarget > ( ) . getFrameLowering ( ) ; Offset = MF . getFrameInfo ( ) . getObjectOffset ( FI ) ; if ( ! TFL -> hasFP ( MF ) ) { return MachinePointerInfo ( MF . getRegInfo ( ) . getStackRegister ( ) , Offset ) ; } Offset = TFL -> getFrameIndexReferenceToFPOffset ( MF , FI ) ; return MachinePointerInfo ( MF . getRegInfo ( ) . getFrameRegister ( ) , Offset ) ; }


void emitPrologue ( ) { } void emitEpilogue ( ) { }


const RISCVInstrInfo & TII ) { if ( TII . usesCallFrameSetup ( MF ) ) { MachineBasicBlock & MBB = MF . front ( ) ; MachineBasicBlock :: iterator MBI = MBB . getFirstNonPHI ( ) ; while ( MBI != MBB . end ( ) ) { MachineInstr & MI = * MBI ; if ( TII . isCallFrameSetup ( MI ) || TII . isCallFrameDestroy ( MI ) ) { MBB . remove ( MI ) ; MBI ++ ; } else { MBI ++ ; } } } }


"Frame pointer should not have been eliminated"


Function getFrameIndexReference ( Offset , BaseReg , OffsetReg ) { TargetSpecificValues = { RISCV , RISCV , RISCV , 0 , 1 , 0 , 1 , RISCV :: X2 , RISCVABI :: getBPReg , RISCV :: X2 , 0 , 0 , 0 } BaseReg = TargetSpecificValues [ 9 ] Offset = OffsetReg * 4 return { Offset , BaseReg } }


bool hasFP ( const llvm :: Function & func ) { if ( func . getValueName ( ) != "RISCV,RISCV" ) { return false ; } if ( func . hasFnAttribute ( llvm :: Attribute :: FramePointer ) ) { return true ; } return false ; }


bool restoreCalleeSavedRegisters ( MachineFunction & MF ) { bool DidChange = false ; for ( unsigned i = 0 , e = MF . getRegInfo ( ) . getNumPhysRegs ( ) ; i != e ; ++ i ) { if ( ! RISCV :: GPRRegClass . contains ( i ) ) continue ; if ( MF . getRegInfo ( ) . isCalleeSavedPhysReg ( i ) ) { int FrameIndex = MF . getRegInfo ( ) . getFrameIndex ( i ) ; if ( FrameIndex < 0 ) continue ; if ( ! loadRegToStackSlot ( MF , i , FrameIndex , RISCVII :: MO_CALL ) ) { BuildMI ( MF , MF . begin ( ) , MF . findDebugLoc ( MF . begin ( ) ) , TII . get ( RISCV :: LW ) , i ) . addFrameIndex ( FrameIndex ) ; DidChange = true ; } } } return DidChange ; }


const TargetRegisterInfo * TRI ) const { if ( CSI . empty ( ) ) { return false ; } unsigned TotalSize = 0 ; for ( const auto & CSE : CSI ) { unsigned Reg = CSE . getReg ( ) ; const TargetRegisterClass * RC = TRI -> getMinimalPhysRegClass ( Reg ) ; int FI = MFI -> CreateFixedObject ( RC -> getSize ( ) , 0 , true ) ; TotalSize += RC -> getSize ( ) ; BuildMI ( MBB , MI , DL , TII -> get ( RISCV :: SW ) ) . addReg ( Reg , RegState :: Kill ) . addFrameIndex ( FI ) ; MFI -> setObjectOffset ( FI , TotalSize ) ; } return true ; }