mirror of
https://github.com/espressif/esp-idf.git
synced 2026-09-22 13:01:16 +03:00
141 lines
5.3 KiB
CMake
141 lines
5.3 KiB
CMake
# SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
|
#
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
|
|
include_guard(GLOBAL)
|
|
|
|
# ESP-IDF LLVM optimization framework: map menuconfig-selected optimizations to
|
|
# compiler flags. Component CMakeLists only mark opt-in scopes (file / list /
|
|
# component). Flags for each menuconfig option are also published as
|
|
# IDF_LLVM_OPT_* for standard CMake (third-party).
|
|
|
|
function(__idf_llvm_opt_collect_flags memcpy_out all_out)
|
|
set(memcpy "")
|
|
set(all "")
|
|
|
|
if(CONFIG_IDF_TOOLCHAIN_CLANG AND CMAKE_C_COMPILER_ID MATCHES "Clang")
|
|
if(CONFIG_COMPILER_LLVM_MEMCPY_OPTIMIZATION)
|
|
list(APPEND memcpy "-mllvm=-riscv-esp32-p4-mem-intrin")
|
|
# PIE 2.1 vs 2.2 comes from -mcpu (components/soc/project_include.cmake).
|
|
# +espv-lowering is still required for .m intrinsic isel (vld/vst.128.ip.m).
|
|
# Do not pass +xespv2p1: that name is not a Clang target-feature and is ignored.
|
|
list(APPEND memcpy "-Xclang" "-target-feature" "-Xclang" "+espv-lowering")
|
|
endif()
|
|
list(APPEND all ${memcpy})
|
|
endif()
|
|
|
|
set(${memcpy_out} "${memcpy}" PARENT_SCOPE)
|
|
set(${all_out} "${all}" PARENT_SCOPE)
|
|
endfunction()
|
|
|
|
# SHELL-wrapped lists for target_compile_options. Empty when Kconfig is off or not Clang.
|
|
function(__idf_llvm_opt_publish_flags)
|
|
__idf_llvm_opt_collect_flags(memcpy_flags all_flags)
|
|
__idf_llvm_opt_shell_wrap_xclang("${memcpy_flags}" memcpy_wrapped)
|
|
__idf_llvm_opt_shell_wrap_xclang("${all_flags}" all_wrapped)
|
|
set(IDF_LLVM_OPT_MEMCPY "${memcpy_wrapped}" CACHE INTERNAL
|
|
"Flags for CONFIG_COMPILER_LLVM_MEMCPY_OPTIMIZATION; empty if off or not Clang" FORCE)
|
|
set(IDF_LLVM_OPT_ALL "${all_wrapped}" CACHE INTERNAL
|
|
"Flags for all LLVM optimizations enabled in menuconfig; empty if none or not Clang" FORCE)
|
|
endfunction()
|
|
|
|
function(__idf_llvm_opt_get_options output)
|
|
set(options ${ARGN})
|
|
__idf_llvm_opt_publish_flags()
|
|
|
|
if(NOT CONFIG_IDF_TOOLCHAIN_CLANG OR NOT CMAKE_C_COMPILER_ID MATCHES "Clang")
|
|
set(${output} "" PARENT_SCOPE)
|
|
return()
|
|
endif()
|
|
|
|
__idf_llvm_opt_collect_flags(_memcpy all_flags)
|
|
list(APPEND options ${all_flags})
|
|
set(${output} "${options}" PARENT_SCOPE)
|
|
endfunction()
|
|
|
|
# target_compile_options de-duplicates identical tokens, which splits
|
|
# "-Xclang" "<arg>" pairs. SHELL: keeps each consecutive -Xclang group intact.
|
|
# Source COMPILE_OPTIONS are not de-duplicated and do not honour SHELL:.
|
|
function(__idf_llvm_opt_shell_wrap_xclang input output)
|
|
set(result "")
|
|
set(i 0)
|
|
list(LENGTH input n)
|
|
while(i LESS n)
|
|
list(GET input ${i} item)
|
|
if(item STREQUAL "-Xclang")
|
|
set(group "")
|
|
while(i LESS n)
|
|
list(GET input ${i} tok)
|
|
if(NOT tok STREQUAL "-Xclang")
|
|
break()
|
|
endif()
|
|
math(EXPR nxt "${i} + 1")
|
|
if(nxt GREATER_EQUAL n)
|
|
message(FATAL_ERROR "LLVM opt flags: -Xclang missing argument")
|
|
endif()
|
|
list(GET input ${nxt} arg)
|
|
if(group STREQUAL "")
|
|
set(group "-Xclang ${arg}")
|
|
else()
|
|
string(APPEND group " -Xclang ${arg}")
|
|
endif()
|
|
math(EXPR i "${nxt} + 1")
|
|
endwhile()
|
|
list(APPEND result "SHELL:${group}")
|
|
else()
|
|
list(APPEND result "${item}")
|
|
math(EXPR i "${i} + 1")
|
|
endif()
|
|
endwhile()
|
|
set(${output} "${result}" PARENT_SCOPE)
|
|
endfunction()
|
|
|
|
function(__idf_apply_llvm_opt_to_target target)
|
|
__idf_llvm_opt_get_options(options ${ARGN})
|
|
if(options)
|
|
__idf_llvm_opt_shell_wrap_xclang("${options}" options)
|
|
target_compile_options(${target} PRIVATE ${options})
|
|
endif()
|
|
endfunction()
|
|
|
|
function(__idf_apply_llvm_opt_to_sources)
|
|
set(multi_value SRCS OPTIONS)
|
|
cmake_parse_arguments(ARG "" "" "${multi_value}" ${ARGN})
|
|
|
|
if(ARG_UNPARSED_ARGUMENTS)
|
|
message(FATAL_ERROR "Unknown idf_component_enable_llvm_opt arguments: ${ARG_UNPARSED_ARGUMENTS}")
|
|
endif()
|
|
|
|
__idf_llvm_opt_get_options(options ${ARG_OPTIONS})
|
|
if(options)
|
|
set_property(SOURCE ${ARG_SRCS} APPEND PROPERTY COMPILE_OPTIONS ${options})
|
|
endif()
|
|
endfunction()
|
|
|
|
# Apply menuconfig-selected LLVM optimizations to one source, a source list, or
|
|
# the whole current component. OPTIONS is an advanced escape hatch for custom
|
|
# Clang/LLVM optimization options and is ignored with non-Clang toolchains.
|
|
function(idf_component_enable_llvm_opt)
|
|
set(multi_value SRCS OPTIONS)
|
|
cmake_parse_arguments(ARG "" "" "${multi_value}" ${ARGN})
|
|
|
|
if(ARG_UNPARSED_ARGUMENTS)
|
|
message(FATAL_ERROR "Unknown idf_component_enable_llvm_opt arguments: ${ARG_UNPARSED_ARGUMENTS}")
|
|
endif()
|
|
|
|
if(ARG_SRCS)
|
|
__idf_apply_llvm_opt_to_sources(SRCS ${ARG_SRCS} OPTIONS ${ARG_OPTIONS})
|
|
return()
|
|
endif()
|
|
|
|
if(COMPONENT_LIB AND TARGET ${COMPONENT_LIB})
|
|
set(component_target ${COMPONENT_LIB})
|
|
elseif(COMPONENT_TARGET AND TARGET ${COMPONENT_TARGET})
|
|
set(component_target ${COMPONENT_TARGET})
|
|
else()
|
|
message(FATAL_ERROR "idf_component_enable_llvm_opt must be called after idf_component_register")
|
|
endif()
|
|
|
|
__idf_apply_llvm_opt_to_target(${component_target} ${ARG_OPTIONS})
|
|
endfunction()
|