Core.Builtins
The following builtin functions are considered unstable, but provide the basic definitions for what defines the abilities and behaviors of a Julia program. They are typically accessed through a higher level generic API.
Raw access to memory
Core.Intrinsics.pointerref — Function
Core.Intrinsics.pointerref(p::Ptr{T}, i::Int, align::Int)Load a value of type T from the address of the ith element (1-indexed)
starting at p. This is equivalent to the C expression p[i-1].
The alignment must be a power of two, or 0, indicating the default alignment
for T. If p[i-1] is out of bounds, invalid, or is not aligned, the behavior
is undefined. An alignment of 1 is always safe.
See also unsafe_load.
Core.Intrinsics.pointerset — Function
Core.Intrinsics.pointerset(p::Ptr{T}, x::T, i::Int, align::Int)Store a value of type T to the address of the ith element (1-indexed)
starting at p. This is equivalent to the C expression p[i-1] = x.
The alignment must be a power of two, or 0, indicating the default alignment
for T. If p[i-1] is out of bounds, invalid, or is not aligned, the behavior
is undefined. An alignment of 1 is always safe.
See also unsafe_store!.
Core.Intrinsics.atomic_pointerref — Function
Core.Intrinsics.atomic_pointerref(pointer::Ptr{T}, order::Symbol) --> TSee unsafe_load.
Core.Intrinsics.atomic_pointerset — Function
Core.Intrinsics.atomic_pointerset(pointer::Ptr{T}, new::T, order::Symbol) --> pointerSee unsafe_store!.
Core.Intrinsics.atomic_pointerswap — Function
Core.Intrinsics.atomic_pointerswap(pointer::Ptr{T}, new::T, order::Symbol) --> oldSee unsafe_swap!.
Core.Intrinsics.atomic_pointermodify — Function
Core.Intrinsics.atomic_pointermodify(pointer::Ptr{T}, function::(old::T,arg::S)->T, arg::S, order::Symbol) --> oldSee unsafe_modify!.
Core.Intrinsics.atomic_pointerreplace — Function
Core.Intrinsics.atomic_pointerreplace(pointer::Ptr{T}, expected::Any, new::T, success_order::Symbol, failure_order::Symbol) --> (old, cmp)See unsafe_replace!.
Managed memory
Core.memorynew — Function
Core.memorynew(::Type{T} where T <: GenericMemory, n::Int)Construct an uninitialized GenericMemory of length n.
See also Memory, Memory{T}(undef, n).
Core.memoryrefnew — Function
Core.memoryrefnew(::GenericMemory)
Core.memoryrefnew(::GenericMemoryRef, index::Int, [boundscheck::Bool])Return a GenericMemoryRef for a GenericMemory. See memoryref.
Core.memoryrefoffset — Function
Core.memoryrefoffset(::GenericMemoryRef)Return the offset index that was used to construct the MemoryRef. See memoryref.
Core.memoryrefget — Function
Core.memoryrefget(::GenericMemoryRef, ordering::Symbol, boundscheck::Bool)Return the value stored at the MemoryRef, throwing a BoundsError if the Memory is empty. See ref[].
The memory ordering specified must be compatible with the isatomic parameter.
Core.memoryrefset! — Function
Core.memoryrefset!(::GenericMemoryRef, value, ordering::Symbol, boundscheck::Bool)Store the value to the MemoryRef, throwing a BoundsError if the Memory is empty. See ref[] = value.
The memory ordering specified must be compatible with the isatomic parameter.
Core.memoryref_isassigned — Function
Core.memoryref_isassigned(::GenericMemoryRef, ordering::Symbol, boundscheck::Bool)Return whether there is a value stored at the MemoryRef, returning false if the Memory
is empty. See isassigned(::Base.RefValue), Core.memoryrefget.
The memory ordering specified must be compatible with the isatomic parameter.
Core.memoryrefswap! — Function
Core.memoryrefswap!(::GenericMemoryRef, value, ordering::Symbol, boundscheck::Bool)Atomically perform the operations to simultaneously get and set a MemoryRef value.
See also swapproperty!, Core.memoryrefset!.
Core.memoryrefmodify! — Function
Core.memoryrefmodify!(::GenericMemoryRef, op, value, ordering::Symbol, boundscheck::Bool)::PairAtomically perform the operations to get and set a MemoryRef value after applying
the function op.
See also modifyproperty!, Core.memoryrefset!.
Core.memoryrefreplace! — Function
Core.memoryrefreplace!(::GenericMemoryRef, expected, desired,
success_order::Symbol, fail_order::Symbol=success_order, boundscheck::Bool) -> (; old, success::Bool)Atomically perform the operations to get and conditionally set a MemoryRef value.
See also replaceproperty!, Core.memoryrefset!.
Core.memoryrefsetonce! — Function
Core.memoryrefsetonce!(::GenericMemoryRef, value,
success_order::Symbol, fail_order::Symbol=success_order, boundscheck::Bool) -> success::BoolAtomically perform the operations to set a MemoryRef to
a given value, only if it was previously not set.
See also setpropertyonce!, Core.memoryrefset!.
Module bindings
Core.get_binding_type — Function
Core.get_binding_type(module::Module, name::Symbol)Retrieve the declared type of the binding name from the module module.
Various helper functions
Base.quoted — Function
quoted(x)Return x made safe for inserting as a constant into IR. Note that this does
not make it safe for inserting into an AST, since eval will sometimes copy some
types of AST object inside, and even may sometimes evaluate and interpolate any
$ inside, depending on the context.
Base.isa_ast_node — Function
isa_ast_node(x)Return false if x is not interpreted specially by any of inference, lowering,
or codegen as either an AST or IR special form.
Other
Core.IntrinsicFunction — Type
Core.IntrinsicFunction <: Core.Builtin <: FunctionThe Core.IntrinsicFunction type defines some basic primitives for what defines the
abilities and behaviors of a Julia program
Core.Intrinsics — Module
Core.IntrinsicsThe Core.Intrinsics module holds the Core.IntrinsicFunction objects.
Core._task — Function
Core._task(f, size) -> Task
Core._task(f, size, invoked) -> TaskCreate a new Task that will execute function f with the specified stack size.
The optional third argument invoked can be a Method, CodeInstance, or tuple
Type that will be used for optimized task invocation via Core.invoke.
This builtin is an implementation detail used by the Task constructor and should
not be called directly by end-users. Use Task(f) instead. It is a low-level
interface that bypasses safety checks and initialization performed by the public
Task constructor.
Core.task_result_type — Function
Core.task_result_type(task) -> TypeReturn a conservative upper bound for the return type of the closure provided when
task was created. At runtime this builtin always returns the type Any; however,
inference may replace calls to it with a more precise result type.
Adding New Builtin Functions
This section documents the process for adding a new builtin function to Julia (using _task as an example).
Overview
Adding a new builtin function requires changes across multiple subsystems in Julia:
C runtime implementation
Julia inference integration
Complex inference integration (if required)
Optimization passes (if applicable)
Codegen changes (if applicable)
Step-by-Step Process
1. Add to Builtin Function Registry
File: src/builtin_proto.h
// Add to JL_BUILTIN_FUNCTIONS macro (alphabetically)
#define JL_BUILTIN_FUNCTIONS(XX) \
// ... other functions
XX(_using, "_using") \
XX(_your_builtin,"_your_builtin") \ // <-- Add your function here
XX(applicable,"applicable") \
// ... other functionsFile: src/builtins.c
// Implement the C function
JL_CALLABLE(jl_f__your_builtin)
{
JL_NARGS(_your_builtin, 2, 3);
JL_TYPECHK(_your_builtin, long, args[1]);
return _your_builtin_impl(args, nargs);
}Argument validation: Always validate argument count and types in the C implementation.
2. Julia Inference Integration
File: Compiler/src/tfuncs.jl
# Add simple tfunc if no special state is required (the tfunc always takes the
# inference lattice as its first argument, before the builtin's own arguments)
@nospecs function your_builtin_tfunc(𝕃::AbstractLattice, arg1, arg2, optional...)
return Typ
end
add_tfunc(Core._your_builtin, 2, 3, your_builtin_tfunc, 20)
# OR for complex cases requiring AbstractInterpreter state:
# Leave out add_tfunc and implement in abstractinterpretation.jl insteadAlso model the builtin's effects: register it in _EFFECTS_KNOWN_BUILTINS and teach
builtin_effects (and _builtin_nothrow, if the throwing conditions can be refined
from the argument types) about it. Builtins that are absent from that list are
pessimistically assumed to have fully unknown effects.
3. Complex Inference Integration (if add_tfunc was insufficient)
File: Compiler/src/stmtinfo.jl
# For builtins that perform deferred/indirect calls, define a `CallInfo` wrapping
# the call information of the deferred call (see e.g. `FinalizerInfo`, `ModifyOpInfo`
# and `TaskCallInfo`). Define `add_edges_impl` to forward the wrapped edges, unless
# merely creating the object should not imply invalidation edges.
struct YourBuiltinCallInfo <: CallInfo
info::CallInfo # the callinfo for the deferred call
end
add_edges_impl(edges::Vector{Any}, info::YourBuiltinCallInfo) = add_edges!(edges, info.info)File: Compiler/src/abstractinterpretation.jl
# Add to the builtin-specific handling in abstract_call_known
elseif f === Core._your_builtin
return abstract_eval_your_builtin(interp, arginfo, si, vtypes, sv)
# Implement custom abstract evaluation if needed
function abstract_eval_your_builtin(interp::AbstractInterpreter, arginfo::ArgInfo,
si::StmtInfo, vtypes::Union{VarTable,Nothing},
sv::AbsIntState)
# Validation and inference logic
return Future(CallMeta(return_type, exception_type, effects, call_info))
end4. Optimization Passes (if applicable)
For example, if the operator has a special inlining:
File: Compiler/src/ssair/inlining.jl
# Add to special builtin handling
if (f !== Core.invoke &&
f !== Core.finalizer &&
# ... other functions
f !== Core._your_builtin) # <-- Add here
# Add optimization logic in `assemble_inline_todo!`, dispatching on the `CallInfo`
# recorded by inference
elseif isa(info, YourBuiltinCallInfo)
handle_your_builtin_call!(ir, idx, stmt, info, state)
end5. Documentation
File: base/docs/basedocs.jl
"""
Core._your_builtin(arg1, arg2) -> ReturnType
Core._your_builtin(arg1, arg2, optional_arg) -> ReturnType
This builtin is an implementation detail used by [higher-level function] and should
not be called directly by end-users. Use `HigherLevelFunction(args...)` instead.
Brief description of what the builtin does and its parameters.
The optional third argument `optional_arg` can be a [description of types/purpose].
"""
Core._your_builtinFile: doc/src/devdocs/builtins.md
# Add to the @docs block in the appropriate section
Core._your_builtin6. Testing
File: Compiler/test/effects.jl
# Add test for effects modeling (if your builtin has specific effects)
let effects = Base.infer_effects(Core._your_builtin, (ArgType,))
@test !Compiler.is_consistent(effects)
@test Compiler.is_nothrow(effects)
endFile: Compiler/test/inference.jl
# Add test for return type inference
@test Base.infer_return_type(Core._your_builtin, (ArgType,)) === ExpectedReturnType