Skip to content
This repository was archived by the owner on Aug 10, 2021. It is now read-only.

Added embedded bitcode support for ios #1564

Closed
wants to merge 1 commit into from

Conversation

evant
Copy link

@evant evant commented May 6, 2018

This introduces the flags '--embed_bitcode' and '--embed_bitcode_marker' to
make it possible to build bitcode-enabled frameworks.

Fixes #1202, #1408

@evant evant force-pushed the bitcode-support branch from a84c7b3 to 6cb486c Compare May 6, 2018 00:38
val bytes = if (marker) {
byteArrayOf()
} else {
val buf = LLVMWriteBitcodeToMemoryBuffer(context.llvmModule)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

buf -> buffer (we keep unshortened variable names in K/N).

if (context.shouldContainDebugInfo()) {
DIFinalize(context.debugInfo.builder)
}
}

private fun embedBitcode(context: Context, marker: Boolean) {
val isIos = context.config.platform.configurables.target.family == Family.IOS
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, why IOS is specific here?

Copy link
Author

@evant evant May 6, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Taken from rust-lang/rust@0e0f74b#diff-a3b24dbe2ea7c1981f9ac79f9745f40aR851 and https://github.com/llvm-mirror/clang/blob/master/lib/CodeGen/BackendUtil.cpp#L1237
the section name is just different on that platform. Unsure if this should be on macos as well?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's Apple specific - so isApple maybe?

@evant evant force-pushed the bitcode-support branch from 6cb486c to 5e9e88b Compare May 7, 2018 12:45
@@ -16,6 +16,7 @@

package org.jetbrains.kotlin.cli.bc

import org.jetbrains.kotlin.backend.konan.EmbedBitcode
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This import seems to be redundant.

@@ -139,5 +140,10 @@ class K2NativeCompilerArguments : CommonCompilerArguments() {
@Argument(value = "--verify_ir", description = "Verify IR")
var verifyIr: Boolean = false

@Argument(value = "--embed_bitcode", description = "embed LLVM bitcode in object files")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It makes sense to enable bitcode embedding by default on macOS and iOS targets.
@olonho WDYT?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How much bigger binaries would become then?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The smallish sample project I was testing with went from 153MB to 238MB

@@ -130,11 +131,49 @@ internal fun emitLLVM(context: Context) {
irModule.acceptVoid(codegenVisitor)
}

when (context.shouldEmbedBitcode()) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is bitcode embedding performed before debug info generation intentionally?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not

name = "konan.embedded.module",
elemType = int8Type,
elements = bytes.map { Int8(it) },
isExported = true
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the purpose of passing isExported = true and then setting linkage to private?
Passing isExported = true just sets linkage to external (i.e. public).

@@ -176,7 +179,13 @@ internal class LinkStage(val context: Context) {
KonanTarget.MACOS_X64 -> "Versions/A/$dylibName"
else -> error(target)
}
frameworkLinkerArgs = listOf("-install_name", "@rpath/${framework.name}/$dylibRelativePath")
val args = mutableListOf("-install_name", "@rpath/${framework.name}/$dylibRelativePath")
when (context.shouldEmbedBitcode()) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't the same args be passed to linker when compiling the program instead of framework?

This introduces the flags '--embed_bitcode' and '--embed_bitcode_marker' to
make it possible to build bitcode-enabled frameworks.
@evant evant force-pushed the bitcode-support branch from 5e9e88b to 3625d77 Compare May 9, 2018 17:31
@olonho
Copy link
Contributor

olonho commented May 13, 2018

It seems that bitcode embedding need to be somewhat trickier than that, as we need to ensure, that what's get embedded is actual bitcode after link time optimizations, at least dead code elimination, otherwise code grows awfully large. So we will investigate possibilities here.

@SvyatoslavScherbina
Copy link
Collaborator

We made some investigations. There are problems (besides mentioned above) with bitcode embedding that aren't solved by this pull request.

  1. To emit bitcode our compiler uses LLVM 5.0.0 built from original sources, but Xcode toolchain uses LLVM with custom patches, different versioning scheme and unclear update policy. So to emit proper bitcode we have to use Xcode's LLVM.
  2. Our resulting binaries contain code built from assembly, e.g. in libffi. It is OK on iOS, but doesn't seem to be permitted on watchOS.

So bitcode embedding on watchOS can't be supported by this PR.
As for iOS, it is possible to make binary look like it has bitcode embedded, without really embedding bitcode that we emit when compiling Kotlin code, and we are considering to implement this trick.

@dnedrow
Copy link

dnedrow commented May 18, 2018

As for iOS, it is possible to make binary look like it has bitcode embedded, without really embedding bitcode…

What are the implications when a bitcode enabled app is uploaded to the AppStore, but any include K/N code isn’t actually bitcode enabled?

Bitcode is enabled by default for new Xcode projects.

@SvyatoslavScherbina
Copy link
Collaborator

@dnedrow the implications would be the same as when Xcode project has assembly files. Assembly files are permitted on iOS even when bitcode is enabled. So this solution doesn't seem to cause any observable implications. Xcode is able to recompile an archive with such an application as any other bitcode-enabled application archive.

@olonho
Copy link
Contributor

olonho commented Jun 26, 2018

Seems this way valid bitcode cannot be generated, so let's close this one for now, and come back again, when focus on that feature again.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants