diff --git a/backend.native/konan.properties b/backend.native/konan.properties index 70f8e17afdd..02b285684ae 100644 --- a/backend.native/konan.properties +++ b/backend.native/konan.properties @@ -331,3 +331,16 @@ llcOptFlags.wasm32 = -O3 llcDebugFlags.wasm32 = -O0 # The stack size is in bytes. s2wasmFlags.wasm32 = --allocate-stack 1048576 --import-memory + +# Zephyr RTOS. +targetToolchain.linux-zephyr = target-gcc-toolchain-6-2017q2-linux-armemb/arm-none-eabi +dependencies.linux-zephyr = \ + clang-llvm-5.0.0-linux-x86-64 \ + target-gcc-toolchain-6-2017q2-linux-armemb \ + target-sysroot-2-wasm \ + zephyr-host-tools-1-linux \ + zephyr-zephyr-v1.10.0 + +quadruple.zephyr = armv7m-none-eabi +targetSysRoot.zephyr = target-sysroot-2-wasm +entrySelector.zephyr = --defsym main=Konan_main diff --git a/runtime/src/main/cpp/Math.cpp b/runtime/src/main/cpp/Math.cpp index 26ca1c2fdaa..4fd0c2aed21 100644 --- a/runtime/src/main/cpp/Math.cpp +++ b/runtime/src/main/cpp/Math.cpp @@ -27,7 +27,7 @@ #define KONAN_NEED_ASINH_ACOSH 0 #endif -#ifdef KONAN_WASM +#if KONAN_WASM || __ZEPHYR__ #define KONAN_NO_MATH 1 #else #define KONAN_NO_MATH 0 diff --git a/runtime/src/main/cpp/Porting.cpp b/runtime/src/main/cpp/Porting.cpp index df95405bec5..2031992d3f4 100644 --- a/runtime/src/main/cpp/Porting.cpp +++ b/runtime/src/main/cpp/Porting.cpp @@ -34,7 +34,7 @@ #include "Porting.h" -#ifdef KONAN_WASM +#if KONAN_WASM || __ZEPHYR__ extern "C" void Konan_abort(const char*); extern "C" void Konan_exit(int32_t status); #endif @@ -124,7 +124,7 @@ static void onThreadExitInit() { void onThreadExit(void (*destructor)()) { #if KONAN_NO_THREADS -#ifdef KONAN_WASM +#if KONAN_WASM || __ZEPHYR__ // No way to do that. #else #error "How to do onThreadExit()?" @@ -145,7 +145,7 @@ void abort() { ::abort(); } -#ifdef KONAN_WASM +#if KONAN_WASM || __ZEPHYR__ void exit(int32_t status) { Konan_exit(status); } @@ -159,7 +159,7 @@ void exit(int32_t status) { // memcpy/memmove are not here intentionally, as frequently implemented/optimized // by C compiler. void* memmem(const void *big, size_t bigLen, const void *little, size_t littleLen) { -#if KONAN_WINDOWS || KONAN_WASM +#if KONAN_WINDOWS || KONAN_WASM || __ZEPHYR__ for (size_t i = 0; i + littleLen <= bigLen; ++i) { void* pos = ((char*)big) + i; if (::memcmp(little, pos, littleLen) == 0) return pos; @@ -180,9 +180,11 @@ int snprintf(char* buffer, size_t size, const char* format, ...) { return rv; } +#if !__ZEPHYR__ size_t strnlen(const char* buffer, size_t maxSize) { return ::strnlen(buffer, maxSize); } +#endif // Memory operations. #if KONAN_INTERNAL_DLMALLOC @@ -241,7 +243,7 @@ uint64_t getTimeMicros() { #if KONAN_INTERNAL_DLMALLOC // This function is being called when memory allocator needs more RAM. -#ifdef KONAN_WASM +#if KONAN_WASM || __ZEPHYR__ // This one is an interface to query module.env.memory.buffer.byteLength extern "C" unsigned long Konan_heap_upper(); @@ -302,7 +304,7 @@ long getpagesize() { } // namespace konan extern "C" { -#ifdef KONAN_WASM +#if KONAN_WASM || __ZEPHYR__ // TODO: get rid of these. void _ZNKSt3__220__vector_base_commonILb1EE20__throw_length_errorEv(void) { @@ -399,4 +401,60 @@ extern "C" { } #endif +#if __ZEPHYR__ + + /* Support the alias for the __aeabi_memcpy which may + assume memory alignment. */ + void __aeabi_memcpy4 (void *dest, const void *source, size_t n) + __attribute__ ((alias ("memcpy"))); + + void __aeabi_memcpy8 (void *dest, const void *source, size_t n) + __attribute__ ((alias ("memcpy"))); + + void __aeabi_memcpy (void *dest, const void *source, size_t n) + __attribute__ ((alias ("memcpy"))); + + /* Support the alias for the __aeabi_memmove which may + assume memory alignment. */ + void __aeabi_memmove4 (void *dest, const void *source, size_t n) + __attribute__ ((alias ("memmove"))); + + void __aeabi_memmove8 (void *dest, const void *source, size_t n) + __attribute__ ((alias ("memmove"))); + + void __aeabi_memmove (void *dest, const void *source, size_t n) + __attribute__ ((alias ("memmove"))); + + /* Support the alias for the __aeabi_memset which may + assume memory alignment. */ + void __aeabi_memset4 (void *dest, size_t n, int c) + __attribute__ ((alias ("__aeabi_memset"))); + + void __aeabi_memset8 (void *dest, size_t n, int c) + __attribute__ ((alias ("__aeabi_memset"))); + + /* Support the routine __aeabi_memset. Can't alias to memset + because it's not defined in the same translation unit. */ + void __aeabi_memset (void *dest, size_t n, int c) + { + /*Note that relative to ANSI memset, __aeabi_memset hase the order + of its second and third arguments reversed. */ + memset (dest, c, n); + } + + /* Support the alias for the __aeabi_memclr which may + assume memory alignment. */ + void __aeabi_memclr4 (void *dest, size_t n) + __attribute__ ((alias ("__aeabi_memclr"))); + + void __aeabi_memclr8 (void *dest, size_t n) + __attribute__ ((alias ("__aeabi_memclr"))); + + /* Support the routine __aeabi_memclr. */ + void __aeabi_memclr (void *dest, size_t n) + { + __aeabi_memset (dest, n, 0); + } + +#endif } diff --git a/runtime/src/main/cpp/Types.h b/runtime/src/main/cpp/Types.h index d490605ba42..7db903d2f61 100644 --- a/runtime/src/main/cpp/Types.h +++ b/runtime/src/main/cpp/Types.h @@ -19,7 +19,7 @@ #include -#if KONAN_WASM && !defined(assert) +#if (KONAN_WASM || __ZEPHYR__) && !defined(assert) // assert() is needed by WASM STL. #define assert(cond) if (!(cond)) abort() #endif diff --git a/runtime/src/main/cpp/dlmalloc/malloc.cpp b/runtime/src/main/cpp/dlmalloc/malloc.cpp index 28c73c7efe3..7cce18210c1 100644 --- a/runtime/src/main/cpp/dlmalloc/malloc.cpp +++ b/runtime/src/main/cpp/dlmalloc/malloc.cpp @@ -525,13 +525,13 @@ MAX_RELEASE_CHECK_RATE default: 4095 unless not HAVE_MMAP /**** Start of Konan-specific dlmalloc configuration. ****/ #define USE_DL_PREFIX 1 -#if KONAN_WASM +#if KONAN_WASM || __ZEPHYR__ #define USE_LOCKS 0 #define LACKS_TIME_H 1 #define NO_MALLOC_STATS 1 -#define HAVE_MMAP 0 // don't try to allocate large chunks of memory using mmap(). +#define HAVE_MMAP 0 // don't try to allocate large chunks of memory using mmap(). // It will go to malloc->calloc->sbrk->morecore chain anyways. -#else +#else #define USE_LOCKS 1 #endif #define DLMALLOC_EXPORT extern "C" diff --git a/samples/zephyr/CMakeLists.txt b/samples/zephyr/CMakeLists.txt new file mode 100644 index 00000000000..5b4e05b9997 --- /dev/null +++ b/samples/zephyr/CMakeLists.txt @@ -0,0 +1,4 @@ +include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE) +project(NONE) + +target_sources(app PRIVATE build/program.o) diff --git a/samples/zephyr/build.sh b/samples/zephyr/build.sh new file mode 100755 index 00000000000..a00cd5c08dc --- /dev/null +++ b/samples/zephyr/build.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +DIR=$(cd "$(dirname "${BASH_SOURCE[0]}" )" && pwd ) + +source "$DIR/../konan.sh" + +mkdir -p $DIR/build && cd $DIR/build + +konanc $DIR/src/main.kt -target zephyr + +DEP="$HOME/.konan/dependencies" +export ZEPHYR_BASE="$DEP/zephyr-zephyr-v1.10.0" +export ZEPHYR_GCC_VARIANT=gccarmemb +export GCCARMEMB_TOOLCHAIN_PATH="$DEP/target-gcc-toolchain-6-2017q2-linux-armemb/" +export PATH="$DEP/zephyr-host-tools-1-linux/bin:$PATH" + +[ -f CMakeCache.txt ] || cmake -DBOARD=qemu_cortex_m3 .. +make run diff --git a/samples/zephyr/prj.conf b/samples/zephyr/prj.conf new file mode 100644 index 00000000000..fa6ff34bed9 --- /dev/null +++ b/samples/zephyr/prj.conf @@ -0,0 +1,4 @@ +CONFIG_CPLUSPLUS=y +CONFIG_PRINTK=y +CONFIG_BOOT_BANNER=y +CONFIG_BUILD_OUTPUT_BIN=y diff --git a/samples/zephyr/src/main.cpp b/samples/zephyr/src/main.cpp new file mode 100644 index 00000000000..04bd688f5f3 --- /dev/null +++ b/samples/zephyr/src/main.cpp @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2012-2014 Wind River Systems, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +void main(void) +{ + printk("Hello World! %s\n", CONFIG_ARCH); +} diff --git a/samples/zephyr/src/main.kt b/samples/zephyr/src/main.kt new file mode 100644 index 00000000000..1e42b4ff19a --- /dev/null +++ b/samples/zephyr/src/main.kt @@ -0,0 +1,3 @@ +fun main(args: Array) { + println("Hello World!") +} diff --git a/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/ClangArgs.kt b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/ClangArgs.kt index 2be9ae0c13a..436f5b357f8 100644 --- a/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/ClangArgs.kt +++ b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/ClangArgs.kt @@ -81,6 +81,20 @@ class ClangArgs(private val configurables: Configurables) : Configurables by con "-nostdinc", "-Xclang", "-nobuiltininc", "-Xclang", "-nostdsysteminc", "-Xclang", "-isystem$absoluteTargetSysRoot/include/libcxx", "-Xclang", "-isystem$absoluteTargetSysRoot/lib/libcxxabi/include", "-Xclang", "-isystem$absoluteTargetSysRoot/include/compat", "-Xclang", "-isystem$absoluteTargetSysRoot/include/libc") + KonanTarget.ZEPHYR -> + listOf("-target", targetArg!!, "-mabi=aapcs", "-mthumb", "-mcpu=cortex-m3", + "-Os", "-g", + "-fno-rtti", + "-fno-exceptions", + "-fno-asynchronous-unwind-tables", + "-fno-pie", + "-fno-pic", + "-nostdinc", + "-isystem$sysRoot/include/libcxx", + "-isystem$sysRoot/lib/libcxxabi/include", + "-isystem$sysRoot/include/compat", + "-isystem$sysRoot/include/libc") + } return result } @@ -120,6 +134,9 @@ class ClangArgs(private val configurables: Configurables) : Configurables by con KonanTarget.WASM32 -> listOf("-DKONAN_WASM=1", "-DKONAN_NO_FFI=1", "-DKONAN_NO_THREADS=1", "-DKONAN_NO_EXCEPTIONS=1", "-DKONAN_INTERNAL_DLMALLOC=1", "-DKONAN_INTERNAL_SNPRINTF=1", "-DKONAN_INTERNAL_NOW=1") + KonanTarget.ZEPHYR -> + listOf( "-D__ZEPHYR__=1", "-DKONAN_NO_FFI=1", "-DKONAN_NO_THREADS=1", "-DKONAN_NO_EXCEPTIONS=1", + "-DKONAN_INTERNAL_DLMALLOC=1", "-DKONAN_INTERNAL_SNPRINTF=1", "-DKONAN_INTERNAL_NOW=1") } private val host = TargetManager.host diff --git a/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/KonanTarget.kt b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/KonanTarget.kt index 81b6dee4bc2..235aa909444 100644 --- a/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/KonanTarget.kt +++ b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/KonanTarget.kt @@ -26,7 +26,8 @@ enum class Family(val exeSuffix:String, val dynamicPrefix: String, val dynamicSu LINUX ("kexe", "lib", "so" ), WINDOWS ("exe" , "" , "dll" ), ANDROID ("so" , "lib", "so" ), - WASM ("wasm", "" , "wasm" ) + WASM ("wasm", "" , "wasm" ), + ZEPHYR ("o" , "lib", "a" ) } enum class Architecture(val bitness: Int) { @@ -50,6 +51,8 @@ sealed class KonanTarget(override val name: String, val family: Family, val arch object LINUX_MIPS32 : KonanTarget( "linux_mips32", Family.LINUX, Architecture.MIPS32, "linux_mips32") object LINUX_MIPSEL32 : KonanTarget( "linux_mipsel32", Family.LINUX, Architecture.MIPSEL32, "linux_mipsel32") object WASM32 : KonanTarget( "wasm32", Family.WASM, Architecture.WASM32, "wasm32") + // Tunable targets + class ZEPHYR(val subName: String) : KonanTarget("$zephyr_$subName", Family.ZEPHYR, Architecture.ARM32, "$zephyr_$subName") companion object { protected val memberObjects = mutableListOf() @@ -59,6 +62,12 @@ sealed class KonanTarget(override val name: String, val family: Family, val arch init { memberObjects.add(this) } + + fun generateZephyrTargets(subtargets: List) { + subtargets.forEach { + object : ZEPHYR(it) + } + } } fun hostTargetSuffix(host: KonanTarget, target: KonanTarget) = @@ -179,12 +188,13 @@ class TargetManager(val userRequest: String? = null) { when (host) { KonanTarget.LINUX -> { KonanTarget.LINUX.enabled = true - KonanTarget.RASPBERRYPI.enabled = true + /*KonanTarget.RASPBERRYPI.enabled = true KonanTarget.LINUX_MIPS32.enabled = true KonanTarget.LINUX_MIPSEL32.enabled = true KonanTarget.ANDROID_ARM32.enabled = true KonanTarget.ANDROID_ARM64.enabled = true - KonanTarget.WASM32.enabled = true + KonanTarget.WASM32.enabled = true*/ + KonanTarget.ZEPHYR.enabled = true } KonanTarget.MINGW -> { KonanTarget.MINGW.enabled = true diff --git a/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Linker.kt b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Linker.kt index b467dc9ce61..75f40da643d 100644 --- a/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Linker.kt +++ b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Linker.kt @@ -285,6 +285,25 @@ open class WasmLinker(targetProperties: WasmConfigurables) } } +open class ZephyrLinker(targetProperties: ZephyrConfigurables) + : LinkerFlags(targetProperties), ZephyrConfigurables by targetProperties { + + private val linker = "$targetToolchain/bin/ld" + + override val useCompilerDriverAsLinker: Boolean get() = false + + override fun filterStaticLibraries(binaries: List) + = emptyList() + + override fun linkCommand(objectFiles: List, executable: ExecutableFile, optimize: Boolean, debug: Boolean, dynamic: Boolean): Command { + return Command(linker).apply { + + listOf("-r", "--gc-sections", "--entry", "main") + + listOf("-o", executable) + + objectFiles + } + } +} + fun linker(configurables: Configurables): LinkerFlags = when (configurables.target) { KonanTarget.LINUX, KonanTarget.RASPBERRYPI ->