Porting layer (#741)
This commit is contained in:
@@ -23,12 +23,14 @@
|
|||||||
#include <new>
|
#include <new>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
#include "Porting.h"
|
||||||
|
|
||||||
inline void* konanAllocMemory(size_t size) {
|
inline void* konanAllocMemory(size_t size) {
|
||||||
return calloc(1, size);
|
return konan::calloc(1, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void konanFreeMemory(void* memory) {
|
inline void konanFreeMemory(void* memory) {
|
||||||
free(memory);
|
konan::free(memory);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename ...A>
|
template <typename T, typename ...A>
|
||||||
|
|||||||
@@ -14,11 +14,12 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include "Porting.h"
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
void RuntimeAssertFailed(const char* location, const char* message) {
|
void RuntimeAssertFailed(const char* location, const char* message) {
|
||||||
// TODO: produce stacktrace and such.
|
// TODO: produce stacktrace and such.
|
||||||
fprintf(stderr, "%s: runtime assert: %s\n", location, message);
|
char buf[1024];
|
||||||
abort();
|
konan::snprintf(buf, sizeof(buf), "%s: runtime assert: %s\n", location, message);
|
||||||
|
konan::consoleErrorUtf8(buf, konan::strnlen(buf, sizeof(buf)));
|
||||||
|
konan::abort();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,27 +13,15 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "Assert.h"
|
#include "Assert.h"
|
||||||
#include "Memory.h"
|
#include "Memory.h"
|
||||||
#include "Natives.h"
|
#include "Natives.h"
|
||||||
#include "KString.h"
|
#include "KString.h"
|
||||||
|
#include "Porting.h"
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
|
|
||||||
#include "utf8.h"
|
#include "utf8.h"
|
||||||
|
|
||||||
#ifdef KONAN_ANDROID
|
|
||||||
#include <android/log.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
// io/Console.kt
|
// io/Console.kt
|
||||||
@@ -43,11 +31,7 @@ void Kotlin_io_Console_print(KString message) {
|
|||||||
const KChar* utf16 = CharArrayAddressOfElementAt(message, 0);
|
const KChar* utf16 = CharArrayAddressOfElementAt(message, 0);
|
||||||
KStdString utf8;
|
KStdString utf8;
|
||||||
utf8::utf16to8(utf16, utf16 + message->count_, back_inserter(utf8));
|
utf8::utf16to8(utf16, utf16 + message->count_, back_inserter(utf8));
|
||||||
#ifdef KONAN_ANDROID
|
konan::consoleWriteUtf8(utf8.c_str(), utf8.size());
|
||||||
__android_log_print(ANDROID_LOG_INFO, "Konan_main", "%s", utf8.c_str());
|
|
||||||
#else
|
|
||||||
write(STDOUT_FILENO, utf8.c_str(), utf8.size());
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Kotlin_io_Console_println(KString message) {
|
void Kotlin_io_Console_println(KString message) {
|
||||||
@@ -56,17 +40,13 @@ void Kotlin_io_Console_println(KString message) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Kotlin_io_Console_println0() {
|
void Kotlin_io_Console_println0() {
|
||||||
#ifdef KONAN_ANDROID
|
konan::consoleWriteUtf8("\n", 1);
|
||||||
__android_log_print(ANDROID_LOG_INFO, "Konan_main", "\n");
|
|
||||||
#else
|
|
||||||
write(STDOUT_FILENO, "\n", 1);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OBJ_GETTER0(Kotlin_io_Console_readLine) {
|
OBJ_GETTER0(Kotlin_io_Console_readLine) {
|
||||||
char data[4096];
|
char data[4096];
|
||||||
if (!fgets(data, sizeof(data) - 1, stdin)) {
|
if (konan::consoleReadUtf8(data, sizeof(data)) == 0) {
|
||||||
return nullptr;
|
RETURN_OBJ(nullptr);
|
||||||
}
|
}
|
||||||
RETURN_RESULT_OF(CreateStringFromCString, data);
|
RETURN_RESULT_OF(CreateStringFromCString, data);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
#include "Memory.h"
|
#include "Memory.h"
|
||||||
#include "Natives.h"
|
#include "Natives.h"
|
||||||
#include "KString.h"
|
#include "KString.h"
|
||||||
|
#include "Porting.h"
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
|
|
||||||
#include "utf8.h"
|
#include "utf8.h"
|
||||||
@@ -1015,16 +1016,6 @@ KInt Kotlin_String_lastIndexOfChar(KString thiz, KChar ch, KInt fromIndex) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
static void* memmem(const void* big, size_t big_len, const void* little, size_t little_len) {
|
|
||||||
for (size_t i = 0; i + little_len <= big_len; ++i) {
|
|
||||||
void* pos = ((char*)big) + i;
|
|
||||||
if (memcmp(little, pos, little_len) == 0) return pos;
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// TODO: or code up Knuth-Moris-Pratt.
|
// TODO: or code up Knuth-Moris-Pratt.
|
||||||
KInt Kotlin_String_indexOfString(KString thiz, KString other, KInt fromIndex) {
|
KInt Kotlin_String_indexOfString(KString thiz, KString other, KInt fromIndex) {
|
||||||
if (fromIndex < 0 || fromIndex > thiz->count_ ||
|
if (fromIndex < 0 || fromIndex > thiz->count_ ||
|
||||||
@@ -1038,8 +1029,8 @@ KInt Kotlin_String_indexOfString(KString thiz, KString other, KInt fromIndex) {
|
|||||||
KInt count = thiz->count_;
|
KInt count = thiz->count_;
|
||||||
const KChar* thizRaw = CharArrayAddressOfElementAt(thiz, fromIndex);
|
const KChar* thizRaw = CharArrayAddressOfElementAt(thiz, fromIndex);
|
||||||
const KChar* otherRaw = CharArrayAddressOfElementAt(other, 0);
|
const KChar* otherRaw = CharArrayAddressOfElementAt(other, 0);
|
||||||
void* result = memmem(thizRaw, (thiz->count_ - fromIndex) * sizeof(KChar),
|
void* result = konan::memmem(thizRaw, (thiz->count_ - fromIndex) * sizeof(KChar),
|
||||||
otherRaw, other->count_ * sizeof(KChar));
|
otherRaw, other->count_ * sizeof(KChar));
|
||||||
if (result == nullptr) return -1;
|
if (result == nullptr) return -1;
|
||||||
|
|
||||||
return (reinterpret_cast<intptr_t>(result) - reinterpret_cast<intptr_t>(
|
return (reinterpret_cast<intptr_t>(result) - reinterpret_cast<intptr_t>(
|
||||||
|
|||||||
@@ -0,0 +1,127 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2017 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef KONAN_ANDROID
|
||||||
|
#include <android/log.h>
|
||||||
|
#endif
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#if KONAN_WINDOWS
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
|
#include "Porting.h"
|
||||||
|
|
||||||
|
namespace konan {
|
||||||
|
|
||||||
|
// Console operations.
|
||||||
|
void consoleInit() {
|
||||||
|
#if KONAN_WINDOWS
|
||||||
|
// Note that this code enforces UTF-8 console output, so we may want to rethink
|
||||||
|
// how we perform console IO, if it turns out, that UTF-16 is better output format.
|
||||||
|
::SetConsoleCP(CP_UTF8);
|
||||||
|
::SetConsoleOutputCP(CP_UTF8);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void consoleWriteUtf8(const void* utf8, uint32_t sizeBytes) {
|
||||||
|
#ifdef KONAN_ANDROID
|
||||||
|
// TODO: use sizeBytes!
|
||||||
|
__android_log_print(ANDROID_LOG_INFO, "Konan_main", "%s", utf8);
|
||||||
|
#else
|
||||||
|
::write(STDOUT_FILENO, utf8, sizeBytes);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void consoleErrorUtf8(const void* utf8, uint32_t sizeBytes) {
|
||||||
|
#ifdef KONAN_ANDROID
|
||||||
|
// TODO: use sizeBytes!
|
||||||
|
__android_log_print(ANDROID_LOG_ERROR, "Konan_main", "%s", utf8);
|
||||||
|
#else
|
||||||
|
::write(STDERR_FILENO, utf8, sizeBytes);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t consoleReadUtf8(void* utf8, uint32_t maxSizeBytes) {
|
||||||
|
char* result = ::fgets(reinterpret_cast<char*>(utf8), maxSizeBytes - 1, stdin);
|
||||||
|
if (result == nullptr) return 0;
|
||||||
|
return ::strlen(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process execution.
|
||||||
|
void abort() {
|
||||||
|
::abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
// String/byte operations.
|
||||||
|
// 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
|
||||||
|
for (size_t i = 0; i + littleLen <= bigLen; ++i) {
|
||||||
|
void* pos = ((char*)big) + i;
|
||||||
|
if (::memcmp(little, pos, littleLen) == 0) return pos;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
#else
|
||||||
|
return ::memmem(big, bigLen, little, littleLen);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int snprintf(char* buffer, size_t size, const char* format, ...) {
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
int rv = ::vsnprintf(buffer, size, format, args);
|
||||||
|
va_end(args);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t strnlen(const char* buffer, size_t maxSize) {
|
||||||
|
return ::strnlen(buffer, maxSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Memory operations.
|
||||||
|
void* calloc(size_t count, size_t size) {
|
||||||
|
return ::calloc(count, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void free(void* pointer) {
|
||||||
|
return ::free(pointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Time operations.
|
||||||
|
using namespace std::chrono;
|
||||||
|
|
||||||
|
uint64_t getTimeMillis() {
|
||||||
|
return duration_cast<milliseconds>(high_resolution_clock::now().time_since_epoch()).count();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t getTimeNanos() {
|
||||||
|
return duration_cast<nanoseconds>(high_resolution_clock::now().time_since_epoch()).count();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t getTimeMicros() {
|
||||||
|
return duration_cast<microseconds>(high_resolution_clock::now().time_since_epoch()).count();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace konan
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2017 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef RUNTIME_PORTING_H
|
||||||
|
#define RUNTIME_PORTING_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
namespace konan {
|
||||||
|
|
||||||
|
// Console operations.
|
||||||
|
void consoleInit();
|
||||||
|
void consoleWriteUtf8(const void* utf8, uint32_t sizeBytes);
|
||||||
|
void consoleErrorUtf8(const void* utf8, uint32_t sizeBytes);
|
||||||
|
uint32_t consoleReadUtf8(void* utf8, uint32_t maxSizeBytes);
|
||||||
|
|
||||||
|
// Process control.
|
||||||
|
void abort();
|
||||||
|
|
||||||
|
// String/byte operations.
|
||||||
|
// memcpy/memmove/memcmp 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);
|
||||||
|
int snprintf(char* buffer, size_t size, const char* format, ...);
|
||||||
|
size_t strnlen(const char* buffer, size_t maxSize);
|
||||||
|
|
||||||
|
// Memory operations.
|
||||||
|
void* calloc(size_t count, size_t size);
|
||||||
|
void free(void* ptr);
|
||||||
|
|
||||||
|
// Time operations.
|
||||||
|
uint64_t getTimeMillis();
|
||||||
|
uint64_t getTimeMicros();
|
||||||
|
uint64_t getTimeNanos();
|
||||||
|
|
||||||
|
} // namespace konan
|
||||||
|
|
||||||
|
#endif // RUNTIME_PORTING_H
|
||||||
@@ -15,12 +15,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#if KONAN_WINDOWS
|
|
||||||
#include <windows.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "Alloc.h"
|
#include "Alloc.h"
|
||||||
#include "Memory.h"
|
#include "Memory.h"
|
||||||
|
#include "Porting.h"
|
||||||
#include "Runtime.h"
|
#include "Runtime.h"
|
||||||
|
|
||||||
struct RuntimeState {
|
struct RuntimeState {
|
||||||
@@ -48,9 +46,7 @@ void InitOrDeinitGlobalVariables(int initialize) {
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
|
||||||
|
|
||||||
void AppendToInitializersTail(InitNode *next) {
|
void AppendToInitializersTail(InitNode *next) {
|
||||||
// TODO: use RuntimeState.
|
// TODO: use RuntimeState.
|
||||||
@@ -68,12 +64,7 @@ RuntimeState* InitRuntime() {
|
|||||||
result->memoryState = InitMemory();
|
result->memoryState = InitMemory();
|
||||||
// Keep global variables in state as well.
|
// Keep global variables in state as well.
|
||||||
InitOrDeinitGlobalVariables(true);
|
InitOrDeinitGlobalVariables(true);
|
||||||
#if KONAN_WINDOWS
|
konan::consoleInit();
|
||||||
// Note that this code enforces UTF-8 console output, so we may want to rethink
|
|
||||||
// how we perform console IO, if it turns out, that UTF-16 is better output format.
|
|
||||||
SetConsoleCP(CP_UTF8);
|
|
||||||
SetConsoleOutputCP(CP_UTF8);
|
|
||||||
#endif
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,6 +76,4 @@ void DeinitRuntime(RuntimeState* state) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
} // extern "C"
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|||||||
@@ -1,21 +1,35 @@
|
|||||||
#include <chrono>
|
/*
|
||||||
#include "Types.h"
|
* Copyright 2010-2017 JetBrains s.r.o.
|
||||||
#include "Natives.h"
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
using namespace std::chrono;
|
#include "Natives.h"
|
||||||
|
#include "Porting.h"
|
||||||
|
#include "Types.h"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
KLong Kotlin_system_getTimeMillis() {
|
KLong Kotlin_system_getTimeMillis() {
|
||||||
return duration_cast<milliseconds>(high_resolution_clock::now().time_since_epoch()).count();
|
return konan::getTimeMillis();
|
||||||
}
|
}
|
||||||
|
|
||||||
KLong Kotlin_system_getTimeNanos() {
|
KLong Kotlin_system_getTimeNanos() {
|
||||||
return duration_cast<nanoseconds>(high_resolution_clock::now().time_since_epoch()).count();
|
return konan::getTimeNanos();
|
||||||
}
|
}
|
||||||
|
|
||||||
KLong Kotlin_system_getTimeMicros() {
|
KLong Kotlin_system_getTimeMicros() {
|
||||||
return duration_cast<microseconds>(high_resolution_clock::now().time_since_epoch()).count();
|
return konan::getTimeMicros();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
|||||||
@@ -17,9 +17,7 @@
|
|||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
#include "Exceptions.h"
|
#include "Exceptions.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
|
||||||
|
|
||||||
KBoolean IsInstance(const ObjHeader* obj, const TypeInfo* type_info) {
|
KBoolean IsInstance(const ObjHeader* obj, const TypeInfo* type_info) {
|
||||||
// We assume null check is handled by caller.
|
// We assume null check is handled by caller.
|
||||||
@@ -52,6 +50,4 @@ void CheckInstance(const ObjHeader* obj, const TypeInfo* type_info) {
|
|||||||
ThrowClassCastException();
|
ThrowClassCastException();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
} // extern "C"
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|||||||
Reference in New Issue
Block a user