/* Ċ Ġ* ĠCopyright Ġ 2 0 1 0 - 2 0 1 8 ĠJetBrains Ġs . r . o . ĠUse Ġof Ġthis Ġsource Ġcode Ġis Ġgoverned Ġby Ġthe ĠApache Ġ 2 . 0 Ġlicense Ċ Ġ* Ġthat Ġcan Ġbe Ġfound Ġin Ġthe ĠLICENSE Ġfile . Ċ Ġ*/ Ċ package Ġorg . jetbrains . kotlin . backend . kon an Ċ Ċ import Ġllvm .* Ċ import Ġorg . jetbrains . kotlin . backend . common . serialization . K lib Ir Version Ċ import Ġorg . jetbrains . kotlin . backend . common . serialization . metadata . K lib Metadata Version Ċ import Ġorg . jetbrains . kotlin . backend . kon an . llvm .* Ċ import Ġorg . jetbrains . kotlin . backend . kon an . llvm . objc . link Obj C Ċ import Ġorg . jetbrains . kotlin . kon an . CURRENT Ċ import Ġorg . jetbrains . kotlin . kon an . Compiler Version Ċ import Ġorg . jetbrains . kotlin . kon an . file . is Bit code Ċ import Ġorg . jetbrains . kotlin . kon an . library . impl . build Library Ċ import Ġorg . jetbrains . kotlin . kon an . target . Compiler Output Kind Ċ import Ġorg . jetbrains . kotlin . library .* Ċ Ċ /** Ċ Ġ* ĠSup posed Ġto Ġbe Ġtrue Ġfor Ġa Ġsingle ĠLLVM Ġmodule Ġwithin Ġfinal Ġbinary . Ċ Ġ*/ Ċ val ĠCompiler Output Kind . is Final Binary : ĠBoolean Ġget () Ġ= Ġwhen Ġ( this ) Ġ{ ĊĠĠĠ ĠCompiler Output Kind . PROGRAM , ĠCompiler Output Kind . DYNAMIC , ĊĠĠĠ ĠCompiler Output Kind . STATIC , ĠCompiler Output Kind . FRAME WORK Ġ-> Ġtrue ĊĠĠĠ ĠCompiler Output Kind . DYNAMIC _ CACHE , ĠCompiler Output Kind . STATIC _ CACHE , ĊĠĠĠ ĠCompiler Output Kind . LIBRARY , ĠCompiler Output Kind . BIT CODE Ġ-> Ġfalse Ċ } Ċ Ċ val ĠCompiler Output Kind . in vol ves Bit code Generation : ĠBoolean ĊĠĠĠ Ġget () Ġ= Ġthis Ġ!= ĠCompiler Output Kind . LIBRARY Ċ Ċ internal Ġval ĠContext . pro duced Ll vm Module Contains Std lib : ĠBoolean ĊĠĠĠ Ġget () Ġ= Ġthis . llvm Module Specification . contains Module ( this . stdlib Module ) Ċ Ċ val ĠCompiler Output Kind . in vol ves Link Stage : ĠBoolean ĊĠĠĠ Ġget () Ġ= Ġwhen Ġ( this ) Ġ{ ĊĠĠĠĠĠĠĠ ĠCompiler Output Kind . PROGRAM , ĠCompiler Output Kind . DYNAMIC , ĊĠĠĠĠĠĠĠ ĠCompiler Output Kind . DYNAMIC _ CACHE , ĠCompiler Output Kind . STATIC _ CACHE , ĊĠĠĠĠĠĠĠ ĠCompiler Output Kind . STATIC , ĠCompiler Output Kind . FRAME WORK Ġ-> Ġtrue ĊĠĠĠĠĠĠĠ ĠCompiler Output Kind . LIBRARY , ĠCompiler Output Kind . BIT CODE Ġ-> Ġfalse ĊĠĠĠ Ġ} Ċ Ċ val ĠCompiler Output Kind . is Cache : ĠBoolean ĊĠĠĠ Ġget () Ġ= Ġ( this Ġ== ĠCompiler Output Kind . STATIC _ CACHE Ġ|| Ġthis Ġ== ĠCompiler Output Kind . DYNAMIC _ CACHE ) Ċ Ċ internal Ġfun Ġproduce C Stub s ( context : ĠContext ) Ġ{ ĊĠĠĠ Ġval Ġllvm Module Ġ= Ġcontext . llvm Module !! ĊĠĠĠ Ġcontext . c Stub s Manager . compile ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcontext . config . clang , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcontext . message Collector , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcontext . in Verbose Phase ĊĠĠĠ Ġ). forEach Ġ{ ĊĠĠĠĠĠĠĠ Ġparse And Link Bit code File ( context , Ġllvm Module , Ġit . absolute Path ) ĊĠĠĠ Ġ} Ċ } Ċ Ċ private Ġfun Ġlink All Dependencies ( context : ĠContext , Ġgenerated Bit code Files : ĠList < String >) Ġ{ ĊĠĠĠ Ġval Ġconfig Ġ= Ġcontext . config ĊĊĠĠĠ Ġval Ġruntime Native Libraries Ġ= Ġconfig . runtime Native Libraries ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. take If Ġ{ Ġcontext . pro duced Ll vm Module Contains Std lib Ġ}. or Empty () ĊĊĠĠĠ Ġval Ġlauncher Native Libraries Ġ= Ġconfig . launcher Native Libraries ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. take If Ġ{ Ġconfig . produce Ġ== ĠCompiler Output Kind . PROGRAM Ġ}. or Empty () ĊĊĠĠĠ Ġlink Obj C ( context ) ĊĊĠĠĠ Ġval Ġnative Libraries Ġ= Ġconfig . native Libraries Ġ+ Ġruntime Native Libraries Ġ+ Ġlauncher Native Libraries ĊĊĠĠĠ Ġval Ġbit code Libraries Ġ= Ġcontext . llvm . bit code To Link . map Ġ{ Ġit . bit code Paths Ġ}. flatten (). filter Ġ{ Ġit . is Bit code Ġ} ĊĠĠĠ Ġval Ġadditional Bit code Files To Link Ġ= Ġcontext . llvm . additional Pro duced Bit code Files ĊĠĠĠ Ġval Ġexceptions Support Native Library Ġ= Ġconfig . exceptions Support Native Library ĊĠĠĠ Ġval Ġbit code Files Ġ= Ġ( native Libraries Ġ+ Ġgenerated Bit code Files Ġ+ Ġadditional Bit code Files To Link Ġ+ Ġbit code Libraries ). to Mutable Set () ĊĠĠĠ Ġif Ġ( config . produce Ġ== ĠCompiler Output Kind . DYNAMIC _ CACHE ) ĊĠĠĠĠĠĠĠ Ġbit code Files Ġ+= Ġexceptions Support Native Library ĊĊĠĠĠ Ġval Ġllvm Module Ġ= Ġcontext . llvm Module !! ĊĠĠĠ Ġbit code Files . forEach Ġ{ ĊĠĠĠĠĠĠĠ Ġparse And Link Bit code File ( context , Ġllvm Module , Ġit ) ĊĠĠĠ Ġ} Ċ } Ċ Ċ private Ġfun Ġinsert Alias To EntryPoint ( context : ĠContext ) Ġ{ ĊĠĠĠ Ġval Ġn omain Ġ= Ġcontext . config . configuration . get ( Kon an Config Keys . NO MAIN ) Ġ?: Ġfalse ĊĠĠĠ Ġif Ġ( context . config . produce Ġ!= ĠCompiler Output Kind . PROGRAM Ġ|| Ġn omain ) ĊĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠ Ġval Ġmodule Ġ= Ġcontext . llvm Module ĊĠĠĠ Ġval Ġentry Point Ġ= ĠLLVM Get Named Function ( module , Ġ" Kon an _ main ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ?: Ġerror (" Module Ġdoesn 't Ġcontain Ġ` Kon an _ main ` ") ĊĠĠĠ ĠLLVM Add Alias ( module , ĠLLVM TypeOf ( entry Point ) !! , Ġentry Point , Ġ" main ") Ċ } Ċ Ċ internal Ġfun Ġlink Bit code Dependencies ( context : ĠContext ) Ġ{ ĊĠĠĠ Ġval Ġconfig Ġ= Ġcontext . config . configuration ĊĠĠĠ Ġval Ġtemp Files Ġ= Ġcontext . config . temp Files ĊĠĠĠ Ġval Ġproduce Ġ= Ġconfig . get ( Kon an Config Keys . PRO DU CE ) ĊĊĠĠĠ Ġval Ġgenerated Bit code Files Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( produce Ġ== ĠCompiler Output Kind . DYNAMIC Ġ|| Ġproduce Ġ== ĠCompiler Output Kind . STATIC ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġproduce C Adapter Bit code ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontext . config . clang , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtemp Files . c Adapter Cpp Name , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtemp Files . c Adapter Bit code Name ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠlistOf ( temp Files . c Adapter Bit code Name ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġempty List () ĊĠĠĠ Ġif Ġ( produce Ġ== ĠCompiler Output Kind . FRAME WORK Ġ&& Ġcontext . config . produce Static Framework ) Ġ{ ĊĠĠĠĠĠĠĠ Ġembed Apple Link er Options To Bit code ( context . llvm , Ġcontext . config ) ĊĠĠĠ Ġ} ĊĠĠĠ Ġlink All Dependencies ( context , Ġgenerated Bit code Files ) Ċ } Ċ Ċ internal Ġfun Ġproduce Output ( context : ĠContext ) Ġ{ ĊĊĠĠĠ Ġval Ġconfig Ġ= Ġcontext . config . configuration ĊĠĠĠ Ġval Ġtemp Files Ġ= Ġcontext . config . temp Files ĊĠĠĠ Ġval Ġproduce Ġ= Ġconfig . get ( Kon an Config Keys . PRO DU CE ) ĊĊĠĠĠ Ġwhen Ġ( produce ) Ġ{ ĊĠĠĠĠĠĠĠ ĠCompiler Output Kind . STATIC , ĊĠĠĠĠĠĠĠ ĠCompiler Output Kind . DYNAMIC , ĊĠĠĠĠĠĠĠ ĠCompiler Output Kind . FRAME WORK , ĊĠĠĠĠĠĠĠ ĠCompiler Output Kind . DYNAMIC _ CACHE , ĊĠĠĠĠĠĠĠ ĠCompiler Output Kind . STATIC _ CACHE , ĊĠĠĠĠĠĠĠ ĠCompiler Output Kind . PROGRAM Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġoutput Ġ= Ġtemp Files . native Binary FileName ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcontext . bit code FileName Ġ= Ġoutput ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠInsert Ġ`_ main ` Ġafter Ġpipeline Ġso Ġwe Ġwon 't Ġworry Ġabout Ġoptimizations ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġcorrupt ing Ġentry Ġpoint . ĊĠĠĠĠĠĠĠĠĠĠĠ Ġinsert Alias To EntryPoint ( context ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLLVM Write Bit code ToFile ( context . llvm Module !! , Ġoutput ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ ĠCompiler Output Kind . LIBRARY Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnop ack Ġ= Ġconfig . getBoolean ( Kon an Config Keys . NOP ACK ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġoutput Ġ= Ġcontext . config . output Files . k lib Output FileName (! nop ack ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġlibrary Name Ġ= Ġcontext . config . module Id ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġshort Library Name Ġ= Ġcontext . config . short ModuleName ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġneeded Libraries Ġ= Ġcontext . libraries With Dependencies ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġabi Version Ġ= ĠKotlin Ab i Version . CURRENT ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġcompiler Version Ġ= ĠCompiler Version . CURRENT . toString () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġlibrary Version Ġ= Ġconfig . get ( Kon an Config Keys . LIBRARY _ VERSION ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġmetadata Version Ġ= ĠK lib Metadata Version . INSTANCE . toString () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġir Version Ġ= ĠK lib Ir Version . INSTANCE . toString () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġversions Ġ= ĠKotlin Library Version ing ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġabi Version Ġ= Ġabi Version , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlibrary Version Ġ= Ġlibrary Version , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcompiler Version Ġ= Ġcompiler Version , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmetadata Version Ġ= Ġmetadata Version , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġir Version Ġ= Ġir Version ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġtarget Ġ= Ġcontext . config . target ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġmanifest Properties Ġ= Ġcontext . config . manifest Properties ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! nop ack ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġsuffix Ġ= Ġcontext . config . output Files . produce . suffix ( target ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! output . endsWith ( suffix )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġerror (" please Ġspecify Ġcorrect Ġoutput : Ġpacked : Ġ${ ! nop ack }, Ġ$ output $ suffix ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġlibrary Ġ= Ġbuild Library ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontext . config . native Libraries , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontext . config . include Bin aries , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġneeded Libraries , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontext . serialized Metadata !! , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontext . serialized Ir , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġversions , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtarget , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġoutput , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlibrary Name , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnop ack , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġshort Library Name , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmanifest Properties , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontext . data Flow Graph ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġcontext . bit code FileName Ġ= Ġlibrary . main Bit code FileName ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ ĠCompiler Output Kind . BIT CODE Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġoutput Ġ= Ġcontext . config . outputFile ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcontext . bit code FileName Ġ= Ġoutput ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLLVM Write Bit code ToFile ( context . llvm Module !! , Ġoutput ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ Ċ private Ġfun Ġparse And Link Bit code File ( context : ĠContext , Ġllvm Module : ĠLLVM Module Ref , Ġpath : ĠString ) Ġ{ ĊĠĠĠ Ġval Ġparsed Module Ġ= Ġparse Bit code File ( path ) ĊĠĠĠ Ġval Ġfailed Ġ= Ġllvm Link Modules 2 ( context , Ġllvm Module , Ġparsed Module ) ĊĠĠĠ Ġif Ġ( failed Ġ!= Ġ 0 ) Ġ{ ĊĠĠĠĠĠĠĠ Ġthrow ĠError (" failed Ġto Ġlink Ġ$ path ") Ġ// ĠTODO : Ġretrieve Ġerror Ġmessage Ġfrom ĠLLVM . ĊĠĠĠ Ġ} Ċ } Ċ Ċ private Ġfun Ġembed Apple Link er Options To Bit code ( llvm : ĠL l vm , Ġconfig : ĠKon an Config ) Ġ{ ĊĠĠĠ Ġfun Ġfind Embed d able Options ( options : ĠList < String >): ĠList < List < String >> Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġresult Ġ= Ġmutable ListOf < List < String >>() ĊĠĠĠĠĠĠĠ Ġval Ġiterator Ġ= Ġoptions . iterator () ĊĠĠĠĠĠĠĠ Ġloop @ while Ġ( iterator . hasNext ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġoption Ġ= Ġiterator . next () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġresult Ġ+= Ġwhen Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġoption . startsWith ("- l ") Ġ-> ĠlistOf ( option ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġoption Ġ== Ġ"- framework " Ġ&& Ġiterator . hasNext () Ġ-> ĠlistOf ( option , Ġiterator . next ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġbreak @ loop Ġ// ĠIgnore Ġthe Ġrest . ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġreturn Ġresult ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġval Ġoptions To Embed Ġ= Ġfind Embed d able Options ( config . platform . configur ables . linker Kon an Flags ) Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġllvm . all Native Dependencies . flatMap Ġ{ Ġfind Embed d able Options ( it . linker Opts ) Ġ} ĊĊĠĠĠ Ġembed Ll vm Link Options ( llvm . llvm Module , Ġoptions To Embed ) Ċ } Ċ