Name Strings

SPV_INTEL_variable_length_array

Contact

To report problems with this extension, please open a new issue at:

Contributors

  • Alexey Sotkin, Intel

  • Ben Ashbaugh, Intel

  • Vyacheslav Zakharin, Intel

  • Michael Kinsner, Intel

  • Dmitry Sidorov, Intel

  • Viktoria Maksimova, Intel

  • Victor Lomuller, Codeplay

Notice

Copyright (c) 2025 Intel Corporation. All rights reserved.

Status

  • Complete

Version

Last Modified Date

2025-03-14

Revision

3

Dependencies

This extension is written against the SPIR-V Specification, Version 1.6 Revision 5.

This extension interacts with SPV_KHR_untyped_pointers extension.

This extension requires SPIR-V 1.0.

Overview

This extension allows to allocate local arrays whose number of elements is unknown at compile time. This is useful for implementing high-level language features like C99 variable length arrays.

Extension Name

To use this extension within a SPIR-V module, the appropriate OpExtension must be present in the module:

OpExtension "SPV_INTEL_variable_length_array"

Modifications to the SPIR-V Specification, Version 1.6

Capabilities

Modify Section 3.31, Capability, adding rows to the Capability table:

Capability Implicitly Declares

5817

VariableLengthArrayINTEL
Uses OpVariableLengthArrayINTEL, OpSaveMemoryINTEL and OpRestoreMemoryINTEL instructions.

6243

UntypedVariableLengthArrayINTEL
Uses UntypedOpVariableLengthArrayINTEL instruction.

VariableLengthArrayINTEL, UntypedPointersKHR

Instructions

Modify Section 3.56.8. Memory Instructions, adding to the end of the list of instructions:

OpVariableLengthArrayINTEL

Allocate a runtime-sized array in memory, resulting in a pointer to it, which can be used with OpLoad and OpStore. The memory is allocated in Function storage class and is uninitialized. Loading from uninitialized memory will return indeterminate values. Size of memory to be allocated is computed as the size of Type operand of the Result Type multiplied by the Length.

Result Type must be OpTypePointer with Function storage class. Its Type operand is the type of array elements. The type of array elements must be a Concrete Type.

Length is the number of elements in the array. It must have a scalar integer type. Length is treated as unsigned. If value of Length is 0, no memory will be allocated and accessing such array is undefined behavior.

The current invocation’s memory is deallocated when it executes any function termination instruction of the dynamic instance of the function it was allocated by.

If there is insufficient memory space for the allocation the behavior is undefined.

Capability:
VariableLengthArrayINTEL

4

5818

<id> Result Type

<id> Result

<id> Length

OpUntypedVariableLengthArrayINTEL

Allocate a runtime-sized array in memory, resulting in a pointer to it, which can be used with OpLoad and OpStore. The memory is allocated in Function storage class and is uninitialized. Loading from uninitialized memory will return indeterminate values. Size of memory to be allocated is computed as the size of ElementType operand multiplied by the Length.

Result Type must be OpTypeUntypedPointerKHR with Function storage class.

ElementType must be a Concrete Type. It’s the type of array elements.

Length is the number of elements in the array. It must have a scalar integer type. Length is treated as unsigned. If value of Length is 0, no memory will be allocated and accessing such array is undefined behavior.

The current invocation’s memory is deallocated when it executes any function termination instruction of the dynamic instance of the function it was allocated by.

If there is insufficient memory space for the allocation the behavior is undefined.

Capability:
UntypedVariableLengthArrayINTEL

5

6244

<id> Result Type

<id> Result

<id> Element Type

<id> Length

OpSaveMemoryINTEL

Save the current state of the Function storage class memory. Returns a pointer that should be passed to OpRestoreMemoryINTEL. When OpRestoreMemoryINTEL is called it restores the saved state of the Function storage class memory by deallocating memory allocated by every OpVariableLengthArrayINTEL or OpUntypedVariableLengthArrayINTEL instructions executed after this OpSaveMemoryINTEL.

Result Type must be a pointer type with Function storage class.

Capability:
VariableLengthArrayINTEL

3

5819

<id> Result Type

<id> Result

OpRestoreMemoryINTEL

Restore the Function storage class memory to the state it was in when the OpSaveMemoryINTEL was executed.

Ptr is a pointer value returned by OpSaveMemoryINTEL. It must be a pointer type with Function storage class.

The behavior is undefined if 2 or more dynamic instances of this instruction use the result of the same dynamic instance as Ptr operand.

If in the control flow graph there are multiple OpRestoreMemoryINTEL instructions postdominating multiple OpSaveMemoryINTEL instructions, then OpRestoreMemoryINTEL instructions should be executed in the reversed order of OpSaveMemoryINTEL instructions, otherwise the behavior is undefined. E.g. the following example is UB:

%state1 = OpSaveMemoryINTEL
%vla1 = OpVariableLengthArrayINTEL
%state2 = OpSaveMemoryINTEL
%vla2 = OpVariableLengthArrayINTEL
/* ... */
OpRestoreMemoryINTEL %state1
OpRestoreMemoryINTEL %state2 <--- causes double deallocation

Capability:
VariableLengthArrayINTEL

2

5820

<id> Ptr

Validation Rules

  • In control flow graph every OpVariableLengthArrayINTEL and OpUntypedVariableLengthArrayINTEL must be dominated by at least one OpSaveMemoryINTEL.

Issues

  1. Can OpVariableLengthArrayINTEL be used without OpSaveMemoryINTEL and OpRestoreMemoryINTEL?

    RESOLVED: It will result in undefined behavior.

  2. Should we mention that the memory should be automatically deallocated when the control flow reaches the end of the (Function?) scope?

    RESOLVED: reuse OpVariable definition.

  3. Should we restrict usage of the instructions declared in this extension to uniform(convergent) control flow only?

    RESOLVED: no, as each invocation owns its own Function memory.

  4. Should zero-length VLA allocation return nullptr?

    RESOLVED: No. Yet accessing such allocation is undefined behavior.

  5. Should we clarify order of OpRestoreMemoryINTEL instructions when they are postdominating several OpSaveMemoryINTEL instructions?

    RESOLVED: If the order of deallocations is not reversed to the order of OpSaveMemoryINTEL instructions, then the behavior is undefined.

Revision History

Rev Date Author Changes

1

2020-08-31

Alexey Sotkin

Initial revision

2

2025-01-28

Dmitry Sidorov

Add untyped capability

3

2025-03-14

Dmitry Sidorov

Add notes about UB in case of multiple deallocations