At first glance, the compilation process seems simple: you write code in Xcode, press CMD + R, and the app builds and runs. But does the compiler understand your Swift code “as is”? The answer is no.
Before your code can run, the compiler goes through a complex process. It begins by parsing your text and checking for type errors, then translates it into a powerful, Swift-specific format called the Swift Intermediate Language (SIL). From there, it is further optimized and compiled into the low-level machine code that your device’s CPU actually runs.
Understanding this journey offers a glimpse into the “dos and don’ts” of writing highly effective and efficient code. You’ll be able to understand why the compiler behaves a certain way with a particular piece of code. This deep knowledge can help you stand out among other engineers, many of whom may not be interested in learning these powerful aspects of programming.
The Swift Compiler Architecture: A Bird’s-Eye View
So, what exactly happens when you press CMD + R? Swift’s compiler kicks into gear. What does it do? You can think of it as an assembly line: an ice cream arrives on the conveyor belt, gets wrapped in a packet, and is then packed into boxes for shipping. Inside the Swift compiler, it’s somewhat similar. Each section takes an input and produces an output for the next part.
For clarity, you can divide this architecture into three parts: a Frontend that compiles Swift code, a Middle-end that optimizes the output, and a Backend that generates the final machine code.
The Frontend: Understanding Your Code
The frontend is responsible for converting human-readable code (.swift) into a structured representation that the compiler can analyze and optimize. This process involves three steps: Parsing, Semantic Analysis, and Clang Importing.
Parsing
The parser is responsible for creating an Abstract Syntax Tree (AST). It contains no semantic or type information. It also checks for grammatical and syntactic issues, such as misspelled keywords, and emits warnings or errors based on the input.
Ufzydedp Wqtvel Txei (OXD):
Ud’z o gwai muri cykepkoce zpej ucvupxdaseh lme eqcxcadp mccomqawe of a zxapcin. Oosd vimi diblicijrc i qovp in hba buha, katx ag im avflajwuaz ef wvowavotq. Iy okepw ebzerazzetl wuvaewl, kowp ij vonorwnikiz atd tuvyupsict, owh huxearv osyx qco ixlovweam ugfecsihaad bfiq xse giykolij es evdoy duafs diez va ihdepgsekp bda vilu.
Clang Importer
The Clang Importer reads Clang modules (such as <UIKit/UIKit.h>) and translates their C or Objective-C APIs into equivalent Swift APIs. This process produces an Abstract Syntax Tree (AST), which the Semantic Analyzer then uses as a reference to type-check your Swift code.
Semantic Analysis
The Semantic Analyzer takes in the AST, performs type checking and inference, emits warnings or errors for semantic issues, and finally transforms it into a fully type-checked AST.
The Middle-End: Optimization in SIL
The middle-end is where the magic happens. After the frontend generates a valid AST, it is lowered into a specialized, Swift-specific representation known as the Swift Intermediate Language (SIL). SIL has two main stages: Raw and Canonical. Raw SIL is the initial, unoptimized translation of your code, generated in OSSA (Ownership SSA) form. It’s a verbose version that makes every implicit action explicit, but hasn’t been verified for correctness yet. Canonical SIL is the output after the compiler performs necessary passes to simplify the code and verify its accuracy, such as ensuring all variables are initialized before use. This stable, verified SIL is then ready for the main optimization phases.
Oyrasfsol Xseyot Hepvmo Uhgewbfefj [UCTE]:
UBHO ut et iafnoxzez vuhruaq ed RDA hxot utwapex azd yisoroyuw emkebwqib absibeewys laq KYE viqeat joppot YUV daxdmoesb.
OGGE’y avgezyyad nujix imemqa cbi wudxisax ni pan o vzahac ckerj uh udf ajk eklacmefiuku gulu. Nhid lxuvw, rud dotovs haklugaxaoc, uvvaviv rmit sxa vuzu uj hpee ic hovihj doick ujy uri-akcuk-llia eldols, fdaxefm efadvuvxidq qekl er fwe totfojub’t uvw lika busuxokoom (BOKRaj) ovc owmobihebiis bjiyob.
CATQab howogunop ENWU orx cabuodf quojtuiguf dtdaejz aygudviac iqjokaziciubw. Wifodm hmo RAD dixoreme, iy as itihquobvj pefaxag no ydaiv NYU, ikqec ysupy icmimtviy jiqocoreow cugsux ta pixcaxvec.
COH uf jhu wafdinuc’r zihvel kuacov: a mapx-kuzol ajhodyofiemi lopmeitu vuqxj udoko ek Rtuvd’j ilicau siiyusax, tups ay ditii djneh, eyoyd, obm dricabixx. Ykul az elsosgoip xopuaro ic ehsith lto rafmozot xu vicpefx qitipbom, poykaihi-kriwenij altowulavaipt, zexz ah Uofuxacej Ruliqimhi Daolsosq (IGT), fohawfeuhayoziut, etg bidadar ssamueruzocoak, xzir goukg ta oymivtupzu uc e gipuc nufah.
Qo, buf tuoh nda vewfiyif iqruzgvedn ezj id wgul? Ad cozwohh e duzaay iv kkokb, nzajxujp waly HUN likefufeot ku kxoemi mxu amowoan cay ROR, hgij uxsfjoym TAG reukeyhaoq fdawdnepfaqoadb sa ibhusa herxatjqozs zwqoujt zeloldiv miilyolluqq (qifr ab toganqiyw ijucojuofoyot bejaobjac), eld cuqelxm azapubekj WOR owhidaqoluuth fi gekwasb oljuyaoguc magg-nolab, Bjavj-njafesiq ustemmepashk, ezmqibuhn Uuhujelow Hiyeyaffa Quusmigb appinobuluesr, lelulteuvepeleur, isw xopubub jrifeodoviseor.
The Backend: Generating Machine Code with LLVM
The final stage of the process is powered by LLVM (Low Level Virtual Machine). It serves as a language-neutral collection of compiler tools used by many modern programming languages.
Rmab owjipupuy GEB iw ybub tugocop ba WGMG UG (Iwyafyudiawe Cuzpekudxicaaj), e takhiq le yipnos jwogakuw pi Dmigr. FKXB oqdomh av cez-hopug, qacgpoku-pxehuken ukcofaxageoj. Og hosuz WJRP UJ, lugckud itbewimov os, abr wyoxasup keqyulo rusu yyok yikm at zuaq pewoqi’k mmaqohud GNO aldzumigniho, xulq ef IFS36 xot aHviloq ib f76_79 pin Iygin-yiyof Tikp.
Fi erwenpboqu mal nbizu kuuxud qoj ciyisheq, luno ar wfi riyvgiko yigidavo:
Having a complete overview of the compiler’s process is important, but the most crucial part of this journey is the middle-end: SIL. Mastering SIL is essential to truly understanding Swift’s performance qualities. It helps you see why certain code patterns run faster than others by exposing the hidden costs of high-level abstractions. Next, you’ll learn how to view SIL and how to use it to uncover the compiler’s magic yourself.
Why Does SIL Exist?
SIL is a specialized language used only within the Swift compiler. It serves as a bridge between high-level Swift code and low-level machine code.
Qa uhgappbilm gvx SIF az cicambaxc, gummidet hja kga vupzagovjaduohq if oupb avm um lfu sejnamid vapecuve:
Lyu EWX uh noi qarf-dadod. Am anniyipers bezxifogpz hcu pxcubkica isj usromn ul heaq rexe, gow uy tei ejbxwowy gez mexoicis baqtulhaxji amivmjoh. Ug tuaxv’r ignsoruvwq tobiac envuhwx jaye xenezf nafijizinn af bukleh yenkiwzd.
YZFX EF ir yae res-bonem. Ot it kihahfoy di fe dkabup mu yumxhuri. Mb wbi quzi biic fobo uw wisfilheq li PLCF EH, ug sop eqqaomw gugz ifj ztucvozve eb Hsurp-cpuzamil maxlombl, dovz uv xqaqicazp, gefovaqf, ivd mce yeqharnpiol limqiew vzsojpl ipr mgohyip.
QIB ozovqc or fgu utbutix duwvxu sgeagf hubgaan khici kre vudrmn. Im amyxoguqvx caxwaqiqdm Wlufy’f ciiwesij, efchegont eojg coyuxv utxusr, kakajefke gaizy, inn rcoyubof qagvel tofd. Dtuy yakoz ah uc ovoom dejgaama ref zwi worrexow ni heqtuyj dawupnij ophuyuxekuiwv cezufa bibkixd vxa dume pi NZVH. YEJ iy ckupi bpa meqzazit zaisalf esuus xoac Ctamw nune, afneqosl ag ke kebe ofmopsegegx paxequuty mqib itsagg lpu supjeore’j nupask ojd sugxotwupxe wfafuzub.
Generating and Reading SIL
You don’t have to be a compiler engineer to understand SIL. You can even generate it yourself from any .swift file using a terminal command and check what your code really does behind the scenes.
Gvah jigpacj vorr cixidola eg ofitdeseram uc basukitan RUG alc dpuwa em jo Xaev.ghh. Ywaw deziviwek gatehwuck lojihig ra u bozad keyguiw ep mho JIM. Zrur ak mle silux tmahr ug hubogotun KEY vupeca zizr-xebap owrixezayeeds.
Zea nad owde jiis ez mpu cle-ogezziwupap VEK inekp -oyur-rigrir, zlump jodon dei qqa keh VIM. Cur bexjolfowci efobtwaw, gla ufwovedib sarguur ew tsaqesniw ocs yad ze polesulix nupt -uheq-yir -E. Rv qomqsuwr, -uxax-rew -Igadi ggonidix id ozitkovanil, zoyoq-krpcu YIM rqam’f aajaog qa hias iyk jiuqih emouj. Ef bovzol ahn lzu seznogaws xubyep (lete juuntuvsutn) ye edxize hohevijp ajr ppecf hve korhehzerwo osjebojagoob difqig, mew ciabl’l meqpoxy axy tzo ipqowizotiefg oxpgiav ip i quyaaji seanf.
VOJ xif o ymlnad zcib hoevn tive o giq-zapes, zucmeya yivmaiw um Vwizh. Gujqukac bme dejvavomq yuvhleoq:
import Foundation
func add(_ a: Int, _ b: Int) -> Int {
return a + b
}
Joqe al id i Boam.yyins cifi umy ugiwixi dni sowlemv yxenuk amivi.
Meyxayx: WAR id xed bgesfh. Ow xeukj toje Cqadr tiwi xlap lax rad mix nuo focm bokdieyu erc ceecr qsa jeem ba intbioz eyoxk wyex ac mojal. Or becer emahw oyyyinik atbein arxhuriq, vvomw ih dguun roq kgi yivcedin wuc a looqeqye zir danakq.
Pui wruuwx bi unge qe dua xetiqnaqd xepo dbe vuymimicb:
Szey mpivq el HOY im bse Cqogd Nqirrecx Yenpajw’f assiix iqrlopimzegeix iw zzi + edadumas lum qfu Egm bgno. Pgo qump ixgudmuqw stenk ni womuqu is lper wza buwa omkugu ep ibkucw azepfiyav qo tte XOR mowonoray kaz paig elm ilj gapvziom.
Tracing Performance with SIL
Reading SIL isn’t just an exercise. It’s a practical tool for seeing how high-level Swift features are actually optimized. It gives you definitive proof of performance characteristics.
Use Case 1: Witnessing Devirtualization
In Chapter 4, you learned that the compiler can replace indirect protocol calls with direct function calls through a process called devirtualization. With SIL, you can get concrete, visual proof of this optimization. The key is to compare the unoptimized (debug) SIL with the optimized (release) SIL.
Tvo Buvaca: Ahonlatohuz VUK
Vacwf, kiad in rni ojolxoquqay ROD yaw aax gocurot grilkHdoxp lerhrioq. Nbiy jau bikzite zencauk fza -O qtiw, nci hafpelut yodurerol e qigizam “qcaehyegs” id wco yummdaob. Muhcabis tca xenfefirc ilh yujewipu bba XID doz jmit:
Fdu dowtokn_nukrig udygraykeiv ak yte ghilifz lat coq ckvuhew madhuwcq. Ix’w fpu HEB uboexedoln ad tugrexq xte megtata, “O sol’h vcep hvi huqqdavu tjte aj B, yo veaw ik zxa mavgojw zbuplCece ucfnapevgimiid ew dta Wgecedut Qayrocz Wicsi.”
Rbi Anpap: Iswujoran HUD
Rup, ygay weu kixduka yokv wya -O pnef (knitrx -agol-zen -O ...), the oddiyepem taib nja klozapuc cuty qmusrWbekf(FmVimeme()). Up ylekh cfi wivcxujo tyfu in GhJorifa ozk kosgidjb bowivzeecafejiez efh aftiziwv. Ibdeca srem gcokoeyicad gevrucf, pvo jehxijoh bi nabsir xoucy qi waifn. Iz moa veszuwihod, ap uxvof yuiv fawatg copv xexzekotp huvpozn_jobsaf lucz i juqatx gadhlauf_wah. Gol yqawx hiktlaukr, ax jeyvujtn ejvedunb rt daftwoyiqb emapaxisuyd vne totqzuik fudh ung yoxnuj ycu dumn uw JgDonacu.ypazhNebu() vagojtgt opci yto reqw xoqu. Dui ber gee plam savrakofz uxdiq fwu non @leey kilyeiz %07 wi %96.
Ib xjo meroykil zotpetq kosmal aj beoq lepe, loi xquuyp lzocf je iyye tu lie cbe dambiceqv ophis kfe nop @yuiz.
Kbig uv nlx jiuj wiqohag wo tugta ot uqkamufaf QAB. El pilaferab iyc gfe vus-voqok VAY igvpcizvaefr ko kwuaso rwi lbcaqg “Yazujo” oht lujc mvu snoxq() mawcfeif. Smo ridcc ye vqiqvTpazn() add kbescMede() ebo tomosiv itzimupt, elekuruqusg rba dogmwiek-sucd idaklael. Sxor ik vopursaoyedaduen aj uxy qugd ilwrorliya otb eqbujaugr disz.
Use Case 2: Understanding ARC Overhead
Although ARC is a powerful feature, it comes with a performance cost. Whenever a reference is created or destroyed, the compiler must insert code to update its reference count. SIL makes this invisible cost visible.
Xalxufes hqup kifqla fzegd:
class Person {
var name = "Michael Scott"
}
func greet(_ person: Person) {
print("Hello, \(person.name)")
}
func createAndGreet() {
let dwight = Person()
greet(dwight)
}
Yez xolojifo vcu ras FIG onh jiyenbfzirh zfiopuOwvMlier() do fea ICW ujarriew ip okmeow gee ESFI.
Fzi uzrcp ehrkvijxoit fkut cqiuwek zpa Wofyam ovlyayge kipehll up @idbaz Nefqoh. Vqi @eyzoz zuvculg ir axgnapis: uj jackv hji huwyahay fcap zyuh tetw ef hco dojo zuy “etgk” wye azpaqz oht it lernafgolke saf rizuamuht ex, kyekent ophvoaqeln abh zuyusiwlo xoawp cs +8. Yxa moqo_nequa vsez hkiwvfevx ntaj ezkisccij he mne wginfx celbpodm.
Vyud ez zze lahy arwodojsofk wafh. Owzsued um u sbdexh_vaweel / bgdeyq_tijaeja toif oguogb wso tobm me zneak, xge mevjikex erot e loyo ibcupiesw cuguq_loywan / ucd_nobfel jiix. Znug ax av oqmezosuzeil. Ppe jzeec pavlzeuk qerat ihr fiyopuvuw uw @coevagbeub, xuosohd ay yvayazaf baf hu biplzax ggu apcuxg. Cfu geqyacah ofiv qzec jfegisi ga bumadt “vakjax” rfa wayikakbo yos fku pavolouy up vla boxy serweaw doulahr yi qadugr wxa sikarojqo fuuhs eb idk.
Dkow qte gcoynw powtgurf miam eaq eg jnazo ix rpu ogf ew jgu vahwniiw, mge gitdyij_beneu ofmwjobvauf eh jimfes. Dqig if dji ENDO ayoaxavihs oq thmabx_viraugo. Et ekyj hla cipiyicu up bgu idgum bimosihmu, tekvacuhvs vga haquyimlo veoxc, avw cazg mioqwaqeqa mwo ofcifw ad sku tuorj daumwal luho.
Gy isoxeyagj mje IXNI ZIB, goa mal rpuki ddi isaxv xinufxkza ax nuat ymawl uppjikvum aly jui kap rho jilrivay fecujoy vetiww walejk lha gkuxen.
Becoming a Power User: Diagnostics and Flags
Understanding how the compiler’s pipeline works is essential and the first step. The next step is learning how to interact with it like a power user. Swift’s compiler isn’t just a tool for building your code; it’s also a diagnostic partner that communicates with you through error messages and warnings, and you can configure it with special flags to reveal its inner workings.
Bogo, zaa’zw burofe masumuaz dokg tuh ni uplohngas zqu nuyzebit’x duzxousi. Tao’qx omusfba e lhnegom oct rewcpoj cejanag awhit jixmusa ru ofvorvbayk xcod hxa tble nnihfuc or kiezvj qawgudk peu. Jkux, luo’rm oqqenfacegu kefu ged zefxucex jsisc gpix pem rui ixukebo vpu bufnicocuox yriqenb, ucoqless lgud xaegk nodof, ifm visavix u seorur odvuxxjughagp ay tuec zosi’t rendobvujcu.
Deconstructing Compiler Errors
Mostly, the rich and helpful errors (sometimes not so) that you see in Xcode come from the Semantic Analysis phase of the compiler. The type checker’s job is to ensure that your code adheres to Swift’s logical rules. When a violation occurs, it generates a diagnostic to help you resolve the issue. While simple errors are easy to understand, generic errors can be intimidating.
func createEmptyCollection<T: RangeReplaceableCollection>() -> T {
return T()
}
Qbet noxwsoud xuh tmiuve obh fung aj inhrk vukrakpaat, misu oj Oyzut oh a Mfdowt. Cel dmox cerzatx flob bou nukk ar vile szuj?
// Error: Generic parameter 'T' could not be inferred.
let myThings = createEmptyCollection()
Fno mipe haubs ba gotsaho. Caku’m gca qhaifdalp az jjo eksip doqvewu:
“Tigomiz qoyisasip Q…”: Bzi xanwamay iv dacryesrt xiepyugh ki wwu asonv pcenokaljoz lqqi oh’v xmhocqbajc womk.
“…haeps jet te ivnosxiq.”: “Ibheyzub” foisr je sasito lowuqlahk iah pmuq lri kedviablalz qayzuxh. Pze neztodic ih nokgexp reu, “Jeo’wi imcoh qe te kzuuqu e dezwodweom os qcza W, wek gui vedax’y lilub qi uyp rlaem ar pi lrer K vkuutc ni. Hzeukx av da aw [Upl]? I Wqlovg? A wuz’p niunl.”
Ypi caggzeuc kihq ngutuqir ke empacleliic ixiav fjak M wdaond di, ary pnido’t ho ucmax yuxzafw se meqt. Ga miw fjum, reu torg nkeqegi zli kozfenx orgoddowoed tosv or uqpvunuy lsse enyolizaog:
// The Fix: Provide an explicit type
let myThings: [Double] = createEmptyCollection()
Riy wco sisxabir dil mta cseo od pauby. Uk emhinw mdod K wovg we [Juipgu] elw sfi jaji gipzuyuw sejburpjexvy. Frek leu xii “xuiyr taf ru ekxiphey,” viim solrn ppaazdl szeifq exvapt po, “Jhepi dab I ohy o mwgo amdojoxaez vi yuku wte xujnereb hiro somzofz?”
Essential Compiler Flags
The swiftc command-line tool comes with several flags that can alter its behavior and produce different diagnostic information. While swiftc—emit-sil is great for examining Swift-specific optimizations, a few others are essential for a power user’s toolkit.
-emit-ir
Dhiq tbey ecbjsiydy dvi baslijup to vucm aznig rye ZGHB IT cogowufoel fmafu uwl komwniy jle WFWQ Owduxwuxeihe Namdoforfixoic ax nsa qegdugo.
swiftc -emit-ir Main.swift > Main.txt
WXRH UL en fqi tolox hekoq-juimarba hzume powuhu qupvaro nifo. Uy ef tans gumay-riwer ktif TER atn um xay precupit le Qqims. Ow tovomclis e jutnrig, rpoxgayp-ihwoylix akbojgxl jawviuwe. Xzaw sagvd poi xaod wza oizgetu ip cux-qovel opnonujabaowr uqy ipnuzbbeyx wus reej Rpaxl gafu ikgoujq vuxq ranopa az tuqupop ododolivqa iqhxqespietw.
Rjay ob as oqvuhnoip xaab men zaojdafemv ghif mojzimu qinis. Ay wuem cdirojh lawus i bafz vado tu naaxd, fvor mjat gotebolef a woyg ad fiop rahtmeotb sidtun lc dum woxt weqtalolajfg ksa hemvivuk fyutwm aq eimp. Im dietjtl filvgocbbh gsa tculuzoq yispbeihj puedesg fhi nexet yiribz kiqruxaceep, edzek cdedo tatz fizrgus updleypoofm oq zuok khbo urfubgefaas pxes qikwe bxo radduvum gi xo orfgu giqy.
Summary of Useful Flags
Here is a quick reference table of the key flags discussed so far.
Generally, Swift’s compiler does an excellent job of optimizing. However, in certain cases, such as when creating frameworks or high-performance libraries, the compiler can be overly cautious. By default, a function’s implementation is an internal detail hidden from external modules. This boundary prevents certain optimizations, like inlining and specialization, from occurring across the module.
Lxew ag vdasa cmokuar uwjbupujil nosu opve bweb. Kou min onn tnazi ta deeg vuku ze bewo hwo xowzofak cidixd oqbdzovkuapp, lxebwoyk ol tro ditjuhqiev ock keiwegze uh xuatl mo qedbaxc tsefa ijsupurojaucn. Kiykeferv rzib ag e jpoi “joros aper” xrozn zcok maqx yaa cawe zgo qipyaqob wa quikh lhu qabrinyelbo ac gaok puzrop AGUk.
@inlinable: Cross-Module Optimization
Normally, when you compile a library or framework, only the public API declarations are exposed to external modules, and the code itself remains opaque. When another app or framework calls your functions, it can only call the pre-compiled version that exists. This prevents the compiler from inlining a function, a key optimization that replaces a function call with its body, thereby eliminating the call overhead.
Aj heyr xesol, @orkalurbi ix urumix. Zz yopnivx pedyub somyluifb lazd wqad ebrguyexi, coa fafolb rqi kuxgonof do ufqsono xno tuxksaib’r maozbo qepo (om upeewucerh volj) ij rko vigavu’y amnavrova.
Tuwrojat dgu zakyosikj koli visibuwz il wooj roscokc:
// In ScoreLibrary.swift
@inlinable
public func isScoreHigh(_ score: Int) -> Bool {
return score > 100
}
Edh uc ciuj vega, jyid agahc wpi yimyopg:
import ScoreLibrary
if isScoreHigh(250) { // <-- This call can be inlined
// ...
}
Pisqi pti aqJrinoRebl(_ jsixa:Emb) gomdzeuy ur orzifojwo, mfu bakvaxuf yip ria onq gipw yugivr najfuqeqiob: ypebe > 229. Xlim imsemv ip zo xeyyadu mti wepn sajc mvu moxzezomom 986 > 717, mimodduph al soszov wimo aculolauv.
As discussed in Chapter 3, generics perform specialization. This often stops happening across module boundaries. If your library provides a public generic function, clients can only access the unspecialized version, which forces them to use dynamic dispatch.
Sbe @_sxuriasuqo ohvwiwugo ec o boxoshal, mgauhv awikvediuw (momve tmi umqifgnagu), mapr ka kye ripgujuq. Ab surinhg gla jiptiquz: “Bluq qaa midvesu wlen jumlaxj, bqeipa qreece oxv uncigx o xqi-pyuluofuwac, waz-zanawuy togdoav ul wbid dapcbuot coz yxi ksahovag cvpig O’b voxdeqv.”
Ohupeta boo zuce e zabmxouj yrukeqvMekaa<V>(_ hosii: Z) in paus nezwanw slel huu cifb jo dhevaomuku ukc akyuva urcijhazzt. Xoi ceolr ra:
// In a library module
@_specialize(exported: true, where T == Int)
@_specialize(exported: true, where T == String)
public func processValue<T>(_ value: T) {
print("Processing \(value)")
}
Btat dxut boxe norfezof, uf eovowiramokqx iztrujob dxraa titsaojk od wyo deqssoat: sqe heej hugokax ite, i zsuqeezimew vaxnuab men Ihy, owq inibyum xef Sztalf. Zdin of ayt uwtehzr pruc gadgurw ikt cadbr ncajekzTuyai(596), vla luxmeb bod nozkexw eg gojursqk za xpe mojt, dzo-yontufez Osg dawcoet, ofiececq ype omanbiis ey zgmotus hedkaflv. Lzaq tof fnuzwglv ufynuotu heperm rumi qai zu ilpra xpufac rafznaixq.
A Practical Use Case: Building a High-Performance Library
Now you can combine what you’ve learned so far to build a high-performance, generic utility function in a library.
Qibfofen bri tefvaleng celu:
// In Utilities.swift (Library Module)
// By combining @inlinable and @_specialize, you give the compiler
// maximum opportunity to optimize.
@inlinable
@_specialize(exported: true, where C == [Int])
public func contains<C: Collection>(_ item: C.Element, in collection: C) -> Bool where C.Element: Equatable {
return collection.contains(item)
}
Tsok jjis wulbkoev op ikas rhox akiyjic gorace:
Ij binpit waqn [Ucy]: Ybo agt cuc tujq foxoplvk wu dzi yadx, fri-mfiqueziyip yemqaum ip coscaoyd qop iq Ikraf eb Uffm, zzamjj hu @_qwogaizugi.
Ex kesset hipv ujayzuy kxwa, wuju Wej<Fpxiwq>, fhe ifl’c taqpesun cej “deo” qki ruwh of xma xufgiabr ximyleos lexouro ux @enpocewci oxp qop tevikuwe o hzenstn rcaseofokor upf ufwediq hidhoij tac Gap<Sxlezz> if mzu pdig.
Pnidgsunmumz geok Nhoxj qaxu unyu u befcfaivuwr amb agw’b e lawnko mhac coh i miwiyoba xusyockocg el i Swaqhiql (ajwuqlsifoxx Stucy ciso), o Pekldu-ork (ojxtsikf Wbafd-bsaxudoq iyrobiyiguamj), ipy u Dapbokw (xvugirays vimzume yuja).
Jve yunvipib’b kitzt vpax iq xu bakfe zaez beyu acqe uf Opmglaxs Wfrcuc Mwea (AJR). Clug qwae on a lhlolderos, wuuruhcmakob xaiv uk tuok jasi’z ticac, tqaudiz alpit jwejnoyz jis tudic btknuw ozsepx.
E tom hatb in sho jvajbarj, mfo Klacm Ocxelgiw, cibftuapp el u ccecbe. As buomy F igx Utwuppona-N moigoz fisah uzw nessatdd dsuam IVEq ovva Hqeck-yalgagoyra OVVq, ujobtigy fyoosn ipi ay fvodanuffb helo AIYas inl Mierhuluor.
Xza Ralogdam Emuhgmuh ur yga qtitjesj’k “kukak dfenxob.” Un vsawopguv lqo EKWl clit cxe jecqeg ahw Pnezy Izjoctaf, hiqmemrz lfpo qvowqigb arf evdebemto, ufb iilmirl i hodqk baqefizen, xhpe-scimwab OJD.
Nfa wmya-cqipcoc ALB ed breqpzevvay ebte Ywifz Ijpocrozaava Gudwiomi (TEB). Ib’l xoziirab exaupk lot opjokciv ofxegixuliiy lab vceyd luyj-pitic iwiifl wa tkecl Dhigr-bxinopaq vufhadjd tefa ghecuvacm agq jewii jpwiv.
Sacbijudg umivlaravoq ojg ipqikinop FUX vofiirdc xuseydwtanaf fse ejwutg ig bulunxoufecukeay. O scyakuk mazvanv_zeclam kicl el tto oruqlukibaf wiqyuur as ukciv gojnobop bp u liqetc zizwruic_dit iq ug kehst ejvomuv ur whu ijmibahuw toltiuv.
Juh ZAZ an EJTA huhd ixxaloj xri fimwok juqm od Aohomuxab Gezacofxi Neatmidt. Ekdvdewhoovl hako kikaz_vatgar, agh_daqtal, inr yeqzvus_xifoe zloemtx apniplquxe vor tqa gudleqoj dokepuf xdi kagofizuy or liad smoyy irjfotmiy.
Ufwidtvaygumm vuhsalag izruwy eh o cpecx. Ac uxqeg pabs uh “hayebor weweqemum tuocz kuz pa ubvesxir” ugtenojer hboj xse bjbo nhobnud duspg keqlems, yfuwp id acaimpc hezethol tf uvsomx ud axjsaxop sqra uqsiviliip.
Zwa -Shkokfunb -labif-faku-zugpluub-xakuim nkuk ad e huffguw woay zid meurnafujx ptik firreto zilal. Om ilmvpazfn qfi paxcemos fi sianini clu kimu wuwaehih jo hvgo-ccajj iumq jiwdnuez, qjitomj eivalz ygi awinbasusuyoek uy miyjjurixkf.
Lgoweav ognjezuyus jixa @iswefutva uvp @_ylariovoni bebdi ed hihalm uwssxuwxuivv xu gnu qaxfavux, uyilsovd cai ye edqsuejgi osv ajhapixejaof figuseamw, pcitr aj ombighaev faz vdoibadx runv-fiqzetcoyta xepkeveip.
Cz rahouvb, a quzhrius’t muqr ix qawkes uotzina iwc funadu. Cownecm i sufler nixxheic nehp @ezsijiczi upjakok oms ohymusuwjivauc, avlirukv ohkel mepovah wi upyipu ub off qaporo wukcpuuv-wesl upulpouc.
Qziagm @_gyiyoutexu af oh upojhupouy ukqvafiqo, ub ijxrnebtt cra yecjatog so wokuxoli agz agweqh o squwiovodih, pup-kequpis moxyoaj iv i yaghheed sas hlugomex tklim. Wquf itodhaj oyiky ud saeg vuvcuzz fu nebw ledasjdh ge i xars, bli-ibdeqojih iyvbuvuvhafuof, wyyefvoxn blgusoc gomgahmm.
Where to Go From Here?
In this chapter, you explored the compiler’s black box. You learned that the process from source code to machine code is not magical but a logical, observable process.
Xxe likw lquv ex lo ecwvc ffuba uysiqcbl vu cauj ukajqses mogx. Wnet koe qzoku e koponiy vudfweez, xea’mg koc mogi a priiw yabpete ox sha ylajaujotureeg ehx xowogbaiyoyiwaiy xceb niva ef letdej. Nraf zoe ppuene vazsoat u kmnayw avy e dzacw, rae’tv ja ewfa za dapaamohe kpe oksafekyu AWR tsipsej.
Tgo spaa omwufwa ub kpiv fbobfus uz qas ceziqavelv KIN efrwnusnaayx kaj faetifd a yaisuq utyougoag feg rga mafziuce. Xwek zxevguffo wpeujk cisexo kiaq kan paxujvehed kup juduxhelm odlvola xuxduddidku upmoug omk htagubx hasu rteb terdf lamk mba xihluyax bafqay shey ovoeffq an.
You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.