Clang OpenMP
Clang Frontend OpenMP Handling Notes¶
Context¶
- Target input:
tests/nonsmoke/functional/input_codes/axpy_omp.c. - Goal: compile the source with
./build/bin/rose-compilerwhile ensuring generated code (rose_axpy_omp.c) preserves OpenMP pragmas and is accepted by stockclang. - Environment: Clang/LLVM 20 frontend in ROSE (“rex”).
Findings & Fixes¶
- Clang builtin redeclarations: local prototypes for
__builtin_va_start/__builtin_va_end/__builtin_allocaconflicted with the Clang 20 headers. Added__has_builtinguards and adjusted signatures to match Clang’s runtime expectations. - OpenMP command-line detection: prior behaviour never forwarded
-fopenmpto Clang, so OpenMP constructs were ignored. The frontend now: - Detects
-fopenmp,-fopenmp-simd, and_OPENMPdefines. - Sets
LangOptions::OpenMP/OpenMPSimdwhen present. - For pure passthrough mode it suppresses reinsertion of
_OPENMPintodefine_list, avoiding macro redefinition. - Loop condition canonicalization: Clang unparses
for (int i = 0; ((long)((int)i)) < ((long)n); ++i)inside OpenMP regions. Clang’s OMP semantic checks reject that.VisitForStmtnow strips redundant cast layers before rebuilding the test expression so the unparser emitsi < n. - Pragma preservation: Instead of dropping the directive or asserting,
VisitOMPExecutableDirectivecaptures the source text (#pragma ...) and attaches it asPreprocessingInfoto the associated statement. During unparsing the original directive is reproduced verbatim, satisfying the passthrough requirement. - Captured statements: OpenMP target regions introduce
CapturedStmtnodes. The previousROSE_ASSERT(FAIL_TODO==0)aborted. The traversal now simply forwards the captured body (or inserts a null statement), enabling the generic pragma path. - Array subscripting casts: the earlier generated code used nested casts such as
((char *)((char **)argv)[1]).VisitArraySubscriptExprnow normalises pointer casts when the base expression originates from an array decaying to a pointer, preventing-Wint-to-pointer-cast.
Proposed Mode Strategy¶
- Pure passthrough (current focus)
- Triggered when users supply
-fopenmpwithout ROSE-specific OpenMP controls. - Behaviour: treat OpenMP directives as opaque text, attach them (as
SgPragmaDeclarationorPreprocessingInfo), do not build ROSE OpenMP IR. Unparser emits original pragmas. Generated C is accepted byclang -fopenmp. -
Status: implemented with
PreprocessingInfoattachment. -
ROSE OpenMP AST construction + lowering (future)
- Triggered by
-fopenmpplus existing-rose:openmp:*options. -
Behaviour: reuse the mature legacy frontend-based pipeline—parse pragmas, build ROSE OpenMP IR, then generate lowered multithreaded code. Clang frontend would need parity with the legacy frontend path (currently incomplete).
-
Clang-native OpenMP-to-SAGE translation (long-term)
- Triggered by an explicit
--rex-openmp-clangor similar. - Behaviour: rely on Clang’s OpenMP AST nodes to build precise ROSE IR, bypassing text-based handling.
- Status: not yet implemented; would require comprehensive mapping from Clang OpenMP classes to
SgOmp*nodes.
Outstanding Items¶
- Evaluate whether pure passthrough should use
SgPragmaDeclarationinstead of rawPreprocessingInfofor improved tooling compatibility. - Investigate compatibility of existing ROSE OpenMP lowering passes when driven from Clang ASTs (mode 2).
- Design command-line UX for selecting between modes 1–3 without confusing legacy frontend users.
- Add regression coverage: run
rose-compiler -fopenmpand verify that the emitted pragmas and loop headers remain canonical.
Practical Notes¶
- The current passthrough path allows the user to recompile the generated file with
clang-20 -fopenmpsuccessfully. - When no OpenMP flags are supplied, pragmas remain untouched but Clang also does not attempt to parse them as structured directives, matching legacy frontend’s historical behaviour.
- Mode selection logic lives entirely in
clang-frontend.cpp; no build-system changes are required.