Skip to content

Commit e6e57fe

Browse files
committed
[fusilli] Supported ASAN build
Signed-off-by: Alexandra Sidorova <asidorov@amd.com>
1 parent 4e74766 commit e6e57fe

8 files changed

Lines changed: 126 additions & 5 deletions

File tree

.github/workflows/build-and-test-linux.yml

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ jobs:
3030
strategy:
3131
fail-fast: false
3232
matrix:
33-
name: ["gfx942_clang22_release", "cpu_clang18_debug", "gfx942_clang22_debug", "cpu_gcc13_codecov"]
33+
name: ["gfx942_clang22_release", "cpu_clang18_debug", "gfx942_clang22_debug", "cpu_gcc13_codecov", "gfx942_clang22_asan", "cpu_clang18_asan"]
3434
include:
3535
- name: gfx942_clang22_release
3636
runs-on: linux-mi325-1gpu-ossci-iree-org
@@ -67,6 +67,30 @@ jobs:
6767
-DFUSILLI_CODE_COVERAGE=ON
6868
-DFUSILLI_SYSTEMS_AMDGPU=OFF
6969
-DFUSILLI_ENABLE_CLANG_TIDY=ON
70+
- name: gfx942_clang22_asan
71+
runs-on: linux-mi325-1gpu-ossci-iree-org
72+
cmake-options:
73+
-DCMAKE_C_COMPILER=clang-22
74+
-DCMAKE_CXX_COMPILER=clang++-22
75+
-DCMAKE_BUILD_TYPE=Debug
76+
-DFUSILLI_SYSTEMS_AMDGPU=ON
77+
-DFUSILLI_ENABLE_ASAN=ON
78+
asan-env: >-
79+
ASAN_SYMBOLIZER_PATH=/workspace/.cache/docker/venv/bin/llvm-symbolizer-22
80+
ASAN_OPTIONS=detect_leaks=1:halt_on_error=0
81+
LSAN_OPTIONS=suppressions=/workspace/build_tools/sanitizers/lsan_suppressions.txt
82+
- name: cpu_clang18_asan
83+
runs-on: azure-linux-scale
84+
cmake-options:
85+
-DCMAKE_C_COMPILER=clang-18
86+
-DCMAKE_CXX_COMPILER=clang++-18
87+
-DCMAKE_BUILD_TYPE=Debug
88+
-DFUSILLI_SYSTEMS_AMDGPU=OFF
89+
-DFUSILLI_ENABLE_ASAN=ON
90+
asan-env: >-
91+
ASAN_SYMBOLIZER_PATH=/usr/bin/llvm-symbolizer-18
92+
ASAN_OPTIONS=detect_leaks=1:halt_on_error=0
93+
LSAN_OPTIONS=suppressions=/workspace/build_tools/sanitizers/lsan_suppressions.txt
7094
7195
steps:
7296
- name: Checkout fusilli
@@ -81,14 +105,14 @@ jobs:
81105
cmake --build build --target all"
82106
83107
- name: Test fusilli (libIREECompiler CAPI)
84-
if: ${{ matrix.name != 'cpu_gcc13_codecov' }}
108+
if: ${{ matrix.name != 'cpu_gcc13_codecov' && matrix.name != 'gfx942_clang22_asan' && matrix.name != 'cpu_clang18_asan' }}
85109
run: |
86110
build_tools/docker/exec_docker_ci.sh \
87111
bash -c "ctest --test-dir build --output-on-failure --extra-verbose --timeout 120 -j \$(nproc) && \
88112
tests/test_cache_empty.sh"
89113
90114
- name: Test fusilli (iree-compile CLI)
91-
if: ${{ matrix.name != 'cpu_gcc13_codecov' }}
115+
if: ${{ matrix.name != 'cpu_gcc13_codecov' && matrix.name != 'gfx942_clang22_asan' && matrix.name != 'cpu_clang18_asan' }}
92116
run: |
93117
build_tools/docker/exec_docker_ci.sh \
94118
bash -c "FUSILLI_COMPILE_BACKEND_USE_CLI=1 ctest --test-dir build --output-on-failure --extra-verbose --timeout 120 -j \$(nproc) && \
@@ -109,3 +133,11 @@ jobs:
109133
with:
110134
name: coverage-report
111135
path: ${{ github.workspace }}/coverage_report
136+
137+
- name: Run AddressSanitizer
138+
if: ${{ matrix.name == 'gfx942_clang22_asan' || matrix.name == 'cpu_clang18_asan' }}
139+
run: |
140+
build_tools/docker/exec_docker_ci.sh \
141+
bash -c "${{ matrix.asan-env }} \
142+
ctest --test-dir build --output-on-failure --extra-verbose --timeout 120 -j \$(nproc) && \
143+
tests/test_cache_empty.sh"

CMakeLists.txt

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ endif()
5252
# Includes
5353
include(CTest)
5454
include(FetchContent)
55+
include(CheckCXXCompilerFlag)
5556

5657
# Local Includes
5758
list(APPEND CMAKE_MODULE_PATH
@@ -67,13 +68,22 @@ option(FUSILLI_CODE_COVERAGE "Enable code coverage for tests" OFF)
6768
option(FUSILLI_ENABLE_LOGGING "Enable logging for tests and samples" OFF)
6869
option(FUSILLI_ENABLE_CLANG_TIDY "Enable clang-tidy" OFF)
6970
option(FUSILLI_SYSTEMS_AMDGPU "Builds for AMD GPU systems" OFF)
71+
option(FUSILLI_ENABLE_ASAN "Enable AddressSanitizer" OFF)
7072

7173
message(STATUS "Fusilli supported systems:")
7274
if(FUSILLI_SYSTEMS_AMDGPU)
7375
message(STATUS " - AMD GPU")
7476
endif()
7577
message(STATUS " - Host")
7678

79+
if(FUSILLI_ENABLE_ASAN AND NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
80+
message(FATAL_ERROR "AddressSanitizer requires Clang as the C++ compiler, but '${CMAKE_CXX_COMPILER_ID}' was detected.")
81+
endif()
82+
83+
if(FUSILLI_ENABLE_ASAN AND FUSILLI_CODE_COVERAGE)
84+
message(FATAL_ERROR "FUSILLI_ENABLE_ASAN and FUSILLI_CODE_COVERAGE cannot be enabled simultaneously.")
85+
endif()
86+
7787
################################################################################
7888
# IREE Dependency
7989
#
@@ -121,6 +131,10 @@ if(FUSILLI_SYSTEMS_AMDGPU)
121131
set(IREE_HAL_DRIVER_HIP ON)
122132
set(IREE_HIP_TEST_TARGET_CHIP "" CACHE STRING "Enable ROCm testing on specific architecture (e.g. gfx942)")
123133
endif()
134+
# Enable ASAN build for IREE if ASAN is used in Fusilli
135+
if(FUSILLI_ENABLE_ASAN)
136+
set(IREE_ENABLE_ASAN ON)
137+
endif()
124138

125139
if(IREE_SOURCE_DIR)
126140
message(STATUS "Using existing IREE sources: ${IREE_SOURCE_DIR}")
@@ -184,6 +198,20 @@ if(FUSILLI_CODE_COVERAGE)
184198
set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Debug build" FORCE)
185199
endif()
186200

201+
# Configure sanitizer flags
202+
set(FUSILLI_SANITIZER_COMPILE_FLAGS "")
203+
set(FUSILLI_SANITIZER_LINK_FLAGS "")
204+
if(FUSILLI_ENABLE_ASAN)
205+
message(STATUS "AddressSanitizer enabled")
206+
list(APPEND FUSILLI_SANITIZER_COMPILE_FLAGS -fsanitize=address -fno-omit-frame-pointer -g)
207+
list(APPEND FUSILLI_SANITIZER_LINK_FLAGS -fsanitize=address)
208+
209+
check_cxx_compiler_flag("-fsanitize-recover=address" SANITIZE_RECOVER_ADDRESS_SUPPORTED)
210+
if (SANITIZE_RECOVER_ADDRESS_SUPPORTED)
211+
list(APPEND FUSILLI_SANITIZER_COMPILE_FLAGS -fsanitize-recover=address)
212+
endif()
213+
endif()
214+
187215
# Enable AMD GPU build if requested
188216
if(FUSILLI_SYSTEMS_AMDGPU)
189217
# Check for Linux AMD GPU device node - `/dev/kfd`

README.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,39 @@ FUSILLI_COMPILE_BACKEND_USE_CLI=1 \
245245
-f commands.txt
246246
```
247247

248+
### Sanitizers (AddressSanitizer)
249+
250+
Fusilli supports building with AddressSanitizer (ASAN) for detecting memory errors such as use-after-free, buffer overflows, and memory leaks.
251+
252+
To build with AddressSanitizer, specify the cmake flag `-DFUSILLI_ENABLE_ASAN=ON`:
253+
```shell
254+
cmake -GNinja -S. -Bbuild \
255+
-DCMAKE_C_COMPILER=clang \
256+
-DCMAKE_CXX_COMPILER=clang++ \
257+
-DCMAKE_BUILD_TYPE=Debug \
258+
-DFUSILLI_ENABLE_ASAN=ON \
259+
-DIREE_SOURCE_DIR=</path/to/iree/source>
260+
cmake --build build --target all
261+
ctest --test-dir build
262+
```
263+
264+
To customize AddressSanitizer behavior at runtime, use the `ASAN_OPTIONS` environment variable:
265+
```shell
266+
ASAN_OPTIONS=detect_leaks=1:halt_on_error=0 LSAN_OPTIONS=suppressions=build_tools/sanitizers/lsan_suppressions.txt ctest --test-dir build
267+
```
268+
269+
To make AddressSanitizer symbolize its output you need to set the `ASAN_SYMBOLIZER_PATH` environment variable
270+
to point to the llvm-symbolizer binary (or make sure llvm-symbolizer is in your `$PATH`):
271+
```shell
272+
ASAN_SYMBOLIZER_PATH=/usr/bin/llvm-symbolizer ...
273+
```
274+
275+
> [!NOTE]
276+
> - Debug builds (`-DCMAKE_BUILD_TYPE=Debug`) provide better stack traces.
277+
> - Sanitizer builds have runtime overhead and are intended for development/testing, not production.
278+
> - AddressSanitizer and Code Coverage cannot be used simultaneously, because both add heavy runtime instrumentation
279+
and combining them often leads to slow/flaky tests and less reliable diagnostics.
280+
248281
### Code Coverage (using gcov + lcov)
249282

250283
This works with gcc builds (code coverage with clang instrumentation is future
@@ -279,6 +312,10 @@ lcov --remove build/coverage.info '/usr/*' '*/iree/*' --output-file build/covera
279312
genhtml build/coverage.info --output-directory coverage_report
280313
```
281314

315+
> [!NOTE]
316+
> - AddressSanitizer and Code Coverage cannot be used simultaneously, because both add heavy runtime instrumentation
317+
and combining them often leads to slow/flaky tests and less reliable diagnostics.
318+
282319
### Lint
283320

284321
This project is set up to use [pre-commit](https://pre-commit.com/) hooks for

benchmarks/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ set_target_properties(
1919
# Enable clang-tidy.
2020
fusilli_enable_clang_tidy(fusilli_benchmark_driver)
2121

22+
# Set compiler options for sanitizers.
23+
if(FUSILLI_ENABLE_ASAN)
24+
target_compile_options(fusilli_benchmark_driver PRIVATE ${FUSILLI_SANITIZER_COMPILE_FLAGS})
25+
target_link_options(fusilli_benchmark_driver PRIVATE ${FUSILLI_SANITIZER_LINK_FLAGS})
26+
endif()
27+
2228
# Test benchmark runner
2329
if(FUSILLI_SYSTEMS_AMDGPU)
2430
add_test(

build_tools/cmake/FusilliTestUtils.cmake

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,12 @@ function(_add_fusilli_executable_for_test)
369369
target_link_options(${_RULE_NAME} PRIVATE -coverage)
370370
endif()
371371

372+
# Set compiler options for sanitizers.
373+
if(FUSILLI_ENABLE_ASAN)
374+
target_compile_options(${_RULE_NAME} PRIVATE ${FUSILLI_SANITIZER_COMPILE_FLAGS})
375+
target_link_options(${_RULE_NAME} PRIVATE ${FUSILLI_SANITIZER_LINK_FLAGS})
376+
endif()
377+
372378
# Place executable in the build/bin sub-directory.
373379
set_target_properties(
374380
${_RULE_NAME} PROPERTIES
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# LSAN suppressions for leaks in external libraries (IREE, ROCm)
2+
3+
leak:iree_hal_hip_dispatch_completed_create
4+
leak:libamdhip64.so
5+
leak:libhsa-runtime64.so
6+
leak:libamd_comgr.so

include/fusilli/backend/runtime.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,9 +145,14 @@ inline ErrorObject Handle::createAMDGPUDevice(int deviceId, uintptr_t stream) {
145145

146146
// Create device.
147147
iree_hal_device_t *rawDevice = nullptr;
148-
FUSILLI_CHECK_ERROR(iree_hal_driver_create_device_by_id(
148+
iree_status_t deviceStatus = iree_hal_driver_create_device_by_id(
149149
driver, HIP_DEVICE_ID_TO_IREE_DEVICE_ID(deviceId), /*param_count=*/0,
150-
/*params=*/nullptr, iree_allocator_system(), &rawDevice));
150+
/*params=*/nullptr, iree_allocator_system(), &rawDevice);
151+
152+
// Release the driver regardless of whether device creation succeeded.
153+
iree_hal_driver_release(driver);
154+
155+
FUSILLI_CHECK_ERROR(deviceStatus);
151156

152157
// Wrap the raw device ptr with a unique_ptr and custom deleter
153158
// for lifetime management.

include/fusilli/support/logging.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ struct [[nodiscard]] ErrorObject {
102102
// Write error message into `errMsg` variable using the runtime's fprint
103103
// based reporting.
104104
iree_status_fprint(FprintToString(errMsg), status);
105+
iree_status_ignore(status);
105106
}
106107

107108
ErrorCode getCode() const { return code; }

0 commit comments

Comments
 (0)