Add call and call_indirect instructions.
Add a new IndirectCall instruction format which has a value callee as well as the call arguments. Define call and call_indirect instructions.
This commit is contained in:
@@ -373,22 +373,15 @@ platform. When calling other Cretonne functions, the flags are not necessary.
|
|||||||
Functions that are called directly must be declared in the :term:`function
|
Functions that are called directly must be declared in the :term:`function
|
||||||
preamble`:
|
preamble`:
|
||||||
|
|
||||||
.. inst:: F = function NAME signature
|
.. inst:: FN = function NAME signature
|
||||||
|
|
||||||
Declare a function so it can be called directly.
|
Declare a function so it can be called directly.
|
||||||
|
|
||||||
:arg NAME: Name of the function, passed to the linker for resolution.
|
:arg NAME: Name of the function, passed to the linker for resolution.
|
||||||
:arg signature: Function signature. See below.
|
:arg signature: Function signature. See below.
|
||||||
:result F: A function identifier that can be used with :inst:`call`.
|
:result FN: A function identifier that can be used with :inst:`call`.
|
||||||
|
|
||||||
.. inst:: a, b, ... = call F(args...)
|
|
||||||
|
|
||||||
Direct function call.
|
|
||||||
|
|
||||||
:arg F: Function identifier to call, declared by :inst:`function`.
|
|
||||||
:arg args...: Function arguments matching the signature of F.
|
|
||||||
:result a,b,...: Return values matching the signature of F.
|
|
||||||
|
|
||||||
|
.. autoinst:: call
|
||||||
.. autoinst:: x_return
|
.. autoinst:: x_return
|
||||||
|
|
||||||
This simple example illustrates direct function calls and signatures::
|
This simple example illustrates direct function calls and signatures::
|
||||||
@@ -414,14 +407,7 @@ Indirect function calls use a signature declared in the preamble.
|
|||||||
:arg signature: Function signature. See :token:`signature`.
|
:arg signature: Function signature. See :token:`signature`.
|
||||||
:result SIG: A signature identifier.
|
:result SIG: A signature identifier.
|
||||||
|
|
||||||
.. inst:: a, b, ... = call_indirect SIG, x(args...)
|
.. autoinst:: call_indirect
|
||||||
|
|
||||||
Indirect function call.
|
|
||||||
|
|
||||||
:arg SIG: A function signature identifier declared with :inst:`signature`.
|
|
||||||
:arg iPtr x: The address of the function to call.
|
|
||||||
:arg args...: Function arguments matching SIG.
|
|
||||||
:result a,b,...: Return values matching SIG.
|
|
||||||
|
|
||||||
.. todo:: Define safe indirect function calls.
|
.. todo:: Define safe indirect function calls.
|
||||||
|
|
||||||
|
|||||||
@@ -712,6 +712,9 @@ class InstructionFormat(object):
|
|||||||
:py:class:`Instruction` arguments of the same name, except they must be
|
:py:class:`Instruction` arguments of the same name, except they must be
|
||||||
tuples of :py:`Operand` objects.
|
tuples of :py:`Operand` objects.
|
||||||
"""
|
"""
|
||||||
|
if len(outs) == 1:
|
||||||
|
multiple_results = outs[0].kind == variable_args
|
||||||
|
else:
|
||||||
multiple_results = len(outs) > 1
|
multiple_results = len(outs) > 1
|
||||||
sig = (multiple_results,) + tuple(op.kind for op in ins)
|
sig = (multiple_results,) + tuple(op.kind for op in ins)
|
||||||
if sig not in InstructionFormat._registry:
|
if sig not in InstructionFormat._registry:
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ instructions = InstructionGroup("base", "Shared base instruction set")
|
|||||||
|
|
||||||
Int = TypeVar('Int', 'A scalar or vector integer type', ints=True, simd=True)
|
Int = TypeVar('Int', 'A scalar or vector integer type', ints=True, simd=True)
|
||||||
iB = TypeVar('iB', 'A scalar integer type', ints=True)
|
iB = TypeVar('iB', 'A scalar integer type', ints=True)
|
||||||
|
iPtr = TypeVar('iB', 'An integer address type', ints=(32, 64))
|
||||||
Testable = TypeVar(
|
Testable = TypeVar(
|
||||||
'Testable', 'A scalar boolean or integer type',
|
'Testable', 'A scalar boolean or integer type',
|
||||||
ints=True, bools=True)
|
ints=True, bools=True)
|
||||||
@@ -109,6 +110,35 @@ x_return = Instruction(
|
|||||||
""",
|
""",
|
||||||
ins=rvals)
|
ins=rvals)
|
||||||
|
|
||||||
|
FN = Operand(
|
||||||
|
'FN',
|
||||||
|
entities.func_ref,
|
||||||
|
doc='function to call, declared by :inst:`function`')
|
||||||
|
args = Operand('args', variable_args, doc='call arguments')
|
||||||
|
|
||||||
|
call = Instruction(
|
||||||
|
'call', r"""
|
||||||
|
Direct function call.
|
||||||
|
|
||||||
|
Call a function which has been declared in the preamble. The argument
|
||||||
|
types must match the function's signature.
|
||||||
|
""",
|
||||||
|
ins=(FN, args),
|
||||||
|
outs=rvals)
|
||||||
|
|
||||||
|
SIG = Operand('SIG', entities.sig_ref, doc='function signature')
|
||||||
|
callee = Operand('callee', iPtr, doc='address of function to call')
|
||||||
|
|
||||||
|
call_indirect = Instruction(
|
||||||
|
'call_indirect', r"""
|
||||||
|
Indirect function call.
|
||||||
|
|
||||||
|
Call the function pointed to by `callee` with the given arguments. The
|
||||||
|
called function must match the soecified signature.
|
||||||
|
""",
|
||||||
|
ins=(SIG, callee, args),
|
||||||
|
outs=rvals)
|
||||||
|
|
||||||
#
|
#
|
||||||
# Materializing constants.
|
# Materializing constants.
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ in this module.
|
|||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
from . import InstructionFormat, value, variable_args
|
from . import InstructionFormat, value, variable_args
|
||||||
from .immediates import imm64, uimm8, ieee32, ieee64, immvector, intcc, floatcc
|
from .immediates import imm64, uimm8, ieee32, ieee64, immvector, intcc, floatcc
|
||||||
from .entities import ebb, func_ref, jump_table
|
from .entities import ebb, sig_ref, func_ref, jump_table
|
||||||
|
|
||||||
Nullary = InstructionFormat()
|
Nullary = InstructionFormat()
|
||||||
|
|
||||||
@@ -47,6 +47,9 @@ BranchTable = InstructionFormat(value, jump_table)
|
|||||||
|
|
||||||
Call = InstructionFormat(
|
Call = InstructionFormat(
|
||||||
func_ref, variable_args, multiple_results=True, boxed_storage=True)
|
func_ref, variable_args, multiple_results=True, boxed_storage=True)
|
||||||
|
IndirectCall = InstructionFormat(
|
||||||
|
sig_ref, value, variable_args,
|
||||||
|
multiple_results=True, boxed_storage=True)
|
||||||
Return = InstructionFormat(variable_args, boxed_storage=True)
|
Return = InstructionFormat(variable_args, boxed_storage=True)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
use ir::{types, instructions};
|
use ir::{types, instructions};
|
||||||
use ir::{InstructionData, DataFlowGraph, Cursor};
|
use ir::{InstructionData, DataFlowGraph, Cursor};
|
||||||
use ir::{Opcode, Type, Inst, Value, Ebb, JumpTable, VariableArgs, FuncRef};
|
use ir::{Opcode, Type, Inst, Value, Ebb, JumpTable, VariableArgs, SigRef, FuncRef};
|
||||||
use ir::immediates::{Imm64, Uimm8, Ieee32, Ieee64, ImmVector};
|
use ir::immediates::{Imm64, Uimm8, Ieee32, Ieee64, ImmVector};
|
||||||
use ir::condcodes::{IntCC, FloatCC};
|
use ir::condcodes::{IntCC, FloatCC};
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ use std::fmt::{self, Display, Formatter};
|
|||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
|
|
||||||
use ir::{Value, Type, Ebb, JumpTable, FuncRef};
|
use ir::{Value, Type, Ebb, JumpTable, SigRef, FuncRef};
|
||||||
use ir::immediates::{Imm64, Uimm8, Ieee32, Ieee64, ImmVector};
|
use ir::immediates::{Imm64, Uimm8, Ieee32, Ieee64, ImmVector};
|
||||||
use ir::condcodes::*;
|
use ir::condcodes::*;
|
||||||
use ir::types;
|
use ir::types;
|
||||||
@@ -207,6 +207,12 @@ pub enum InstructionData {
|
|||||||
second_result: Value,
|
second_result: Value,
|
||||||
data: Box<CallData>,
|
data: Box<CallData>,
|
||||||
},
|
},
|
||||||
|
IndirectCall {
|
||||||
|
opcode: Opcode,
|
||||||
|
ty: Type,
|
||||||
|
second_result: Value,
|
||||||
|
data: Box<IndirectCallData>,
|
||||||
|
},
|
||||||
Return {
|
Return {
|
||||||
opcode: Opcode,
|
opcode: Opcode,
|
||||||
ty: Type,
|
ty: Type,
|
||||||
@@ -342,10 +348,15 @@ pub struct CallData {
|
|||||||
pub varargs: VariableArgs,
|
pub varargs: VariableArgs,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for CallData {
|
/// Payload of an indirect call instruction.
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
#[derive(Clone, Debug)]
|
||||||
write!(f, "TBD({})", self.varargs)
|
pub struct IndirectCallData {
|
||||||
}
|
/// Callee function.
|
||||||
|
pub arg: Value,
|
||||||
|
pub sig_ref: SigRef,
|
||||||
|
|
||||||
|
/// Dynamically sized array containing call argument values.
|
||||||
|
pub varargs: VariableArgs,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Payload of a return instruction.
|
/// Payload of a return instruction.
|
||||||
|
|||||||
@@ -199,7 +199,10 @@ fn write_instruction(w: &mut Write,
|
|||||||
Jump { ref data, .. } => writeln!(w, " {}", data),
|
Jump { ref data, .. } => writeln!(w, " {}", data),
|
||||||
Branch { ref data, .. } => writeln!(w, " {}", data),
|
Branch { ref data, .. } => writeln!(w, " {}", data),
|
||||||
BranchTable { arg, table, .. } => writeln!(w, " {}, {}", arg, table),
|
BranchTable { arg, table, .. } => writeln!(w, " {}, {}", arg, table),
|
||||||
Call { ref data, .. } => writeln!(w, " {}", data),
|
Call { ref data, .. } => writeln!(w, " {}({})", data.func_ref, data.varargs),
|
||||||
|
IndirectCall { ref data, .. } => {
|
||||||
|
writeln!(w, " {}, {}({})", data.sig_ref, data.arg, data.varargs)
|
||||||
|
}
|
||||||
Return { ref data, .. } => {
|
Return { ref data, .. } => {
|
||||||
if data.varargs.is_empty() {
|
if data.varargs.is_empty() {
|
||||||
writeln!(w, "")
|
writeln!(w, "")
|
||||||
|
|||||||
@@ -158,6 +158,11 @@ impl Context {
|
|||||||
try!(self.map.rewrite_values(&mut data.varargs, loc));
|
try!(self.map.rewrite_values(&mut data.varargs, loc));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
InstructionData::IndirectCall { ref mut data, .. } => {
|
||||||
|
try!(self.map.rewrite_value(&mut data.arg, loc));
|
||||||
|
try!(self.map.rewrite_values(&mut data.varargs, loc));
|
||||||
|
}
|
||||||
|
|
||||||
InstructionData::Return { ref mut data, .. } => {
|
InstructionData::Return { ref mut data, .. } => {
|
||||||
try!(self.map.rewrite_values(&mut data.varargs, loc));
|
try!(self.map.rewrite_values(&mut data.varargs, loc));
|
||||||
}
|
}
|
||||||
@@ -1171,6 +1176,12 @@ impl<'a> Parser<'a> {
|
|||||||
args: [lhs, rhs],
|
args: [lhs, rhs],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
InstructionFormat::Call => {
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
InstructionFormat::IndirectCall => {
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
InstructionFormat::Return => {
|
InstructionFormat::Return => {
|
||||||
let args = try!(self.parse_value_list());
|
let args = try!(self.parse_value_list());
|
||||||
InstructionData::Return {
|
InstructionData::Return {
|
||||||
@@ -1190,9 +1201,6 @@ impl<'a> Parser<'a> {
|
|||||||
table: table,
|
table: table,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
InstructionFormat::Call => {
|
|
||||||
unimplemented!();
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user