Reference
The full public API. Everything else under PTX, PTX.IR, PTX.Codegen, PTX.Parser is internal and may change without notice.
Authoring
PTX.@ptx_str — Macro
ptx"opcode.mod1.mod2..."Construct an Operation{op, mods} singleton — op::Symbol is the opcode (first segment), mods::Tuple{Vararg{Symbol}} is the modifier chain. Splits on .; each segment becomes one Symbol verbatim, so :: (PTX sub-namespace separator), digit-leading tokens (3d, m16n8k32), and underscores in modifier names all flow through cleanly.
Supports $x / $(expr) interpolation. The macro expands to a chain of type-domain * compositions:
- Static segments fold into the initial
Operation{op, mods}()and subsequentChain{(...)}()constants. - A glued interpolation (literal chars adjacent on either side, e.g.
x$(N)or$(N)d) emitsSymbol(pre, expr, post)and composes viaOperation * Symbol. With a compile-time-constant interpolated value (e.g.Nfrom aVal{N}unwrap) the whole site folds to the same singleton the literal form would produce — making it safe to use inside device kernels. - A bare interpolation (between two
.s) emits_ptx_dyn_seg(expr), which yields aChain— supportsStringvalues containing.(split into multiple modifier segments) for host-side use. - An interpolated opcode (first segment) falls back to
_ptx_op_from_string(...). Device kernels should keep the opcode literal.
Examples:
ptx"add.f32"(a, b)
ptx"mma.sync.aligned.m16n8k16.row.col.f32.bf16.bf16.f32"(a, b, c)
ptx"cp.async.bulk.tensor.3d.shared::cta.global.tile.mbarrier::complete_tx::bytes"(...)
ptx"bar.sync"(Val(0))
ptx"mov.u32"(sreg"%tid.x")
dt = "u32"
ptx"mov.$dt"(x) # ≡ ptx"mov.u32"(x)
ptx"st.$(space).b32"(p, v) # $(...) for non-identifier exprs
# Glued — folds to a literal singleton when N is Val-known:
@inline f(p, ::Val{N}) where {N} =
ptx"ldmatrix.sync.aligned.m8n8.x$(N).shared.b16"(p)Empty literal parts (consecutive ., leading/trailing ., or empty string) error at expansion for the static path, and at runtime for the interp path.
See also: @mod_str for modifier-only chains usable on the right side of *.
PTX.@optype_str — Macro
optype"opcode.mod1.mod2..."The method-definition companion of @ptx_str: expands to the annotation ::Operation{op, mods} for the same static spelling, so a typed wrapper is defined in ISA text instead of a hand-transcribed mods tuple:
@inline optype"add.f32"(a::Float32, b::Float32) = ...is exactly
@inline (::Operation{:add, (:f32,)})(a::Float32, b::Float32) = ...Both string macros share one parser, so the definition is dispatchable by the ptx"" spelling that reads back out of it, by construction — modifier transcription typos (which produce unreachable methods that only a count pin can catch) become impossible.
Definition-site only; no $ interpolation (a generated family should use an explicit @eval loop over its spec, which builds mods tuples directly).
PTX.@sreg_str — Macro
sreg"name"Construct a SpecialReg{Symbol("%name")} singleton — a compile-time literal for a PTX special register. Bakes the verbatim asm token, so underscore-bearing names (%cluster_ctarank, %lanemask_eq, %total_smem_size) round-trip losslessly. The legacy spelling %warpsize is the exception: PTX 9.3 defines WARP_SZ as an immediate, so it returns Val(32). Other names accept either form:
sreg"tid.x" ≡ sreg"%tid.x" → "%tid.x"
sreg"cluster_ctarank" ≡ sreg"%cluster_ctarank" → "%cluster_ctarank"
sreg"warpsize" ≡ sreg"%warpsize" → Val(32)PTX.@mod_str — Macro
mod"mod1.mod2..."Construct a Chain{mods} singleton — a sequence of PTX modifiers with no opcode. Splits on . like @ptx_str but does not accept $ interpolation: there is no opcode context to interpolate against, and the type-level * (below) already handles compile-time composition.
mod"" is the empty chain Chain{()}. Composing it via * is a no-op — useful as an "absent modifier" sentinel for conditional helpers.
Pointers
PTX.Address — Type
Address{T}An isbits role marker for a 32- or 64-bit integer that represents a bracketed PTX address operand. Address is not a pointer conversion and is removed before inline-assembly argument passing. Construct it through address.
Core.LLVMPtr values are deliberately not wrapped: their pointer type already preserves the address role, address space, and exact typed-wrapper dispatch.
PTX.address — Function
address(value)Preserve a bracketed PTX address role through Julia lowering. A 32- or 64-bit integer becomes an Address marker; an Address and a Core.LLVMPtr are returned unchanged. Other carriers are rejected.
PTX.reinterpret_addrspace — Function
reinterpret_addrspace(Val(AS′), p::Core.LLVMPtr{T,AS}) -> Core.LLVMPtr{T,AS′}Reinterpret a pointer's raw 64-bit value in another address space — a ptrtoint/inttoptr pair, deliberately NOT an addrspacecast. NVPTX lowers addrspacecast to cvta window translation, which is wrong for several raw retypes that tier-2 wrappers need:
Shared → SharedCluster: the ISA definesshared::ctaaddresses as validshared::clusteraddresses (own-CTA window), so the raw value is already correct; the cast'scvta.shared+cvta.to.shared::clusterround-trip is two wasted instructions.Const → Genericfor TMA descriptors: the descriptor blob lives in global memory and is typedAS.Constby convention (TMADescriptorPtr), so its raw value is already a generic address —cvta.constwould translate it as if it were a const-window offset and corrupt it.Global → Genericfor a live tensor-map descriptor: global and generic use the same full virtual address for global storage. The tensor-map acquire intrinsic requires the latter carrier even when the preceding descriptor update correctly uses an explicitly global operand.
128-bit registers
The exported carrier B128 and constructor b128 are documented on the Chain DSL page.
Extended-precision arithmetic
PTX.add_with_carry — Function
add_with_carry(a::NTuple{N,T}, b::NTuple{N,T}[, carry::Bool])
-> (words::NTuple{N,T}, carry_out::Bool)Add two little-endian limb tuples and return the same-width sum plus carry-out. An optional explicit carry-in is accepted. T may be UInt32, Int32, UInt64, or Int64; PTX defines identical carry behavior for signed and unsigned add. The complete straight-line sequence is emitted as one opaque, non-convergent inline-assembly call so CC.CF never crosses an LLVM boundary.
PTX.sub_with_borrow — Function
sub_with_borrow(a::NTuple{N,T}, b::NTuple{N,T}[, borrow::Bool])
-> (words::NTuple{N,T}, borrow_out::Bool)Subtract little-endian limb tuple b from a, returning the same-width difference and borrow-out. An optional explicit borrow-in is accepted. The entire sequence is one side-effecting, non-convergent asm block; see add_with_carry for supported limb types.
PTX.mul_wide — Function
mul_wide(a::NTuple{2,T}, b::NTuple{2,T}) -> NTuple{4,T}Multiply two little-endian, two-limb unsigned integers and return the full four-limb product. T may be UInt32 or UInt64. This embeds the PTX §9.7.2.6 UInt32 mad.cc/madc sequence, generalized to the legal UInt64 forms, in one side-effecting, non-convergent asm block. Signed multi-limb multiplication is intentionally not inferred from per-limb signed mad.hi semantics.
Vector loads
PTX.vector_load — Function
vector_load(ptx"ld....vN.type", address, Val(mask))Emit a wide PTX vector load with an explicit destination-lane mask. true returns that lane and false emits PTX's _ sink, which guarantees the corresponding memory location is not read. Sink lanes are supported only for the ISA's wide ld.v8.{b32,u32,s32,f32} and ld.v4.{b64,u64,s64,f64} forms. The result is the homogeneous tuple of live lanes in source order. All-false masks are rejected: current ptxas cannot assemble an all-_ destination, and eliding a load would require a separate memory-model audit.
Transpiler
PTX.Codegen.ptx_to_julia — Function
ptx_to_julia(source) -> StringParse PTX source text and emit Julia source code. Returns a string of one or more function ... end definitions calling the ptx"..." macro after validating the complete module against the transpiler's deliberately closed subset. Lexical, parse, and transpiler-contract errors throw instead of returning a partial program. Acceptance is a lowering-contract guarantee, not a proof of semantic equivalence for every accepted PTX program.
PTX.Codegen.ir_to_julia — Function
ir_to_julia(mod::IR.Module) -> StringValidate a parsed IR.Module and convert it into Julia source code. Each accepted Function becomes one Julia function definition. Validation covers the complete module and finishes before emission, so an unsupported node, declaration, control-flow edge, or instruction form raises TranspilerError without returning partial Julia.
PTX.Codegen.TranspilerError — Type
TranspilerError(path, category, detail)Raised before PTX-to-Julia emission when parsed IR falls outside the closed semantic subset. path identifies the rejected IR node, category separates unsupported structure/operands from reviewed schema misses, and detail explains the missing contract. This is not evidence that the input PTX is invalid; parsing and lossless formatting intentionally support a broader IR.
Parser
PTX.Parser.tokenize — Function
tokenize(source::AbstractString) -> Vector{Token}Tokenize PTX source text. The token stream includes NEWLINE / COMMENT tokens (needed for formatting preservation) and ends with an EOF token. Raises LexError on unrecognizable characters.
PTX.Parser.Token — Type
TokenA single token from the PTX source. leading_whitespace carries the spaces/tabs that preceded this token on the same line, used by the parser to reconstruct FormattingInfo for byte-identical round-trip.
PTX.Parser.TokenKind — Module
TokenKindToken kinds produced by tokenize. EnumX-nested so values are referenced as TokenKind.IDENTIFIER, TokenKind.NEWLINE, etc.
PTX.Parser.LexError — Type
LexErrorRaised by tokenize on unrecognizable input.
PTX.Parser.parse — Function
parse(source::AbstractString) -> IR.ModuleParse PTX source text into a Module. Module-header (.version / .target / .addresssize) and supported module/function/body statements are parsed into structured IR; blank lines and comments are preserved. Instructions do not require a known-opcode inventory. A post-header statement that fails the fault-tolerant statement parser is generally retained as an opaque RawLine, but lexical errors, invalid initial headers, malformed or misplaced .version/.target/`.addresssizedirectives, and target invariants still throw.RawLine` preserves text only and is not a semantic parse.
The original nonempty input is retained in Module.raw_source, so formatting an unmodified parsed module is byte-identical without exercising field-driven structural reconstruction.
PTX.Parser.ParseError — Type
ParseErrorRaised by parse on input the recursive-descent parser cannot consume. Carries the source line and col of the failed token.
IR
PTX.IR.format — Function
format(mod::IR.Module) -> StringReconstruct PTX text from a parsed IR.Module. Returns mod.raw_source verbatim when set (the lossless fast path used by parser-produced IR); otherwise emits the module structurally — header, leading prelude, then each directive. A statement uses formatting.raw_line when present and field-driven reconstruction otherwise. An opaque RawLine is also emitted verbatim, but carries no reconstructed statement semantics.
Per-statement format(stmt) methods (one per IR.Statement kind) implement the structural fallback and can be called individually. Construction-time-only nodes without a PTX spelling, such as IntrinsicScope, error rather than discarding their metadata.
Index
PTX.MBarriersPTX.NVVMPTX.Parser.TokenKindPTX.PipelinesPTX.UtilsPTX.WarpsPTX.AddressPTX.B128PTX.Codegen.TranspilerErrorPTX.MBarriers.BarrierArrayPTX.MBarriers.BarrierGroupPTX.MBarriers.BarrierSetPTX.NVVM.CeilingPTX.NVVM.IntrinsicPTX.Parser.LexErrorPTX.Parser.ParseErrorPTX.Parser.TokenPTX.Pipelines.PipelinePTX.Codegen.ir_to_juliaPTX.Codegen.ptx_to_juliaPTX.Codegen.validate_transpilablePTX.IR._symPTX.IR.canonicalizePTX.IR.diffPTX.IR.formatPTX.IR.normalizePTX.MBarriers.barrier_arrivePTX.MBarriers.barrier_arrive_clusterPTX.MBarriers.barrier_arrive_expect_txPTX.MBarriers.barrier_bytesPTX.MBarriers.barrier_initPTX.MBarriers.barrier_offsetPTX.MBarriers.barrier_try_waitPTX.MBarriers.barrier_waitPTX.MBarriers.barrierset_init!PTX.NVVM.abitypPTX.NVVM.acceptsPTX.NVVM.callsite_ceilingPTX.NVVM.canonicalPTX.NVVM.check_ceilingPTX.NVVM.describePTX.NVVM.intrinsicPTX.NVVM.isintrinsicPTX.NVVM.llvmtypePTX.NVVM.manglePTX.NVVM.matchingPTX.NVVM.observability_classPTX.NVVM.overloadedPTX.NVVM.synthesizePTX.Parser.parsePTX.Parser.tokenizePTX.Pipelines.pipeline_cursorPTX.Pipelines.pipeline_init!PTX.Pipelines.pipeline_phasePTX.Pipelines.pipeline_stagePTX.Utils.strided_reducePTX.Warps.warp_reducePTX.add_with_carryPTX.addressPTX.b128PTX.ceiledPTX.form_contractPTX.layout_for_aPTX.layout_for_mn_majorPTX.loweringPTX.mul_widePTX.pick_gmma_layoutPTX.register_wrapper!PTX.reinterpret_addrspacePTX.smem_addr_u32PTX.step_descPTX.sub_with_borrowPTX.tcgen05_descriptorPTX.tcgen05_instr_desc_f16bf16_f32PTX.tcgen05_instr_desc_f8f6f4PTX.tcgen05_instr_desc_i8PTX.tcgen05_instr_desc_mxf4PTX.tcgen05_instr_desc_mxf4nvf4PTX.tcgen05_instr_desc_mxf8f6f4PTX.tensor_map_encode_tiledPTX.tensor_map_tile_2dPTX.vector_loadPTX.wgmma_descriptorPTX.wrapper_asm_formsPTX.wrapper_intrinsic_callPTX.wrapper_intrinsic_namesPTX.wrapper_missing_intrinsicsPTX.wrapper_recordsPTX.@mod_strPTX.@optype_strPTX.@ptx_strPTX.@sreg_strPTX.NVVM.@nvvm_strPTX.Utils.@unroll