Browse Source

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.
pull/3/head
Jakob Stoklund Olesen 8 years ago
parent
commit
e4e1c30f87
  1. 22
      docs/langref.rst
  2. 5
      lib/cretonne/meta/cretonne/__init__.py
  3. 30
      lib/cretonne/meta/cretonne/base.py
  4. 5
      lib/cretonne/meta/cretonne/formats.py
  5. 2
      lib/cretonne/src/ir/builder.rs
  6. 21
      lib/cretonne/src/ir/instructions.rs
  7. 5
      lib/cretonne/src/write.rs
  8. 14
      lib/reader/src/parser.rs

22
docs/langref.rst

@ -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
preamble`:
.. inst:: F = function NAME signature
.. inst:: FN = function NAME signature
Declare a function so it can be called directly.
:arg NAME: Name of the function, passed to the linker for resolution.
:arg signature: Function signature. See below.
:result F: 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.
:result FN: A function identifier that can be used with :inst:`call`.
.. autoinst:: call
.. autoinst:: x_return
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`.
:result SIG: A signature identifier.
.. inst:: a, b, ... = call_indirect SIG, x(args...)
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.
.. autoinst:: call_indirect
.. todo:: Define safe indirect function calls.

5
lib/cretonne/meta/cretonne/__init__.py

@ -712,7 +712,10 @@ class InstructionFormat(object):
:py:class:`Instruction` arguments of the same name, except they must be
tuples of :py:`Operand` objects.
"""
multiple_results = len(outs) > 1
if len(outs) == 1:
multiple_results = outs[0].kind == variable_args
else:
multiple_results = len(outs) > 1
sig = (multiple_results,) + tuple(op.kind for op in ins)
if sig not in InstructionFormat._registry:
raise RuntimeError(

30
lib/cretonne/meta/cretonne/base.py

@ -15,6 +15,7 @@ instructions = InstructionGroup("base", "Shared base instruction set")
Int = TypeVar('Int', 'A scalar or vector integer type', ints=True, simd=True)
iB = TypeVar('iB', 'A scalar integer type', ints=True)
iPtr = TypeVar('iB', 'An integer address type', ints=(32, 64))
Testable = TypeVar(
'Testable', 'A scalar boolean or integer type',
ints=True, bools=True)
@ -109,6 +110,35 @@ x_return = Instruction(
""",
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.
#

5
lib/cretonne/meta/cretonne/formats.py

@ -8,7 +8,7 @@ in this module.
from __future__ import absolute_import
from . import InstructionFormat, value, variable_args
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()
@ -47,6 +47,9 @@ BranchTable = InstructionFormat(value, jump_table)
Call = InstructionFormat(
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)

2
lib/cretonne/src/ir/builder.rs

@ -5,7 +5,7 @@
use ir::{types, instructions};
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::condcodes::{IntCC, FloatCC};

21
lib/cretonne/src/ir/instructions.rs

@ -10,7 +10,7 @@ use std::fmt::{self, Display, Formatter};
use std::str::FromStr;
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::condcodes::*;
use ir::types;
@ -207,6 +207,12 @@ pub enum InstructionData {
second_result: Value,
data: Box<CallData>,
},
IndirectCall {
opcode: Opcode,
ty: Type,
second_result: Value,
data: Box<IndirectCallData>,
},
Return {
opcode: Opcode,
ty: Type,
@ -342,10 +348,15 @@ pub struct CallData {
pub varargs: VariableArgs,
}
impl Display for CallData {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "TBD({})", self.varargs)
}
/// Payload of an indirect call instruction.
#[derive(Clone, Debug)]
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.

5
lib/cretonne/src/write.rs

@ -199,7 +199,10 @@ fn write_instruction(w: &mut Write,
Jump { ref data, .. } => writeln!(w, " {}", data),
Branch { ref data, .. } => writeln!(w, " {}", data),
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, .. } => {
if data.varargs.is_empty() {
writeln!(w, "")

14
lib/reader/src/parser.rs

@ -158,6 +158,11 @@ impl Context {
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, .. } => {
try!(self.map.rewrite_values(&mut data.varargs, loc));
}
@ -1171,6 +1176,12 @@ impl<'a> Parser<'a> {
args: [lhs, rhs],
}
}
InstructionFormat::Call => {
unimplemented!();
}
InstructionFormat::IndirectCall => {
unimplemented!();
}
InstructionFormat::Return => {
let args = try!(self.parse_value_list());
InstructionData::Return {
@ -1190,9 +1201,6 @@ impl<'a> Parser<'a> {
table: table,
}
}
InstructionFormat::Call => {
unimplemented!();
}
})
}
}

Loading…
Cancel
Save