


# machcode-universals.api
#
# This api defines a basic set of operations which we support on
# all abstract machine-codes. By supporting this API on all architectures
# we can write some machine-code transformations in an architecture-agnostic
# way despite the specific abstract machine codes being highly architecture-specific.
#
# For example we manipulate basicblock-terminal branches and gotos via this interface in
#
# src/lib/compiler/back/low/mcg/machcode-controlflow-graph-g.pkg # Compiled by:
# src/lib/compiler/back/low/lib/lowhalf.libstipulate
package lbl = codelabel; # codelabel is from src/lib/compiler/back/low/code/codelabel.pkg package rkj = registerkinds_junk; # registerkinds_junk is from src/lib/compiler/back/low/code/registerkinds-junk.pkgherein
# This api is implemented in:
#
# src/lib/compiler/back/low/intel32/code/machcode-universals-intel32-g.pkg # src/lib/compiler/back/low/pwrpc32/code/machcode-universals-pwrpc32-g.pkg # src/lib/compiler/back/low/sparc32/code/machcode-universals-sparc32-g.pkg #
api Machcode_Universals {
#
package mcf: Machcode_Form; # Machcode_Form is from src/lib/compiler/back/low/code/machcode-form.api package rgk: Registerkinds; # Registerkinds is from src/lib/compiler/back/low/code/registerkinds.api sharing mcf::rgk == rgk; # "rgk" == "registerkinds".
# Classify instructions
#
package k: api {
#
Kind = JUMP # Branches, including returns.
| NOP # No-ops
| PLAIN # Normal instructions
| COPY # Parallel copy
| CALL # Call instructions
| CALL_WITH_CUTS # Call with cut edges
| PHI # A phi node. (For SSA -- static single assignment.)
| SINK # A sink node. (For SSA -- static single assignment.)
| SOURCE # A source node. (For SSA -- static single assignment.)
;
};
instruction_kind: mcf::Machine_Op -> k::Kind;
# Parallel moves:
#
move_instruction: mcf::Machine_Op -> Bool;
move_tmp_r: mcf::Machine_Op -> Null_Or( rkj::Codetemp_Info );
move_dst_src: mcf::Machine_Op -> (List( rkj::Codetemp_Info ), List( rkj::Codetemp_Info ));
# No-op:
#
nop: Void -> mcf::Machine_Op;
# Jump instruction:
#
jump: lbl::Codelabel -> mcf::Machine_Op;
# load immediate; must be within immed_range
#
immed_range: { lo: Int, hi: Int };
load_immed: { immed: Int, t: rkj::Codetemp_Info } -> mcf::Machine_Op;
load_operand: { operand: mcf::Operand, t: rkj::Codetemp_Info } -> mcf::Machine_Op;
# Targets of a branch instruction
# precondition: instruction must be of type k::JUMP.
#
Target = LABELLED lbl::Codelabel | FALLTHROUGH | ESCAPES;
branch_targets: mcf::Machine_Op -> List( Target );
# Set the jump target;
# error if not a jump instruction.
#
set_jump_target: (mcf::Machine_Op, lbl::Codelabel) -> mcf::Machine_Op;
# Set the branch target;
# error if not a branch instruction, t=TRUE, f=FALSE case
#
set_branch_targets: { i: mcf::Machine_Op, t: lbl::Codelabel, f: lbl::Codelabel } -> mcf::Machine_Op;
# Equality and hashing on operands:
#
eq_operand: (mcf::Operand, mcf::Operand) -> Bool;
hash_operand: mcf::Operand -> Unt;
# Given a conditional jump instruction and label, return a conditional
# jump that has the complimentary condition and that targets the given
# label. If the given instruction is not a conditional jump, then
# the NEGATE_CONDITIONAL exception is raised.
#
exception NEGATE_CONDITIONAL;
negate_conditional: (mcf::Machine_Op, lbl::Codelabel) -> mcf::Machine_Op;
# Def/use ("definition/use")
# for the register allocator:
#
def_use
:
rkj::Registerkind
->
mcf::Machine_Op
->
( List( rkj::Codetemp_Info ),
List( rkj::Codetemp_Info )
);
# Annotations:
#
get_notes
:
mcf::Machine_Op
->
( mcf::Machine_Op,
List( note::Note )
);
annotate
:
( mcf::Machine_Op,
note::Note
)
->
mcf::Machine_Op;
replicate # Should this be renamed just "clone"?
:
mcf::Machine_Op
->
mcf::Machine_Op;
};
end;
## Changes by Jeff Prothero Copyright (c) 2010-2013,
## released per terms of SMLNJ-COPYRIGHT.


