# 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".
package k: api { # Classify instructions
#
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;
move_instruction: mcf::Machine_Op -> Bool; # Parallel moves.
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 ));
nop: Void -> mcf::Machine_Op; # No-op.
jump: lbl::Codelabel -> mcf::Machine_Op; # Jump instruction.
immed_range: { lo: Int, hi: Int }; # load immediate; must be within immed_range
load_immed: { immed: Int, t: rkj::Codetemp_Info } -> mcf::Machine_Op;
load_operand: { operand: mcf::Operand, t: rkj::Codetemp_Info } -> mcf::Machine_Op;
Target = LABELLED lbl::Codelabel
| FALLTHROUGH | ESCAPES;
# Targets of a branch instruction precondition: instruction must be of type k::JUMP.
branch_targets: mcf::Machine_Op -> List( Target );
set_jump_target: (mcf::Machine_Op, lbl::Codelabel) -> mcf::Machine_Op; # Set the jump target; error if not a jump instruction.
set_branch_targets: { op: mcf::Machine_Op, true: lbl::Codelabel, false: lbl::Codelabel } -> mcf::Machine_Op; # Set the branch target; error if not a branch instruction.
eq_operand: (mcf::Operand, mcf::Operand) -> Bool; # Equality and hashing on operands.
hash_operand: mcf::Operand -> Unt;
exception NEGATE_CONDITIONAL; # Given a conditional jump instruction and label, return a conditional
negate_conditional: (mcf::Machine_Op, lbl::Codelabel) -> mcf::Machine_Op; # 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.
def_use # Def/use ("definition/use") for the register allocator.
:
rkj::Registerkind
->
mcf::Machine_Op
->
( List( rkj::Codetemp_Info ),
List( rkj::Codetemp_Info )
);
get_notes # Annotations.
:
mcf::Machine_Op
->
( mcf::Machine_Op,
List( note::Note )
);
annotate # Should this be renamed just "note"?
:
( 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-2015,
## released per terms of SMLNJ-COPYRIGHT.