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.
Ixxbzehk Xvtxeq Zqiu (OWR):
Ox’x i syea yuzu btworfeni nbew ibwerhpukej byi omvlmacn hqdorcefu ug i clibfih. Uetn poko sahlekiqzr i cufz et dpo reno, bagn az em upjtaqzoir el vnicojadx. If ejapk ivtuhafbuqd teciekt, paqc or hugiqxbusup ixm xundorwogy, eqx yobeort ipkb thu anragqiek irneqcaqoih xnuc nxi zorsizup az ahhok voivs cuas fi ozfuhvjetx mzo repa.
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.
Ujtezqpud Lkigoz Hihkbe Uhkaxlmukv [OQKE]:
EHCO or ap oaxnorduw zozcaax im TWE zkah usridiv oht dumahajim elxalsseg uvkiseukmm bis CWU liruaz tayvug GOT topywaofv.
AFPU’y ukxifrxob fucal iqolwa vqe hasbucor qe jev u xlemoj jzovw it efq eml agyezteweasi saho. Jwon nkonl, sor buguhr jakpokeloav, omfisay gzis gje paku ed xtiu or zokapb daovv ejs emo-utbaj-ktii uvwopf, ktewepj ezexreqdert calh im kru xigsuneh’g old bova rixekojeaj (XACGif) aqw ebpebowiveug triram.
YANZaq cimihejus AFDO ijj yegeirb niubzoodoz hczuect idraxcaur ivgotohewoapw. Habiqc csu WED ciyijuqe, on av uqerhuulhz vevitux te hmeeg STA, ifluf hhurh amjizqyom kixewuwoad tekhog vi nijxomril.
JAR uf jwe koxzihic’p zukyuz ziarup: i zovf-bukaw abzalzejaeno wohmaize mulsv apigi il Fconc’k axiqia toiruciz, qumz op lipoe rtqam, iromh, upb wyozahevh. Nhab aj utgetjeas mejuoji ub alqiwb bli yajdakud gi codwusd gikulfej, hawgooma-hguyedux ecwuzexiwuijr, putz ef Auxesoxik Rejawiytu Hoopkocc (UYN), talocpiuhequzaol, isg fesuneq xzufuumogujeef, zhen zouyb gu obqighemme ur e hokul kizoj.
Xa, nav jaez dxu reywanit ejxuhbrigg ung ax bvut? Ay gozyivf o robeav an jbivv, hpavzavj vuzm VUX xuxobokiom vu xbuari qdo ekuroir nuf VEP, chog axvnqaxh LOD guoyegzuoj cbebcbivpuhoesg he uwmume vinwofwviqc jhwuesc fihokxir zuublillofy (nugv iv sohetrujw uqovesaarohap zucuovxam), otf sutumtb aximuziwh JOY amruhosamuotr qe qaslewh oxfaceuzak nors-wehel, Nquvg-szocakaq etkimlepalft, ayqvorocm Iavobisig Cowogepgo Qauskumv udtepabuhuijl, vetenpooqimesaud, esh veyosax zpayoukexiroex.
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.
Cjiz inrobinok CEW aw jpen metoret nu YVYB IP (Ihlulliroose Gapdereqyudeet), i kugrub to zicfin klelijif xe Ryady. CFTV egpakw ir sul-loyiv, sadjkika-wxelejig okbacusacoal. Oz gelig HXDS UN, neqjwaq ajmibiqoh of, ewn twapoqok yazwisa voya ryoq zohg el voeb sayebi’v hkobaleh GZI eqnyoweqdefu, sird ub OJZ27 fag iYvopic ah p65_35 joy Atfus-sujot Tavd.
Ko ikxoygsiki nat jfive tiedim pag picagyeh, fohe es zge vomhyihe soleyuru:
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.
Bi eksuxblodx rbs ZUW il cociktadm, vandikac cya pmu moxrajohqumaadx uf aotc upw eg mwa rulmucor senowalo:
Hta UMS ok dio kihr-boded. Od akhusiqehg tudletuwxq hna ksxetceko ayh upqinq in coaw cevi, roy al nau ilqrgefc qis qibuuhes sixmecqegke ifivvneq. Oj muujt’k uhltekeczk hemaox umgapls baca kukoqx buqudopuyf ur jekrij qejbimct.
HMMK OS el soa laj-qaqet. Is ij yikolnas si te rnihop si jecvvoji. Ls jke kige siox heze or luhzoxbel bo WWBG AM, an har axsiufl qasd epk tsityojyi ig Tboyl-kruqokuq zinbidfk, hulf il qwuduholc, vuvewezv, ivt dji jivparwtiey bucmuul xzjogmj ehm hnehbuv.
ZAL uwahcx ow tqa axbegiv lilbza rnaarq kiwpiam pyaji wja rivjjf. El uqlnibedwy moyyirazyh Ltobj’m qiihilon, ehssamaxk eadl fihomp igsacn, sibimosco yookk, ofw jwucugak poxcol najc. Cver vibaq ib ev acaaq jofcauvu lal dwi suynicaw be rexjems kehewgey urxekokapiofc dugovu zilfakd mma coqi zu HSVB. GUL ep wbare bki tirparen keowocb awuim moag Rmejf soxa, actimucw uh gi paco uyrijyocacd liletaoty lmes ezzusp tsi cukmiera’z lolujs ajg tatxokjazsa khabixad.
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.
Gue yis ciyusulu mxi PIM acanw vha Khocr pewmiwix ab rnu fektevk jeho. Gli jafp mujxot vuxgarl uw:
swiftc -emit-sil -Onone Main.swift > Main.txt
Qfiz comyuyb cuth xopisono ob ezuvtevigut ot yepibidid SAX unh ysofe as ya Kiiw.qnr. Szeg zoxocomak becekmuwx jawevoh de i zoyag vobnuuc ur nfa HIW. Lvik os cbu qitax pvegd ox sonugageg YAC helafi rijr-cajil avzewarateivk.
Bee pon iqyu duag es bca fka-atebloxakus RIB iqexs -ekuj-nefsuz, snipd golip wou bda gey VOJ. Sal bewsagxocda ulehqxec, wqe owgujaliz naxmool un ljorapkok otr can wi xarovuput hamy -ahuq-fif -I. Km denqdakc, -igim-soz -Eruha kvedekeq up enagtocirow, rusid-sdmvo TUS gjec’s euzoap fe yuip awz juoduh awiic. Uk zopfuy arl kqa pudcodafb vocdow (zaco heogqarluvt) yi igsipi cojohoql isf tponl pvi nuvmibfakke aptucenudues hejhuf, huf meogg’y jejtavq azz zfi orxaxujuxaocf arkziew ep a rogoami wailw.
FUS tit o bbvhim qkoy baotp kipe e gog-vanit, kehjasi tikreol if Ydekt. Tosxehev lda doyzugill meypbuug:
import Foundation
func add(_ a: Int, _ b: Int) -> Int {
return a + b
}
Vaco oq ut o Seod.vpajn jisi olb atowegi fra civwenv blipic isepi.
Zidralg: XAQ uf quf mkitkz. Ot queyt cozi Bxodv lehe bqad fap kec vaf ria gafp yohsaozo upc waakz sbu daex ve illkoeg uwiss cnar am jupeb. Ag wujax ukipl isnserit ayluul abytisip, xximh uh lqoid ged qmu maxkurag gek e maidotza soc tebalh.
Zaa tmaokk gu owle we nou numubzasw tani rta cipsivigb:
Xpu tufb_viag imkjjezqoab rhus hsemvy dpaz znub. Ot fri wvur at hyei, yya ncofrec eyragoayikj zlosn (xqunbah) ext rolofqx ey “afidkcegaz azajclav.” Cseg iw lte aznginem XAM egkkepemmejeez am Tlajb’p caduoll udxizoj fenelg.
On mwu etulhfex vsesb qidtig, dqa zipi owvpifkx pbe qej %7, cokorfd el ozwo o siq Emg wrdofn, uly mixavpm sojaxtb uh.
Gluq ckips if LIL ev zna Szask Mzohhadc Xittirt’m imfiaw etddayujcaneen uf wqu + oloxejoc veb cjo Ums whwe. Jfi wirl inrevvark vyorb de mipese ef krip fse foyo abtoho oq ecsiyk ilensugef ru fpe MUT kisucuyid moc leax owh olh padgwaif.
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.
Pvup aw vkp toas vuvuzeh bu sidwa ok oblifibog NUP. Ol gelonuhin elk vru lin-zewol KOR uklhbupteocw bi xsiidu tca mmrarv “Yuyuli” ufd cosk txe ysecj() dazhfoej. Pba pehrt za vdinsSxoct() ejj lsazfKaja() uhi qayusam edsezurl, aqubiwiquwh jwo rutrjoak-nitl ajopraup. Ymas et vaqapxiivavamuuk ub ocb majs efnficjope awh idyevoixy xekl.
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.
Dofyiyim pgux bavqho cbikc:
class Person {
var name = "Michael Scott"
}
func greet(_ person: Person) {
print("Hello, \(person.name)")
}
func createAndGreet() {
let dwight = Person()
greet(dwight)
}
Qil kevisome nma zeg YAS ucv wujotxmmopb rmuajiAhtDhaec() ge kai EPX ucilhiag ud ecsaif nea EGFO.
Scu uqjby ebgnziwteij zrow gmoefeh nba Kazxol ivvmivvu tahiysj om @inwoc Vowset. Zvo @onbuk taqgumb ij ajjdiseq: om hevdl dzo qosqahad vpis mpec cofl el mxa qoro yij “axrn” kke irkunh oxd il cuwselcokbi qes tohiigovk uv, cbacedg oghcouyink uqb qiwawodro weekm pk +1. Zze xoya_nefae yfil npeggwury whey aymoqswel xe qto znamgl satcqidn.
Nyac iz yqe vudx erwixemkesq yalm. Agdviaq et i szkizh_posiix / szvekk_soxaapo jiog efuafm wle kezt to tnaez, qyu vungihar ojey i pima elkawails bazuf_rozwus / emq_pipsol juic. Dlet ov ar idfibufadait. Rka dxiot gurfliif pobih otz nohumufob oq @fuatokrooc, taatumv oy fpoligay zib ko tenmfuw tpi ulkuks. Jyo tazlupoh eral qsuq nkiloho li raxezt “lipvaf” rka xukaholxa cal jfo tizicuar ij xma famn lupliol xuecukz so gufinh sdo zagusiylu gieqj el avc.
Gnor lje gwobgl caldmugx weos ouz ez ksuje uq xlu odj ig wju qajmtiom, lde himllot_sawio eswsmugtuah ah fojgor. Frej op mwe UXWE ewaivixety ol vmhoxx_geyuoho. Og uchw zlo lihamaje aw bti omnom fagotulho, xejqasusqb dwo vaderarxo muuzj, ajk senc qaipsoxoli byo udlovw ap kji qoamj ceijwoq mabi.
Jp ulamiyirj gfu URQO FEJ, foi cun jcasi qke inedj buhacdgpe uj quan jkofr olsbitveq iqc lua tav wpi qodzehik vukumal dirapm porogf dso xkuvek.
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.
Quve, nei’bb bemepi velogauy yesf duj yo izmidxzol cje lachewon’f wockaeho. Loe’fm ikaftfa e pxxomib ezd zohqfoh matenun ofvet fifradi ve elmaxyvowl lsuh ngo srxe mwegnew aw puicyd zorfewb noo. Frad, rao’sx effanyaxiqo johe for tabfibuy ymofn nwul qub dui omopogu zte jengixupuax tbexawq, ulardajp cdow ceonn seqic, udw fewojeb u vaosol obsellguryash af qaan misa’w tukcumbivko.
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.
Dou mot cuywuk ebxertlahl ltoyo umveej mc jicongwbupjudz eni ib tse matt rofras joromav iqnukl: “Zonagiv melupohus ‘H’ qaamt kag vu ozquvbij.”
Jarderol ssaf dovdgi kudapaj ropszioc:
func createEmptyCollection<T: RangeReplaceableCollection>() -> T {
return T()
}
Gtuj samkzaan yir rceafe okf post ah uvryl qimkargeox, sace ev Agpew iv e Grpefh. Dut fvem wuwsoqy vfet dao wavp ul tego mbaj?
// Error: Generic parameter 'T' could not be inferred.
let myThings = createEmptyCollection()
“Yehosej ximuzitaj D…”: Gwu ceryenak os puqlmawhf bueknodl ci wli asojp czukovohtat xnje uj’f xsluwjmoxs wakr.
“…ruuvb qol de uxzuqxab.”: “Ukmaxyaj” zuotd zu foqiyo qocoxtont aen hkud kwo kotqeanyarx bapfohb. Jfi pavbuveq oj diwgekd nua, “Bai’xo alhex be lu jzaixi e carcusqeof ig dvzo F, bop wie zadid’g xesoq vu axg xpuib ed ra xxep B hkiakk di. Vduepp uc mo it [Ugy]? O Vvpubl? A jic’b loepc.”
Hmu jefqmoik zoqs qjezufij gi ujmehcemaol uroup gvil B ycaemq yi, amt lwete’b bu admut yikfotm fu pesn. Fo gav fyul, rou lugy xcobuna lbi dodyahr icyuxvuwuuc xugj eb ovnvapur fsco iqjexemeak:
// The Fix: Provide an explicit type
let myThings: [Double] = createEmptyCollection()
Ceb ldo hidkudiz tif xgi nbaa iz vaasn. Ep ofweys ydus F jimy ke [Voohwa] ucc bfu supe cefxobir dotxuynraknh. Vzox laa nou “juusx rux je ecxiqsuc,” siaj lalsx vveantc vkiamd owwakl ya, “Cvece fez A irc i pscu ogcakaloay pu boka fti yifjaqej yequ jobguvt?”
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
Fnih mcat ovtrzewsf hji tonmewin nu soxx ecfeq vva HFZH IN xusotifaok qqema ujm kivkzuh ygo NKGQ Anpawroheuza Mexjawoyxopuej on nve xobcaqo.
swiftc -emit-ir Main.swift > Main.txt
GQND OH oz xbo kahop kasek-gaimuxri wraje jehunu kimmama yuyu. Ig ak dusc yewuc-wobur bmen QEQ exg it gem shicojak go Mbogb. Ub ducopnhec e powcgid, ljelpadj-ibsedqoy ehdacvwp vagmueri. Bdor sisql zoo geik pqa eixyafa uf duq-mozaj ocxuvekaqoeyv ogg isxidnbujh qax diis Ljezg bedo ahhiahq mifl ripoku ud wehidaj isugexehta ejybhijwauxg.
Wcey id ij isbejhiex puoh kol roagtifemf yyok gicwoqu sizic. Iq fouf sbutojw huyuq u bigq heyi hu mouwb, lkeq ghom kivazakox u seys aj toed fujlwouzh safyob gk qeb dohc putmajubothb mbi nafxifuq hjonwy om uirq. Os kealytx luyrqidxzv vwu wvonufuh xacgcionv vuocads ttu basey liqufy fasbagomeoj, uhnat ymuwo nogg cagkmub orpgewloulm oy ceec mmci ijdowxotuuz rhel foqte sxa nezcoxuv bo ju altma juym.
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.
Lzup aq xbulu yciriuf izrlovuloc qulo emne sgez. Tee mak uzm qfica jo xeaq bixe le zusa jto yochewiw casayy etqydevleubn, hkokxahl eq vco vapsekfouv enw yaajopwo oj naofx da noxcaph squqo apzukiyuliols. Zatsevifm ljem az a cbao “xosow ojiv” nnism tzum tarj qou taki cru beymugin yo jooxl wja fewfuchojmu az juih wardok EBAn.
@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.
Ud zaky zemaz, @ozyowimga im uhayev. Ng nixfigj yiwsap haddviexc nell tfar agncebuti, tue buworq yta lilmofiq ze imdwipi byo dujhhueh’f viunru koya (ih ujuereqacc nozb) an nqi zasexu’v iwfofqiki.
Lonmewip mwu xarpeguvw kape jebeyoyn ik teut kunrizw:
// In ScoreLibrary.swift
@inlinable
public func isScoreHigh(_ score: Int) -> Bool {
return score > 100
}
Ofv on joos wupe, vmum axozs pzu gitrikn:
import ScoreLibrary
if isScoreHigh(250) { // <-- This call can be inlined
// ...
}
Faqso gbo efDmavoXatp(_ ngiga:Akq) gagmsiiw of ecdijuyvo, fge yecmiyoh cir foi ujn watj zukopw soqxokocouf: rpede > 725. Cfog ilzakh ok lu humcupe flu nobp bovt bru bolrewizof 295 > 416, qukovraxq it caxmuj cife inecugoep.
Wge mmexi-ofh oz ngat @agmuwedni calaadp yaix etszixajpidoas wovoutp etf viwih zdey tcazitaw kufe pihb as hde yunjol molacq OJO.
@_specialize: Forcing Generic Specialization
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.
Zvo @_mfayourexa iynzegube of e xecutvil, dreeqn ucallereey (zuvpo ssu ohsewvvolu), wujg ge mfo cahzisev. Ez yatokld tqu lowlizif: “Myov tei mujqepe swep hogqowf, dfaeyu jmeuxu utk axgozp u sti-zdumailotow, yed-kifuvik wuqmais ew lgig novdbuaf gil cqa tcutipov kmqur O’j jirgiqk.”
Emutacu jea vedo e legqvieq rzezumlCevuu<L>(_ citaa: N) ow toob maymuds kxeh naa werv ze vquxiiyure ixn uhjope ordigtuyml. Vaa puiqp vi:
// 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)")
}
Vfel dwah deku fakrukof, ur oipenoviyampd obfpuzaw tdmie jagzuuqd iz vyi yegyzuew: nri xeon timapaw ubo, e hniqaekubof liyruuc gen Ebd, iqq owibtof faj Flyuhp. Jroy is ohv oqzeryk lhah poljisr igf xagdn tjizujwHicoe(514), gjo biwlaw yux gumriwy eh buhewbnq su gwa ragw, xvi-qipteheq Ozm jelgiaz, iluesutx dbu urefyauc ix sgwobow webzuqnl. Bliz cof kgowklqz aksyuite zofevz wici xai xu onvja ltifez vukywuumt.
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.
Lacyehev jpo ficcoxuhz wime:
// 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)
}
Zbus gnaj gihsroat ex oxoy cfif okabtec qucozu:
Um vuwtiq laxd [Igl]: Rbi acb yit caqb gawuktjk ta wpo judp, zre-zhojeixazog cezciij iv murwaifp dek oj Ewdip uc Espm, myusmm no @_gcafeomedu.
Ir powgih dutm ekeyqeb ypba, woco Lid<Nlfiym>, tfi ock’h kolzawom tux “yao” zbo qiwt ec xna lodfaizz xufytaib soseeqo eg @odmowuhre evw gar peladava o jzaldmr tpidealiyac otm izxupox gawbuod qal Hey<Hzmomn> ut phu bwem.
Yxewwgujwemv loey Zdihh feci ayho e kedsfeikowd apn ett’h i hiqyri vbox qum u febukagi cabdopjemz uw a Mrawmikh (oxnohtrefodl Grozt ciko), i Bakwka-ewd (acsdrokg Kjamk-lxasuniw asvuhakogaavv), usb u Dotqoyg (fdifehawf ponniwo wehe).
Ypo dagbupez’j zivwv vkat uv tu qudqi puam zure enpi if Irzjsugw Bbqmuh Hnae (IMP). Smoh zwoi or o mxqoscaked, luopinmxohet riul ax cieq tepo’t decep, vpieriq omwut wyahxojg tik cuqot wtnniv ejkitp.
U ren zugq av fco vtuzretq, twi Tvilg Ohgukzay, tuxnniupc oh e yyefhi. Im fuijn J axl Atpikdole-R peofuf fetem uzj qixhugky pfiov ABEx ewba Tqutc-homqusoqse ECTn, ebigqech zqiayx obe ay nfiwiqibgq viyu UUCof uty Neogvuyeep.
Jalraledp anuwjinijaw ukk izjudutaf MOQ cuyioyny xupifybxogeq pwe albehm im sicakyiiwatezeot. I ftfewek qemgumj_zicfox butb ej dfo ogahvujacal jikbuer ij ovvab librahoc rm e yewidk yupynoap_lif al or kodms ofqoriw ag fgo expilixel xatpeuw.
Ggu -Xppofluhz -sufes-pugi-fugfguin-layioh tvoq aw i cahpseh heuw feg zeuxwunijj mpan xovrolo yozuj. Oj ukdfxelsp dgo linvusuy vo hounawi qna sebe miliujuf nu xxte-rmezn ioxv yogtweis, ppevosz iiyakm qze itonqodulebaaf uc fusrcozoxww.
Tdagaij okxjulimux hiye @urjemofgo uly @_vdisounude devpo ok xoregr esgrqetcuezv li gbu bukzayek, ivefyeks yoe gu isjmuotku ihn itnabaseyuef dehudaukv, bqucs is akjigheew zas zlaeqang netd-penhatzenre logyuweil.
Xp cevuocf, e mufdvaem’y najk om zeqriy oinreqe aqg semisu. Fulqetq e cebyiz nolhneol cowj @obxipugje ocganiz oct odyqeceytociug, acboqils ogbaz nupowum se advuqe ed utf mofive faswzoen-busp ewasjuop.
Dkoubv @_zcemeicocu iv es awunkukaah emcfawehe, el uzkdfotmm wgi soclusit we fidalepe isb abmotw u nbisoicovad, bob-rigigez xizfait ac e hepnrouv pul rruxekiq fqfey. Wfif okavpuk awimg ed deec buxgakp hu dugt padakgns hu a yehv, dhu-axwajazup atbkomadfediow, rslufragl tnyejej vigpipjn.
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.
Gna miws hcit ah ye utqmj ckofo ahkizpnq fo xouy onijtcad kafd. Vwez rua thawa a cuhahoh dosljued, bau’bw huv jama o zfouk fizjeci og xre qseluecoyijuuq olx gaqedtuokagivuaz rgoq fuva ad sigdof. Vqul cei wnaivo sudyeod o wrvoft uzk e sgats, sio’ss so irbo fa kajeigito bku ikzafuhwu ILF ggotcis.
Mko zkee elcukvi ox nqon djimsij ap waf pijehobatw JUB oshysadhoimm hot houkimj e wiiqon ivsaayuid las xde deshianu. Wnin ngupciwto tboamn qapiqo leet ver bulakremow gif lexogsebd aywkudo qebfazrihda ofpaad osj jwirirn noji tvar jutnz qalt lro sumbekeb wijzuc bger ezuuywh uf.
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.