diff --git a/res/pygments/ptx.py b/res/pygments/ptx.py deleted file mode 100644 index 52e437d3..00000000 --- a/res/pygments/ptx.py +++ /dev/null @@ -1,72 +0,0 @@ -from pygments.lexer import RegexLexer, include, words -from pygments.token import * - -# https://docs.nvidia.com/cuda/parallel-thread-execution/index.html - -class CustomLexer(RegexLexer): - string = r'"[^"]*?"' - - followsym = r'[a-zA-Z0-9_$]*' - identifier = r'(?:[a-zA-Z]' + followsym + r'| [_$%]' + followsym + r')' - - tokens = { - 'root': [ - include('whitespace'), - (r'%' + identifier, Name.Variable), - - include('definition'), - include('statement'), - include('type'), - - (identifier, Name.Variable), - - (r'(\d+\.\d*|\.\d+|\d+)[eE][+-]?\d+[LlUu]*', Number.Float), - (r'(\d+\.\d*|\.\d+|\d+[fF])[fF]?', Number.Float), - (r'0x[0-9a-fA-F]+[LlUu]*', Number.Hex), - (r'0[0-7]+[LlUu]*', Number.Oct), - (r'\b\d+[LlUu]*\b', Number.Integer), - - (r'[&|^+*/%=~-]', Operator), - (r'[()\[\]\{\},.;<>@]', Punctuation), - ], - 'whitespace': [ - (r'(\n|\s)+', Text), - (r'/\*.*?\*/', Comment.Multiline), - (r'//.*?\n', Comment.Single), - ], - 'definition': [ - (words(('func', 'reg'), prefix=r'\.', suffix=r'\b'), Keyword.Reserved), - (r'^' + identifier + r':', Name.Label), - ], - 'statement': [ - # directive - (words(( - 'address_size', 'file', 'minnctapersm', 'target', 'align', 'func', 'param', - 'tex', 'branchtarget', 'global', 'pragma', 'version', 'callprototype', - 'loc', 'reg', 'visible', 'calltargets', 'local', 'reqntid', 'weak', 'const', - 'maxnctapersm', 'section', 'entry', 'maxnreg', 'shared', 'extern', - 'maxntid', 'sreg', ), prefix=r'\.', suffix=r'\b'), Keyword), - # instruction - (words(( - 'abs', 'div', 'or', 'sin', 'add', 'ex2', 'pmevent', 'slct', 'vmad', 'addc', - 'exit', 'popc', 'sqrt', 'vmax', 'and', 'fma', 'prefetch', 'st', 'atom', - 'isspacep', 'prefetchu', 'sub', 'vmin', 'bar', 'ld', 'prmt', 'subc', 'bfe', - 'ldu', 'rcp', 'suld', 'vote', 'bfi', 'lg2', 'red', 'suq', 'vset', 'bfind', - 'mad', 'rem', 'sured', 'bret', 'sust', 'vshl', 'brev', 'madc', 'rsqrt', - 'testp', 'vshr', 'brkpt', 'max', 'sad', 'tex', 'vsub', 'call', 'membar', - 'selp', 'tld4', 'clz', 'min', 'set', 'trap', 'xor', 'cnot', 'mov', 'setp', - 'txq', 'copysign', 'mul', 'shf', 'vabsdiff', 'cos', 'shfl', 'cvta', 'not', - 'shr', 'cvt', 'neg', 'shl', 'vadd'), prefix=r'\b', suffix=r'[\.\w]+\b'), Keyword), - (words(( - 'vavrg', 'vmax', 'vmin', 'vset', 'mad', 'vsub', 'mul', 'vabsdiff', - 'vadd'), prefix=r'\b', suffix=r'[24]\b'), Keyword), - ], - 'type': [ - (words(( - 's8', 's16', 's32', 's64', - 'u8', 'u16', 'u32', 'u64', - 'f16', 'f16x2', 'f32', 'f64', - 'b8', 'b16', 'b32', 'b64', - 'pred'), prefix=r'\.', suffix=r'\b'), Keyword.Type), - ], - } diff --git a/src/gcn.jl b/src/gcn.jl index 7105b2ae..62735af4 100644 --- a/src/gcn.jl +++ b/src/gcn.jl @@ -12,6 +12,8 @@ GCNCompilerTarget(dev_isa; features="") = GCNCompilerTarget(dev_isa, features) llvm_triple(::GCNCompilerTarget) = "amdgcn-amd-amdhsa" +source_code(target::GCNCompilerTarget) = "gcn" + function llvm_machine(target::GCNCompilerTarget) triple = llvm_triple(target) t = Target(triple=triple) diff --git a/src/reflection.jl b/src/reflection.jl index 26ee62bd..07b53a5a 100644 --- a/src/reflection.jl +++ b/src/reflection.jl @@ -16,23 +16,92 @@ function pygmentize() return _pygmentize[] end +const _pygmentize_version = Ref{Union{VersionNumber,Nothing}}() +function pygmentize_version() + isassigned(_pygmentize_version) && return _pygmentize_version[] + + pygmentize_cmd = pygmentize() + if isnothing(pygmentize_cmd) + return _pygmentize_version[] = nothing + end + + cmd = `$pygmentize_cmd -V` + @static if Sys.iswindows() + # Avoid encoding issues with pipes on Windows by using cmd.exe to capture stdout for us + cmd = `cmd.exe /C $cmd` + cmd = addenv(cmd, "PYTHONUTF8" => 1) + end + version_str = readchomp(cmd) + + pos = findfirst("Pygments version ", version_str) + if !isnothing(pos) + version_start = last(pos) + 1 + version_end = findnext(',', version_str, version_start) - 1 + version = tryparse(VersionNumber, version_str[version_start:version_end]) + else + version = nothing + end + + if isnothing(version) + @warn "Could not parse Pygments version:\n$version_str" + end + + return _pygmentize_version[] = version +end + +function pygmentize_support(lexer) + highlighter_ver = pygmentize_version() + if isnothing(highlighter_ver) + @warn "Syntax highlighting of $lexer code relies on Pygments.\n\ + Use `pip install pygments` to install the lastest version" maxlog=1 + return false + elseif lexer == "ptx" + if highlighter_ver < v"2.16" + @warn "Pygments supports PTX highlighting starting from version 2.16\n\ + Detected version $highlighter_ver\n\ + Please update with `pip install pygments -U`" maxlog=1 + return false + end + return true + elseif lexer == "gcn" + if highlighter_ver < v"2.8" + @warn "Pygments supports GCN highlighting starting from version 2.8\n\ + Detected version $highlighter_ver\n\ + Please update with `pip install pygments -U`" maxlog=1 + return false + end + return true + else + return false + end +end + function highlight(io::IO, code, lexer) - highlighter = pygmentize() have_color = get(io, :color, false) if !have_color print(io, code) elseif lexer == "llvm" InteractiveUtils.print_llvm(io, code) - elseif highlighter !== nothing - custom_lexer = joinpath(dirname(@__DIR__), "res", "pygments", "$lexer.py") - if isfile(custom_lexer) - lexer = `$custom_lexer -x` + elseif pygmentize_support(lexer) + lexer = lexer == "gcn" ? "amdgpu" : lexer + pygments_args = String[pygmentize(), "-f", "terminal", "-P", "bg=dark", "-l", lexer] + @static if Sys.iswindows() + # Avoid encoding issues with pipes on Windows by using a temporary file + mktemp() do tmp_path, tmp_io + println(tmp_io, code) + close(tmp_io) + push!(pygments_args, "-o", tmp_path, tmp_path) + cmd = Cmd(pygments_args) + wait(open(cmd)) # stdout and stderr go to devnull + print(io, read(tmp_path, String)) + end + else + cmd = Cmd(pygments_args) + pipe = open(cmd, "r+") + print(pipe, code) + close(pipe.in) + print(io, read(pipe, String)) end - - pipe = open(`$highlighter -f terminal -P bg=dark -l $lexer`, "r+") - print(pipe, code) - close(pipe.in) - print(io, read(pipe, String)) else print(io, code) end diff --git a/test/utils.jl b/test/utils.jl index 52db84be..82bbbffa 100644 --- a/test/utils.jl +++ b/test/utils.jl @@ -45,3 +45,30 @@ end # problematic examples @test mangle(identity, String, Matrix{Float32}, Broadcast.Broadcasted{Broadcast.ArrayStyle{Matrix{Float32}}, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}, typeof(Base.literal_pow), Tuple{Base.RefValue{typeof(sin)}, Broadcast.Extruded{Matrix{Float32}, Tuple{Bool, Bool}, Tuple{Int64, Int64}}}}) == "identity(String, Array, Broadcasted>, Tuple, OneTo>, literal_pow, Tuple, Extruded, Tuple, Tuple>>>)" end + +@testset "highlighting" begin + ansi_color = "\x1B[3" # beginning of any foreground color change + + @testset "PTX" begin + sample = """ + max.s64 %rd24, %rd18, 0; + add.s64 %rd7, %rd23, -1; + setp.lt.u64 %p2, %rd7, %rd24; + @%p2 bra \$L__BB0_3; + """ + can_highlight = GPUCompiler.pygmentize_support("ptx") + highlighted = sprint(GPUCompiler.highlight, sample, "ptx"; context=(:color => true)) + @test occursin(ansi_color, highlighted) skip=!can_highlight + end + + @testset "GCN" begin + sample = """ + v_add_u32 v3, vcc, s0, v0 + v_mov_b32 v4, s1 + v_addc_u32 v4, vcc, v4, 0, vcc + """ + can_highlight = GPUCompiler.pygmentize_support("gcn") + highlighted = sprint(GPUCompiler.highlight, sample, "gcn"; context=(:color => true)) + @test occursin(ansi_color, highlighted) skip=!can_highlight + end +end