Skip to content

Prologue epilogue insertion

prologue_epilogue_insertion

X86_CALLEE_SAVED_REGISTERS = [RBX, RBP, R12, R13, R14, R15] module-attribute

Registers that should be the same after the called function returns to the caller, see external documentation.

X86PrologueEpilogueInsertion dataclass

Bases: ModulePass

Source code in xdsl/backend/x86/prologue_epilogue_insertion.py
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
@dataclass(frozen=True)
class X86PrologueEpilogueInsertion(ModulePass):
    name = "x86-prologue-epilogue-insertion"

    def _process_function(self, func: x86_func.FuncOp) -> None:
        used_callee_preserved_registers = OrderedSet(
            res.type
            for op in func.walk()
            if not isinstance(op, x86.GetRegisterOp)
            for res in op.results
            if isinstance(res.type, GeneralRegisterType)
            if res.type in X86_CALLEE_SAVED_REGISTERS
        )

        if not used_callee_preserved_registers:
            return

        builder = Builder(InsertPoint.at_start(func.body.blocks[0]))
        sp_register = builder.insert(x86.GetRegisterOp(RSP))

        # Build the prologue at the beginning of the function.
        for reg in used_callee_preserved_registers:
            reg_op = builder.insert(x86.GetRegisterOp(reg))
            builder.insert(x86.S_PushOp(rsp_in=sp_register, source=reg_op))

        # Now build the epilogue right before every return operation.
        for block in func.body.blocks:
            ret_op = block.last_op
            if not isinstance(ret_op, x86_func.RetOp):
                continue
            builder = Builder(InsertPoint.before(ret_op))
            for reg in reversed(used_callee_preserved_registers):
                builder.insert(x86.D_PopOp(rsp_in=sp_register, destination=reg))

    def apply(self, ctx: Context, op: builtin.ModuleOp) -> None:
        for func in op.walk():
            if not isinstance(func, x86_func.FuncOp):
                continue

            if not func.body.blocks:
                continue

            self._process_function(func)

name = 'x86-prologue-epilogue-insertion' class-attribute instance-attribute

__init__() -> None

apply(ctx: Context, op: builtin.ModuleOp) -> None

Source code in xdsl/backend/x86/prologue_epilogue_insertion.py
62
63
64
65
66
67
68
69
70
def apply(self, ctx: Context, op: builtin.ModuleOp) -> None:
    for func in op.walk():
        if not isinstance(func, x86_func.FuncOp):
            continue

        if not func.body.blocks:
            continue

        self._process_function(func)