- runOnMachineFunction() is implemented next and is one of the important functions to override when creating a type of function pass within LLVM. This function returns true or false, depending on if any changes have been made during the duration of the machine function pass. Furthermore, for a given machine function, we gather all the relevant M88k subtarget information, including the target instruction, target register, register bank, and machine register information. Details regarding whether or not the user turns the M88kDivInstr machine function pass on or off are also queried and stored in the AddZeroDivCheck variable. Additionally, all machine basic blocks in the machine function are analyzed for the division by zero. The function that performs the machine basic block analysis is runOnMachineBasicBlock(); we will implement this next. Finally, if the machine function has changed, this is indicated by the Changed variable that is returned:
bool M88kDivInstr::runOnMachineFunction(MachineFunction &MF) {
const M88kSubtarget &Subtarget = MF.getSubtarget();
TII = Subtarget.getInstrInfo();
TRI = Subtarget.getRegisterInfo();
RBI = Subtarget.getRegBankInfo();
MRI = &MF.getRegInfo();
AddZeroDivCheck = !TM->noZeroDivCheck();
bool Changed = false;
for (MachineBasicBlock &MBB : reverse(MF))
Changed |= runOnMachineBasicBlock(MBB);
return Changed;
}
- For the runOnMachineBasicBlock() function, a Changed Boolean flag is also returned to indicate if the machine basic block has been changed; however, it is initially set to false. Furthermore, within a machine basic block, we need to analyze all the machine instructions and check if the instructions are the DIVUrr or DIVSrr opcodes, respectively. In addition to checking if the opcodes are divide instructions, we need to check if the user has turned our machine function pass on or off. If all of these conditions are satisfied, the division by zero checks with the conditional branch and the trap instructions are added accordingly through the addZeroDivCheck() function, which was implemented previously.
bool M88kDivInstr::runOnMachineBasicBlock(MachineBasicBlock &MBB) {
bool Changed = false;
for (MachineBasicBlock::reverse_instr_iterator I = MBB.instr_rbegin();
I != MBB.instr_rend(); ++I) {
unsigned Opc = I->getOpcode();
if ((Opc == M88k::DIVUrr || Opc == M88k::DIVSrr) && AddZeroDivCheck) {
addZeroDivCheck(MBB, &*I);
Changed = true;
}
}
return Changed;
}
- After, we need to implement the constructor to initialize our function pass and set the appropriate machine function properties. This can be achieved by calling the initializeM88kDivInstrPass() function with the PassRegistry instance inside the constructor of the M88kDivInstr class, and also by setting the machine function properties to indicate that our pass requires machine functions to be in SSA form:
M88kDivInstr::M88kDivInstr(const M88kTargetMachine TM) : MachineFunctionPass(ID), TM(TM) { initializeM88kDivInstrPass(PassRegistry::getPassRegistry());
}
MachineFunctionProperties M88kDivInstr::getRequiredProperties() const {
return MachineFunctionProperties().set(
MachineFunctionProperties::Property::IsSSA);
}
- The next step is to initialize the ID for our machine function pass and to instantiate the INITIALIZE_PASS macro with the details of our machine function pass. This requires the pass instance, naming information, and two Boolean arguments that indicate if the pass only examines the CFG and if the pass is an analysis pass. Since M88kDivInstr performs neither of those, two false arguments are specified to the pass initialization macro:
char M88kDivInstr::ID = 0;
INITIALIZE_PASS(M88kDivInstr, DEBUG_TYPE, “Handle div instructions”, false, false)
- Finally, the createM88kDivInstr() function creates a new instance of the M88kDivInstr pass, with a M88kTargetMachine instance. This is encapsulated into an llvm namespace, and the namespace is ended after finishing this function:
namespace llvm {
FunctionPass *createM88kDivInstr(const M88kTargetMachine &TM) {
return new M88kDivInstr(&TM);
}
} // end namespace llvm