IAR: Add tests covering IAR toolchains

Run the tests only if enabled explicitly by an undocumented cache
entry.  We will enable it on hosts known to have the toolchains.
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index 5a23b8b..7fa5b88 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -1097,3 +1097,8 @@
 if(WIN32)
   add_RunCMake_test(Win32GenEx)
 endif()
+
+if(CMake_TEST_IAR_TOOLCHAINS)
+  add_RunCMake_test(IAR -DCMake_TEST_IAR_TOOLCHAINS=${CMake_TEST_IAR_TOOLCHAINS})
+  set_property(TEST RunCMake.IAR APPEND PROPERTY LABELS "IAR")
+endif()
diff --git a/Tests/RunCMake/IAR/CMakeLists.txt b/Tests/RunCMake/IAR/CMakeLists.txt
new file mode 100644
index 0000000..6a9ce76
--- /dev/null
+++ b/Tests/RunCMake/IAR/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.28)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/IAR/RunCMakeTest.cmake b/Tests/RunCMake/IAR/RunCMakeTest.cmake
new file mode 100644
index 0000000..2049740
--- /dev/null
+++ b/Tests/RunCMake/IAR/RunCMakeTest.cmake
@@ -0,0 +1,64 @@
+include(RunCMake)
+
+if(RunCMake_GENERATOR MATCHES "Makefile|Ninja")
+  file(GLOB _iar_toolchains
+    "${CMake_TEST_IAR_TOOLCHAINS}/bx*-*/*/bin/icc*" )
+  if(_iar_toolchains STREQUAL "")
+    message(FATAL_ERROR "Could not find any IAR toolchains at: ${CMake_TEST_IAR_TOOLCHAINS}.")
+  endif()
+endif()
+
+foreach(_iar_toolchain IN LISTS _iar_toolchains)
+  message(STATUS "Found IAR toolchain: ${_iar_toolchain}")
+  cmake_path(GET _iar_toolchain PARENT_PATH BIN_DIR)
+  cmake_path(GET BIN_DIR PARENT_PATH TOOLKIT_DIR)
+  cmake_path(GET TOOLKIT_DIR FILENAME ARCH)
+
+  # Sets the minimal requirements for linking each target architecture
+  if(ARCH STREQUAL rl78)
+    set(LINK_OPTS
+"--config_def _STACK_SIZE=256 \
+--config_def _NEAR_HEAP_SIZE=0x400 \
+--config_def _FAR_HEAP_SIZE=4096 \
+--config_def _HUGE_HEAP_SIZE=0 \
+--config_def _NEAR_CONST_LOCATION_START=0x2000 \
+--config_def _NEAR_CONST_LOCATION_SIZE=0x6F00 \
+--define_symbol _NEAR_CONST_LOCATION=0 \
+--config ${TOOLKIT_DIR}/config/lnkrl78_s3.icf" )
+  else()
+    set(LINK_OPTS "")
+  endif()
+
+  # Set IAR Assembler (ILINK || XLINK)
+  find_program(IAR_ASSEMBLER
+    NAMES iasm${ARCH} a${ARCH}
+    PATHS ${BIN_DIR}
+    REQUIRED )
+
+  set(RunCMake_TEST_OPTIONS
+    -DCMAKE_SYSTEM_NAME=Generic
+    -DCMAKE_C_COMPILER=${_iar_toolchain}
+    -DCMAKE_EXE_LINKER_FLAGS=${LINK_OPTS}
+  )
+  run_cmake(iar-c)
+
+  set(RunCMake_TEST_OPTIONS
+    -DCMAKE_SYSTEM_NAME=Generic
+    -DCMAKE_CXX_COMPILER=${_iar_toolchain}
+    -DCMAKE_EXE_LINKER_FLAGS=${LINK_OPTS}
+  )
+  run_cmake(iar-cxx)
+
+  set(RunCMake_TEST_OPTIONS
+    -DCMAKE_SYSTEM_NAME=Generic
+    -DCMAKE_ASM_COMPILER=${IAR_ASSEMBLER}
+    )
+  run_cmake(iar-asm)
+
+  set(RunCMake_TEST_OPTIONS
+    -DCMAKE_SYSTEM_NAME=Generic
+    -DCMAKE_C_COMPILER=${_iar_toolchain}
+    -DCMAKE_EXE_LINKER_FLAGS=${LINK_OPTS}
+    )
+  run_cmake(iar-lib)
+endforeach()
diff --git a/Tests/RunCMake/IAR/iar-asm.cmake b/Tests/RunCMake/IAR/iar-asm.cmake
new file mode 100644
index 0000000..7ff64f6
--- /dev/null
+++ b/Tests/RunCMake/IAR/iar-asm.cmake
@@ -0,0 +1,5 @@
+enable_language(ASM)
+
+add_executable(exec-asm)
+target_sources(exec-asm PRIVATE module.asm)
+target_link_options(exec-asm PRIVATE ${LINKER_OPTS})
diff --git a/Tests/RunCMake/IAR/iar-c.cmake b/Tests/RunCMake/IAR/iar-c.cmake
new file mode 100644
index 0000000..a36f096
--- /dev/null
+++ b/Tests/RunCMake/IAR/iar-c.cmake
@@ -0,0 +1,5 @@
+enable_language(C)
+
+add_executable(exec-c)
+target_sources(exec-c PRIVATE module.c)
+target_link_options(exec-c PRIVATE ${LINKER_OPTS})
diff --git a/Tests/RunCMake/IAR/iar-cxx.cmake b/Tests/RunCMake/IAR/iar-cxx.cmake
new file mode 100644
index 0000000..6b005b5
--- /dev/null
+++ b/Tests/RunCMake/IAR/iar-cxx.cmake
@@ -0,0 +1,5 @@
+enable_language(CXX)
+
+add_executable(exec-cxx)
+target_sources(exec-cxx PRIVATE module.cxx)
+target_link_options(exec-cxx PRIVATE ${LINKER_OPTS})
diff --git a/Tests/RunCMake/IAR/iar-lib.cmake b/Tests/RunCMake/IAR/iar-lib.cmake
new file mode 100644
index 0000000..78b3136
--- /dev/null
+++ b/Tests/RunCMake/IAR/iar-lib.cmake
@@ -0,0 +1,10 @@
+enable_language(C)
+
+add_library(iar-test-lib)
+target_sources(iar-test-lib PRIVATE libmod.c)
+
+add_executable(exec-lib-c)
+target_sources(exec-lib-c PRIVATE module.c)
+target_compile_definitions(exec-lib-c PRIVATE __USE_LIBFUN)
+target_link_libraries(exec-lib-c LINK_PUBLIC iar-test-lib)
+target_link_options(exec-lib-c PRIVATE ${LINKER_OPTS})
diff --git a/Tests/RunCMake/IAR/libmod.c b/Tests/RunCMake/IAR/libmod.c
new file mode 100644
index 0000000..d6c3b73
--- /dev/null
+++ b/Tests/RunCMake/IAR/libmod.c
@@ -0,0 +1,4 @@
+int iar_libfun()
+{
+  return 42;
+}
diff --git a/Tests/RunCMake/IAR/module.asm b/Tests/RunCMake/IAR/module.asm
new file mode 100644
index 0000000..1e08236
--- /dev/null
+++ b/Tests/RunCMake/IAR/module.asm
@@ -0,0 +1,41 @@
+#if defined(__IASM8051__) || defined(__IASM430__)
+  NAME main
+#else
+  MODULE main
+#endif
+
+  PUBLIC main
+  PUBLIC __iar_program_start
+  PUBLIC __program_start
+
+#if defined(__IASMSTM8__)
+  EXTERN CSTACK$$Limit
+  SECTION `.near_func.text`:CODE:NOROOT(0)
+#elif defined(__IASMAVR__)
+  ORG  $0
+  RJMP main
+  RSEG CODE
+#elif defined(__IASM8051__)
+  ORG  0FFFEh
+  DC16 main
+  RSEG RCODE
+?cmain:
+#elif defined(__IASM430__)
+  ORG  0FFFEh
+  DC16 init
+  RSEG CSTACK
+  RSEG CODE
+init:
+  MOV #SFE(CSTACK), SP
+#else
+  EXTERN __iar_static_base$$GPREL
+  SECTION CSTACK:DATA:NOROOT(4)
+  SECTION `.cstartup`:CODE(2)
+  CODE
+#endif
+
+__program_start:
+__iar_program_start:
+main:
+  NOP
+  END
diff --git a/Tests/RunCMake/IAR/module.c b/Tests/RunCMake/IAR/module.c
new file mode 100644
index 0000000..2f72a42
--- /dev/null
+++ b/Tests/RunCMake/IAR/module.c
@@ -0,0 +1,14 @@
+#include "module.h"
+#if defined(__USE_LIBFUN)
+extern int iar_libfun();
+#endif
+__root int i;
+__root int main()
+{
+#if defined(__USE_LIBFUN)
+  i = iar_libfun();
+#else
+  i = INTERNAL;
+#endif
+  return i;
+}
diff --git a/Tests/RunCMake/IAR/module.cxx b/Tests/RunCMake/IAR/module.cxx
new file mode 100644
index 0000000..5604435
--- /dev/null
+++ b/Tests/RunCMake/IAR/module.cxx
@@ -0,0 +1,7 @@
+#include "module.h"
+__root int i;
+__root int main()
+{
+  i = INTERNAL;
+  return i;
+}
diff --git a/Tests/RunCMake/IAR/module.h b/Tests/RunCMake/IAR/module.h
new file mode 100644
index 0000000..5f9c87b
--- /dev/null
+++ b/Tests/RunCMake/IAR/module.h
@@ -0,0 +1,14 @@
+#ifndef __MODULE_H__
+#define __MODULE_H__
+
+#if defined(__cplusplus)
+#  define INTERNAL 64
+#elif !defined(__cplusplus) && defined(__IAR_SYSTEMS_ICC__)
+#  define INTERNAL 32
+#elif defined(__IAR_SYSTEMS_ASM__)
+#  define INTERNAL 16
+#else
+#  error "Unable to determine INTERNAL symbol."
+#endif /* __IAR_SYSTEMS_ICC */
+
+#endif /* __MODULE_H__ */