Skip to content
Merged
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
7 changes: 7 additions & 0 deletions .codespellrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[codespell]
builtin = clear,rare,en-GB_to_en-US,names,informal,code
check-filenames =
check-hidden =
skip = */.git,*/build*,*/.codespellrc,*/install
quiet-level = 2
ignore-regex = ^#include <(?:stdio)\.h>$|DEPENDEES|\\endcode
88 changes: 65 additions & 23 deletions .github/workflows/basic-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,38 +5,80 @@ on:
branches: [ master, devel ]
pull_request:

env:
CXX: clang++
CC: clang

jobs:
formatting-check:
runs-on: ubuntu-20.04
if: "!contains(github.event.head_commit.message, '[ci skip]')"
format-check:
runs-on: ubuntu-22.04

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

- name: Check code format
uses: jidicula/clang-format-action@v3.2.0
with:
clang-format-version: '10'
- name: Format source code
run: |
find demo lib test \
-type f \
-a \( -name "*.c" -o -name "*.cpp" -o -name "*.h" \) \
-print0 \
| xargs -0 clang-format-14 -i

- name: Format check
run: |
git status --porcelain --untracked-files=no
git status --porcelain --untracked-files=no | xargs -o -I {} test -z \"{}\"

codespell:
runs-on: ubuntu-22.04

build-and-run-test:
runs-on: ubuntu-20.04
if: "!contains(github.event.head_commit.message, '[ci skip]')"
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- uses: codespell-project/actions-codespell@v2

- name: Install Clang and libs
run: sudo apt-get install clang-tools-10 clang-tidy-10 libclang-10-dev libclang-cpp10-dev libedit-dev
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

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

steps:
- uses: actions/checkout@v4

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

- name: Install LLVM
run: sudo apt-get install libllvm${{ matrix.llvm-version }} llvm-${{ matrix.llvm-version }} llvm-${{ matrix.llvm-version }}-dev

- name: Install Clang
run: sudo apt-get install clang-${{ matrix.llvm-version }} clang-tidy-${{ matrix.llvm-version }} clang-tools-${{ matrix.llvm-version }} libclang-${{ matrix.llvm-version }}-dev libclang-cpp${{ matrix.llvm-version }}-dev libedit-dev

- name: Setup env
run: |
sudo ln -f -s /usr/bin/clang-10 /usr/bin/clang
sudo ln -f -s /usr/bin/clang++-10 /usr/bin/clang++
sudo ln -f -s /usr/bin/FileCheck-10 /usr/bin/FileCheck
sudo ln -f -s /usr/bin/clang-tidy-10 /usr/bin/clang-tidy
echo "CC=clang-10" >> $GITHUB_ENV
echo "CXX=clang++-10" >> $GITHUB_ENV
echo "EXTERNAL_LIT=/usr/lib/llvm-10/build/utils/lit/lit.py" >> $GITHUB_ENV
sudo ln -f -s /usr/bin/clang-${{ matrix.llvm-version }} /usr/bin/clang
sudo ln -f -s /usr/bin/clang++-${{ matrix.llvm-version }} /usr/bin/clang++
echo "LLVM_CMAKE_DIR=/usr/lib/llvm-${{ matrix.llvm-version }}/cmake" >> $GITHUB_ENV
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
cmake --build build --parallel --target install
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 --build build_rel --parallel --target install
8 changes: 5 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
CMAKE_MINIMUM_REQUIRED(VERSION 3.14)
PROJECT(irprinter)
CMAKE_MINIMUM_REQUIRED(VERSION 3.20)
PROJECT(irprinter
VERSION 0.3
)

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_VERBOSE_MAKEFILE ON)
Expand All @@ -21,4 +23,4 @@ add_format_target(format-sources
include/*.h
)

add_subdirectory(src)
add_subdirectory(src)
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2018 Alexander Hück
Copyright (c) 2018-2025 Alexander Hück

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
32 changes: 16 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
# irprinter
# irprinter &middot; ![License](https://img.shields.io/github/license/ahueck/irprinter)

*irprinter* is a small commandline-based tool developed to explore LLVM IR code.
The tool can print IR code of only specific functions, when dumping of the whole translation unit would produce too much output.
*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.


## Main features
Print LLVM IR code of a translation unit (C/C++) to a console.
- Ability to modify and add compiler flags (e.g., replace `-g` with `-O2`) and re-generate the (modified) IR
- Regex matching of (demangled) function names, with the ability to print
1) Function signatures only, and,
2) Functions including body
- Dump whole IR code of the TU
## 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:
1. Function signatures only.
2. Functions including their bodies.
* Dump the entire IR code of the translation unit.

## Usage
See [main.cpp](src/main.cpp) for all possible commandline arguments.
See [main.cpp](src/main.cpp) for all possible command-line arguments.

### Example of using *irprinter*
Assume *test.c* contains the code:
Expand Down Expand Up @@ -72,13 +72,13 @@ define i32 @main() local_unnamed_addr #1 {

## How to build
###### Requirements
- cmake >= 3.14
- Clang/LLVM 10.0 (cmake needs to find the installation, see
the [LLVM cmake documentation](https://llvm.org/docs/CMake.html#id14))
- C++ compiler with support for the C++17 standard, e.g., Clang 10
- 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

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

```
cmake -B build -DCMAKE_INSTALL_PREFIX=*your path*
Expand Down
25 changes: 20 additions & 5 deletions cmake/ToolchainOptions.cmake
Original file line number Diff line number Diff line change
@@ -1,18 +1,33 @@
include(FeatureSummary)

set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules)

# Setup of all necessary include/lib dirs for the development of a Clang based tool
find_package(LLVM 10 REQUIRED)
find_package(Clang REQUIRED)
find_package(LLVM CONFIG HINTS "${LLVM_DIR}")
if(NOT LLVM_FOUND)
message(STATUS "LLVM not found at: ${LLVM_DIR}.")
find_package(LLVM REQUIRED CONFIG)
endif()

set_package_properties(LLVM PROPERTIES
URL https://llvm.org/
TYPE REQUIRED
PURPOSE
"LLVM framework installation required to compile."
)

message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")

list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_DIR}")

find_package(Clang REQUIRED HINTS "${Clang_DIR}")

include(AddLLVM)
include(clang-tidy)
include(clang-format)
include(log-util)
include(target-util)

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

if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE)
Expand All @@ -22,4 +37,4 @@ endif ()
if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(CMAKE_INSTALL_PREFIX "${irprinter_SOURCE_DIR}/install/irprinter" CACHE PATH "Default install path" FORCE)
message(STATUS "Installing to (default): ${CMAKE_INSTALL_PREFIX}")
endif ()
endif ()
18 changes: 0 additions & 18 deletions cmake/modules/FindLibEdit.cmake

This file was deleted.

4 changes: 2 additions & 2 deletions cmake/modules/clang-format.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ function(add_format_target target comment)
endforeach()

find_program(FORMAT_COMMAND
NAMES clang-format clang-format-6.0 clang-format-5.0 clang-format-4.0)
NAMES clang-format clang-format-12 clang-format-14 clang-format-18)
if(FORMAT_COMMAND)
add_custom_target(${target}
COMMAND ${FORMAT_COMMAND} -i -style=file ${ARG_OTHER} ${ARG_UNPARSED_ARGUMENTS}
Expand All @@ -34,4 +34,4 @@ function(add_format_target target comment)
add_custom_target(${target}
COMMAND ${CMAKE_COMMAND} -E echo "${target} does nothing, no clang-format found.")
endif()
endfunction()
endfunction()
4 changes: 2 additions & 2 deletions cmake/modules/clang-tidy.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ function(add_tidy_target target comment)
endforeach()

find_program(TIDY_COMMAND
NAMES clang-tidy clang-tidy-6.0 clang-tidy-5.0 clang-tidy-4.0)
NAMES clang-tidy clang-tidy-12 clang-tidy-14 clang-tidy-18)
if(TIDY_COMMAND)
add_custom_target(${target}
COMMAND ${TIDY_COMMAND} -p ${CMAKE_BINARY_DIR}
Expand Down Expand Up @@ -54,4 +54,4 @@ function(make_tidy_check name sources)
SOURCES ${sources}
OTHER --header-filter=${CMAKE_CURRENT_SOURCE_DIR} -checks=-*,modernize-*,llvm-namespace-comment,google-explicit-constructor
)
endfunction()
endfunction()
2 changes: 1 addition & 1 deletion cmake/modules/log-util.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ function(target_define_file_basename targetname)
PROPERTIES COMPILE_DEFINITIONS ${compile_defs}
)
endforeach()
endfunction()
endfunction()
2 changes: 1 addition & 1 deletion cmake/modules/target-util.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,4 @@ function(target_project_compile_definitions target)
"${ARG_PUBLIC_DEFS}"
)
endif ()
endfunction()
endfunction()
8 changes: 6 additions & 2 deletions include/Util.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,12 @@ inline std::string dump(const Val& s) {

template <typename String>
inline std::string try_demangle(String s) {
std::string name = s;
auto demangle = llvm::itaniumDemangle(s.data(), nullptr, nullptr, nullptr);
std::string name{s};
#if LLVM_VERSION_MAJOR == 18
auto demangle = llvm::itaniumDemangle(s.data());
#else
auto demangle = llvm::itaniumDemangle(s.data(), nullptr, nullptr, nullptr);
#endif
if (demangle && std::string(demangle) != "") {
return std::string(demangle);
}
Expand Down
21 changes: 15 additions & 6 deletions src/main.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#include <printer/IRNodeFinder.h>

#include <clang/Tooling/CommonOptionsParser.h>
#include <llvm/ADT/Optional.h>
#include <llvm/Support/Regex.h>
#include <llvm/ADT/StringRef.h>
#include <llvm/IR/Module.h>
#include <llvm/LineEditor/LineEditor.h>
Expand Down Expand Up @@ -41,9 +41,18 @@ StringRef lexWord(StringRef word) {
} // namespace

int main(int argc, const char** argv) {
#if LLVM_VERSION_MAJOR < 14
CommonOptionsParser op(argc, argv, IRPrinter);

irprinter::IRNodeFinder ir(op);
#else
auto op = CommonOptionsParser::create(argc, argv, IRPrinter);
if (!op) {
llvm::outs() << "Erroneous input";
return 1;
}
irprinter::IRNodeFinder ir(op.get());
#endif


auto ret = ir.parse();
if (ret != 0) {
Expand All @@ -52,7 +61,7 @@ int main(int argc, const char** argv) {
}

llvm::LineEditor le("ir-printer");
while (llvm::Optional<std::string> line = le.readLine()) {
while (auto line = le.readLine()) {
StringRef ref = *line;
auto cmd = lexWord(ref);

Expand Down Expand Up @@ -80,13 +89,13 @@ int main(int argc, const char** argv) {
}
}
if (cmd == "p" || cmd == "print") {
ir.printFunction(str);
ir.printFunction(std::string{str});
} else {
ir.listFunction(str);
ir.listFunction(std::string{str});
}
} else if (cmd == "d" || cmd == "demangle") {
auto str = lexWord(StringRef(cmd.end(), ref.end() - cmd.end()));
auto demangled_name = irprinter::IRNodeFinder::demangle(str);
auto demangled_name = irprinter::IRNodeFinder::demangle(std::string{str});
llvm::outs() << "Demangled name: " << demangled_name << "\n";
}

Expand Down