Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 40 additions & 15 deletions .github/workflows/basic-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,31 @@ env:

jobs:
format-check:
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5

- run: |
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
echo "deb http://apt.llvm.org/noble/ llvm-toolchain-noble-18 main" | sudo tee /etc/apt/sources.list.d/llvm-18.list

- name: Update apt
run: sudo apt-get update

- name: Install clang-format
run: |
sudo apt-get remove clang-format-*
sudo apt-get install -t llvm-toolchain-noble-18 clang-format-18

- name: Format source code
run: |
find demo lib test \
-type f \
-a \( -name "*.c" -o -name "*.cpp" -o -name "*.h" \) \
-not -path "*/lulesh/*" -not -path "*/CallSite.h" \
-print0 \
| xargs -0 clang-format-14 -i
| xargs -0 clang-format-18 -i

- name: Format check
run: |
Expand All @@ -33,28 +46,34 @@ jobs:
runs-on: ubuntu-22.04

steps:
- uses: actions/checkout@v4
- uses: codespell-project/actions-codespell@v2
- uses: actions/checkout@v5
- uses: codespell-project/actions-codespell@v2.2

build-project:
strategy:
fail-fast: false
matrix:
include:
- llvm-version: 12
os: ubuntu-20.04
preset: develop
- llvm-version: 14
os: ubuntu-22.04
preset: develop
- llvm-version: 18
os: ubuntu-24.04
preset: develop
- llvm-version: 21
os: ubuntu-24.04
preset: develop

runs-on: ${{ matrix.os }}

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5

- name: LLVM apt
if: ${{ matrix.llvm-version >= 19 }}
run: |
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
echo "deb http://apt.llvm.org/noble/ llvm-toolchain-noble-${{ matrix.llvm-version }} main" | sudo tee /etc/apt/sources.list.d/llvm-${{ matrix.llvm-version }}.list

- name: Update apt
run: sudo apt-get update
Expand All @@ -73,12 +92,18 @@ jobs:
echo "CLANG_CMAKE_DIR=/usr/lib/llvm-${{ matrix.llvm-version }}/lib/cmake/clang" >> $GITHUB_ENV
echo "EXTERNAL_LIT=/usr/lib/llvm-${{ matrix.llvm-version }}/build/utils/lit/lit.py" >> $GITHUB_ENV

- name: Build IRPrinter
run: |
cmake -B build -DCMAKE_BUILD_TYPE=Debug -DLLVM_DIR=${LLVM_CMAKE_DIR} -DClang_DIR=${CLANG_CMAKE_DIR}
cmake --build build --parallel

- name: Build IRPrinter release
run: |
cmake -B build_rel -DCMAKE_BUILD_TYPE=Release -DLLVM_DIR=${LLVM_CMAKE_DIR} -DClang_DIR=${CLANG_CMAKE_DIR}
cmake --preset release -DLLVM_DIR=${LLVM_CMAKE_DIR} -DClang_DIR=${CLANG_CMAKE_DIR} -DLLVM_EXTERNAL_LIT=${EXTERNAL_LIT}
cmake --build build_rel --parallel --target install

- name: Test and Coverage
run: |
cmake --preset coverage -DLLVM_DIR=${LLVM_CMAKE_DIR} -DClang_DIR=${CLANG_CMAKE_DIR} -DLLVM_EXTERNAL_LIT=${EXTERNAL_LIT}
cmake --build build_cov --target coverage-irprinter

- name: Upload coverage
uses: actions/upload-artifact@v6
with:
name: coverage-report-llvm${{ matrix.llvm-version }}
path: build_cov/coverage_report/
9 changes: 6 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
CMAKE_MINIMUM_REQUIRED(VERSION 3.20)
CMAKE_MINIMUM_REQUIRED(VERSION 3.21)
PROJECT(irprinter
VERSION 0.3
VERSION 0.4
)

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
Expand All @@ -17,10 +17,13 @@ list(APPEND CMAKE_MODULE_PATH
include(ToolchainOptions)
include(CMakePackageConfigHelpers)

add_format_target(format-sources
irprinter_add_format_target(format-sources
"Formats project source files"
TARGETS src/*.cpp
include/*.h
)

add_subdirectory(src)
if(PROJECT_IS_TOP_LEVEL)
add_subdirectory(test)
endif()
73 changes: 73 additions & 0 deletions CMakePresets.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
{
"version": 2,
"cmakeMinimumRequired": {
"major": 3,
"minor": 20,
"patch": 0
},
"configurePresets": [
{
"name": "clang-toolchain",
"hidden": true,
"generator": "Unix Makefiles",
"cacheVariables": {
"CMAKE_C_COMPILER": "clang",
"CMAKE_CXX_COMPILER": "clang++"
}
},
{
"name": "develop",
"displayName": "Develop (Debug)",
"description": "Default develop build options for Clang",
"binaryDir": "${sourceDir}/build",
"inherits": [
"clang-toolchain"
],
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug"
}
},
{
"name": "release",
"displayName": "Release",
"description": "Default release build options for Clang",
"binaryDir": "${sourceDir}/build_rel",
"inherits": [
"clang-toolchain"
],
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release"
}
},
{
"name": "coverage",
"displayName": "Coverage (LLVM)",
"description": "Default coverage build options for Clang (LLVM-based)",
"binaryDir": "${sourceDir}/build_cov",
"inherits": [
"clang-toolchain"
],
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"IRPRINTER_ENABLE_COVERAGE": "ON",
"CMAKE_C_FLAGS": "-fprofile-instr-generate -fcoverage-mapping",
"CMAKE_CXX_FLAGS": "-fprofile-instr-generate -fcoverage-mapping",
"CMAKE_EXE_LINKER_FLAGS": "-fprofile-instr-generate -fcoverage-mapping"
}
}
],
"buildPresets": [
{
"name": "develop",
"configurePreset": "develop"
},
{
"name": "release",
"configurePreset": "release"
},
{
"name": "coverage",
"configurePreset": "coverage"
}
]
}
122 changes: 65 additions & 57 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,86 +1,94 @@
# irprinter · ![License](https://img.shields.io/github/license/ahueck/irprinter)

*irprinter* is a command-line tool for exploring LLVM Intermediate Representation (IR) code.
It allows users to print IR code for specific functions, which is particularly useful when dumping the entire translation unit would result in excessive output.

*irprinter* is a command-line tool for exploring LLVM Intermediate Representation (IR).
It allows you to print IR for specific functions, which is especially useful when dumping an entire translation unit would produce excessive output.

## Features
* Print LLVM IR code for a translation unit (C/C++) to the console.
* Modify and add compiler flags (e.g., replace -g with -O2) and regenerate the (modified) IR.
* Regex matching of (demangled) function names, with options to print:
* Print LLVM IR for a translation unit (C/C++) to the console.
* Modify or add compiler flags (e.g., replacing `-g` with `-O2`) and regenerate the IR.
* Match (demangled) function names using regular expressions, with options to print:
1. Function signatures only.
2. Functions including their bodies.
* Dump the entire IR code of the translation unit.
2. Full function bodies.
* Dump the entire IR of a translation unit.
* Print statements within a specific line number range (based on debug information).

## Usage
See [main.cpp](src/main.cpp) for all possible command-line arguments.
Refer to [main.cpp](src/main.cpp) for a full list of command-line arguments.

### Example
Assume `test.c` contains the following code:

### Example of using *irprinter*
Assume *test.c* contains the code:
```c
int foo () {
return 2;
}
int main() {
int val;
val = foo();
return 0;
}
```

```c
int foo () {
return 2;
}
int main() {
int val;
val = foo();
return 0;
}
```
#### Using irprinter on test.c
In this example we
1) load `test.c` with standard Clang flags,
2) list all functions in `test.c`,
3) print the body of main,
4) optimize the code with `-O3`, and finally,
5) print the body of main again.
In this example, we:
1. Load `test.c` with standard Clang and debug flags.
2. List all functions in `test.c`.
3. Print the body of `main`.
4. Print statements within the line range [6, 7].
5. Optimize the code with `-O3`.
6. Print the body of `main` again to see the result of the optimization.

```console
ahueck@sys:~/irprint/install$ ./bin/irprinter ../test.c --
$~/irprint/install$ ./bin/irprinter ../test.c -- -g
ir-printer> l
Match 1 [foo]:
; Function Attrs: noinline nounwind optnone uwtable
define i32 @foo() #0
Match 1 [foo()]:
; Function Attrs: mustprogress noinline nounwind optnone uwtable
define dso_local noundef i32 @_Z3foov() #0 !dbg !10

Match 2 [main]:
; Function Attrs: noinline nounwind optnone uwtable
define i32 @main() #0
; Function Attrs: mustprogress noinline norecurse nounwind optnone uwtable
define dso_local noundef i32 @main() #1 !dbg !10

ir-printer> p main
Match 1 [main]:
; Function Attrs: noinline nounwind optnone uwtable
define i32 @main() #0 {
%1 = alloca i32, align 4
%2 = alloca i32, align 4
store i32 0, i32* %1, align 4
%3 = call i32 @foo()
store i32 %3, i32* %2, align 4
ret i32 0
Match 1 [main]:; Function Attrs: mustprogress noinline norecurse nounwind optnone uwtable
define dso_local noundef i32 @main() #1 !dbg !10 {
entry:
%retval = alloca i32, align 4
%val = alloca i32, align 4
store i32 0, ptr %retval, align 4
#dbg_declare(ptr %val, !16, !DIExpression(), !17)
%call = call noundef i32 @_Z3foov(), !dbg !18
store i32 %call, ptr %val, align 4, !dbg !19
ret i32 0, !dbg !20
}

ir-printer> 6 7
main:
%call = call noundef i32 @_Z3foov(), !dbg !18
store i32 %call, ptr %val, align 4, !dbg !19
ret i32 0, !dbg !20

ir-printer> f -O3
Set flag to -O3. Re-generating module...
ir-printer> p main
Match 1 [main]:
; Function Attrs: norecurse nounwind readnone uwtable
define i32 @main() local_unnamed_addr #1 {
Match 1 [main]:; Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) uwtable
define dso_local noundef i32 @main() local_unnamed_addr #0 {
entry:
ret i32 0
}

```

## How to build
###### Requirements
## How to Build

### Requirements
- CMake >= 3.20
- Clang/LLVM 12, 14, 18 (CMake needs to find the installation, see
the [LLVM CMake documentation](https://llvm.org/docs/CMake.html) or the [CI workflow](.github/workflows/basic-ci.yml))
- C++17 compiler
- Clang/LLVM 12, 14, or 18-21 (CMake must be able to find the installation; see the [LLVM CMake documentation](https://llvm.org/docs/CMake.html) or the [CI workflow](.github/workflows/basic-ci.yml))
- A C++17 compatible compiler

###### Build steps
In the root project folder, execute the following commands (see also [CI workflow](.github/workflows/basic-ci.yml))
### Build Steps
From the root project folder, execute the following commands:

```
cmake -B build -DCMAKE_INSTALL_PREFIX=*your path*
cmake --build build --target install --parallel
```
```bash
cmake -B build -DCMAKE_INSTALL_PREFIX=/path/to/install
cmake --build build --target install --parallel
```
17 changes: 16 additions & 1 deletion cmake/ToolchainOptions.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,22 @@ include(clang-format)
include(log-util)
include(target-util)

set(LOG_LEVEL 0 CACHE STRING "Granularity of the logger. 3 is most verbose, 0 is least.")
set(IRPRINTER_LOG_LEVEL 0 CACHE STRING "Granularity of the logger. 3 is most verbose, 0 is least.")

option(IRPRINTER_AUTO_RESOURCE_DIR "Try to automatically set the Clang resource directory" OFF)
option(IRPRINTER_ENABLE_COVERAGE "Enable LLVM-based coverage" OFF)

if(IRPRINTER_AUTO_RESOURCE_DIR AND NOT IRPRINTER_CLANG_RESOURCE_DIR)
find_program(CLANG_EXECUTABLE NAMES clang-${LLVM_VERSION_MAJOR} clang)
if(CLANG_EXECUTABLE)
execute_process(
COMMAND ${CLANG_EXECUTABLE} -print-resource-dir
OUTPUT_VARIABLE CLANG_RESOURCE_DIR_VAR
OUTPUT_STRIP_TRAILING_WHITESPACE
)
set(IRPRINTER_CLANG_RESOURCE_DIR ${CLANG_RESOURCE_DIR_VAR} CACHE STRING "Clang resource directory")
endif()
endif()

if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE)
Expand Down
4 changes: 2 additions & 2 deletions cmake/modules/clang-format.cmake
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
function(add_format_target target comment)
function(irprinter_add_format_target target comment)
macro(filter_dir _dir_name_)
foreach (SOURCE_FILE ${ALL_CXX_FILES})
string(FIND ${SOURCE_FILE} ${_dir_name_} EXCLUDE_FOUND)
Expand All @@ -20,7 +20,7 @@ function(add_format_target target comment)
endforeach()

find_program(FORMAT_COMMAND
NAMES clang-format clang-format-12 clang-format-14 clang-format-18)
NAMES clang-format-${LLVM_VERSION_MAJOR} clang-format)
if(FORMAT_COMMAND)
add_custom_target(${target}
COMMAND ${FORMAT_COMMAND} -i -style=file ${ARG_OTHER} ${ARG_UNPARSED_ARGUMENTS}
Expand Down
Loading
Loading