WebAssembly effort (#721)
This commit is contained in:
+9
-2
@@ -88,7 +88,8 @@ private val knownTargets = mapOf(
|
|||||||
"raspberrypi" to "raspberrypi",
|
"raspberrypi" to "raspberrypi",
|
||||||
"android_arm32" to "android_arm32",
|
"android_arm32" to "android_arm32",
|
||||||
"android_arm64" to "android_arm64",
|
"android_arm64" to "android_arm64",
|
||||||
"mingw" to "mingw"
|
"mingw" to "mingw",
|
||||||
|
"wasm32" to "wasm32"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -198,6 +199,12 @@ private fun maybeExecuteHelper(dependenciesRoot: String, properties: Properties,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun Properties.getClangFlags(target: String, targetSysRoot: String) : List<String> {
|
||||||
|
val flags = getTargetSpecific("clangFlags", target)
|
||||||
|
if (flags == null) return emptyList()
|
||||||
|
return flags.replace("<sysrootDir>", targetSysRoot).split(' ')
|
||||||
|
}
|
||||||
|
|
||||||
private fun Properties.defaultCompilerOpts(target: String, dependencies: String): List<String> {
|
private fun Properties.defaultCompilerOpts(target: String, dependencies: String): List<String> {
|
||||||
val targetToolchainDir = getHostTargetSpecific("targetToolchain", target)!!
|
val targetToolchainDir = getHostTargetSpecific("targetToolchain", target)!!
|
||||||
val targetToolchain = "$dependencies/$targetToolchainDir"
|
val targetToolchain = "$dependencies/$targetToolchainDir"
|
||||||
@@ -224,7 +231,7 @@ private fun Properties.defaultCompilerOpts(target: String, dependencies: String)
|
|||||||
val arch = getTargetSpecific("arch", target)
|
val arch = getTargetSpecific("arch", target)
|
||||||
val archSelector = if (quadruple != null)
|
val archSelector = if (quadruple != null)
|
||||||
listOf("-target", quadruple) else listOf("-arch", arch!!)
|
listOf("-target", quadruple) else listOf("-arch", arch!!)
|
||||||
val commonArgs = listOf("-isystem", isystem, "--sysroot=$targetSysRoot")
|
val commonArgs = listOf("-isystem", isystem, "--sysroot=$targetSysRoot") + getClangFlags(target, targetSysRoot)
|
||||||
when (host) {
|
when (host) {
|
||||||
"osx" -> {
|
"osx" -> {
|
||||||
val osVersionMinFlag = getTargetSpecific("osVersionMinFlagClang", target)
|
val osVersionMinFlag = getTargetSpecific("osVersionMinFlagClang", target)
|
||||||
|
|||||||
@@ -161,7 +161,9 @@ targetList.each { target ->
|
|||||||
"-Djava.library.path=${project.buildDir}/nativelibs",
|
"-Djava.library.path=${project.buildDir}/nativelibs",
|
||||||
"-Dfile.encoding=UTF-8"]
|
"-Dfile.encoding=UTF-8"]
|
||||||
|
|
||||||
def konanArgs = ['-nopack', '-nostdlib','-ea', '-g',
|
def defaultArgs = ['-nopack', '-nostdlib','-ea' ]
|
||||||
|
if (target != "wasm32") defaultArgs += '-g'
|
||||||
|
def konanArgs = [*defaultArgs,
|
||||||
'-target', target,
|
'-target', target,
|
||||||
'-runtime', project(':runtime').file("build/${target}/runtime.bc"),
|
'-runtime', project(':runtime').file("build/${target}/runtime.bc"),
|
||||||
'-properties', rootProject.konanPropertiesFile.canonicalPath,
|
'-properties', rootProject.konanPropertiesFile.canonicalPath,
|
||||||
|
|||||||
+17
@@ -169,6 +169,21 @@ internal open class MingwPlatform(distribution: Distribution)
|
|||||||
override fun linkCommandSuffix() = linkerKonanFlags
|
override fun linkCommandSuffix() = linkerKonanFlags
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal open class WasmPlatform(distribution: Distribution)
|
||||||
|
: PlatformFlags(distribution.targetProperties) {
|
||||||
|
|
||||||
|
private val clang = "clang"
|
||||||
|
|
||||||
|
override val useCompilerDriverAsLinker: Boolean get() = false
|
||||||
|
|
||||||
|
override fun linkCommand(objectFiles: List<ObjectFile>, executable: ExecutableFile, optimize: Boolean, debug: Boolean): List<String> {
|
||||||
|
|
||||||
|
return mutableListOf(clang).apply{
|
||||||
|
throw Error("Implement me!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal class LinkStage(val context: Context) {
|
internal class LinkStage(val context: Context) {
|
||||||
|
|
||||||
val config = context.config.configuration
|
val config = context.config.configuration
|
||||||
@@ -184,6 +199,8 @@ internal class LinkStage(val context: Context) {
|
|||||||
AndroidPlatform(distribution)
|
AndroidPlatform(distribution)
|
||||||
KonanTarget.MINGW ->
|
KonanTarget.MINGW ->
|
||||||
MingwPlatform(distribution)
|
MingwPlatform(distribution)
|
||||||
|
KonanTarget.WASM32 ->
|
||||||
|
WasmPlatform(distribution)
|
||||||
else ->
|
else ->
|
||||||
error("Unexpected target platform: ${context.config.targetManager.target}")
|
error("Unexpected target platform: ${context.config.targetManager.target}")
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-4
@@ -43,11 +43,14 @@ class Runtime(bitcodeFile: String) {
|
|||||||
val target = LLVMGetTarget(llvmModule)!!.toKString()
|
val target = LLVMGetTarget(llvmModule)!!.toKString()
|
||||||
|
|
||||||
// TODO: deduce TLS model from explicit config parameter.
|
// TODO: deduce TLS model from explicit config parameter.
|
||||||
val tlsMode = if (target.indexOf("android") != -1)
|
val tlsMode by lazy {
|
||||||
LLVMThreadLocalMode.LLVMGeneralDynamicTLSModel else LLVMThreadLocalMode.LLVMLocalExecTLSModel
|
when {
|
||||||
|
target.indexOf("android") != -1 -> LLVMThreadLocalMode.LLVMGeneralDynamicTLSModel
|
||||||
|
target.indexOf("wasm") != -1 -> LLVMThreadLocalMode.LLVMNotThreadLocal
|
||||||
|
else -> LLVMThreadLocalMode.LLVMLocalExecTLSModel
|
||||||
|
}
|
||||||
|
}
|
||||||
val dataLayout = LLVMGetDataLayout(llvmModule)!!.toKString()
|
val dataLayout = LLVMGetDataLayout(llvmModule)!!.toKString()
|
||||||
|
|
||||||
val targetData = LLVMCreateTargetData(dataLayout)!!
|
val targetData = LLVMCreateTargetData(dataLayout)!!
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -209,3 +209,22 @@ entrySelector.mingw = -Wl,--defsym,main=Konan_main
|
|||||||
dependencies.mingw = \
|
dependencies.mingw = \
|
||||||
msys2-mingw-w64-x86_64-gcc-6.3.0-clang-llvm-3.9.1-windows-x86-64 \
|
msys2-mingw-w64-x86_64-gcc-6.3.0-clang-llvm-3.9.1-windows-x86-64 \
|
||||||
libffi-3.2.1-mingw-w64-x86-64
|
libffi-3.2.1-mingw-w64-x86-64
|
||||||
|
|
||||||
|
# WebAssembly 32-bit.
|
||||||
|
targetToolchain.osx-wasm32 = target-toolchain-1-osx-wasm
|
||||||
|
dependencies.osx-wasm32 = \
|
||||||
|
clang-llvm-3.9.0-darwin-macos \
|
||||||
|
target-sysroot-1-wasm \
|
||||||
|
target-toolchain-1-osx-wasm
|
||||||
|
|
||||||
|
quadruple.wasm32 = wasm32
|
||||||
|
entrySelector.wasm32 = -Wl,--defsym -Wl,main=Konan_main
|
||||||
|
llvmLtoFlags.wasm32 = -exported-symbol=Konan_main
|
||||||
|
targetSysRoot.wasm32 = target-sysroot-1-wasm
|
||||||
|
clangFlags.wasm32 = -O1 -fno-rtti -fno-exceptions \
|
||||||
|
-D_LIBCPP_ABI_VERSION=2 -DKONAN_NO_FFI=1 -DKONAN_NO_THREADS=1 -DKONAN_NO_EXCEPTIONS=1 \
|
||||||
|
-nostdinc -Xclang -nobuiltininc -Xclang -nostdsysteminc \
|
||||||
|
-Xclang -isystem<sysrootDir>/include/libcxx -Xclang -isystem<sysrootDir>/lib/libcxxabi/include \
|
||||||
|
-Xclang -isystem<sysrootDir>/include/compat -Xclang -isystem<sysrootDir>/include/libc
|
||||||
|
linkerKonanFlags.wasm32 = -lc
|
||||||
|
linkerDebugFlags.wasm32 = -Wl,-S
|
||||||
+4
-4
@@ -102,7 +102,7 @@ void loadLocalProperties() {
|
|||||||
if (new File("$project.rootDir/local.properties").exists()) {
|
if (new File("$project.rootDir/local.properties").exists()) {
|
||||||
Properties props = new Properties()
|
Properties props = new Properties()
|
||||||
props.load(new FileInputStream("$project.rootDir/local.properties"))
|
props.load(new FileInputStream("$project.rootDir/local.properties"))
|
||||||
props.each {prop -> project.ext.set(prop.key, prop.value)}
|
props.each { prop -> project.ext.set(prop.key, prop.value) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,11 +111,11 @@ void loadCommandLineProperties() {
|
|||||||
throw new Error("Specify either -Ptest_flags or -Pbuild_flags.")
|
throw new Error("Specify either -Ptest_flags or -Pbuild_flags.")
|
||||||
}
|
}
|
||||||
ext.globalBuildArgs = project.hasProperty("build_flags")
|
ext.globalBuildArgs = project.hasProperty("build_flags")
|
||||||
? ext.build_flags.split(' ') : []
|
? ext.build_flags.split(' '): []
|
||||||
ext.globalTestArgs = project.hasProperty("test_flags")
|
ext.globalTestArgs = project.hasProperty("test_flags")
|
||||||
? ext.test_flags.split(' ') : []
|
? ext.test_flags.split(' '): []
|
||||||
ext.testTarget = project.hasProperty("test_target")
|
ext.testTarget = project.hasProperty("test_target")
|
||||||
? ext.test_target : null
|
? ext.test_target: null
|
||||||
}
|
}
|
||||||
|
|
||||||
class PlatformInfo {
|
class PlatformInfo {
|
||||||
|
|||||||
@@ -0,0 +1,193 @@
|
|||||||
|
diff --git a/src/s2wasm.h b/src/s2wasm.h
|
||||||
|
index 0fc0201c..c56a3a8c 100644
|
||||||
|
--- a/src/s2wasm.h
|
||||||
|
+++ b/src/s2wasm.h
|
||||||
|
@@ -153,9 +153,16 @@ class S2WasmBuilder {
|
||||||
|
|
||||||
|
Name getStr() {
|
||||||
|
std::string str; // TODO: optimize this and the other get* methods
|
||||||
|
- while (*s && !isspace(*s)) {
|
||||||
|
- str += *s;
|
||||||
|
- s++;
|
||||||
|
+ if (*s == '\"') {
|
||||||
|
+ str += *s++;
|
||||||
|
+ while (*s && *s != '\"') {
|
||||||
|
+ str += *s++;
|
||||||
|
+ }
|
||||||
|
+ if (*s == '\"') str += *s++;
|
||||||
|
+ } else {
|
||||||
|
+ while (*s && !isspace(*s)) {
|
||||||
|
+ str += *s++;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
return cashew::IString(str.c_str(), false);
|
||||||
|
}
|
||||||
|
@@ -168,6 +175,11 @@ class S2WasmBuilder {
|
||||||
|
|
||||||
|
Name getStrToSep() {
|
||||||
|
std::string str;
|
||||||
|
+ if (*s == '\"') {
|
||||||
|
+ str += *s++;
|
||||||
|
+ while (*s && *s != '\"') str += *s++;
|
||||||
|
+ if (*s == '\"') str += *s++;
|
||||||
|
+ }
|
||||||
|
while (*s && !isspace(*s) && *s != ',' && *s != '(' && *s != ')' && *s != ':' && *s != '+' && *s != '-' && *s != '=') {
|
||||||
|
str += *s;
|
||||||
|
s++;
|
||||||
|
@@ -177,10 +189,15 @@ class S2WasmBuilder {
|
||||||
|
|
||||||
|
Name getStrToColon() {
|
||||||
|
std::string str;
|
||||||
|
- while (*s && !isspace(*s) && *s != ':') {
|
||||||
|
- str += *s;
|
||||||
|
- s++;
|
||||||
|
+ if (*s == '\"') {
|
||||||
|
+ str += *s++;
|
||||||
|
+ while (*s && *s != '\"') {
|
||||||
|
+ str += *s++;
|
||||||
|
+ }
|
||||||
|
+ if (*s == '\"') str += *s++;
|
||||||
|
}
|
||||||
|
+ while (*s && !isspace(*s) && *s != ':')
|
||||||
|
+ str += *s++;
|
||||||
|
return cashew::IString(str.c_str(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -330,9 +347,18 @@ class S2WasmBuilder {
|
||||||
|
Name getSeparated(char separator) {
|
||||||
|
skipWhitespace();
|
||||||
|
std::string str;
|
||||||
|
- while (*s && *s != separator && *s != '\n') {
|
||||||
|
- str += *s;
|
||||||
|
- s++;
|
||||||
|
+ bool inQuoted = false;
|
||||||
|
+ int inBrackets = 0;
|
||||||
|
+ while (*s && (*s != separator || inQuoted || inBrackets > 0) && *s != '\n') {
|
||||||
|
+ if (*s == '\"') {
|
||||||
|
+ inQuoted = !inQuoted;
|
||||||
|
+ } else if (*s == '(') {
|
||||||
|
+ inBrackets++;
|
||||||
|
+ } else if (*s == ')') {
|
||||||
|
+ inBrackets--;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ str += *s++;
|
||||||
|
}
|
||||||
|
skipWhitespace();
|
||||||
|
return cashew::IString(str.c_str(), false);
|
||||||
|
@@ -421,14 +447,32 @@ class S2WasmBuilder {
|
||||||
|
bool isFunctionName(Name name) {
|
||||||
|
return !!strstr(name.str, "@FUNCTION");
|
||||||
|
}
|
||||||
|
- // Drop the @ and after it.
|
||||||
|
- Name cleanFunction(Name name) {
|
||||||
|
- if (!strchr(name.str, '@')) return name;
|
||||||
|
+
|
||||||
|
+ Name cleanName(Name name, char terminator = 0) {
|
||||||
|
char *temp = strdup(name.str);
|
||||||
|
- *strchr(temp, '@') = 0;
|
||||||
|
+ static const char* bads = "\";<>() ";
|
||||||
|
+ static const char* goods = "\'$__$$$";
|
||||||
|
+ int index = 0;
|
||||||
|
+ while (bads[index] != 0) {
|
||||||
|
+ char *pos = temp;
|
||||||
|
+ while ((pos = strchr(pos, bads[index])) != nullptr) {
|
||||||
|
+ *pos = goods[index];
|
||||||
|
+ pos++;
|
||||||
|
+ }
|
||||||
|
+ index++;
|
||||||
|
+ }
|
||||||
|
+ if (terminator != 0) {
|
||||||
|
+ char* pos = strrchr(temp, terminator);
|
||||||
|
+ if (pos != nullptr) *pos = '\0';
|
||||||
|
+ }
|
||||||
|
Name ret = cashew::IString(temp, false);
|
||||||
|
free(temp);
|
||||||
|
return ret;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ // Drop the @ and after it.
|
||||||
|
+ Name cleanFunction(Name name) {
|
||||||
|
+ return cleanName(name, '@');
|
||||||
|
}
|
||||||
|
|
||||||
|
// processors
|
||||||
|
@@ -446,7 +490,7 @@ class S2WasmBuilder {
|
||||||
|
if (match(".hidden")) mustMatch(name.str);
|
||||||
|
mustMatch(name.str);
|
||||||
|
if (match(":")) {
|
||||||
|
- info->implementedFunctions.insert(name);
|
||||||
|
+ info->implementedFunctions.insert(cleanName(name));
|
||||||
|
} else if (match("=")) {
|
||||||
|
Name alias = getAtSeparated();
|
||||||
|
mustMatch("@FUNCTION");
|
||||||
|
@@ -461,7 +505,7 @@ class S2WasmBuilder {
|
||||||
|
s = strchr(s, '\n');
|
||||||
|
} else {
|
||||||
|
// add data aliases
|
||||||
|
- Name lhs = getStrToSep();
|
||||||
|
+ Name lhs = cleanName(getStrToSep());
|
||||||
|
// When the current line contains only one word, e.g.".text"
|
||||||
|
if (match("\n"))
|
||||||
|
continue;
|
||||||
|
@@ -473,7 +517,7 @@ class S2WasmBuilder {
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the original name
|
||||||
|
- Name rhs = getStrToSep();
|
||||||
|
+ Name rhs = cleanName(getStrToSep());
|
||||||
|
assert(!isFunctionName(rhs));
|
||||||
|
Offset offset = 0;
|
||||||
|
if (*s == '+') {
|
||||||
|
@@ -620,7 +664,7 @@ class S2WasmBuilder {
|
||||||
|
}
|
||||||
|
|
||||||
|
void parseGlobl() {
|
||||||
|
- linkerObj->addGlobal(getStr());
|
||||||
|
+ linkerObj->addGlobal(cleanName(getStr()));
|
||||||
|
skipWhitespace();
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -753,7 +797,7 @@ class S2WasmBuilder {
|
||||||
|
skipWhitespace();
|
||||||
|
} else break;
|
||||||
|
}
|
||||||
|
- Function* func = builder.makeFunction(name, std::move(params), resultType, std::move(vars));
|
||||||
|
+ Function* func = builder.makeFunction(cleanName(name), std::move(params), resultType, std::move(vars));
|
||||||
|
|
||||||
|
// parse body
|
||||||
|
func->body = allocator->alloc<Block>();
|
||||||
|
@@ -1343,6 +1387,11 @@ class S2WasmBuilder {
|
||||||
|
mustMatch(name.str);
|
||||||
|
skipWhitespace();
|
||||||
|
}
|
||||||
|
+ if (match(".weak")) {
|
||||||
|
+ // Do nothing special on weak symbols so far.
|
||||||
|
+ mustMatch(name.str);
|
||||||
|
+ skipWhitespace();
|
||||||
|
+ }
|
||||||
|
if (match(".align") || match(".p2align")) {
|
||||||
|
align = getInt();
|
||||||
|
skipWhitespace();
|
||||||
|
@@ -1436,9 +1485,10 @@ class S2WasmBuilder {
|
||||||
|
r->data = (uint32_t*)&raw[i];
|
||||||
|
}
|
||||||
|
// assign the address, add to memory
|
||||||
|
- linkerObj->addStatic(size, align, name);
|
||||||
|
+ Name wasmName = cleanName(name);
|
||||||
|
+ linkerObj->addStatic(size, align, wasmName);
|
||||||
|
if (!zero) {
|
||||||
|
- linkerObj->addSegment(name, raw);
|
||||||
|
+ linkerObj->addSegment(wasmName, raw);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1451,7 +1501,7 @@ class S2WasmBuilder {
|
||||||
|
skipComma();
|
||||||
|
localAlign = 1 << getInt();
|
||||||
|
}
|
||||||
|
- linkerObj->addStatic(size, std::max(align, localAlign), name);
|
||||||
|
+ linkerObj->addStatic(size, std::max(align, localAlign), cleanName(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
void skipImports() {
|
||||||
Vendored
+7
-2
@@ -227,13 +227,18 @@ if (isLinux()) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencyTask(MINGW, LIBFFI)
|
dependencyTask(MINGW, LIBFFI)
|
||||||
} else {
|
} else if (isMac()) {
|
||||||
dependencyTask(MACBOOK, SYSROOT)
|
dependencyTask(MACBOOK, SYSROOT)
|
||||||
dependencyTask(MACBOOK, LIBFFI)
|
dependencyTask(MACBOOK, LIBFFI)
|
||||||
dependencyTask(IPHONE, SYSROOT)
|
dependencyTask(IPHONE, SYSROOT)
|
||||||
dependencyTask(IPHONE, LIBFFI)
|
dependencyTask(IPHONE, LIBFFI)
|
||||||
|
dependencyTask(WASM32, SYSROOT)
|
||||||
|
// No FFI for webassembly.
|
||||||
|
|
||||||
// TODO: re-enable when we known how to bring the simulator sysroot to dependencies.
|
// TODO: re-enable when we known how to bring the simulator sysroot to dependencies.
|
||||||
// dependencyTask(IPHONE_SIM, SYSROOT)
|
// dependencyTask("iphoneSim", SYSROOT)
|
||||||
|
} else {
|
||||||
|
throw new Error("Unsupported host")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isLinux() || isMac()) {
|
if (isLinux() || isMac()) {
|
||||||
|
|||||||
@@ -27,7 +27,8 @@ targetList.each { targetName ->
|
|||||||
target targetName
|
target targetName
|
||||||
compilerArgs '-g'
|
compilerArgs '-g'
|
||||||
compilerArgs '-I' + project.file('../common/src/hash/headers')
|
compilerArgs '-I' + project.file('../common/src/hash/headers')
|
||||||
compilerArgs '-I' + project.file(rootProject.ext.get("${targetName}LibffiDir") + "/include")
|
if (rootProject.hasProperty("${targetName}LibffiDir"))
|
||||||
|
compilerArgs '-I' + project.file(rootProject.ext.get("${targetName}LibffiDir") + "/include")
|
||||||
linkerArgs project.file("../common/build/$targetName/hash.bc").path
|
linkerArgs project.file("../common/build/$targetName/hash.bc").path
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,5 +20,10 @@
|
|||||||
#define RUNTIME_NOTHROW __attribute__((nothrow))
|
#define RUNTIME_NOTHROW __attribute__((nothrow))
|
||||||
#define RUNTIME_CONST __attribute__((const))
|
#define RUNTIME_CONST __attribute__((const))
|
||||||
#define RUNTIME_PURE __attribute__((pure))
|
#define RUNTIME_PURE __attribute__((pure))
|
||||||
|
#if KONAN_NO_THREADS
|
||||||
|
#define THREAD_LOCAL_VARIABLE
|
||||||
|
#else
|
||||||
|
#define THREAD_LOCAL_VARIABLE __thread
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // RUNTIME_COMMON_H
|
#endif // RUNTIME_COMMON_H
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ void Kotlin_io_Console_print(KString message) {
|
|||||||
// TODO: system stdout must be aware about UTF-8.
|
// TODO: system stdout must be aware about UTF-8.
|
||||||
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::unchecked::utf16to8(utf16, utf16 + message->count_, back_inserter(utf8));
|
||||||
konan::consoleWriteUtf8(utf8.c_str(), utf8.size());
|
konan::consoleWriteUtf8(utf8.c_str(), utf8.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,10 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#if KONAN_NO_EXCEPTIONS
|
||||||
|
#define OMIT_BACKTRACE 1
|
||||||
|
#endif
|
||||||
#ifndef OMIT_BACKTRACE
|
#ifndef OMIT_BACKTRACE
|
||||||
#if USE_GCC_UNWIND
|
#if USE_GCC_UNWIND
|
||||||
// GCC unwinder for backtrace.
|
// GCC unwinder for backtrace.
|
||||||
@@ -54,7 +58,7 @@ class AutoFree {
|
|||||||
struct Backtrace {
|
struct Backtrace {
|
||||||
Backtrace(int count, int skip) : index(0), skipCount(skip) {
|
Backtrace(int count, int skip) : index(0), skipCount(skip) {
|
||||||
auto result = AllocArrayInstance(
|
auto result = AllocArrayInstance(
|
||||||
theArrayTypeInfo, count - skipCount, arrayHolder.slot());
|
theArrayTypeInfo, count - skipCount, arrayHolder.slot());
|
||||||
// TODO: throw cached OOME?
|
// TODO: throw cached OOME?
|
||||||
RuntimeAssert(result != nullptr, "Cannot create backtrace array");
|
RuntimeAssert(result != nullptr, "Cannot create backtrace array");
|
||||||
}
|
}
|
||||||
@@ -156,8 +160,10 @@ OBJ_GETTER0(GetCurrentStackTrace) {
|
|||||||
|
|
||||||
void ThrowException(KRef exception) {
|
void ThrowException(KRef exception) {
|
||||||
RuntimeAssert(exception != nullptr && IsInstance(exception, theThrowableTypeInfo),
|
RuntimeAssert(exception != nullptr && IsInstance(exception, theThrowableTypeInfo),
|
||||||
"Throwing something non-throwable");
|
"Throwing something non-throwable");
|
||||||
|
#if KONAN_NO_EXCEPTIONS
|
||||||
|
RuntimeAssert(false, "Exceptions unsupported");
|
||||||
|
#else
|
||||||
#if (__MINGW32__ || __MINGW64__)
|
#if (__MINGW32__ || __MINGW64__)
|
||||||
// Workaround for https://bugs.llvm.org/show_bug.cgi?id=33220
|
// Workaround for https://bugs.llvm.org/show_bug.cgi?id=33220
|
||||||
// This code forces the function to have at least one landingpad:
|
// This code forces the function to have at least one landingpad:
|
||||||
@@ -165,6 +171,7 @@ void ThrowException(KRef exception) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
throw ObjHolder(exception);
|
throw ObjHolder(exception);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -17,14 +17,20 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifndef KONAN_NO_FFI
|
||||||
#include <ffi.h>
|
#include <ffi.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "Memory.h"
|
#include "Memory.h"
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
typedef int FfiTypeKind;
|
typedef int FfiTypeKind;
|
||||||
|
|
||||||
|
#ifndef KONAN_NO_FFI
|
||||||
// Also declared in Varargs.kt
|
// Also declared in Varargs.kt
|
||||||
const FfiTypeKind FFI_TYPE_KIND_VOID = 0;
|
const FfiTypeKind FFI_TYPE_KIND_VOID = 0;
|
||||||
const FfiTypeKind FFI_TYPE_KIND_SINT8 = 1;
|
const FfiTypeKind FFI_TYPE_KIND_SINT8 = 1;
|
||||||
@@ -49,6 +55,7 @@ ffi_type* convertFfiTypeKindToType(FfiTypeKind typeKind) {
|
|||||||
default: assert(false); return nullptr;
|
default: assert(false); return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif // KONAN_NO_FFI
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
@@ -57,8 +64,9 @@ extern "C" {
|
|||||||
void Kotlin_Interop_callWithVarargs(void* codePtr, void* returnValuePtr, FfiTypeKind returnTypeKind,
|
void Kotlin_Interop_callWithVarargs(void* codePtr, void* returnValuePtr, FfiTypeKind returnTypeKind,
|
||||||
void** arguments, intptr_t* argumentTypeKinds,
|
void** arguments, intptr_t* argumentTypeKinds,
|
||||||
int fixedArgumentsNumber, int totalArgumentsNumber) {
|
int fixedArgumentsNumber, int totalArgumentsNumber) {
|
||||||
|
#ifdef KONAN_NO_FFI
|
||||||
|
RuntimeAssert(false, "Vararg calls are not supported on this platform");
|
||||||
|
#else
|
||||||
ffi_type** argumentTypes = (ffi_type**)argumentTypeKinds;
|
ffi_type** argumentTypes = (ffi_type**)argumentTypeKinds;
|
||||||
// In-place convertion:
|
// In-place convertion:
|
||||||
for (int i = 0; i < totalArgumentsNumber; ++i) {
|
for (int i = 0; i < totalArgumentsNumber; ++i) {
|
||||||
@@ -71,6 +79,7 @@ void Kotlin_Interop_callWithVarargs(void* codePtr, void* returnValuePtr, FfiType
|
|||||||
convertFfiTypeKindToType(returnTypeKind), argumentTypes);
|
convertFfiTypeKindToType(returnTypeKind), argumentTypes);
|
||||||
|
|
||||||
ffi_call(&cif, (void (*)())codePtr, returnValuePtr, arguments);
|
ffi_call(&cif, (void (*)())codePtr, returnValuePtr, arguments);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
KNativePtr Kotlin_Interop_createStablePointer(KRef any) {
|
KNativePtr Kotlin_Interop_createStablePointer(KRef any) {
|
||||||
|
|||||||
@@ -38,12 +38,12 @@
|
|||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
OBJ_GETTER(utf8ToUtf16, const char* rawString, size_t rawStringLength) {
|
OBJ_GETTER(utf8ToUtf16, const char* rawString, size_t rawStringLength) {
|
||||||
uint32_t charCount = utf8::distance(rawString, rawString + rawStringLength);
|
uint32_t charCount = utf8::unchecked::distance(rawString, rawString + rawStringLength);
|
||||||
ArrayHeader* result = AllocArrayInstance(
|
ArrayHeader* result = AllocArrayInstance(
|
||||||
theStringTypeInfo, charCount, OBJ_RESULT)->array();
|
theStringTypeInfo, charCount, OBJ_RESULT)->array();
|
||||||
KChar* rawResult = CharArrayAddressOfElementAt(result, 0);
|
KChar* rawResult = CharArrayAddressOfElementAt(result, 0);
|
||||||
auto convertResult =
|
auto convertResult =
|
||||||
utf8::utf8to16(rawString, rawString + rawStringLength, rawResult);
|
utf8::unchecked::utf8to16(rawString, rawString + rawStringLength, rawResult);
|
||||||
RETURN_OBJ(result->obj());
|
RETURN_OBJ(result->obj());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -738,7 +738,7 @@ OBJ_GETTER(Kotlin_String_toUtf8Array, KString thiz, KInt start, KInt size) {
|
|||||||
}
|
}
|
||||||
const KChar* utf16 = CharArrayAddressOfElementAt(thiz, start);
|
const KChar* utf16 = CharArrayAddressOfElementAt(thiz, start);
|
||||||
KStdString utf8;
|
KStdString utf8;
|
||||||
utf8::utf16to8(utf16, utf16 + size, back_inserter(utf8));
|
utf8::unchecked::utf16to8(utf16, utf16 + size, back_inserter(utf8));
|
||||||
ArrayHeader* result = AllocArrayInstance(
|
ArrayHeader* result = AllocArrayInstance(
|
||||||
theByteArrayTypeInfo, utf8.size() + 1, OBJ_RESULT)->array();
|
theByteArrayTypeInfo, utf8.size() + 1, OBJ_RESULT)->array();
|
||||||
::memcpy(ByteArrayAddressOfElementAt(result, 0), utf8.c_str(), utf8.size());
|
::memcpy(ByteArrayAddressOfElementAt(result, 0), utf8.c_str(), utf8.size());
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ struct MemoryState {
|
|||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
// TODO: can we pass this variable as an explicit argument?
|
// TODO: can we pass this variable as an explicit argument?
|
||||||
__thread MemoryState* memoryState = nullptr;
|
THREAD_LOCAL_VARIABLE MemoryState* memoryState = nullptr;
|
||||||
|
|
||||||
inline bool isFreeable(const ContainerHeader* header) {
|
inline bool isFreeable(const ContainerHeader* header) {
|
||||||
return (header->refCount_ & CONTAINER_TAG_MASK) < CONTAINER_TAG_PERMANENT;
|
return (header->refCount_ & CONTAINER_TAG_MASK) < CONTAINER_TAG_PERMANENT;
|
||||||
@@ -649,6 +649,13 @@ OBJ_GETTER(InitInstance,
|
|||||||
|
|
||||||
ObjHeader* object = AllocInstance(type_info, OBJ_RESULT);
|
ObjHeader* object = AllocInstance(type_info, OBJ_RESULT);
|
||||||
UpdateRef(location, object);
|
UpdateRef(location, object);
|
||||||
|
#if KONAN_NO_EXCEPTIONS
|
||||||
|
ctor(object);
|
||||||
|
#if TRACE_MEMORY
|
||||||
|
memoryState->globalObjects->push_back(location);
|
||||||
|
#endif
|
||||||
|
return object;
|
||||||
|
#else
|
||||||
try {
|
try {
|
||||||
ctor(object);
|
ctor(object);
|
||||||
#if TRACE_MEMORY
|
#if TRACE_MEMORY
|
||||||
@@ -660,6 +667,7 @@ OBJ_GETTER(InitInstance,
|
|||||||
UpdateRef(location, nullptr);
|
UpdateRef(location, nullptr);
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetRef(ObjHeader** location, const ObjHeader* object) {
|
void SetRef(ObjHeader** location, const ObjHeader* object) {
|
||||||
@@ -882,7 +890,9 @@ OBJ_GETTER(DerefStablePointer, KNativePtr pointer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
OBJ_GETTER(AdoptStablePointer, KNativePtr pointer) {
|
OBJ_GETTER(AdoptStablePointer, KNativePtr pointer) {
|
||||||
|
#ifndef KONAN_NO_THREADS
|
||||||
__sync_synchronize();
|
__sync_synchronize();
|
||||||
|
#endif
|
||||||
KRef ref = reinterpret_cast<KRef>(pointer);
|
KRef ref = reinterpret_cast<KRef>(pointer);
|
||||||
// Somewhat hacky.
|
// Somewhat hacky.
|
||||||
*OBJ_RESULT = ref;
|
*OBJ_RESULT = ref;
|
||||||
|
|||||||
@@ -17,6 +17,13 @@
|
|||||||
#ifndef RUNTIME_TYPES_H
|
#ifndef RUNTIME_TYPES_H
|
||||||
#define RUNTIME_TYPES_H
|
#define RUNTIME_TYPES_H
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#if KONAN_WASM
|
||||||
|
// assert() is needed by WASM STL.
|
||||||
|
#define assert(cond) if (!(cond)) abort()
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|||||||
@@ -13,7 +13,10 @@
|
|||||||
* 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.
|
||||||
*/
|
*/
|
||||||
#define WITH_WORKERS 1
|
|
||||||
|
#ifndef KONAN_NO_THREADS
|
||||||
|
# define WITH_WORKERS 1
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -462,6 +465,11 @@ KInt stateOfFuture(KInt id) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KInt schedule(KInt id, KInt transferMode, KRef producer, KNativePtr jobFunction) {
|
||||||
|
ThrowWorkerUnsupported();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
OBJ_GETTER(consumeFuture, KInt id) {
|
OBJ_GETTER(consumeFuture, KInt id) {
|
||||||
ThrowWorkerUnsupported();
|
ThrowWorkerUnsupported();
|
||||||
RETURN_OBJ(nullptr);
|
RETURN_OBJ(nullptr);
|
||||||
|
|||||||
@@ -525,7 +525,9 @@ MAX_RELEASE_CHECK_RATE default: 4095 unless not HAVE_MMAP
|
|||||||
|
|
||||||
/**** Start of Konan-specific dlmalloc configuration. ****/
|
/**** Start of Konan-specific dlmalloc configuration. ****/
|
||||||
#define USE_DL_PREFIX 1
|
#define USE_DL_PREFIX 1
|
||||||
|
#if !KONAN_WASM
|
||||||
#define USE_LOCKS 1
|
#define USE_LOCKS 1
|
||||||
|
#endif
|
||||||
#define DLMALLOC_EXPORT extern "C"
|
#define DLMALLOC_EXPORT extern "C"
|
||||||
#define HAVE_MORECORE 1
|
#define HAVE_MORECORE 1
|
||||||
#define MORECORE konan::moreCore
|
#define MORECORE konan::moreCore
|
||||||
|
|||||||
@@ -642,7 +642,7 @@ KDouble Konan_FloatingPointParser_parseDoubleImpl (KString s, KInt e)
|
|||||||
{
|
{
|
||||||
const KChar* utf16 = CharArrayAddressOfElementAt(s, 0);
|
const KChar* utf16 = CharArrayAddressOfElementAt(s, 0);
|
||||||
KStdString utf8;
|
KStdString utf8;
|
||||||
utf8::utf16to8(utf16, utf16 + s->count_, back_inserter(utf8));
|
utf8::unchecked::utf16to8(utf16, utf16 + s->count_, back_inserter(utf8));
|
||||||
const char *str = utf8.c_str();
|
const char *str = utf8.c_str();
|
||||||
auto dbl = createDouble (str, e);
|
auto dbl = createDouble (str, e);
|
||||||
|
|
||||||
|
|||||||
@@ -549,7 +549,7 @@ Konan_FloatingPointParser_parseFloatImpl (KString s, KInt e)
|
|||||||
{
|
{
|
||||||
const KChar* utf16 = CharArrayAddressOfElementAt(s, 0);
|
const KChar* utf16 = CharArrayAddressOfElementAt(s, 0);
|
||||||
KStdString utf8;
|
KStdString utf8;
|
||||||
utf8::utf16to8(utf16, utf16 + s->count_, back_inserter(utf8));
|
utf8::unchecked::utf16to8(utf16, utf16 + s->count_, back_inserter(utf8));
|
||||||
const char *str = utf8.c_str();
|
const char *str = utf8.c_str();
|
||||||
auto flt = createFloat (str, e);
|
auto flt = createFloat (str, e);
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ DEALINGS IN THE SOFTWARE.
|
|||||||
#ifndef UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731
|
#ifndef UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731
|
||||||
#define UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731
|
#define UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731
|
||||||
|
|
||||||
#include "utf8/checked.h"
|
|
||||||
#include "utf8/unchecked.h"
|
#include "utf8/unchecked.h"
|
||||||
|
|
||||||
#endif // header guard
|
#endif // header guard
|
||||||
|
|||||||
@@ -19,16 +19,15 @@ package org.jetbrains.kotlin.konan.target
|
|||||||
import org.jetbrains.kotlin.konan.properties.KonanProperties
|
import org.jetbrains.kotlin.konan.properties.KonanProperties
|
||||||
import org.jetbrains.kotlin.konan.file.File
|
import org.jetbrains.kotlin.konan.file.File
|
||||||
|
|
||||||
class ClangTarget(val target: KonanTarget, val konanProperties: KonanProperties) {
|
class ClangTarget(val target: KonanTarget, konanProperties: KonanProperties) {
|
||||||
|
|
||||||
val sysRoot = konanProperties.absoluteTargetSysRoot!!
|
val sysRoot = konanProperties.absoluteTargetSysRoot
|
||||||
val targetArg = konanProperties.targetArg
|
val targetArg = konanProperties.targetArg
|
||||||
|
|
||||||
val specificClangArgs: List<String> get() {
|
val specificClangArgs: List<String> get() {
|
||||||
return when (target) {
|
val result = when (target) {
|
||||||
|
|
||||||
KonanTarget.LINUX ->
|
KonanTarget.LINUX ->
|
||||||
listOf("--sysroot=$sysRoot",
|
listOf("--sysroot=$sysRoot",
|
||||||
"-DUSE_GCC_UNWIND=1", "-DUSE_ELF_SYMBOLS=1", "-DELFSIZE=64")
|
"-DUSE_GCC_UNWIND=1", "-DUSE_ELF_SYMBOLS=1", "-DELFSIZE=64")
|
||||||
KonanTarget.RASPBERRYPI ->
|
KonanTarget.RASPBERRYPI ->
|
||||||
listOf("-target", targetArg!!,
|
listOf("-target", targetArg!!,
|
||||||
@@ -67,7 +66,16 @@ class ClangTarget(val target: KonanTarget, val konanProperties: KonanProperties)
|
|||||||
// HACKS!
|
// HACKS!
|
||||||
"-I$sysRoot/usr/include/c++/4.9.x",
|
"-I$sysRoot/usr/include/c++/4.9.x",
|
||||||
"-I$sysRoot/usr/include/c++/4.9.x/aarch64-linux-android")
|
"-I$sysRoot/usr/include/c++/4.9.x/aarch64-linux-android")
|
||||||
|
|
||||||
|
KonanTarget.WASM32 ->
|
||||||
|
listOf("-target", targetArg!!, "-O1", "-fno-rtti", "-fno-exceptions", "-DKONAN_WASM=1",
|
||||||
|
"-D_LIBCPP_ABI_VERSION=2", "-DKONAN_NO_FFI=1", "-DKONAN_NO_THREADS=1", "-DKONAN_NO_EXCEPTIONS=1",
|
||||||
|
"-DKONAN_INTERNAL_DLMALLOC=1",
|
||||||
|
"-nostdinc", "-Xclang", "-nobuiltininc", "-Xclang", "-nostdsysteminc",
|
||||||
|
"-Xclang", "-isystem$sysRoot/include/libcxx", "-Xclang", "-isystem$sysRoot/lib/libcxxabi/include",
|
||||||
|
"-Xclang", "-isystem$sysRoot/include/compat", "-Xclang", "-isystem$sysRoot/include/libc")
|
||||||
}
|
}
|
||||||
|
return result + (if (target != KonanTarget.WASM32) listOf("-g") else emptyList())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,9 @@ enum class KonanTarget(val targetSuffix: String, val programSuffix: String, var
|
|||||||
LINUX("linux", "kexe"),
|
LINUX("linux", "kexe"),
|
||||||
MINGW("mingw", "exe"),
|
MINGW("mingw", "exe"),
|
||||||
MACBOOK("osx", "kexe"),
|
MACBOOK("osx", "kexe"),
|
||||||
RASPBERRYPI("raspberrypi", "kexe");
|
RASPBERRYPI("raspberrypi", "kexe"),
|
||||||
|
WASM32("wasm32", "kexe");
|
||||||
|
|
||||||
val userName get() = name.toLowerCase()
|
val userName get() = name.toLowerCase()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,7 +117,7 @@ class TargetManager(val userRequest: String? = null) {
|
|||||||
else -> throw TargetSupportException("Unknown host: $host.")
|
else -> throw TargetSupportException("Unknown host: $host.")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun host_arch(): String {
|
fun host_arch(): String {
|
||||||
val javaArch = System.getProperty("os.arch")
|
val javaArch = System.getProperty("os.arch")
|
||||||
return when (javaArch) {
|
return when (javaArch) {
|
||||||
"x86_64" -> "x86_64"
|
"x86_64" -> "x86_64"
|
||||||
@@ -153,6 +155,7 @@ class TargetManager(val userRequest: String? = null) {
|
|||||||
//KonanTarget.IPHONE_SIM.enabled = true
|
//KonanTarget.IPHONE_SIM.enabled = true
|
||||||
KonanTarget.ANDROID_ARM32.enabled = true
|
KonanTarget.ANDROID_ARM32.enabled = true
|
||||||
KonanTarget.ANDROID_ARM64.enabled = true
|
KonanTarget.ANDROID_ARM64.enabled = true
|
||||||
|
KonanTarget.WASM32.enabled = true
|
||||||
}
|
}
|
||||||
else ->
|
else ->
|
||||||
throw TargetSupportException("Unknown host platform: $host")
|
throw TargetSupportException("Unknown host platform: $host")
|
||||||
|
|||||||
Reference in New Issue
Block a user