-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-- FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
-- IN THE MATERIALS.
-- This header is automatically generated by the same tool that creates
-- the Binary Section of the SPIR-V specification.
-- Enumeration tokens for SPIR-V, in various styles:
--   C, C++, C++11, JSON, Lua, Python
--
-- - C will have tokens with a "Spv" prefix, e.g.: SpvSourceLanguageGLSL
-- - C++ will have tokens in the "spv" name space, e.g.: spv::SourceLanguageGLSL
-- - C++11 will use enum classes in the spv namespace, e.g.: spv::SourceLanguage::GLSL
-- - Lua will use tables, e.g.: spv.SourceLanguage.GLSL
-- - Python will use dictionaries, e.g.: spv['SourceLanguage']['GLSL']
--
-- Some tokens act like mask values, which can be OR'd together,
-- while others are mutually exclusive.  The mask-like ones have
-- "Mask" in their name, and a parallel enum that has the shift
-- amount (1 << x) for each corresponding enumerant.
spv = {
    MagicNumber = 0x07230203,
    Version = 0x00010200,
    Revision = 2,
    OpCodeMask = 0xffff,
    WordCountShift = 16,
    SourceLanguage = {
        Unknown = 0,
        ESSL = 1,
        GLSL = 2,
        OpenCL_C = 3,
        OpenCL_CPP = 4,
        HLSL = 5,
    },
    ExecutionModel = {
        Vertex = 0,
        TessellationControl = 1,
        TessellationEvaluation = 2,
        Geometry = 3,
        Fragment = 4,
        GLCompute = 5,
        Kernel = 6,
    },
    AddressingModel = {
        Logical = 0,
        Physical32 = 1,
        Physical64 = 2,
    },
    MemoryModel = {
        Simple = 0,
        GLSL450 = 1,
        OpenCL = 2,
    },
    ExecutionMode = {
        Invocations = 0,
        SpacingEqual = 1,
        SpacingFractionalEven = 2,
        SpacingFractionalOdd = 3,
        VertexOrderCw = 4,
        VertexOrderCcw = 5,
        PixelCenterInteger = 6,
        OriginUpperLeft = 7,
        OriginLowerLeft = 8,
        EarlyFragmentTests = 9,
        PointMode = 10,
        Xfb = 11,
        DepthReplacing = 12,
        DepthGreater = 14,
        DepthLess = 15,
        DepthUnchanged = 16,
        LocalSize = 17,
        LocalSizeHint = 18,
        InputPoints = 19,
        InputLines = 20,
        InputLinesAdjacency = 21,
        Triangles = 22,
        InputTrianglesAdjacency = 23,
        Quads = 24,
        Isolines = 25,
        OutputVertices = 26,
        OutputPoints = 27,
        OutputLineStrip = 28,
        OutputTriangleStrip = 29,
        VecTypeHint = 30,
        ContractionOff = 31,
        Initializer = 33,
        Finalizer = 34,
        SubgroupSize = 35,
        SubgroupsPerWorkgroup = 36,
        SubgroupsPerWorkgroupId = 37,
        LocalSizeId = 38,
        LocalSizeHintId = 39,
        PostDepthCoverage = 4446,
        StencilRefReplacingEXT = 5027,
    },
    StorageClass = {
        UniformConstant = 0,
        Input = 1,
        Uniform = 2,
        Output = 3,
        Workgroup = 4,
        CrossWorkgroup = 5,
        Private = 6,
        Function = 7,
        Generic = 8,
        PushConstant = 9,
        AtomicCounter = 10,
        Image = 11,
        StorageBuffer = 12,
    },
    Dim = {
        Dim1D = 0,
        Dim2D = 1,
        Dim3D = 2,
        Cube = 3,
        Rect = 4,
        Buffer = 5,
        SubpassData = 6,
    },
    SamplerAddressingMode = {
        None = 0,
        ClampToEdge = 1,
        Clamp = 2,
        Repeat = 3,
        RepeatMirrored = 4,
    },
    SamplerFilterMode = {
        Nearest = 0,
        Linear = 1,
    },
    ImageFormat = {
        Unknown = 0,
        Rgba32f = 1,
        Rgba16f = 2,
        R32f = 3,
        Rgba8 = 4,
        Rgba8Snorm = 5,
        Rg32f = 6,
        Rg16f = 7,
        R11fG11fB10f = 8,
        R16f = 9,
        Rgba16 = 10,
        Rgb10A2 = 11,
        Rg16 = 12,
        Rg8 = 13,
        R16 = 14,
        R8 = 15,
        Rgba16Snorm = 16,
        Rg16Snorm = 17,
        Rg8Snorm = 18,
        R16Snorm = 19,
        R8Snorm = 20,
        Rgba32i = 21,
        Rgba16i = 22,
        Rgba8i = 23,
        R32i = 24,
        Rg32i = 25,
        Rg16i = 26,
        Rg8i = 27,
        R16i = 28,
        R8i = 29,
        Rgba32ui = 30,
        Rgba16ui = 31,
        Rgba8ui = 32,
        R32ui = 33,
        Rgb10a2ui = 34,
        Rg32ui = 35,
        Rg16ui = 36,
        Rg8ui = 37,
        R16ui = 38,
        R8ui = 39,
    },
    ImageChannelOrder = {
        R = 0,
        A = 1,
        RG = 2,
        RA = 3,
        RGB = 4,
        RGBA = 5,
        BGRA = 6,
        ARGB = 7,
        Intensity = 8,
        Luminance = 9,
        Rx = 10,
        RGx = 11,
        RGBx = 12,
        Depth = 13,
        DepthStencil = 14,
        sRGB = 15,
        sRGBx = 16,
        sRGBA = 17,
        sBGRA = 18,
        ABGR = 19,
    },
    ImageChannelDataType = {
        SnormInt8 = 0,
        SnormInt16 = 1,
        UnormInt8 = 2,
        UnormInt16 = 3,
        UnormShort565 = 4,
        UnormShort555 = 5,
        UnormInt101010 = 6,
        SignedInt8 = 7,
        SignedInt16 = 8,
        SignedInt32 = 9,
        UnsignedInt8 = 10,
        UnsignedInt16 = 11,
        UnsignedInt32 = 12,
        HalfFloat = 13,
        Float = 14,
        UnormInt24 = 15,
        UnormInt101010_2 = 16,
    },
    ImageOperandsShift = {
        Bias = 0,
        Lod = 1,
        Grad = 2,
        ConstOffset = 3,
        Offset = 4,
        ConstOffsets = 5,
        Sample = 6,
        MinLod = 7,
    },
    ImageOperandsMask = {
        MaskNone = 0,
        Bias = 0x00000001,
        Lod = 0x00000002,
        Grad = 0x00000004,
        ConstOffset = 0x00000008,
        Offset = 0x00000010,
        ConstOffsets = 0x00000020,
        Sample = 0x00000040,
        MinLod = 0x00000080,
    },
    FPFastMathModeShift = {
        NotNaN = 0,
        NotInf = 1,
        NSZ = 2,
        AllowRecip = 3,
        Fast = 4,
    },
    FPFastMathModeMask = {
        MaskNone = 0,
        NotNaN = 0x00000001,
        NotInf = 0x00000002,
        NSZ = 0x00000004,
        AllowRecip = 0x00000008,
        Fast = 0x00000010,
    },
    FPRoundingMode = {
        RTE = 0,
        RTZ = 1,
        RTP = 2,
        RTN = 3,
    },
    LinkageType = {
        Export = 0,
        Import = 1,
    },
    AccessQualifier = {
        ReadOnly = 0,
        WriteOnly = 1,
        ReadWrite = 2,
    },
    FunctionParameterAttribute = {
        Zext = 0,
        Sext = 1,
        ByVal = 2,
        Sret = 3,
        NoAlias = 4,
        NoCapture = 5,
        NoWrite = 6,
        NoReadWrite = 7,
    },
    Decoration = {
        RelaxedPrecision = 0,
        SpecId = 1,
        Block = 2,
        BufferBlock = 3,
        RowMajor = 4,
        ColMajor = 5,
        ArrayStride = 6,
        MatrixStride = 7,
        GLSLShared = 8,
        GLSLPacked = 9,
        CPacked = 10,
        BuiltIn = 11,
        NoPerspective = 13,
        Flat = 14,
        Patch = 15,
        Centroid = 16,
        Sample = 17,
        Invariant = 18,
        Restrict = 19,
        Aliased = 20,
        Volatile = 21,
        Constant = 22,
        Coherent = 23,
        NonWritable = 24,
        NonReadable = 25,
        Uniform = 26,
        SaturatedConversion = 28,
        Stream = 29,
        Location = 30,
        Component = 31,
        Index = 32,
        Binding = 33,
        DescriptorSet = 34,
        Offset = 35,
        XfbBuffer = 36,
        XfbStride = 37,
        FuncParamAttr = 38,
        FPRoundingMode = 39,
        FPFastMathMode = 40,
        LinkageAttributes = 41,
        NoContraction = 42,
        InputAttachmentIndex = 43,
        Alignment = 44,
        MaxByteOffset = 45,
        AlignmentId = 46,
        MaxByteOffsetId = 47,
        ExplicitInterpAMD = 4999,
        OverrideCoverageNV = 5248,
        PassthroughNV = 5250,
        ViewportRelativeNV = 5252,
        SecondaryViewportRelativeNV = 5256,
        HlslCounterBufferGOOGLE = 5634,
        HlslSemanticGOOGLE = 5635,
    },
    BuiltIn = {
        Position = 0,
        PointSize = 1,
        ClipDistance = 3,
        CullDistance = 4,
        VertexId = 5,
        InstanceId = 6,
        PrimitiveId = 7,
        InvocationId = 8,
        Layer = 9,
        ViewportIndex = 10,
        TessLevelOuter = 11,
        TessLevelInner = 12,
        TessCoord = 13,
        PatchVertices = 14,
        FragCoord = 15,
        PointCoord = 16,
        FrontFacing = 17,
        SampleId = 18,
        SamplePosition = 19,
        SampleMask = 20,
        FragDepth = 22,
        HelperInvocation = 23,
        NumWorkgroups = 24,
        WorkgroupSize = 25,
        WorkgroupId = 26,
        LocalInvocationId = 27,
        GlobalInvocationId = 28,
        LocalInvocationIndex = 29,
        WorkDim = 30,
        GlobalSize = 31,
        EnqueuedWorkgroupSize = 32,
        GlobalOffset = 33,
        GlobalLinearId = 34,
        SubgroupSize = 36,
        SubgroupMaxSize = 37,
        NumSubgroups = 38,
        NumEnqueuedSubgroups = 39,
        SubgroupId = 40,
        SubgroupLocalInvocationId = 41,
        VertexIndex = 42,
        InstanceIndex = 43,
        SubgroupEqMaskKHR = 4416,
        SubgroupGeMaskKHR = 4417,
        SubgroupGtMaskKHR = 4418,
        SubgroupLeMaskKHR = 4419,
        SubgroupLtMaskKHR = 4420,
        BaseVertex = 4424,
        BaseInstance = 4425,
        DrawIndex = 4426,
        DeviceIndex = 4438,
        ViewIndex = 4440,
        BaryCoordNoPerspAMD = 4992,
        BaryCoordNoPerspCentroidAMD = 4993,
        BaryCoordNoPerspSampleAMD = 4994,
        BaryCoordSmoothAMD = 4995,
        BaryCoordSmoothCentroidAMD = 4996,
        BaryCoordSmoothSampleAMD = 4997,
        BaryCoordPullModelAMD = 4998,
        FragStencilRefEXT = 5014,
        ViewportMaskNV = 5253,
        SecondaryPositionNV = 5257,
        SecondaryViewportMaskNV = 5258,
        PositionPerViewNV = 5261,
        ViewportMaskPerViewNV = 5262,
    },
    SelectionControlShift = {
        Flatten = 0,
        DontFlatten = 1,
    },
    SelectionControlMask = {
        MaskNone = 0,
        Flatten = 0x00000001,
        DontFlatten = 0x00000002,
    },
    LoopControlShift = {
        Unroll = 0,
        DontUnroll = 1,
        DependencyInfinite = 2,
        DependencyLength = 3,
    },
    LoopControlMask = {
        MaskNone = 0,
        Unroll = 0x00000001,
        DontUnroll = 0x00000002,
        DependencyInfinite = 0x00000004,
        DependencyLength = 0x00000008,
    },
    FunctionControlShift = {
        Inline = 0,
        DontInline = 1,
        Pure = 2,
        Const = 3,
    },
    FunctionControlMask = {
        MaskNone = 0,
        Inline = 0x00000001,
        DontInline = 0x00000002,
        Pure = 0x00000004,
        Const = 0x00000008,
    },
    MemorySemanticsShift = {
        Acquire = 1,
        Release = 2,
        AcquireRelease = 3,
        SequentiallyConsistent = 4,
        UniformMemory = 6,
        SubgroupMemory = 7,
        WorkgroupMemory = 8,
        CrossWorkgroupMemory = 9,
        AtomicCounterMemory = 10,
        ImageMemory = 11,
    },
    MemorySemanticsMask = {
        MaskNone = 0,
        Acquire = 0x00000002,
        Release = 0x00000004,
        AcquireRelease = 0x00000008,
        SequentiallyConsistent = 0x00000010,
        UniformMemory = 0x00000040,
        SubgroupMemory = 0x00000080,
        WorkgroupMemory = 0x00000100,
        CrossWorkgroupMemory = 0x00000200,
        AtomicCounterMemory = 0x00000400,
        ImageMemory = 0x00000800,
    },
    MemoryAccessShift = {
        Volatile = 0,
        Aligned = 1,
        Nontemporal = 2,
    },
    MemoryAccessMask = {
        MaskNone = 0,
        Volatile = 0x00000001,
        Aligned = 0x00000002,
        Nontemporal = 0x00000004,
    },
    Scope = {
        CrossDevice = 0,
        Device = 1,
        Workgroup = 2,
        Subgroup = 3,
        Invocation = 4,
    },
    GroupOperation = {
        Reduce = 0,
        InclusiveScan = 1,
        ExclusiveScan = 2,
    },
    KernelEnqueueFlags = {
        NoWait = 0,
        WaitKernel = 1,
        WaitWorkGroup = 2,
    },
    KernelProfilingInfoShift = {
        CmdExecTime = 0,
    },
    KernelProfilingInfoMask = {
        MaskNone = 0,
        CmdExecTime = 0x00000001,
    },
    Capability = {
        Matrix = 0,
        Shader = 1,
        Geometry = 2,
        Tessellation = 3,
        Addresses = 4,
        Linkage = 5,
        Kernel = 6,
        Vector16 = 7,
        Float16Buffer = 8,
        Float16 = 9,
        Float64 = 10,
        Int64 = 11,
        Int64Atomics = 12,
        ImageBasic = 13,
        ImageReadWrite = 14,
        ImageMipmap = 15,
        Pipes = 17,
        Groups = 18,
        DeviceEnqueue = 19,
        LiteralSampler = 20,
        AtomicStorage = 21,
        Int16 = 22,
        TessellationPointSize = 23,
        GeometryPointSize = 24,
        ImageGatherExtended = 25,
        StorageImageMultisample = 27,
        UniformBufferArrayDynamicIndexing = 28,
        SampledImageArrayDynamicIndexing = 29,
        StorageBufferArrayDynamicIndexing = 30,
        StorageImageArrayDynamicIndexing = 31,
        ClipDistance = 32,
        CullDistance = 33,
        ImageCubeArray = 34,
        SampleRateShading = 35,
        ImageRect = 36,
        SampledRect = 37,
        GenericPointer = 38,
        Int8 = 39,
        InputAttachment = 40,
        SparseResidency = 41,
        MinLod = 42,
        Sampled1D = 43,
        Image1D = 44,
        SampledCubeArray = 45,
        SampledBuffer = 46,
        ImageBuffer = 47,
        ImageMSArray = 48,
        StorageImageExtendedFormats = 49,
        ImageQuery = 50,
        DerivativeControl = 51,
        InterpolationFunction = 52,
        TransformFeedback = 53,
        GeometryStreams = 54,
        StorageImageReadWithoutFormat = 55,
        StorageImageWriteWithoutFormat = 56,
        MultiViewport = 57,
        SubgroupDispatch = 58,
        NamedBarrier = 59,
        PipeStorage = 60,
        SubgroupBallotKHR = 4423,
        DrawParameters = 4427,
        SubgroupVoteKHR = 4431,
        StorageBuffer16BitAccess = 4433,
        StorageUniformBufferBlock16 = 4433,
        StorageUniform16 = 4434,
        UniformAndStorageBuffer16BitAccess = 4434,
        StoragePushConstant16 = 4435,
        StorageInputOutput16 = 4436,
        DeviceGroup = 4437,
        MultiView = 4439,
        VariablePointersStorageBuffer = 4441,
        VariablePointers = 4442,
        AtomicStorageOps = 4445,
        SampleMaskPostDepthCoverage = 4447,
        ImageGatherBiasLodAMD = 5009,
        FragmentMaskAMD = 5010,
        StencilExportEXT = 5013,
        ImageReadWriteLodAMD = 5015,
        SampleMaskOverrideCoverageNV = 5249,
        GeometryShaderPassthroughNV = 5251,
        ShaderViewportIndexLayerEXT = 5254,
        ShaderViewportIndexLayerNV = 5254,
        ShaderViewportMaskNV = 5255,
        ShaderStereoViewNV = 5259,
        PerViewAttributesNV = 5260,
        SubgroupShuffleINTEL = 5568,
        SubgroupBufferBlockIOINTEL = 5569,
        SubgroupImageBlockIOINTEL = 5570,
    },
    Op = {
        OpNop = 0,
        OpUndef = 1,
        OpSourceContinued = 2,
        OpSource = 3,
        OpSourceExtension = 4,
        OpName = 5,
        OpMemberName = 6,
        OpString = 7,
        OpLine = 8,
        OpExtension = 10,
        OpExtInstImport = 11,
        OpExtInst = 12,
        OpMemoryModel = 14,
        OpEntryPoint = 15,
        OpExecutionMode = 16,
        OpCapability = 17,
        OpTypeVoid = 19,
        OpTypeBool = 20,
        OpTypeInt = 21,
        OpTypeFloat = 22,
        OpTypeVector = 23,
        OpTypeMatrix = 24,
        OpTypeImage = 25,
        OpTypeSampler = 26,
        OpTypeSampledImage = 27,
        OpTypeArray = 28,
        OpTypeRuntimeArray = 29,
        OpTypeStruct = 30,
        OpTypeOpaque = 31,
        OpTypePointer = 32,
        OpTypeFunction = 33,
        OpTypeEvent = 34,
        OpTypeDeviceEvent = 35,
        OpTypeReserveId = 36,
        OpTypeQueue = 37,
        OpTypePipe = 38,
        OpTypeForwardPointer = 39,
        OpConstantTrue = 41,
        OpConstantFalse = 42,
        OpConstant = 43,
        OpConstantComposite = 44,
        OpConstantSampler = 45,
        OpConstantNull = 46,
        OpSpecConstantTrue = 48,
        OpSpecConstantFalse = 49,
        OpSpecConstant = 50,
        OpSpecConstantComposite = 51,
        OpSpecConstantOp = 52,
        OpFunction = 54,
        OpFunctionParameter = 55,
        OpFunctionEnd = 56,
        OpFunctionCall = 57,
        OpVariable = 59,
        OpImageTexelPointer = 60,
        OpLoad = 61,
        OpStore = 62,
        OpCopyMemory = 63,
        OpCopyMemorySized = 64,
        OpAccessChain = 65,
        OpInBoundsAccessChain = 66,
        OpPtrAccessChain = 67,
        OpArrayLength = 68,
        OpGenericPtrMemSemantics = 69,
        OpInBoundsPtrAccessChain = 70,
        OpDecorate = 71,
        OpMemberDecorate = 72,
        OpDecorationGroup = 73,
        OpGroupDecorate = 74,
        OpGroupMemberDecorate = 75,
        OpVectorExtractDynamic = 77,
        OpVectorInsertDynamic = 78,
        OpVectorShuffle = 79,
        OpCompositeConstruct = 80,
        OpCompositeExtract = 81,
        OpCompositeInsert = 82,
        OpCopyObject = 83,
        OpTranspose = 84,
        OpSampledImage = 86,
        OpImageSampleImplicitLod = 87,
        OpImageSampleExplicitLod = 88,
        OpImageSampleDrefImplicitLod = 89,
        OpImageSampleDrefExplicitLod = 90,
        OpImageSampleProjImplicitLod = 91,
        OpImageSampleProjExplicitLod = 92,
        OpImageSampleProjDrefImplicitLod = 93,
        OpImageSampleProjDrefExplicitLod = 94,
        OpImageFetch = 95,
        OpImageGather = 96,
        OpImageDrefGather = 97,
        OpImageRead = 98,
        OpImageWrite = 99,
        OpImage = 100,
        OpImageQueryFormat = 101,
        OpImageQueryOrder = 102,
        OpImageQuerySizeLod = 103,
        OpImageQuerySize = 104,
        OpImageQueryLod = 105,
        OpImageQueryLevels = 106,
        OpImageQuerySamples = 107,
        OpConvertFToU = 109,
        OpConvertFToS = 110,
        OpConvertSToF = 111,
        OpConvertUToF = 112,
        OpUConvert = 113,
        OpSConvert = 114,
        OpFConvert = 115,
        OpQuantizeToF16 = 116,
        OpConvertPtrToU = 117,
        OpSatConvertSToU = 118,
        OpSatConvertUToS = 119,
        OpConvertUToPtr = 120,
        OpPtrCastToGeneric = 121,
        OpGenericCastToPtr = 122,
        OpGenericCastToPtrExplicit = 123,
        OpBitcast = 124,
        OpSNegate = 126,
        OpFNegate = 127,
        OpIAdd = 128,
        OpFAdd = 129,
        OpISub = 130,
        OpFSub = 131,
        OpIMul = 132,
        OpFMul = 133,
        OpUDiv = 134,
        OpSDiv = 135,
        OpFDiv = 136,
        OpUMod = 137,
        OpSRem = 138,
        OpSMod = 139,
        OpFRem = 140,
        OpFMod = 141,
        OpVectorTimesScalar = 142,
        OpMatrixTimesScalar = 143,
        OpVectorTimesMatrix = 144,
        OpMatrixTimesVector = 145,
        OpMatrixTimesMatrix = 146,
        OpOuterProduct = 147,
        OpDot = 148,
        OpIAddCarry = 149,
        OpISubBorrow = 150,
        OpUMulExtended = 151,
        OpSMulExtended = 152,
        OpAny = 154,
        OpAll = 155,
        OpIsNan = 156,
        OpIsInf = 157,
        OpIsFinite = 158,
        OpIsNormal = 159,
        OpSignBitSet = 160,
        OpLessOrGreater = 161,
        OpOrdered = 162,
        OpUnordered = 163,
        OpLogicalEqual = 164,
        OpLogicalNotEqual = 165,
        OpLogicalOr = 166,
        OpLogicalAnd = 167,
        OpLogicalNot = 168,
        OpSelect = 169,
        OpIEqual = 170,
        OpINotEqual = 171,
        OpUGreaterThan = 172,
        OpSGreaterThan = 173,
        OpUGreaterThanEqual = 174,
        OpSGreaterThanEqual = 175,
        OpULessThan = 176,
        OpSLessThan = 177,
        OpULessThanEqual = 178,
        OpSLessThanEqual = 179,
        OpFOrdEqual = 180,
        OpFUnordEqual = 181,
        OpFOrdNotEqual = 182,
        OpFUnordNotEqual = 183,
        OpFOrdLessThan = 184,
        OpFUnordLessThan = 185,
        OpFOrdGreaterThan = 186,
        OpFUnordGreaterThan = 187,
        OpFOrdLessThanEqual = 188,
        OpFUnordLessThanEqual = 189,
        OpFOrdGreaterThanEqual = 190,
        OpFUnordGreaterThanEqual = 191,
        OpShiftRightLogical = 194,
        OpShiftRightArithmetic = 195,
        OpShiftLeftLogical = 196,
        OpBitwiseOr = 197,
        OpBitwiseXor = 198,
        OpBitwiseAnd = 199,
        OpNot = 200,
        OpBitFieldInsert = 201,
        OpBitFieldSExtract = 202,
        OpBitFieldUExtract = 203,
        OpBitReverse = 204,
        OpBitCount = 205,
        OpDPdx = 207,
        OpDPdy = 208,
        OpFwidth = 209,
        OpDPdxFine = 210,
        OpDPdyFine = 211,
        OpFwidthFine = 212,
        OpDPdxCoarse = 213,
        OpDPdyCoarse = 214,
        OpFwidthCoarse = 215,
        OpEmitVertex = 218,
        OpEndPrimitive = 219,
        OpEmitStreamVertex = 220,
        OpEndStreamPrimitive = 221,
        OpControlBarrier = 224,
        OpMemoryBarrier = 225,
        OpAtomicLoad = 227,
        OpAtomicStore = 228,
        OpAtomicExchange = 229,
        OpAtomicCompareExchange = 230,
        OpAtomicCompareExchangeWeak = 231,
        OpAtomicIIncrement = 232,
        OpAtomicIDecrement = 233,
        OpAtomicIAdd = 234,
        OpAtomicISub = 235,
        OpAtomicSMin = 236,
        OpAtomicUMin = 237,
        OpAtomicSMax = 238,
        OpAtomicUMax = 239,
        OpAtomicAnd = 240,
        OpAtomicOr = 241,
        OpAtomicXor = 242,
        OpPhi = 245,
        OpLoopMerge = 246,
        OpSelectionMerge = 247,
        OpLabel = 248,
        OpBranch = 249,
        OpBranchConditional = 250,
        OpSwitch = 251,
        OpKill = 252,
        OpReturn = 253,
        OpReturnValue = 254,
        OpUnreachable = 255,
        OpLifetimeStart = 256,
        OpLifetimeStop = 257,
        OpGroupAsyncCopy = 259,
        OpGroupWaitEvents = 260,
        OpGroupAll = 261,
        OpGroupAny = 262,
        OpGroupBroadcast = 263,
        OpGroupIAdd = 264,
        OpGroupFAdd = 265,
        OpGroupFMin = 266,
        OpGroupUMin = 267,
        OpGroupSMin = 268,
        OpGroupFMax = 269,
        OpGroupUMax = 270,
        OpGroupSMax = 271,
        OpReadPipe = 274,
        OpWritePipe = 275,
        OpReservedReadPipe = 276,
        OpReservedWritePipe = 277,
        OpReserveReadPipePackets = 278,
        OpReserveWritePipePackets = 279,
        OpCommitReadPipe = 280,
        OpCommitWritePipe = 281,
        OpIsValidReserveId = 282,
        OpGetNumPipePackets = 283,
        OpGetMaxPipePackets = 284,
        OpGroupReserveReadPipePackets = 285,
        OpGroupReserveWritePipePackets = 286,
        OpGroupCommitReadPipe = 287,
        OpGroupCommitWritePipe = 288,
        OpEnqueueMarker = 291,
        OpEnqueueKernel = 292,
        OpGetKernelNDrangeSubGroupCount = 293,
        OpGetKernelNDrangeMaxSubGroupSize = 294,
        OpGetKernelWorkGroupSize = 295,
        OpGetKernelPreferredWorkGroupSizeMultiple = 296,
        OpRetainEvent = 297,
        OpReleaseEvent = 298,
        OpCreateUserEvent = 299,
        OpIsValidEvent = 300,
        OpSetUserEventStatus = 301,
        OpCaptureEventProfilingInfo = 302,
        OpGetDefaultQueue = 303,
        OpBuildNDRange = 304,
        OpImageSparseSampleImplicitLod = 305,
        OpImageSparseSampleExplicitLod = 306,
        OpImageSparseSampleDrefImplicitLod = 307,
        OpImageSparseSampleDrefExplicitLod = 308,
        OpImageSparseSampleProjImplicitLod = 309,
        OpImageSparseSampleProjExplicitLod = 310,
        OpImageSparseSampleProjDrefImplicitLod = 311,
        OpImageSparseSampleProjDrefExplicitLod = 312,
        OpImageSparseFetch = 313,
        OpImageSparseGather = 314,
        OpImageSparseDrefGather = 315,
        OpImageSparseTexelsResident = 316,
        OpNoLine = 317,
        OpAtomicFlagTestAndSet = 318,
        OpAtomicFlagClear = 319,
        OpImageSparseRead = 320,
        OpSizeOf = 321,
        OpTypePipeStorage = 322,
        OpConstantPipeStorage = 323,
        OpCreatePipeFromPipeStorage = 324,
        OpGetKernelLocalSizeForSubgroupCount = 325,
        OpGetKernelMaxNumSubgroups = 326,
        OpTypeNamedBarrier = 327,
        OpNamedBarrierInitialize = 328,
        OpMemoryNamedBarrier = 329,
        OpModuleProcessed = 330,
        OpExecutionModeId = 331,
        OpDecorateId = 332,
        OpSubgroupBallotKHR = 4421,
        OpSubgroupFirstInvocationKHR = 4422,
        OpSubgroupAllKHR = 4428,
        OpSubgroupAnyKHR = 4429,
        OpSubgroupAllEqualKHR = 4430,
        OpSubgroupReadInvocationKHR = 4432,
        OpGroupIAddNonUniformAMD = 5000,
        OpGroupFAddNonUniformAMD = 5001,
        OpGroupFMinNonUniformAMD = 5002,
        OpGroupUMinNonUniformAMD = 5003,
        OpGroupSMinNonUniformAMD = 5004,
        OpGroupFMaxNonUniformAMD = 5005,
        OpGroupUMaxNonUniformAMD = 5006,
        OpGroupSMaxNonUniformAMD = 5007,
        OpFragmentMaskFetchAMD = 5011,
        OpFragmentFetchAMD = 5012,
        OpSubgroupShuffleINTEL = 5571,
        OpSubgroupShuffleDownINTEL = 5572,
        OpSubgroupShuffleUpINTEL = 5573,
        OpSubgroupShuffleXorINTEL = 5574,
        OpSubgroupBlockReadINTEL = 5575,
        OpSubgroupBlockWriteINTEL = 5576,
        OpSubgroupImageBlockReadINTEL = 5577,
        OpSubgroupImageBlockWriteINTEL = 5578,
        OpDecorateStringGOOGLE = 5632,
        OpMemberDecorateStringGOOGLE = 5633,
    },
}


spirv

-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-- FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
-- IN THE MATERIALS.
-- This header is automatically generated by the same tool that creates
-- the Binary Section of the SPIR-V specification.
-- Enumeration tokens for SPIR-V, in various styles:
--   C, C++, C++11, JSON, Lua, Python
--
-- - C will have tokens with a "Spv" prefix, e.g.: SpvSourceLanguageGLSL
-- - C++ will have tokens in the "spv" name space, e.g.: spv::SourceLanguageGLSL
-- - C++11 will use enum classes in the spv namespace, e.g.: spv::SourceLanguage::GLSL
-- - Lua will use tables, e.g.: spv.SourceLanguage.GLSL
-- - Python will use dictionaries, e.g.: spv['SourceLanguage']['GLSL']
--
-- Some tokens act like mask values, which can be OR'd together,
-- while others are mutually exclusive.  The mask-like ones have
-- "Mask" in their name, and a parallel enum that has the shift
-- amount (1 << x) for each corresponding enumerant.
spv = {
    MagicNumber = 0x07230203,
    Version = 0x00010000,
    Revision = 12,
    OpCodeMask = 0xffff,
    WordCountShift = 16,
    SourceLanguage = {
        Unknown = 0,
        ESSL = 1,
        GLSL = 2,
        OpenCL_C = 3,
        OpenCL_CPP = 4,
        HLSL = 5,
    },
    ExecutionModel = {
        Vertex = 0,
        TessellationControl = 1,
        TessellationEvaluation = 2,
        Geometry = 3,
        Fragment = 4,
        GLCompute = 5,
        Kernel = 6,
    },
    AddressingModel = {
        Logical = 0,
        Physical32 = 1,
        Physical64 = 2,
    },
    MemoryModel = {
        Simple = 0,
        GLSL450 = 1,
        OpenCL = 2,
    },
    ExecutionMode = {
        Invocations = 0,
        SpacingEqual = 1,
        SpacingFractionalEven = 2,
        SpacingFractionalOdd = 3,
        VertexOrderCw = 4,
        VertexOrderCcw = 5,
        PixelCenterInteger = 6,
        OriginUpperLeft = 7,
        OriginLowerLeft = 8,
        EarlyFragmentTests = 9,
        PointMode = 10,
        Xfb = 11,
        DepthReplacing = 12,
        DepthGreater = 14,
        DepthLess = 15,
        DepthUnchanged = 16,
        LocalSize = 17,
        LocalSizeHint = 18,
        InputPoints = 19,
        InputLines = 20,
        InputLinesAdjacency = 21,
        Triangles = 22,
        InputTrianglesAdjacency = 23,
        Quads = 24,
        Isolines = 25,
        OutputVertices = 26,
        OutputPoints = 27,
        OutputLineStrip = 28,
        OutputTriangleStrip = 29,
        VecTypeHint = 30,
        ContractionOff = 31,
        PostDepthCoverage = 4446,
        StencilRefReplacingEXT = 5027,
    },
    StorageClass = {
        UniformConstant = 0,
        Input = 1,
        Uniform = 2,
        Output = 3,
        Workgroup = 4,
        CrossWorkgroup = 5,
        Private = 6,
        Function = 7,
        Generic = 8,
        PushConstant = 9,
        AtomicCounter = 10,
        Image = 11,
        StorageBuffer = 12,
    },
    Dim = {
        Dim1D = 0,
        Dim2D = 1,
        Dim3D = 2,
        Cube = 3,
        Rect = 4,
        Buffer = 5,
        SubpassData = 6,
    },
    SamplerAddressingMode = {
        None = 0,
        ClampToEdge = 1,
        Clamp = 2,
        Repeat = 3,
        RepeatMirrored = 4,
    },
    SamplerFilterMode = {
        Nearest = 0,
        Linear = 1,
    },
    ImageFormat = {
        Unknown = 0,
        Rgba32f = 1,
        Rgba16f = 2,
        R32f = 3,
        Rgba8 = 4,
        Rgba8Snorm = 5,
        Rg32f = 6,
        Rg16f = 7,
        R11fG11fB10f = 8,
        R16f = 9,
        Rgba16 = 10,
        Rgb10A2 = 11,
        Rg16 = 12,
        Rg8 = 13,
        R16 = 14,
        R8 = 15,
        Rgba16Snorm = 16,
        Rg16Snorm = 17,
        Rg8Snorm = 18,
        R16Snorm = 19,
        R8Snorm = 20,
        Rgba32i = 21,
        Rgba16i = 22,
        Rgba8i = 23,
        R32i = 24,
        Rg32i = 25,
        Rg16i = 26,
        Rg8i = 27,
        R16i = 28,
        R8i = 29,
        Rgba32ui = 30,
        Rgba16ui = 31,
        Rgba8ui = 32,
        R32ui = 33,
        Rgb10a2ui = 34,
        Rg32ui = 35,
        Rg16ui = 36,
        Rg8ui = 37,
        R16ui = 38,
        R8ui = 39,
    },
    ImageChannelOrder = {
        R = 0,
        A = 1,
        RG = 2,
        RA = 3,
        RGB = 4,
        RGBA = 5,
        BGRA = 6,
        ARGB = 7,
        Intensity = 8,
        Luminance = 9,
        Rx = 10,
        RGx = 11,
        RGBx = 12,
        Depth = 13,
        DepthStencil = 14,
        sRGB = 15,
        sRGBx = 16,
        sRGBA = 17,
        sBGRA = 18,
        ABGR = 19,
    },
    ImageChannelDataType = {
        SnormInt8 = 0,
        SnormInt16 = 1,
        UnormInt8 = 2,
        UnormInt16 = 3,
        UnormShort565 = 4,
        UnormShort555 = 5,
        UnormInt101010 = 6,
        SignedInt8 = 7,
        SignedInt16 = 8,
        SignedInt32 = 9,
        UnsignedInt8 = 10,
        UnsignedInt16 = 11,
        UnsignedInt32 = 12,
        HalfFloat = 13,
        Float = 14,
        UnormInt24 = 15,
        UnormInt101010_2 = 16,
    },
    ImageOperandsShift = {
        Bias = 0,
        Lod = 1,
        Grad = 2,
        ConstOffset = 3,
        Offset = 4,
        ConstOffsets = 5,
        Sample = 6,
        MinLod = 7,
    },
    ImageOperandsMask = {
        MaskNone = 0,
        Bias = 0x00000001,
        Lod = 0x00000002,
        Grad = 0x00000004,
        ConstOffset = 0x00000008,
        Offset = 0x00000010,
        ConstOffsets = 0x00000020,
        Sample = 0x00000040,
        MinLod = 0x00000080,
    },
    FPFastMathModeShift = {
        NotNaN = 0,
        NotInf = 1,
        NSZ = 2,
        AllowRecip = 3,
        Fast = 4,
    },
    FPFastMathModeMask = {
        MaskNone = 0,
        NotNaN = 0x00000001,
        NotInf = 0x00000002,
        NSZ = 0x00000004,
        AllowRecip = 0x00000008,
        Fast = 0x00000010,
    },
    FPRoundingMode = {
        RTE = 0,
        RTZ = 1,
        RTP = 2,
        RTN = 3,
    },
    LinkageType = {
        Export = 0,
        Import = 1,
    },
    AccessQualifier = {
        ReadOnly = 0,
        WriteOnly = 1,
        ReadWrite = 2,
    },
    FunctionParameterAttribute = {
        Zext = 0,
        Sext = 1,
        ByVal = 2,
        Sret = 3,
        NoAlias = 4,
        NoCapture = 5,
        NoWrite = 6,
        NoReadWrite = 7,
    },
    Decoration = {
        RelaxedPrecision = 0,
        SpecId = 1,
        Block = 2,
        BufferBlock = 3,
        RowMajor = 4,
        ColMajor = 5,
        ArrayStride = 6,
        MatrixStride = 7,
        GLSLShared = 8,
        GLSLPacked = 9,
        CPacked = 10,
        BuiltIn = 11,
        NoPerspective = 13,
        Flat = 14,
        Patch = 15,
        Centroid = 16,
        Sample = 17,
        Invariant = 18,
        Restrict = 19,
        Aliased = 20,
        Volatile = 21,
        Constant = 22,
        Coherent = 23,
        NonWritable = 24,
        NonReadable = 25,
        Uniform = 26,
        SaturatedConversion = 28,
        Stream = 29,
        Location = 30,
        Component = 31,
        Index = 32,
        Binding = 33,
        DescriptorSet = 34,
        Offset = 35,
        XfbBuffer = 36,
        XfbStride = 37,
        FuncParamAttr = 38,
        FPRoundingMode = 39,
        FPFastMathMode = 40,
        LinkageAttributes = 41,
        NoContraction = 42,
        InputAttachmentIndex = 43,
        Alignment = 44,
        ExplicitInterpAMD = 4999,
        OverrideCoverageNV = 5248,
        PassthroughNV = 5250,
        ViewportRelativeNV = 5252,
        SecondaryViewportRelativeNV = 5256,
        HlslCounterBufferGOOGLE = 5634,
        HlslSemanticGOOGLE = 5635,
    },
    BuiltIn = {
        Position = 0,
        PointSize = 1,
        ClipDistance = 3,
        CullDistance = 4,
        VertexId = 5,
        InstanceId = 6,
        PrimitiveId = 7,
        InvocationId = 8,
        Layer = 9,
        ViewportIndex = 10,
        TessLevelOuter = 11,
        TessLevelInner = 12,
        TessCoord = 13,
        PatchVertices = 14,
        FragCoord = 15,
        PointCoord = 16,
        FrontFacing = 17,
        SampleId = 18,
        SamplePosition = 19,
        SampleMask = 20,
        FragDepth = 22,
        HelperInvocation = 23,
        NumWorkgroups = 24,
        WorkgroupSize = 25,
        WorkgroupId = 26,
        LocalInvocationId = 27,
        GlobalInvocationId = 28,
        LocalInvocationIndex = 29,
        WorkDim = 30,
        GlobalSize = 31,
        EnqueuedWorkgroupSize = 32,
        GlobalOffset = 33,
        GlobalLinearId = 34,
        SubgroupSize = 36,
        SubgroupMaxSize = 37,
        NumSubgroups = 38,
        NumEnqueuedSubgroups = 39,
        SubgroupId = 40,
        SubgroupLocalInvocationId = 41,
        VertexIndex = 42,
        InstanceIndex = 43,
        SubgroupEqMaskKHR = 4416,
        SubgroupGeMaskKHR = 4417,
        SubgroupGtMaskKHR = 4418,
        SubgroupLeMaskKHR = 4419,
        SubgroupLtMaskKHR = 4420,
        BaseVertex = 4424,
        BaseInstance = 4425,
        DrawIndex = 4426,
        DeviceIndex = 4438,
        ViewIndex = 4440,
        BaryCoordNoPerspAMD = 4992,
        BaryCoordNoPerspCentroidAMD = 4993,
        BaryCoordNoPerspSampleAMD = 4994,
        BaryCoordSmoothAMD = 4995,
        BaryCoordSmoothCentroidAMD = 4996,
        BaryCoordSmoothSampleAMD = 4997,
        BaryCoordPullModelAMD = 4998,
        FragStencilRefEXT = 5014,
        ViewportMaskNV = 5253,
        SecondaryPositionNV = 5257,
        SecondaryViewportMaskNV = 5258,
        PositionPerViewNV = 5261,
        ViewportMaskPerViewNV = 5262,
    },
    SelectionControlShift = {
        Flatten = 0,
        DontFlatten = 1,
    },
    SelectionControlMask = {
        MaskNone = 0,
        Flatten = 0x00000001,
        DontFlatten = 0x00000002,
    },
    LoopControlShift = {
        Unroll = 0,
        DontUnroll = 1,
    },
    LoopControlMask = {
        MaskNone = 0,
        Unroll = 0x00000001,
        DontUnroll = 0x00000002,
    },
    FunctionControlShift = {
        Inline = 0,
        DontInline = 1,
        Pure = 2,
        Const = 3,
    },
    FunctionControlMask = {
        MaskNone = 0,
        Inline = 0x00000001,
        DontInline = 0x00000002,
        Pure = 0x00000004,
        Const = 0x00000008,
    },
    MemorySemanticsShift = {
        Acquire = 1,
        Release = 2,
        AcquireRelease = 3,
        SequentiallyConsistent = 4,
        UniformMemory = 6,
        SubgroupMemory = 7,
        WorkgroupMemory = 8,
        CrossWorkgroupMemory = 9,
        AtomicCounterMemory = 10,
        ImageMemory = 11,
    },
    MemorySemanticsMask = {
        MaskNone = 0,
        Acquire = 0x00000002,
        Release = 0x00000004,
        AcquireRelease = 0x00000008,
        SequentiallyConsistent = 0x00000010,
        UniformMemory = 0x00000040,
        SubgroupMemory = 0x00000080,
        WorkgroupMemory = 0x00000100,
        CrossWorkgroupMemory = 0x00000200,
        AtomicCounterMemory = 0x00000400,
        ImageMemory = 0x00000800,
    },
    MemoryAccessShift = {
        Volatile = 0,
        Aligned = 1,
        Nontemporal = 2,
    },
    MemoryAccessMask = {
        MaskNone = 0,
        Volatile = 0x00000001,
        Aligned = 0x00000002,
        Nontemporal = 0x00000004,
    },
    Scope = {
        CrossDevice = 0,
        Device = 1,
        Workgroup = 2,
        Subgroup = 3,
        Invocation = 4,
    },
    GroupOperation = {
        Reduce = 0,
        InclusiveScan = 1,
        ExclusiveScan = 2,
    },
    KernelEnqueueFlags = {
        NoWait = 0,
        WaitKernel = 1,
        WaitWorkGroup = 2,
    },
    KernelProfilingInfoShift = {
        CmdExecTime = 0,
    },
    KernelProfilingInfoMask = {
        MaskNone = 0,
        CmdExecTime = 0x00000001,
    },
    Capability = {
        Matrix = 0,
        Shader = 1,
        Geometry = 2,
        Tessellation = 3,
        Addresses = 4,
        Linkage = 5,
        Kernel = 6,
        Vector16 = 7,
        Float16Buffer = 8,
        Float16 = 9,
        Float64 = 10,
        Int64 = 11,
        Int64Atomics = 12,
        ImageBasic = 13,
        ImageReadWrite = 14,
        ImageMipmap = 15,
        Pipes = 17,
        Groups = 18,
        DeviceEnqueue = 19,
        LiteralSampler = 20,
        AtomicStorage = 21,
        Int16 = 22,
        TessellationPointSize = 23,
        GeometryPointSize = 24,
        ImageGatherExtended = 25,
        StorageImageMultisample = 27,
        UniformBufferArrayDynamicIndexing = 28,
        SampledImageArrayDynamicIndexing = 29,
        StorageBufferArrayDynamicIndexing = 30,
        StorageImageArrayDynamicIndexing = 31,
        ClipDistance = 32,
        CullDistance = 33,
        ImageCubeArray = 34,
        SampleRateShading = 35,
        ImageRect = 36,
        SampledRect = 37,
        GenericPointer = 38,
        Int8 = 39,
        InputAttachment = 40,
        SparseResidency = 41,
        MinLod = 42,
        Sampled1D = 43,
        Image1D = 44,
        SampledCubeArray = 45,
        SampledBuffer = 46,
        ImageBuffer = 47,
        ImageMSArray = 48,
        StorageImageExtendedFormats = 49,
        ImageQuery = 50,
        DerivativeControl = 51,
        InterpolationFunction = 52,
        TransformFeedback = 53,
        GeometryStreams = 54,
        StorageImageReadWithoutFormat = 55,
        StorageImageWriteWithoutFormat = 56,
        MultiViewport = 57,
        SubgroupBallotKHR = 4423,
        DrawParameters = 4427,
        SubgroupVoteKHR = 4431,
        StorageBuffer16BitAccess = 4433,
        StorageUniformBufferBlock16 = 4433,
        StorageUniform16 = 4434,
        UniformAndStorageBuffer16BitAccess = 4434,
        StoragePushConstant16 = 4435,
        StorageInputOutput16 = 4436,
        DeviceGroup = 4437,
        MultiView = 4439,
        VariablePointersStorageBuffer = 4441,
        VariablePointers = 4442,
        AtomicStorageOps = 4445,
        SampleMaskPostDepthCoverage = 4447,
        ImageGatherBiasLodAMD = 5009,
        FragmentMaskAMD = 5010,
        StencilExportEXT = 5013,
        ImageReadWriteLodAMD = 5015,
        SampleMaskOverrideCoverageNV = 5249,
        GeometryShaderPassthroughNV = 5251,
        ShaderViewportIndexLayerEXT = 5254,
        ShaderViewportIndexLayerNV = 5254,
        ShaderViewportMaskNV = 5255,
        ShaderStereoViewNV = 5259,
        PerViewAttributesNV = 5260,
        SubgroupShuffleINTEL = 5568,
        SubgroupBufferBlockIOINTEL = 5569,
        SubgroupImageBlockIOINTEL = 5570,
    },
    Op = {
        OpNop = 0,
        OpUndef = 1,
        OpSourceContinued = 2,
        OpSource = 3,
        OpSourceExtension = 4,
        OpName = 5,
        OpMemberName = 6,
        OpString = 7,
        OpLine = 8,
        OpExtension = 10,
        OpExtInstImport = 11,
        OpExtInst = 12,
        OpMemoryModel = 14,
        OpEntryPoint = 15,
        OpExecutionMode = 16,
        OpCapability = 17,
        OpTypeVoid = 19,
        OpTypeBool = 20,
        OpTypeInt = 21,
        OpTypeFloat = 22,
        OpTypeVector = 23,
        OpTypeMatrix = 24,
        OpTypeImage = 25,
        OpTypeSampler = 26,
        OpTypeSampledImage = 27,
        OpTypeArray = 28,
        OpTypeRuntimeArray = 29,
        OpTypeStruct = 30,
        OpTypeOpaque = 31,
        OpTypePointer = 32,
        OpTypeFunction = 33,
        OpTypeEvent = 34,
        OpTypeDeviceEvent = 35,
        OpTypeReserveId = 36,
        OpTypeQueue = 37,
        OpTypePipe = 38,
        OpTypeForwardPointer = 39,
        OpConstantTrue = 41,
        OpConstantFalse = 42,
        OpConstant = 43,
        OpConstantComposite = 44,
        OpConstantSampler = 45,
        OpConstantNull = 46,
        OpSpecConstantTrue = 48,
        OpSpecConstantFalse = 49,
        OpSpecConstant = 50,
        OpSpecConstantComposite = 51,
        OpSpecConstantOp = 52,
        OpFunction = 54,
        OpFunctionParameter = 55,
        OpFunctionEnd = 56,
        OpFunctionCall = 57,
        OpVariable = 59,
        OpImageTexelPointer = 60,
        OpLoad = 61,
        OpStore = 62,
        OpCopyMemory = 63,
        OpCopyMemorySized = 64,
        OpAccessChain = 65,
        OpInBoundsAccessChain = 66,
        OpPtrAccessChain = 67,
        OpArrayLength = 68,
        OpGenericPtrMemSemantics = 69,
        OpInBoundsPtrAccessChain = 70,
        OpDecorate = 71,
        OpMemberDecorate = 72,
        OpDecorationGroup = 73,
        OpGroupDecorate = 74,
        OpGroupMemberDecorate = 75,
        OpVectorExtractDynamic = 77,
        OpVectorInsertDynamic = 78,
        OpVectorShuffle = 79,
        OpCompositeConstruct = 80,
        OpCompositeExtract = 81,
        OpCompositeInsert = 82,
        OpCopyObject = 83,
        OpTranspose = 84,
        OpSampledImage = 86,
        OpImageSampleImplicitLod = 87,
        OpImageSampleExplicitLod = 88,
        OpImageSampleDrefImplicitLod = 89,
        OpImageSampleDrefExplicitLod = 90,
        OpImageSampleProjImplicitLod = 91,
        OpImageSampleProjExplicitLod = 92,
        OpImageSampleProjDrefImplicitLod = 93,
        OpImageSampleProjDrefExplicitLod = 94,
        OpImageFetch = 95,
        OpImageGather = 96,
        OpImageDrefGather = 97,
        OpImageRead = 98,
        OpImageWrite = 99,
        OpImage = 100,
        OpImageQueryFormat = 101,
        OpImageQueryOrder = 102,
        OpImageQuerySizeLod = 103,
        OpImageQuerySize = 104,
        OpImageQueryLod = 105,
        OpImageQueryLevels = 106,
        OpImageQuerySamples = 107,
        OpConvertFToU = 109,
        OpConvertFToS = 110,
        OpConvertSToF = 111,
        OpConvertUToF = 112,
        OpUConvert = 113,
        OpSConvert = 114,
        OpFConvert = 115,
        OpQuantizeToF16 = 116,
        OpConvertPtrToU = 117,
        OpSatConvertSToU = 118,
        OpSatConvertUToS = 119,
        OpConvertUToPtr = 120,
        OpPtrCastToGeneric = 121,
        OpGenericCastToPtr = 122,
        OpGenericCastToPtrExplicit = 123,
        OpBitcast = 124,
        OpSNegate = 126,
        OpFNegate = 127,
        OpIAdd = 128,
        OpFAdd = 129,
        OpISub = 130,
        OpFSub = 131,
        OpIMul = 132,
        OpFMul = 133,
        OpUDiv = 134,
        OpSDiv = 135,
        OpFDiv = 136,
        OpUMod = 137,
        OpSRem = 138,
        OpSMod = 139,
        OpFRem = 140,
        OpFMod = 141,
        OpVectorTimesScalar = 142,
        OpMatrixTimesScalar = 143,
        OpVectorTimesMatrix = 144,
        OpMatrixTimesVector = 145,
        OpMatrixTimesMatrix = 146,
        OpOuterProduct = 147,
        OpDot = 148,
        OpIAddCarry = 149,
        OpISubBorrow = 150,
        OpUMulExtended = 151,
        OpSMulExtended = 152,
        OpAny = 154,
        OpAll = 155,
        OpIsNan = 156,
        OpIsInf = 157,
        OpIsFinite = 158,
        OpIsNormal = 159,
        OpSignBitSet = 160,
        OpLessOrGreater = 161,
        OpOrdered = 162,
        OpUnordered = 163,
        OpLogicalEqual = 164,
        OpLogicalNotEqual = 165,
        OpLogicalOr = 166,
        OpLogicalAnd = 167,
        OpLogicalNot = 168,
        OpSelect = 169,
        OpIEqual = 170,
        OpINotEqual = 171,
        OpUGreaterThan = 172,
        OpSGreaterThan = 173,
        OpUGreaterThanEqual = 174,
        OpSGreaterThanEqual = 175,
        OpULessThan = 176,
        OpSLessThan = 177,
        OpULessThanEqual = 178,
        OpSLessThanEqual = 179,
        OpFOrdEqual = 180,
        OpFUnordEqual = 181,
        OpFOrdNotEqual = 182,
        OpFUnordNotEqual = 183,
        OpFOrdLessThan = 184,
        OpFUnordLessThan = 185,
        OpFOrdGreaterThan = 186,
        OpFUnordGreaterThan = 187,
        OpFOrdLessThanEqual = 188,
        OpFUnordLessThanEqual = 189,
        OpFOrdGreaterThanEqual = 190,
        OpFUnordGreaterThanEqual = 191,
        OpShiftRightLogical = 194,
        OpShiftRightArithmetic = 195,
        OpShiftLeftLogical = 196,
        OpBitwiseOr = 197,
        OpBitwiseXor = 198,
        OpBitwiseAnd = 199,
        OpNot = 200,
        OpBitFieldInsert = 201,
        OpBitFieldSExtract = 202,
        OpBitFieldUExtract = 203,
        OpBitReverse = 204,
        OpBitCount = 205,
        OpDPdx = 207,
        OpDPdy = 208,
        OpFwidth = 209,
        OpDPdxFine = 210,
        OpDPdyFine = 211,
        OpFwidthFine = 212,
        OpDPdxCoarse = 213,
        OpDPdyCoarse = 214,
        OpFwidthCoarse = 215,
        OpEmitVertex = 218,
        OpEndPrimitive = 219,
        OpEmitStreamVertex = 220,
        OpEndStreamPrimitive = 221,
        OpControlBarrier = 224,
        OpMemoryBarrier = 225,
        OpAtomicLoad = 227,
        OpAtomicStore = 228,
        OpAtomicExchange = 229,
        OpAtomicCompareExchange = 230,
        OpAtomicCompareExchangeWeak = 231,
        OpAtomicIIncrement = 232,
        OpAtomicIDecrement = 233,
        OpAtomicIAdd = 234,
        OpAtomicISub = 235,
        OpAtomicSMin = 236,
        OpAtomicUMin = 237,
        OpAtomicSMax = 238,
        OpAtomicUMax = 239,
        OpAtomicAnd = 240,
        OpAtomicOr = 241,
        OpAtomicXor = 242,
        OpPhi = 245,
        OpLoopMerge = 246,
        OpSelectionMerge = 247,
        OpLabel = 248,
        OpBranch = 249,
        OpBranchConditional = 250,
        OpSwitch = 251,
        OpKill = 252,
        OpReturn = 253,
        OpReturnValue = 254,
        OpUnreachable = 255,
        OpLifetimeStart = 256,
        OpLifetimeStop = 257,
        OpGroupAsyncCopy = 259,
        OpGroupWaitEvents = 260,
        OpGroupAll = 261,
        OpGroupAny = 262,
        OpGroupBroadcast = 263,
        OpGroupIAdd = 264,
        OpGroupFAdd = 265,
        OpGroupFMin = 266,
        OpGroupUMin = 267,
        OpGroupSMin = 268,
        OpGroupFMax = 269,
        OpGroupUMax = 270,
        OpGroupSMax = 271,
        OpReadPipe = 274,
        OpWritePipe = 275,
        OpReservedReadPipe = 276,
        OpReservedWritePipe = 277,
        OpReserveReadPipePackets = 278,
        OpReserveWritePipePackets = 279,
        OpCommitReadPipe = 280,
        OpCommitWritePipe = 281,
        OpIsValidReserveId = 282,
        OpGetNumPipePackets = 283,
        OpGetMaxPipePackets = 284,
        OpGroupReserveReadPipePackets = 285,
        OpGroupReserveWritePipePackets = 286,
        OpGroupCommitReadPipe = 287,
        OpGroupCommitWritePipe = 288,
        OpEnqueueMarker = 291,
        OpEnqueueKernel = 292,
        OpGetKernelNDrangeSubGroupCount = 293,
        OpGetKernelNDrangeMaxSubGroupSize = 294,
        OpGetKernelWorkGroupSize = 295,
        OpGetKernelPreferredWorkGroupSizeMultiple = 296,
        OpRetainEvent = 297,
        OpReleaseEvent = 298,
        OpCreateUserEvent = 299,
        OpIsValidEvent = 300,
        OpSetUserEventStatus = 301,
        OpCaptureEventProfilingInfo = 302,
        OpGetDefaultQueue = 303,
        OpBuildNDRange = 304,
        OpImageSparseSampleImplicitLod = 305,
        OpImageSparseSampleExplicitLod = 306,
        OpImageSparseSampleDrefImplicitLod = 307,
        OpImageSparseSampleDrefExplicitLod = 308,
        OpImageSparseSampleProjImplicitLod = 309,
        OpImageSparseSampleProjExplicitLod = 310,
        OpImageSparseSampleProjDrefImplicitLod = 311,
        OpImageSparseSampleProjDrefExplicitLod = 312,
        OpImageSparseFetch = 313,
        OpImageSparseGather = 314,
        OpImageSparseDrefGather = 315,
        OpImageSparseTexelsResident = 316,
        OpNoLine = 317,
        OpAtomicFlagTestAndSet = 318,
        OpAtomicFlagClear = 319,
        OpImageSparseRead = 320,
        OpDecorateId = 332,
        OpSubgroupBallotKHR = 4421,
        OpSubgroupFirstInvocationKHR = 4422,
        OpSubgroupAllKHR = 4428,
        OpSubgroupAnyKHR = 4429,
        OpSubgroupAllEqualKHR = 4430,
        OpSubgroupReadInvocationKHR = 4432,
        OpGroupIAddNonUniformAMD = 5000,
        OpGroupFAddNonUniformAMD = 5001,
        OpGroupFMinNonUniformAMD = 5002,
        OpGroupUMinNonUniformAMD = 5003,
        OpGroupSMinNonUniformAMD = 5004,
        OpGroupFMaxNonUniformAMD = 5005,
        OpGroupUMaxNonUniformAMD = 5006,
        OpGroupSMaxNonUniformAMD = 5007,
        OpFragmentMaskFetchAMD = 5011,
        OpFragmentFetchAMD = 5012,
        OpSubgroupShuffleINTEL = 5571,
        OpSubgroupShuffleDownINTEL = 5572,
        OpSubgroupShuffleUpINTEL = 5573,
        OpSubgroupShuffleXorINTEL = 5574,
        OpSubgroupBlockReadINTEL = 5575,
        OpSubgroupBlockWriteINTEL = 5576,
        OpSubgroupImageBlockReadINTEL = 5577,
        OpSubgroupImageBlockWriteINTEL = 5578,
        OpDecorateStringGOOGLE = 5632,
        OpMemberDecorateStringGOOGLE = 5633,
    },
}


Hello

print("Hello UEFI World")


Fact

-- defines a factorial function
function fact (n)
  if n == 0 then
    return 1
  else
    return n * fact(n-1)
  end
end

print("enter a number:")
a = io.read("*number")        -- read a number
print(fact(a))


automenu

--[[
Automatically generated boot menu of the installed Linux kernels

Example:

m = require "automenu"
m.run { dir = "/",
        default = 1,
        timeout = 5,
        append = "root=/dev/hda2 ro",
}

TODO:
- add hooks
- demo adding break options from user config
- kernel flavor preference (pae/rt)
]]

local lfs = require "lfs"
local sl = require "syslinux"

local single = false
local verbosity = 2

local function modifiers ()
   return (single and " single" or "") .. ({" quiet",""," debug"})[verbosity]
end

local function scan (params)
   local sep = string.sub (params.dir, -1) == "/" and "" or "/"
   if not params.items then params.items = {} end
   for name in lfs.dir (params.dir) do
      local path = params.dir .. sep .. name
      if lfs.attributes (path, "mode") == "file" then
         local from,to,version = string.find (name, "^vmlinuz%-(.*)")
         if from then
            local initrd = params.dir .. sep .. "initrd.img-" .. version
            local initrd_param = ""
            if lfs.attributes (initrd, "size") then
               initrd_param = "initrd=" .. initrd .. " "
            end
            table.insert (params.items, {
                             show = function () return name end,
                             version = version,
                             execute = function () sl.boot_linux (path, initrd_param .. params.append .. modifiers ()) end
                          })
         end
      end
   end
end

local function version_gt (v1, v2)
   local negatives = {"rc", "pre"}
   local m1, r1 = string.match (v1, "^(%D*)(.*)")
   local m2, r2 = string.match (v2, "^(%D*)(.*)")
   if m1 ~= m2 then
      for _, suffix in ipairs (negatives) do
         suffix = "-" .. suffix
         if m1 == suffix and m2 ~= suffix then
            return false
         elseif m1 ~= suffix and m2 == suffix then
            return true
         end
      end
      return m1 > m2
   end
   m1, r1 = string.match (r1, "^(%d*)(.*)")
   m2, r2 = string.match (r2, "^(%d*)(.*)")
   m1 = tonumber (m1) or 0
   m2 = tonumber (m2) or 0
   if m1 ~= m2 then
      return m1 > m2
   end
   if r1 == "" and r2 == "" then
      return false
   end
   return version_gt (r1, r2)
end

local function kernel_gt (k1, k2)
   return version_gt (k1.version, k2.version)
end

local function print_or_call (x, def)
   local t = type (x)
   if t == "nil" then
      if def then print (def) end
   elseif t == "function" then
      x ()
   else
      print (x)
   end
end

local function draw (params)
   print_or_call (params.title, "\n=== Boot menu ===")
   for i, item in ipairs (params.items) do
      print ((i == params.default and " > " or "   ") .. i .. "  " .. item.show ())
   end
   print ("\nKernel arguments:\n  " .. params.append .. modifiers ())
   print ("\nHit a number to select from the menu,\n    ENTER to accept default,\n    ESC to exit\n or any other key to print menu again")
end

local function choose (params)
   draw (params)
   print ("\nBooting in " .. params.timeout .. " s...")
   while true do
      local i = sl.get_key (params.timeout * 1000)
      if i == sl.KEY.ESC then
         break
      else
         if i == sl.KEY.NONE or i == sl.KEY.ENTER then
            i = params.default
         elseif i == sl.KEY.DOWN then
            params.default = params.default < #params.items and params.default + 1 or #params.items
         elseif i == sl.KEY.UP then
            params.default = params.default > 1 and params.default - 1 or 1
         else
            i = i - string.byte "0"
         end
         if params.items[i] then
            params.items[i].execute ()
         end
         params.timeout = 0
         draw (params)
      end
   end
end

local function run (params)
   scan (params)
   if not next (params.items) then
      print ("No kernels found in directory " .. params.dir)
      os.exit (false)
   end
   table.sort (params.items, kernel_gt)
   table.insert (params.items, {
                    show = function () return "Single user: " .. (single and "true" or "false") end,
                    execute = function () single = not single end
                 })
   table.insert (params.items, {
                    show = function () return "Verbosity: " .. ({"quiet","normal","debug"})[verbosity] end,
                    execute = function () verbosity = verbosity < 3 and verbosity + 1 or 1 end
                 })
   choose (params)
end

return {
   scan = scan,
   choose = choose,
   run = run
}


simplemenu

-- A translation of com32/cmenu/simple.c into Lua

local m = require "cmenu"
local sl = require "syslinux"

m.init()
m.set_window_size(1, 1, 23, 78)
local testing = m.add_named_menu("testing", " Testing ")
-- demonstrate identifying (named) submenu by number:
m.add_item("Self Loop", "Go to testing", m.action.SUBMENU, nil, testing)
m.add_item("Memory Test", "Perform extensive memory testing", m.action.RUN, "memtest")
m.add_item("Exit this menu", "Go one level up", m.action.EXITMENU, "exit")

local rescue = m.add_menu(" Rescue Options ")
m.add_item("Linux Rescue", "linresc", m.action.RUN, "linresc")
m.add_item("Dos Rescue", "dosresc", m.action.RUN, "dosresc")
m.add_item("Windows Rescue", "winresc", m.action.RUN, "winresc")
m.add_item("Exit this menu", "Go one level up", m.action.EXITMENU, "exit")

m.add_named_menu("main", " Main Menu ")
m.add_item("Prepare", "prep", m.action.RUN, "prep")
m.add_item("Rescue options...", "Troubleshoot a system", m.action.SUBMENU, nil, rescue)
-- demonstrate identifying submenu by name:
m.add_item("Testing...", "Options to test hardware", m.action.SUBMENU, "testing")
m.add_item("Exit to prompt", "Exit the menu system", m.action.EXITMENU, "exit")

-- demonstrate finding menu explicitly:
local action, data = m.showmenus(m.find_menu_num("main"))

if action == m.action.RUN then
  sl.run_command (data)
else
  print (action, data)
end


sources = {
   "loader_example.cc",
   }

-- premake4.lua
solution "TinyObjLoaderSolution"
   configurations { "Release", "Debug" }

   if (os.is("windows")) then
      platforms { "x32", "x64" }
   else
      platforms { "native", "x32", "x64" }
   end

   -- A project defines one build target
   project "tinyobjloader"
      kind "ConsoleApp"
      language "C++"
      files { sources }

      configuration "Debug"
         defines { "DEBUG" } -- -DDEBUG
         flags { "Symbols" }
         targetname "loader_example_debug"

      configuration "Release"
         -- defines { "NDEBUG" } -- -NDEBUG
         flags { "Symbols", "Optimize" }
         targetname "loader_example"


newoption {
   trigger     = "with-zlib",
   description = "Build with zlib."
}

newoption {
   trigger     = "with-zstd",
   description = "Build with ZStandard compression."
}

newoption {
   trigger     = "clang",
   description = "Use clang compiler."
}

newoption {
   trigger     = "asan",
   description = "Enable AddressSanitizer(gcc or clang only)."
}

solution "objview"
	-- location ( "build" )
	configurations { "Release", "Debug" }
	platforms {"native", "x64", "x32"}

	project "objview"

	kind "ConsoleApp"
	language "C++"
	files { "viewer.cc", "trackball.cc" }
	includedirs { "./" }
	includedirs { "../../" }

	flags { "c++11" }

        if _OPTIONS['clang'] then
           toolset "clang"
        end

	if _OPTIONS['with-zlib'] then
		defines { 'ENABLE_ZLIB' }
		links { 'z' }
	end

	if _OPTIONS['asan'] then
		buildoptions { '-fsanitize=address' }
		linkoptions { '-fsanitize=address' }
	end

	if _OPTIONS['with-zstd'] then
		print("with-zstd")
		defines { 'ENABLE_ZSTD' }
		-- Set path to zstd installed dir.
		includedirs { '$$HOME/local/include' }
		libdirs { '$$HOME/local/lib' }
		links { 'zstd' }
	end

	-- Uncomment if you want address sanitizer(gcc/clang only)
	--buildoptions { "-fsanitize=address" }
	--linkoptions { "-fsanitize=address" }

	configuration { "linux" }
		linkoptions { "`pkg-config --libs glfw3`" }
		links { "GL", "GLU", "m", "GLEW", "X11", "Xrandr", "Xinerama", "Xi", "Xxf86vm", "Xcursor", "dl" }
		linkoptions { "-pthread" }

	configuration { "windows" }
		-- Path to GLFW3
		includedirs { '../../../local/glfw-3.2.bin.WIN64/include' }
		libdirs { '../../../local/glfw-3.2.bin.WIN64/lib-vc2015' }
		-- Path to GLEW
		includedirs { '../../../local/glew-1.13.0/include' }
		libdirs { '../../../local/glew-1.13.0/lib/Release/x64' }

		links { "glfw3", "glew32", "gdi32", "winmm", "user32", "glu32","opengl32", "kernel32" }
		defines { "_CRT_SECURE_NO_WARNINGS" }
		defines { "NOMINMAX" }

	configuration { "macosx" }
		includedirs { "/usr/local/include" }
		buildoptions { "-Wno-deprecated-declarations" }
		libdirs { "/usr/local/lib" }
		links { "glfw3", "GLEW" }
		linkoptions { "-framework OpenGL", "-framework Cocoa", "-framework IOKit", "-framework CoreVideo" }

	configuration "Debug"
		defines { "DEBUG" }
		flags { "Symbols"}

	configuration "Release"
		defines { "NDEBUG" }
		flags { "Optimize"}


lib_sources = {
   "../../tiny_obj_loader.cc"
}

sources = {
   "obj_sticher.cc",
   "obj_writer.cc",
   }

-- premake4.lua
solution "ObjStickerSolution"
   configurations { "Release", "Debug" }

   if (os.is("windows")) then
      platforms { "x32", "x64" }
   else
      platforms { "native", "x32", "x64" }
   end

   includedirs {
      "../../"
   }

   -- A project defines one build target
   project "obj_sticher"
      kind "ConsoleApp"
      language "C++"
      files { lib_sources, sources }

      configuration "Debug"
         defines { "DEBUG" } -- -DDEBUG
         flags { "Symbols" }
         targetname "obj_sticher_debug"

      configuration "Release"
         -- defines { "NDEBUG" } -- -NDEBUG
         flags { "Symbols", "Optimize" }
         targetname "obj_sticher"


solution "objview"
	-- location ( "build" )
	configurations { "Release", "Debug" }
	platforms {"native", "x64", "x32"}

	project "objview"

		kind "ConsoleApp"
		language "C++"
		files { "viewer.cc", "trackball.cc" }
		includedirs { "./" }
		includedirs { "../../" }

		configuration { "linux" }
			linkoptions { "`pkg-config --libs glfw3`" }
			links { "GL", "GLU", "m", "GLEW", "X11", "Xrandr", "Xinerama", "Xi", "Xxf86vm", "Xcursor", "dl" }
			linkoptions { "-pthread" }

		configuration { "windows" }
			-- Path to GLFW3
			includedirs { '../../../../local/glfw-3.1.2.bin.WIN64/include' }
			libdirs { '../../../../local/glfw-3.1.2.bin.WIN64/lib-vc2013' }
			-- Path to GLEW
			includedirs { '../../../../local/glew-1.13.0/include' }
			libdirs { '../../../../local/glew-1.13.0/lib/Release/x64' }

			links { "glfw3", "glew32", "gdi32", "winmm", "user32", "glu32","opengl32", "kernel32" }
			defines { "_CRT_SECURE_NO_WARNINGS" }

		configuration { "macosx" }
			includedirs { "/usr/local/include" }
			buildoptions { "-Wno-deprecated-declarations" }
			libdirs { "/usr/local/lib" }
			links { "glfw3", "GLEW" }
			linkoptions { "-framework OpenGL", "-framework Cocoa", "-framework IOKit", "-framework CoreVideo" }

		configuration "Debug"
			defines { "DEBUG" }
			flags { "Symbols", "ExtraWarnings"}

		configuration "Release"
			defines { "NDEBUG" }
			flags { "Optimize", "ExtraWarnings"}


stacksnoop

#!/usr/bin/env bcc-lua
--[[
--]]
local program = [[
#include <uapi/linux/ptrace.h>
#include <linux/sched.h>
struct data_t {
    u64 stack_id;
    u32 pid;
    char comm[TASK_COMM_LEN];
};
BPF_STACK_TRACE(stack_traces, 128);
BPF_PERF_OUTPUT(events);
void trace_stack(struct pt_regs *ctx) {
    u32 pid = bpf_get_current_pid_tgid();
    FILTER
    struct data_t data = {};
    data.stack_id = stack_traces.get_stackid(ctx, 0),
    data.pid = pid;
    bpf_get_current_comm(&data.comm, sizeof(data.comm));
    events.perf_submit(ctx, &data, sizeof(data));
}
]]
local ffi = require("ffi")
return function(BPF, utils)
  local parser = utils.argparse("stacksnoop",
      "Trace and print kernel stack traces for a kernel function")
  parser:flag("-s --offset")
  parser:flag("-v --verbose")
  parser:option("-p --pid"):convert(tonumber)
  parser:argument("function", "kernel function name"):target("fn")
  local args = parser:parse()
  local ksym = BPF.SymbolCache()
  local filter = ""
  if args.pid then
    filter = "if (pid != %d) { return; }" % args.pid
  end
  local text = program:gsub("FILTER", filter)
  local bpf = BPF:new{text=text}
  bpf:attach_kprobe{event=args.fn, fn_name="trace_stack"}
  if BPF.num_open_kprobes() == 0 then
    print("Function \"%s\" not found. Exiting." % {args.fn})
    return
  end
  if args.verbose then
    print("%-18s %-12s %-6s %-3s %s" %
        {"TIME(s)", "COMM", "PID", "CPU", "FUNCTION"})
  else
    print("%-18s %s" % {"TIME(s)", "FUNCTION"})
  end
  local stack_traces = bpf:get_table("stack_traces")
  local start_ts = utils.posix.time_ns()
  local function print_event(cpu, event)
    local ts = (utils.posix.time_ns() - start_ts) / 1e9
    if args.verbose then
      print("%-18.9f %-12.12s %-6d %-3d %s" %
          {ts, ffi.string(event.comm), event.pid, cpu, args.fn})
    else
      print("%-18.9f %s" % {ts, args.fn})
    end
    for addr in stack_traces:walk(tonumber(event.stack_id)) do
      local sym, offset = ksym:resolve(addr)
      if args.offset then
        print("\t%-16p %s+0x%x" % {addr, sym, tonumber(offset)})
      else
        print("\t%-16p %s" % {addr, sym})
      end
    end
    print()
  end
  local TASK_COMM_LEN = 16 -- linux/sched.h
  bpf:get_table("events"):open_perf_buffer(print_event,
    "struct { uint64_t stack_id; uint32_t pid; char comm[$]; }",
    {TASK_COMM_LEN})
  bpf:perf_buffer_poll_loop()
end


tcplife

#!/usr/bin/env bcc-lua
--[[
18-Mar-2017  Simon Liu Created this.
--]]
local ffi = require("ffi")
local bit = require("bit")
ffi.cdef[[
const char *inet_ntop(int af, const void *src, char *dst, int size);
uint16_t ntohs(uint16_t netshort);
]]
local program = [[
#include <uapi/linux/ptrace.h>
#include <linux/tcp.h>
#include <net/sock.h>
#include <bcc/proto.h>
BPF_HASH(birth, struct sock *, u64);
// separate data structs for ipv4 and ipv6
struct ipv4_data_t {
    // XXX: switch some to u32's when supported
    u64 ts_us;
    u64 pid;
    u64 saddr;
    u64 daddr;
    u64 ports;
    u64 rx_b;
    u64 tx_b;
    u64 span_us;
    char task[TASK_COMM_LEN];
};
BPF_PERF_OUTPUT(ipv4_events);
struct ipv6_data_t {
    u64 ts_us;
    u64 pid;
    u64 saddr[2];
    u64 daddr[2];
    u64 ports;
    u64 rx_b;
    u64 tx_b;
    u64 span_us;
    char task[TASK_COMM_LEN];
};
BPF_PERF_OUTPUT(ipv6_events);
struct id_t {
    u32 pid;
    char task[TASK_COMM_LEN];
};
BPF_HASH(whoami, struct sock *, struct id_t);
int trace_tcp_set_state(struct pt_regs *ctx, struct sock *sk, int state)
{
    bpf_trace_printk("tcp_set_stat");
    u32 pid = bpf_get_current_pid_tgid() >> 32;
    // lport is either used in a filter here, or later
    u16 lport = sk->__sk_common.skc_num;
    FILTER_LPORT
    // dport is either used in a filter here, or later
    u16 dport = sk->__sk_common.skc_dport;
    FILTER_DPORT
    /*
     * This tool includes PID and comm context. It's best effort, and may
     * be wrong in some situations. It currently works like this:
     * - record timestamp on any state < TCP_FIN_WAIT1
     * - cache task context on:
     *       TCP_SYN_SENT: tracing from client
     *       TCP_LAST_ACK: client-closed from server
     * - do output on TCP_CLOSE:
     *       fetch task context if cached, or use current task
     */
    // capture birth time
    if (state < TCP_FIN_WAIT1) {
        /*
         * Matching just ESTABLISHED may be sufficient, provided no code-path
         * sets ESTABLISHED without a tcp_set_state() call. Until we know
         * that for sure, match all early states to increase chances a
         * timestamp is set.
         * Note that this needs to be set before the PID filter later on,
         * since the PID isn't reliable for these early stages, so we must
         * save all timestamps and do the PID filter later when we can.
         */
        u64 ts = bpf_ktime_get_ns();
        birth.update(&sk, &ts);
    }
    // record PID & comm on SYN_SENT
    if (state == TCP_SYN_SENT || state == TCP_LAST_ACK) {
        // now we can PID filter, both here and a little later on for CLOSE
        FILTER_PID
        struct id_t me = {.pid = pid};
        bpf_get_current_comm(&me.task, sizeof(me.task));
        whoami.update(&sk, &me);
    }
    if (state != TCP_CLOSE)
        return 0;
    // calculate lifespan
    u64 *tsp, delta_us;
    tsp = birth.lookup(&sk);
    if (tsp == 0) {
        whoami.delete(&sk);     // may not exist
        return 0;               // missed create
    }
    delta_us = (bpf_ktime_get_ns() - *tsp) / 1000;
    birth.delete(&sk);
    // fetch possible cached data, and filter
    struct id_t *mep;
    mep = whoami.lookup(&sk);
    if (mep != 0)
        pid = mep->pid;
    FILTER_PID
    // get throughput stats. see tcp_get_info().
    u64 rx_b = 0, tx_b = 0, sport = 0;
    struct tcp_sock *tp = (struct tcp_sock *)sk;
    rx_b = tp->bytes_received;
    tx_b = tp->bytes_acked;
    u16 family = sk->__sk_common.skc_family;
    if (family == AF_INET) {
        struct ipv4_data_t data4 = {.span_us = delta_us,
            .rx_b = rx_b, .tx_b = tx_b};
        data4.ts_us = bpf_ktime_get_ns() / 1000;
        data4.saddr = sk->__sk_common.skc_rcv_saddr;
        data4.daddr = sk->__sk_common.skc_daddr;
        // a workaround until data4 compiles with separate lport/dport
        data4.pid = pid;
        data4.ports = ntohs(dport) + ((0ULL + lport) << 32);
        if (mep == 0) {
            bpf_get_current_comm(&data4.task, sizeof(data4.task));
        } else {
            bpf_probe_read_kernel(&data4.task, sizeof(data4.task), (void *)mep->task);
        }
        ipv4_events.perf_submit(ctx, &data4, sizeof(data4));
    } else /* 6 */ {
        struct ipv6_data_t data6 = {.span_us = delta_us,
            .rx_b = rx_b, .tx_b = tx_b};
        data6.ts_us = bpf_ktime_get_ns() / 1000;
        bpf_probe_read_kernel(&data6.saddr, sizeof(data6.saddr),
            sk->__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32);
        bpf_probe_read_kernel(&data6.daddr, sizeof(data6.daddr),
            sk->__sk_common.skc_v6_daddr.in6_u.u6_addr32);
        // a workaround until data6 compiles with separate lport/dport
        data6.ports = ntohs(dport) + ((0ULL + lport) << 32);
        data6.pid = pid;
        if (mep == 0) {
            bpf_get_current_comm(&data6.task, sizeof(data6.task));
        } else {
            bpf_probe_read_kernel(&data6.task, sizeof(data6.task), (void *)mep->task);
        }
        ipv6_events.perf_submit(ctx, &data6, sizeof(data6));
    }
    if (mep != 0)
        whoami.delete(&sk);
    return 0;
}
]]
local debug = false
local start_ts = 0
local inet_addresslen = #"255.255.255.255"
local inet6_addresslen = #"ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"
local AF_INET = 2
local AF_INET6 = 10
local header_string = "%-5s %-10.10s %s%-15s %-5s %-15s %-5s %5s %5s %s"
local format_string = "%-5d %-10.10s %s%-15s %-5d %-15s %-5d %5d %5d %.2f"
local ip_string = ""
local ip_version = false
local arg_timestamp = false
local arg_csv = false
local arg_time = false
local examples = [[examples:
    ./tcplife           # trace all TCP connect()s
    ./tcplife -t        # include time column (HH:MM:SS)
    ./tcplife -w        # wider columns (fit IPv6)
    ./tcplife -stT      # csv output, with times & timestamps
    ./tcplife -p 181    # only trace PID 181
    ./tcplife -L 80     # only trace local port 80
    ./tcplife -L 80,81  # only trace local ports 80 and 81
    ./tcplife -D 80     # only trace remote port 80
]]
local function split(str,sep)
   local t = {}
   for w in string.gmatch(str, '([^,]+)') do
      table.insert(t, w)
   end
   return t
end
local function inet_ntop(af, addr, len)
   local addr_dst = ffi.new("char[?]", len)
   local addr_src
   if af == AF_INET then
      addr_src = ffi.new("uint64_t[1]", addr)
   else
      addr_src = ffi.new("uint64_t[2]", addr)
   end
   ffi.C.inet_ntop(af, addr_src, addr_dst, len)
   return ffi.string(addr_dst, len)
end
local function inet_ntohs(port)
   local p = tonumber(port)
   return ffi.C.ntohs(p)
end
local function print_ipv4_event(cpu, event)
   local event_pid = tonumber(event.pid)
   local event_task = ffi.string(event.task)
   local event_ports = tonumber(event.ports)
   local event_tx_b = tonumber(event.tx_b)
   local event_rx_b = tonumber(event.rx_b)
   local event_span_us = tonumber(event.span_us)
   local event_ts_us = tonumber(event.ts_us)
   local event_saddr = inet_ntop(AF_INET, tonumber(event.saddr), inet_addresslen)
   local event_daddr = inet_ntop(AF_INET, tonumber(event.daddr), inet_addresslen)
   if arg_time then
      if arg_csv then
         io.write("%s," % os.date("%H:%M:%S"))
      else
         io.write("%-8s " % os.date("%H:%M:%S"))
      end
   end
   if arg_timestamp then
      if start_ts == 0 then
         start_ts = event_ts_us
      end
      local delta_s = (event_ts_us - start_ts) / 1000000
      if arg.csv then
         io.write("%.6f," % delta_s)
      else
         io.write("%-9.6f " % delta_s)
      end
   end
   local iv = ""
   if ip_version then
      iv = "4"
   end
   print(string.format(format_string, event_pid, event_task, iv,
                       event_saddr, bit.rshift(event_ports,32),
                       event_daddr, bit.band(event_ports,0xffffffff),
                       (event_tx_b / 1024), (event_rx_b / 1024), event_span_us/ 1000))
end
local function print_ipv6_event(cpu, event)
   local event_pid = tonumber(event.pid)
   local event_task = ffi.string(event.task)
   local event_ports = tonumber(event.ports)
   local event_tx_b = tonumber(event.tx_b)
   local event_rx_b = tonumber(event.rx_b)
   local event_span_us = tonumber(event.span_us)
   local event_ts_us = tonumber(event.ts_us)
   local event_saddr = inet_ntop(AF_INET6, {tonumber(event.saddr[0]), tonumber(event.saddr[1])}, inet6_addresslen)
   local event_daddr = inet_ntop(AF_INET6, {tonumber(event.daddr[0]), tonumber(event.daddr[1])}, inet6_addresslen)
   if arg_time then
      if arg_csv then
         io.write("%s," % os.date("%H:%M:%S"))
      else
         io.write("%-8s " % os.date("%H:%M:%S"))
      end
   end
   if arg_timestamp then
      if start_ts == 0 then
         start_ts = event_ts_us
      end
      local delta_s = (event_ts_us - start_ts) / 1000000
      if arg.csv then
         io.write("%.6f," % delta_s)
      else
         io.write("%-9.6f " % delta_s)
      end
   end
   local iv = ""
   if ip_version then
      iv = "6"
   end
   print(string.format(format_string, event_pid, event_task, iv,
                       event_saddr, bit.rshift(event_ports,32),
                       event_daddr, bit.band(event_ports,0xffffffff),
                       (event_tx_b / 1024), (event_rx_b / 1024), event_span_us/ 1000))
end
local function parse_arg(utils)
   local parser = utils.argparse("tcplife",
                                 "Trace the lifespan of TCP sessions and summarize", examples)
   parser:flag("-T --time", "include time column on output (HH:MM:SS)")
   parser:flag("-t --timestamp", "include timestamp on output (seconds)")
   parser:flag("-w --wide", "wide column output (fits IPv6 addresses)")
   parser:flag("-s --csv", "comma separated values output")
   parser:option("-p --pid", "trace this PID only"):convert(tonumber)
   parser:option("-L --localport", "comma-separated list of local ports to trace.")
   parser:option("-D --remoteport", "comma-separated list of remote ports to trace.")
   local args = parser:parse()
   if args.pid then
      local filter = 'if (pid != %d) { return 0; }' % args.pid
      program = program.gsub('FILTER_PID', filter)
   end
   if args.remoteport then
      local dports = split(args.remoteport, ",")
      local dports_if = ""
      for i,d in ipairs(dports) do
         if dports_if == "" then
            dports_if = 'dport != %d' % inet_ntohs(d)
         else
            dports_if = dports_if .. ' && ' .. ('dport != %d' % inet_ntohs(d))
         end
      end
      local filter = "if (%s) { birth.delete(&sk); return 0; }" % dports_if
      program = program:gsub('FILTER_DPORT', filter)
   end
   if args.localport then
      local lports = split(args.localport,",")
      local lports_if = ""
      for i,l in ipairs(lports) do
         if lports_if == "" then
            lports_if = 'lport != %d' % inet_ntohs(l)
         else
            lports_if = lports_if .. ' && ' .. ('lport != %d' % inet_ntohs(l))
         end
      end
      local filter = "if (%s) { birth.delete(&sk); return 0; }" % lports_if
      program = program:gsub('FILTER_LPORT', filter)
   end
   program = program:gsub('FILTER_PID', '')
   program = program:gsub('FILTER_DPORT', '')
   program = program:gsub('FILTER_LPORT', '')
   if args.wide then
      header_string = "%-5s %-16.16s %-2s %-26s %-5s %-26s %-5s %6s %6s %s"
      format_string = "%-5d %-16.16s %-2s %-26s %-5s %-26s %-5d %6d %6d %.2f"
      ip_string = "IP"
      ip_version = true
   end
   if args.csv then
      header_string = "%s,%s,%s,%s,%s,%s,%s,%s,%s,%s"
      format_string = "%d,%s,%s,%s,%s,%s,%d,%d,%d,%.2f"
      ip_string = "IP"
      ip_version = true
      arg_csv = true
   end
   if args.time then
      arg_time = true
      if args.csv then
         io.write("%s," % ("TIME"))
      else
         io.write("%-8s " % ("TIME"))
      end
   end
   if args.timestamp then
      arg_timestamp = true
      if args.csv then
         io.write("%s," % ("TIME(s)"))
      else
         io.write("%-9s " % ("TIME(s)"))
      end
   end
end
return function(BPF, utils)
   parse_arg(utils)
   if debug then
      print(program)
   end
   local bpf = BPF:new{text=program}
   bpf:attach_kprobe{event="tcp_set_state", fn_name="trace_tcp_set_state"}
   print(header_string % {"PID", "COMM",
                          ip_string, "LADDR",
                          "LPORT", "RADDR", "RPORT", "TX_KB", "RX_KB", "MS"})
   local TASK_COMM_LEN = 16 -- linux/sched.h
   bpf:get_table("ipv4_events"):open_perf_buffer(print_ipv4_event, [[
    struct {
      uint64_t ts_us;
      uint64_t pid;
      uint64_t saddr;
      uint64_t daddr;
      uint64_t ports;
      uint64_t rx_b;
      uint64_t tx_b;
      uint64_t span_us;
      char task[$];
    }
   ]], {TASK_COMM_LEN}, 64)
   bpf:get_table("ipv6_events"):open_perf_buffer(print_ipv6_event, [[
    struct {
      uint64_t ts_us;
      uint64_t pid;
      uint64_t saddr[2];
      uint64_t daddr[2];
      uint64_t ports;
      uint64_t rx_b;
      uint64_t tx_b;
      uint64_t span_us;
      char task[$];
    }
   ]], {TASK_COMM_LEN}, 64)
   bpf:perf_buffer_poll_loop()
end


biosnoop

#!/usr/bin/env bcc-lua
--[[
--]]
local program = [[
#include <uapi/linux/ptrace.h>
#include <linux/blkdev.h>
struct val_t {
    u32 pid;
    char name[TASK_COMM_LEN];
};
struct data_t {
    u32 pid;
    u64 rwflag;
    u64 delta;
    u64 sector;
    u64 len;
    u64 ts;
    char disk_name[DISK_NAME_LEN];
    char name[TASK_COMM_LEN];
};
BPF_HASH(start, struct request *);
BPF_HASH(infobyreq, struct request *, struct val_t);
BPF_PERF_OUTPUT(events);
// cache PID and comm by-req
int trace_pid_start(struct pt_regs *ctx, struct request *req)
{
    struct val_t val = {};
    if (bpf_get_current_comm(&val.name, sizeof(val.name)) == 0) {
        val.pid = bpf_get_current_pid_tgid();
        infobyreq.update(&req, &val);
    }
    return 0;
}
// time block I/O
int trace_req_start(struct pt_regs *ctx, struct request *req)
{
    u64 ts;
    ts = bpf_ktime_get_ns();
    start.update(&req, &ts);
    return 0;
}
// output
int trace_req_completion(struct pt_regs *ctx, struct request *req)
{
    u64 *tsp, delta;
    u32 *pidp = 0;
    struct val_t *valp;
    struct data_t data ={};
    u64 ts;
    // fetch timestamp and calculate delta
    tsp = start.lookup(&req);
    if (tsp == 0) {
        // missed tracing issue
        return 0;
    }
    ts = bpf_ktime_get_ns();
    data.delta = ts - *tsp;
    data.ts = ts / 1000;
    valp = infobyreq.lookup(&req);
    if (valp == 0) {
        data.len = req->__data_len;
        data.name[0] = '?';
        data.name[1] = 0;
    } else {
        data.pid = valp->pid;
        data.len = req->__data_len;
        data.sector = req->__sector;
        bpf_probe_read_kernel(&data.name, sizeof(data.name), valp->name);
        bpf_probe_read_kernel(&data.disk_name, sizeof(data.disk_name),
                       req->rq_disk->disk_name);
    }
/*
 * The following deals with a kernel version change (in mainline 4.7, although
 * it may be backported to earlier kernels) with how block request write flags
 * are tested. We handle both pre- and post-change versions here. Please avoid
 * kernel version tests like this as much as possible: they inflate the code,
 * test, and maintenance burden.
 */
#ifdef REQ_WRITE
    data.rwflag = !!(req->cmd_flags & REQ_WRITE);
#elif defined(REQ_OP_SHIFT)
    data.rwflag = !!((req->cmd_flags >> REQ_OP_SHIFT) == REQ_OP_WRITE);
#else
    data.rwflag = !!((req->cmd_flags & REQ_OP_MASK) == REQ_OP_WRITE);
#endif
    events.perf_submit(ctx,&data,sizeof(data));
    start.delete(&req);
    infobyreq.delete(&req);
    return 0;
}
]]
local ffi = require("ffi")
return function(BPF, utils)
  local bpf = BPF:new{text=program}
  bpf:attach_kprobe{event="blk_account_io_start", fn_name="trace_pid_start"}
  bpf:attach_kprobe{event="blk_start_request", fn_name="trace_req_start"}
  bpf:attach_kprobe{event="blk_mq_start_request", fn_name="trace_req_start"}
  bpf:attach_kprobe{event="blk_account_io_done",
      fn_name="trace_req_completion"}
  print("%-14s %-14s %-6s %-7s %-2s %-9s %-7s %7s" % {"TIME(s)", "COMM", "PID",
    "DISK", "T", "SECTOR", "BYTES", "LAT(ms)"})
  local rwflg = ""
  local start_ts = 0
  local prev_ts = 0
  local delta = 0
  local function print_event(cpu, event)
    local val = -1
    local event_pid = event.pid
    local event_delta = tonumber(event.delta)
    local event_sector = tonumber(event.sector)
    local event_len = tonumber(event.len)
    local event_ts = tonumber(event.ts)
    local event_disk_name = ffi.string(event.disk_name)
    local event_name = ffi.string(event.name)
    if event.rwflag == 1 then
      rwflg = "W"
    end
    if event.rwflag == 0 then
      rwflg = "R"
    end
    if not event_name:match("%?") then
      val = event_sector
    end
    if start_ts == 0 then
      prev_ts = start_ts
    end
    if start_ts == 1 then
      delta = delta + (event_ts - prev_ts)
    end
    print("%-14.9f %-14.14s %-6s %-7s %-2s %-9s %-7s %7.2f" % {
      delta / 1000000, event_name, event_pid, event_disk_name, rwflg, val,
      event_len, event_delta / 1000000})
    prev_ts = event_ts
    start_ts = 1
  end
  local TASK_COMM_LEN = 16 -- linux/sched.h
  local DISK_NAME_LEN = 32 -- linux/genhd.h
  bpf:get_table("events"):open_perf_buffer(print_event, [[
    struct {
      uint32_t pid;
      uint64_t rwflag;
      uint64_t delta;
      uint64_t sector;
      uint64_t len;
      uint64_t ts;
      char disk_name[$];
      char name[$];
    }
  ]], {DISK_NAME_LEN, TASK_COMM_LEN}, 64)
  bpf:perf_buffer_poll_loop()
end


uprobe-readline

#!/usr/bin/env bcc-lua
--[[
]]
-- Trace readline() call from all bash instances (print bash commands from all running shells).
-- This is rough equivallent to `bashreadline`
-- Source: http://www.brendangregg.com/blog/2016-02-08/linux-ebpf-bcc-uprobes.html
local ffi = require('ffi')
local bpf = require('bpf')
local S = require('syscall')
-- Kernel-space part of the program
local probe = bpf.uprobe('/bin/bash:readline', function (ptregs)
	local line = ffi.new('char [40]')              -- Create a 40 byte buffer on stack
	ffi.copy(line, ffi.cast('char *', ptregs.ax))  -- Cast `ax` to string pointer and copy to buffer
	print('%s\n', line)                            -- Print to trace_pipe
end, true, -1, 0)
-- User-space part of the program
local ok, err = pcall(function()
	local log = bpf.tracelog()
	print('            TASK-PID   CPU#         TIMESTAMP  FUNCTION')
	print('               | |      |               |         |')
	while true do
		print(log:read())
	end
end)


#!/usr/bin/env bcc-lua
--[[
]]
local program = [[
#include <uapi/linux/ptrace.h>
int trace_method(struct pt_regs *ctx) {
  uint64_t addr;
  bpf_usdt_readarg(2, ctx, &addr);
  char fn_name[128] = {};
  bpf_probe_read_user(&fn_name, sizeof(fn_name), (void *)addr);
  bpf_trace_printk("%s(...)\n", fn_name);
  return 0;
};
]]
return function(BPF, util)
  if not arg[1] then
    print("usage: rubysyms.lua PID")
    return
  end
  local u = util.USDT:new{pid=tonumber(arg[1])}
  u:enable_probe{probe="method__entry", fn_name="trace_method"}
  local b = BPF:new{text=program, usdt=u}
  local pipe = b:pipe()
  while true do
    print(pipe:trace_fields())
  end
end


kprobe-latency

#!/usr/bin/env bcc-lua
--[[
]]
-- This example program measures latency of block device operations and plots it
-- in a histogram. It is similar to BPF example:
-- https://github.com/torvalds/linux/blob/master/samples/bpf/tracex3_kern.c
local ffi = require('ffi')
local bpf = require('bpf')
local S = require('syscall')
-- Shared part of the program
local bins = 100
local map = bpf.map('hash', 512, ffi.typeof('uint64_t'), ffi.typeof('uint64_t'))
local lat_map = bpf.map('array', bins)
-- Kernel-space part of the program
local trace_start = bpf.kprobe('myprobe:blk_start_request', function (ptregs)
	map[ptregs.parm1] = time()
end, false, -1, 0)
local trace_end = bpf.kprobe('myprobe2:blk_account_io_done', function (ptregs)
	-- The lines below are computing index
	-- using log10(x)*10 = log2(x)*10/log2(10) = log2(x)*3
	-- index = 29 ~ 1 usec
	-- index = 59 ~ 1 msec
	-- index = 89 ~ 1 sec
	-- index = 99 ~ 10sec or more
	local delta = time() - map[ptregs.parm1]
	local index = 3 * math.log2(delta)
	if index >= bins then
		index = bins-1
	end
	xadd(lat_map[index], 1)
	return true
end, false, -1, 0)
-- User-space part of the program
pcall(function()
	local counter = 0
	local sym = {' ',' ','.','.','*','*','o','o','O','O','#','#'}
	while true do
		-- Print header once in a while
		if counter % 50 == 0 then
			print('|1us      |10us     |100us    |1ms      |10ms     |100ms    |1s       |10s')
			counter = 0
		end
		counter = counter + 1
		-- Collect all events
		local hist, events = {}, 0
		for i=29,bins-1 do
			local v = tonumber(lat_map[i] or 0)
			if v > 0 then
				hist[i] = hist[i] or 0 + v
				events = events + v
			end
		end
		-- Print histogram symbols based on relative frequency
		local s = ''
		for i=29,bins-1 do
			if hist[i] then
				local c = math.ceil((hist[i] / (events + 1)) * #sym)
				s = s .. sym[c]
			else s = s .. ' ' end
		end
		print(s .. string.format('  ; %d events', events))
		S.sleep(1)
	end
end)


sock-proto

#!/usr/bin/env bcc-lua
--[[
]]
-- This program looks at IP, UDP and ICMP packets and
-- increments counter for each packet of given type seen
-- Rewrite of https://github.com/torvalds/linux/blob/master/samples/bpf/sock_example.c
local ffi = require("ffi")
local bpf = require("bpf")
local S = require("syscall")
-- Shared part of the program
local map = bpf.map('hash', 256)
map[1], map[6], map[17] = 0, 0, 0
-- Kernel-space part of the program
bpf.socket('lo', function (skb)
   local proto = pkt.ip.proto  -- Get byte (ip.proto) from frame at [23]
   xadd(map[proto], 1)         -- Atomic `map[proto] += 1`
end)
-- User-space part of the program
for _ = 1, 10 do
   local icmp, udp, tcp = map[1], map[17], map[6]
   print(string.format('TCP %d UDP %d ICMP %d packets',
   	     tonumber(tcp or 0), tonumber(udp or 0), tonumber(icmp or 0)))
   S.sleep(1)
end


#!/usr/bin/env bcc-lua
--[[
]]
local program = [[
#include <uapi/linux/ptrace.h>
#include <linux/sched.h>
struct key_t {
  u32 prev_pid;
  u32 curr_pid;
};
// map_type, key_type, leaf_type, table_name, num_entry
BPF_HASH(stats, struct key_t, u64, 1024);
int count_sched(struct pt_regs *ctx, struct task_struct *prev) {
  struct key_t key = {};
  u64 zero = 0, *val;
  key.curr_pid = bpf_get_current_pid_tgid();
  key.prev_pid = prev->pid;
  val = stats.lookup_or_try_init(&key, &zero);
  if (val) {
    (*val)++;
  }
  return 0;
}
]]
return function(BPF)
  local b = BPF:new{text=program, debug=0}
  b:attach_kprobe{event="finish_task_switch", fn_name="count_sched"}
  print("Press any key...")
  io.read()
  local t = b:get_table("stats")
  for k, v in t:items() do
    print("task_switch[%d -> %d] = %d" % {k.prev_pid, k.curr_pid, tonumber(v)})
  end
end


sock-protolen

#!/usr/bin/env bcc-lua
--[[
]]
-- This program counts total bytes received per-protocol in 64-bit counters.
-- The map backend is array in this case to avoid key allocations.
-- increments counter for each packet of given type seen
-- Rewrite of https://github.com/torvalds/linux/blob/master/samples/bpf/sock_example.c
local ffi = require("ffi")
local bpf = require("bpf")
local S = require("syscall")
-- Shared part of the program
local map = bpf.map('array', 256, ffi.typeof('uint32_t'), ffi.typeof('uint64_t'))
-- Kernel-space part of the program
bpf.socket('lo', function (skb)
	local proto = pkt.ip.proto  -- Get byte (ip.proto) from frame at [23]
	xadd(map[proto], skb.len)   -- Atomic `map[proto] += <payload length>`
end)
-- User-space part of the program
for _ = 1, 10 do
	local icmp, udp, tcp = map[1], map[17], map[6]
	print(string.format('TCP %d UDP %d ICMP %d bytes',
		tonumber(tcp or 0), tonumber(udp or 0), tonumber(icmp or 0)))
	S.sleep(1)
end


sock-parse-http

#!/usr/bin/env bcc-lua
--[[
]]
-- Simple parsing example of TCP/HTTP that counts frequency of types of requests
-- and shows more complicated pattern matching constructions and slices.
-- Rewrite of a BCC example:
-- https://github.com/iovisor/bcc/blob/master/examples/networking/http_filter/http-parse-simple.c
local ffi = require("ffi")
local bpf = require("bpf")
local S = require("syscall")
-- Shared part of the program
local map = bpf.map('hash', 64)
-- Kernel-space part of the program
local prog = bpf.socket('lo', function (skb)
	-- Only ingress so we don't count twice on loopback
	if skb.ingress_ifindex == 0 then return end
	local data = pkt.ip.tcp.data  -- Get TCP protocol dissector
	-- Continue only if we have 7 bytes of TCP data
	if data + 7 > skb.len then return end
	-- Fetch 4 bytes of TCP data and compare
	local h = data(0, 4)
	if h == 'HTTP' or h == 'GET ' or
	   h == 'POST' or h == 'PUT ' or
	   h == 'HEAD' or h == 'DELE' then
	   	-- If hash key doesn't exist, create it
	   	-- otherwise increment counter
	   local v = map[h]
	   if not v then map[h] = 1
	   else          xadd(map[h], 1)
	   end
	end
end)
-- User-space part of the program
for _ = 1, 10 do
	local strkey = ffi.new('uint32_t [1]')
	local s = ''
	for k,v in map.pairs,map,0 do
		strkey[0] = bpf.ntoh(k)
		s = s..string.format('%s %d ', ffi.string(strkey, 4):match '^%s*(.-)%s*$', tonumber(v))
	end
	if #s > 0 then print(s..'messages') end
	S.sleep(1)
end


tracepoint-offcputime

#!/usr/bin/env bcc-lua
--[[
]]
-- Summarize off-CPU time by stack trace
-- Related tool: https://github.com/iovisor/bcc/blob/master/tools/offcputime.py
local ffi = require('ffi')
local bpf = require('bpf')
local S = require('syscall')
-- Create BPF maps
-- TODO: made smaller to fit default memory limits
local key_t = 'struct { char name[16]; int32_t stack_id; }'
local starts = assert(bpf.map('hash', 128, ffi.typeof('uint32_t'), ffi.typeof('uint64_t')))
local counts = assert(bpf.map('hash', 128, ffi.typeof(key_t), ffi.typeof('uint64_t')))
local stack_traces = assert(bpf.map('stack_trace', 16))
-- Open tracepoint and attach BPF program
-- The 'arg' parses tracepoint format automatically
local tp = bpf.tracepoint('sched/sched_switch', function (arg)
	-- Update previous thread sleep time
	local pid = arg.prev_pid
	local now = time()
	starts[pid] = now
	-- Calculate current thread's delta time
	pid = arg.next_pid
	local from = starts[pid]
	if not from then
		return 0
	end
	local delta = (now - from) / 1000
	starts[pid] = nil
	-- Check if the delta is below 1us
	if delta < 1 then
		return
	end
	-- Create key for this thread
	local key = ffi.new(key_t)
	comm(key.name)
	key.stack_id = stack_id(stack_traces, BPF.F_FAST_STACK_CMP)
	-- Update current thread off cpu time with delta
	local val = counts[key]
	if not val then
		counts[key] = 0
	end
	xadd(counts[key], delta)
end, 0, -1)
-- Helper: load kernel symbols
ffi.cdef 'unsigned long long strtoull(const char *, char **, int);'
local ksyms = {}
for l in io.lines('/proc/kallsyms') do
	local addr, sym = l:match '(%w+) %w (%S+)'
	if addr then ksyms[ffi.C.strtoull(addr, nil, 16)] = sym end
end
-- User-space part of the program
while true do
	for k,v in counts.pairs,counts,nil do
		local s = ''
		local traces = stack_traces[k.stack_id]
		if traces then
			for i, ip in ipairs(traces) do
				s = s .. string.format("    %-16p %s", ip, ksyms[ip])
			end
		end
		s = s .. string.format("    %-16s %s", "-", ffi.string(k.name))
		s = s .. string.format("        %d", tonumber(v))
		print(s)
	end
	S.sleep(1)
end


kprobe-write

#!/usr/bin/env bcc-lua
--[[
]]
-- Simple tracing example that executes a program on
-- return from sys_write() and tracks the number of hits
local ffi = require('ffi')
local bpf = require('bpf')
local S = require('syscall')
-- Shared part of the program
local map = bpf.map('array', 1)
-- Kernel-space part of the program
local probe = bpf.kprobe('myprobe:sys_write', function (ptregs)
   xadd(map[0], 1)
end, true)
-- User-space part of the program
pcall(function()
	for _ = 1, 10 do
	   print('hits: ', tonumber(map[0]))
	   S.sleep(1)
	end
end)


offcputime

#!/usr/bin/env bcc-lua
--[[
]]
local program = [[
#include <uapi/linux/ptrace.h>
#include <linux/sched.h>
#define MINBLOCK_US	1
struct key_t {
    char name[TASK_COMM_LEN];
    int stack_id;
};
BPF_HASH(counts, struct key_t);
BPF_HASH(start, u32);
BPF_STACK_TRACE(stack_traces, 10240);
int oncpu(struct pt_regs *ctx, struct task_struct *prev) {
    u32 pid;
    u64 ts, *tsp;
    // record previous thread sleep time
    if (FILTER) {
        pid = prev->pid;
        ts = bpf_ktime_get_ns();
        start.update(&pid, &ts);
    }
    // calculate current thread's delta time
    pid = bpf_get_current_pid_tgid();
    tsp = start.lookup(&pid);
    if (tsp == 0)
        return 0;        // missed start or filtered
    u64 delta = bpf_ktime_get_ns() - *tsp;
    start.delete(&pid);
    delta = delta / 1000;
    if (delta < MINBLOCK_US)
        return 0;
    // create map key
    u64 zero = 0, *val;
    struct key_t key = {};
    int stack_flags = 0;
    /*
    if (!(prev->flags & PF_KTHREAD))
      stack_flags |= BPF_F_USER_STACK;
    */
    bpf_get_current_comm(&key.name, sizeof(key.name));
    key.stack_id = stack_traces.get_stackid(ctx, stack_flags);
    val = counts.lookup_or_try_init(&key, &zero);
    if (val) {
        (*val) += delta;
    }
    return 0;
}
]]
return function(BPF, utils)
  local ffi = require("ffi")
  local parser = utils.argparse("offcputime", "Summarize off-cpu time")
  parser:flag("-u --user-only")
  parser:option("-p --pid"):convert(tonumber)
  parser:flag("-f --folded")
  parser:option("-d --duration", "duration to trace for", 9999999):convert(tonumber)
  local args = parser:parse()
  local ksym = BPF.SymbolCache()
  local filter = "1"
  local MAXDEPTH = 20
  if args.pid then
    filter = "pid == %d" % args.pid
  elseif args.user_only then
    filter = "!(prev->flags & PF_KTHREAD)"
  end
  local text = program:gsub("FILTER", filter)
  local b = BPF:new{text=text}
  b:attach_kprobe{event="finish_task_switch", fn_name="oncpu"}
  if BPF.num_open_kprobes() == 0 then
    print("no functions matched. quitting...")
    return
  end
  print("Sleeping for %d seconds..." % args.duration)
  pcall(utils.posix.sleep, args.duration)
  print("Tracing...")
  local counts = b:get_table("counts")
  local stack_traces = b:get_table("stack_traces")
  for k, v in counts:items() do
    for addr in stack_traces:walk(tonumber(k.stack_id)) do
      print("    %-16p %s" % {addr, ksym:resolve(addr)})
    end
    print("    %-16s %s" % {"-", ffi.string(k.name)})
    print("        %d\n" % tonumber(v))
  end
end


bashreadline

#!/usr/bin/env bcc-lua
--[[
]]
local ffi = require("ffi")
return function(BPF)
  local b = BPF:new{src_file="bashreadline.c", debug=0}
  b:attach_uprobe{name="/bin/bash", sym="readline", fn_name="printret", retprobe=true}
  local function print_readline(cpu, event)
    print("%-9s %-6d %s" % {os.date("%H:%M:%S"), tonumber(event.pid), ffi.string(event.str)})
  end
  b:get_table("events"):open_perf_buffer(print_readline, "struct { uint64_t pid; char str[80]; }", nil)
  print("%-9s %-6s %s" % {"TIME", "PID", "COMMAND"})
  b:perf_buffer_poll_loop()
end


uprobe-tailkt

#!/usr/bin/env bcc-lua
--[[
]]
-- Trace operations on keys matching given pattern in KyotoTycoon daemon.
-- This can show you if certain keys were modified or read during the lifetime
-- even if KT doesn't support this. It also shows how to attach to C++ mangled symbols.
local ffi = require('ffi')
local bpf = require('bpf')
local S = require('syscall')
local function help(err)
	print(string.format('%s [get|set] [key]', arg[0]))
	if err then print('error: '..err) end
	os.exit(1)
end
-- Accept the same format as ktremotemgr for clarity: <get|set> <key>
local writeable, watch_key, klen = 'any', arg[2] or '*', 80
if     arg[1] == 'get' then writeable = 0
elseif arg[1] == 'set' then writeable = 1
elseif arg[1] == '-h' or arg[1] == '--help' then help()
elseif arg[1] and arg[1] ~= 'any' then
	help(string.format('bad cmd: "%s"', arg[1]))
end
if watch_key ~= '*' then klen = #watch_key end
-- Find a good entrypoint that has both key and differentiates read/write in KT
-- That is going to serve as an attachment point for BPF program
-- ABI: bool accept(void *this, const char* kbuf, size_t ksiz, Visitor* visitor, bool writable)
local key_type = string.format('char [%d]', klen)
local probe = bpf.uprobe('/usr/local/bin/ktserver:kyotocabinet::StashDB::accept',
function (ptregs)
	-- Watch either get/set or both
	if writeable ~= 'any' then
		if ptregs.parm5 ~= writeable then return end
	end
	local line = ffi.new(key_type)
	ffi.copy(line, ffi.cast('char *', ptregs.parm2))
	-- Check if we're looking for specific key
	if watch_key ~= '*' then
		if ptregs.parm3 ~= klen then return false end
		if line ~= watch_key then return false end
	end
	print('%s write:%d\n', line, ptregs.parm5)
end, false, -1, 0)
-- User-space part of the program
local ok, err = pcall(function()
	local log = bpf.tracelog()
	print('            TASK-PID   CPU#         TIMESTAMP  FUNCTION')
	print('               | |      |               |         |')
	while true do
		print(log:read())
	end
end)