Search code examples
vimsyntaxfoldingllvm-ir

LLVM-IR syntax folding for Vim


I am working with LLVM-IR code, generated by clang -emit-llvm and want to get code folding working.

So far I am using foldmethod=expr and foldexpr=LLVMFold(). I would like to use syntax based folding (i.e. foldmethod=syntax) using the syntax file from the llvm repository. Available here.

Note that the first regex is from the syntax file for the label.

function! LLVMFolds()
    let thisline = getline(v:lnum)
    if match(thisline, '^[-a-zA-Z$._][-a-zA-Z$._0-9]*:') >= 0
        return ">2"
    elseif match(thisline, '^\}$') >= 0
        return "<1"
    elseif match(thisline, '{$') >= 0
        return ">1"
    else
        return "="
    endif
endfunction

Which gobbles the closing braces into the level 2 folds.

Also tried have been foldmethod=indent which didn't fold enough and foldmethod=marker with foldmark="{,}" Ideally for this sample incomplete LLVM-IR code:

define i32 @main() nounwind {
entry:
  %retval = alloca i32, align 4

for.cond:                                         ; preds = %entry
  %4 = load i32* %i, align 4
  %cmp1 = icmp slt i32 %4, 10
  br i1 %cmp1, label %for.body, label %for.end
}

I would like folds to be from the { of the define to the } and in each labelled section, i.e. from the entry: to the clear line.


Solution

  • I have used this function now

    function! LLVMFolds()
        let thisline = getline(v:lnum)
        let nextline = getline(v:lnum + 1)
        " match start of global var block
        if match(thisline, '^@') == 0 && foldlevel(v:lnum - 1) <= 0
            return ">1"
        " match start of global struct block
        elseif match(thisline, '^%') == 0 && foldlevel(v:lnum - 1) <= 0
            return ">1"
        " matches lables
        elseif match(thisline, '^[-a-zA-Z$._][-a-zA-Z$._0-9]*:') >= 0
            return ">2"
        " keep closing brace outside  l2 fold
        elseif match(nextline, '^\}$') >= 0
            return "<2"
        " keep closing brace in l1 fold
        elseif match(thisline, '^\}$') >= 0
            return "<1"
        " open new l1 fold for open brace
        elseif match(thisline, '{$') >= 0
            return ">1"
        " for the next line being empty, close the fold for the var and struct blocks
        elseif match(nextline, '^$') >= 0
            if match(thisline, '^@') == 0 && foldlevel(v:lnum - 1) == 1
                return "<1"
            elseif match(thisline, '^%') >= 0 && foldlevel(v:lnum - 1) == 1
                return "<1"
            else
                return "="
            endif
        else
            return "="
        endif
    endfunction
    

    Which excludes the closing brace from the level 2 fold, and folds the initial lists of global structs and variables.