9.3.7.7 Intrinsic Call Instructions

Guile’s instruction set is low-level. This is good because the separate components of, say, a vector-ref operation might be able to be optimized out, leaving only the operations that need to be performed at run-time.

However some macro-operations may need to perform large amounts of computation at run-time to handle all the edge cases, and whose micro-operation components aren’t amenable to optimization. Residualizing code for the entire macro-operation would lead to code bloat with no benefit.

In this kind of a case, Guile’s VM calls out to intrinsics: run-time routines written in the host language (currently C, possibly more in the future if Guile gains more run-time targets like WebAssembly). There is one instruction for each instrinsic prototype; the intrinsic is specified by index in the instruction.

Instruction: call-thread x24:_ c32:idx

Call the void-returning instrinsic with index idx, passing the current scm_thread* as the argument.

Instruction: call-thread-scm s24:a c32:idx

Call the void-returning instrinsic with index idx, passing the current scm_thread* and the scm local a as arguments.

Instruction: call-thread-scm-scm s12:a s12:b c32:idx

Call the void-returning instrinsic with index idx, passing the current scm_thread* and the scm locals a and b as arguments.

Instruction: call-scm-sz-u32 s12:a s12:b c32:idx

Call the void-returning instrinsic with index idx, passing the locals a, b, and c as arguments. a is a scm value, while b and c are raw u64 values which fit into size_t and uint32_t types, respectively.

Instruction: call-scm<-thread s24:dst c32:idx

Call the SCM-returning instrinsic with index idx, passing the current scm_thread* as the argument. Place the result in dst.

Instruction: call-scm<-u64 s12:dst s12:a c32:idx

Call the SCM-returning instrinsic with index idx, passing u64 local a as the argument. Place the result in dst.

Instruction: call-scm<-s64 s12:dst s12:a c32:idx

Call the SCM-returning instrinsic with index idx, passing s64 local a as the argument. Place the result in dst.

Instruction: call-scm<-scm s12:dst s12:a c32:idx

Call the SCM-returning instrinsic with index idx, passing scm local a as the argument. Place the result in dst.

Instruction: call-u64<-scm s12:dst s12:a c32:idx

Call the uint64_t-returning instrinsic with index idx, passing scm local a as the argument. Place the u64 result in dst.

Instruction: call-s64<-scm s12:dst s12:a c32:idx

Call the int64_t-returning instrinsic with index idx, passing scm local a as the argument. Place the s64 result in dst.

Instruction: call-f64<-scm s12:dst s12:a c32:idx

Call the double-returning instrinsic with index idx, passing scm local a as the argument. Place the f64 result in dst.

Instruction: call-scm<-scm-scm s8:dst s8:a s8:b c32:idx

Call the SCM-returning instrinsic with index idx, passing scm locals a and b as arguments. Place the scm result in dst.

Instruction: call-scm<-scm-uimm s8:dst s8:a c8:b c32:idx

Call the SCM-returning instrinsic with index idx, passing scm local a and uint8_t immediate b as arguments. Place the scm result in dst.

Instruction: call-scm<-thread-scm s12:dst s12:a c32:idx

Call the SCM-returning instrinsic with index idx, passing the current scm_thread* and scm local a as arguments. Place the scm result in dst.

Instruction: call-scm<-scm-u64 s8:dst s8:a s8:b c32:idx

Call the SCM-returning instrinsic with index idx, passing scm local a and u64 local b as arguments. Place the scm result in dst.

Instruction: call-scm-scm s12:a s12:b c32:idx

Call the void-returning instrinsic with index idx, passing scm locals a and b as arguments.

Instruction: call-scm-scm-scm s8:a s8:b s8:c c32:idx

Call the void-returning instrinsic with index idx, passing scm locals a, b, and c as arguments.

Instruction: call-scm-uimm-scm s8:a c8:b s8:c c32:idx

Call the void-returning instrinsic with index idx, passing scm local a, uint8_t immediate b, and scm local c as arguments.

There are corresponding macro-instructions for specific intrinsics. These are equivalent to call-instrinsic-kind instructions with the appropriate intrinsic idx arguments.

Macro Instruction: add dst a b
Macro Instruction: add/immediate dst a b/imm

Add SCM values a and b and place the result in dst.

Macro Instruction: sub dst a b
Macro Instruction: sub/immediate dst a b/imm

Subtract SCM value b from a and place the result in dst.

Macro Instruction: mul dst a b

Multiply SCM values a and b and place the result in dst.

Macro Instruction: div dst a b

Divide SCM value a by b and place the result in dst.

Macro Instruction: quo dst a b

Compute the quotient of SCM values a and b and place the result in dst.

Macro Instruction: rem dst a b

Compute the remainder of SCM values a and b and place the result in dst.

Macro Instruction: mod dst a b

Compute the modulo of SCM value a by b and place the result in dst.

Macro Instruction: logand dst a b

Compute the bitwise and of SCM values a and b and place the result in dst.

Macro Instruction: logior dst a b

Compute the bitwise inclusive or of SCM values a and b and place the result in dst.

Macro Instruction: logxor dst a b

Compute the bitwise exclusive or of SCM values a and b and place the result in dst.

Macro Instruction: logsub dst a b

Compute the bitwise and of SCM value a and the bitwise not of b and place the result in dst.

Macro Instruction: lsh dst a b
Macro Instruction: lsh/immediate a b/imm

Shift SCM value a left by u64 value b bits and place the result in dst.

Macro Instruction: rsh dst a b
Macro Instruction: rsh/immediate dst a b/imm

Shifts SCM value a right by u64 value b bits and place the result in dst.

Macro Instruction: scm->f64 dst src

Convert src to an unboxed f64 and place the result in dst, or raises an error if src is not a real number.

Macro Instruction: scm->u64 dst src

Convert src to an unboxed u64 and place the result in dst, or raises an error if src is not an integer within range.

Macro Instruction: scm->u64/truncate dst src

Convert src to an unboxed u64 and place the result in dst, truncating to the low 64 bits, or raises an error if src is not an integer.

Macro Instruction: scm->s64 dst src

Convert src to an unboxed s64 and place the result in dst, or raises an error if src is not an integer within range.

Macro Instruction: u64->scm dst src

Convert u64 value src to a Scheme integer in dst.

Macro Instruction: s64->scm scm<-s64

Convert s64 value src to a Scheme integer in dst.

Macro Instruction: string-set! str idx ch

Sets the character idx (a u64) of string str to ch (a u64 that is a valid character value).

Macro Instruction: string->number dst src

Call string->number on src and place the result in dst.

Macro Instruction: string->symbol dst src

Call string->symbol on src and place the result in dst.

Macro Instruction: symbol->keyword dst src

Call symbol->keyword on src and place the result in dst.

Macro Instruction: class-of dst src

Set dst to the GOOPS class of src.

Macro Instruction: wind winder unwinder

Push wind and unwind procedures onto the dynamic stack. Note that neither are actually called; the compiler should emit calls to winder and unwinder for the normal dynamic-wind control flow. Also note that the compiler should have inserted checks that winder and unwinder are thunks, if it could not prove that to be the case. See Dynamic Wind.

Macro Instruction: unwind

Exit from the dynamic extent of an expression, popping the top entry off of the dynamic stack.

Macro Instruction: push-fluid fluid value

Dynamically bind value to fluid by creating a with-fluids object, pushing that object on the dynamic stack. See Fluids and Dynamic States.

Macro Instruction: pop-fluid

Leave the dynamic extent of a with-fluid* expression, restoring the fluid to its previous value. push-fluid should always be balanced with pop-fluid.

Macro Instruction: fluid-ref dst fluid

Place the value associated with the fluid fluid in dst.

Macro Instruction: fluid-set! fluid value

Set the value of the fluid fluid to value.

Macro Instruction: push-dynamic-state state

Save the current set of fluid bindings on the dynamic stack and instate the bindings from state instead. See Fluids and Dynamic States.

Macro Instruction: pop-dynamic-state

Restore a saved set of fluid bindings from the dynamic stack. push-dynamic-state should always be balanced with pop-dynamic-state.

Macro Instruction: resolve-module dst name public?

Look up the module named name, resolve its public interface if the immediate operand public? is true, then place the result in dst.

Macro Instruction: lookup dst mod sym

Look up sym in module mod, placing the resulting variable (or #f if not found) in dst.

Macro Instruction: define! dst mod sym

Look up sym in module mod, placing the resulting variable in dst, creating the variable if needed.

Macro Instruction: current-module dst

Set dst to the current module.

Macro Instruction: $car dst src
Macro Instruction: $cdr dst src
Macro Instruction: $set-car! x val
Macro Instruction: $set-cdr! x val
Macro Instruction: $variable-ref dst src
Macro Instruction: $variable-set! x val
Macro Instruction: $vector-length dst x
Macro Instruction: $vector-ref dst x idx
Macro Instruction: $vector-ref/immediate dst x idx/imm
Macro Instruction: $vector-set! x idx v
Macro Instruction: $vector-set!/immediate x idx/imm v
Macro Instruction: $allocate-struct dst vtable nwords
Macro Instruction: $struct-vtable dst src
Macro Instruction: $struct-ref dst src idx
Macro Instruction: $struct-ref/immediate dst src idx/imm
Macro Instruction: $struct-set! x idx v
Macro Instruction: $struct-set!/immediate x idx/imm v

Intrinsics for use by the baseline compiler. The usual strategy for CPS compilation is to expose the component parts of e.g. vector-ref so that the compiler can learn from them and eliminate needless bits. However in the non-optimizing baseline compiler, that’s just overhead, so we have some intrinsics that encapsulate all the usual type checks.