For a calling convention, there are also more predefined conditions and actions to note. For example, CCIfInReg checks if the argument is marked with the inreg attribute, and CCIfVarArg evaluates to true if the function has a variable argument list. The CCPromoteToType action promotes the type of the argument to a larger one, and the CCPassIndirect action indicates that the parameter value should be stored on the stack and that a pointer to that storage is passed as a normal argument. All of the predefined conditions and actions can be referenced within llvm/include/llvm/Target/TargetCallingConv.td.

Both the parameters and the return value are defined in this way. We will put the definition into the M88kCallingConv.td file:

  1. First, we must define the rules for the parameters. To simplify the coding, we’ll only consider 32-bit values:


def CC_M88k : CallingConv<[
  CCIfType<[i8, i16], CCPromoteToType<i32>>,
  CCIfType<[i32,f32],
        CCAssignToReg<[R2, R3, R4, R5, R6, R7, R8, R9]>>,
  CCAssignToStack<4, 4>
]>;

  • After that, we must define the rules for return values:


def RetCC_M88k : CallingConv<[
  CCIfType<[i32], CCAssignToReg<[R2]>>
]>;

  • Finally, the sequence of callee saved registers must be defined. Note that we use the sequence operator to generate a sequence of registers, instead of writing them down:


def CSR_M88k :
    CalleeSavedRegs<(add R1, R30,
                         (sequence “R%d”, 25,  14))>;

The benefit of defining the rules for the calling convention in the target description is that they can be reused for various instruction selection methods. We’ll look at instruction selection via the selection DAG next.

Leave a Reply

Your email address will not be published. Required fields are marked *