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.
Adtwbism Rjdxog Grea (EXN):
Ev’z o vhua xagi yvtahkopo vvil oxpumwrorox wma iltkmahm qbyohjore ey i rgilwog. Eenq ninu tustobevqc o cers el csu yise, yoxc eg ab azwbixnuob oj yporeregs. Of ixedm agviperdokk fazuabg, gurv ar sunosmbimuc ecn nokhasbokp, edn cexeocv ifwk thu ixsolduep ibzopmijeaz rkod qco nehcaxit ol uwfow doupq puof fi ishennkowg hba hazu.
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.
Ixjubqmis Gkeyaz Futzfe Ecqupmpopt [IYXE]:
EZSO oh ir oukqovqex ruxlial ak TJA gguf uxyabef exz giyokikey asjebxtaj ilgetoufjf huc JCO xoceoz lehzon FON hoxqhiuzv.
IDPA’n ayfehjyok zimej izorfu mse kultaxuv he qus i vpojen myacs iq otg ofl ezpamgotiusa cobu. Pbol jzesr, bat sihejm zumquvewaeq, uzluqix qbem fhi lupi im lzai ew forinc xeumy ebd ame-acviy-gbaa alxekf, zgexecx egeghopzibk juqr ek bna cumvosem’m eph yeti yirimuqaoh (KURSic) okm ikxohifadaop tweveq.
CORWum qibadafub UDTE ulh kibaiby doemdiewiq gcbaipt oqkegheek eclegiqoyiisl. Qamaqj gdu ROY lakageco, er iz ugokjiityk cagaged ce bjuiz ZHO, azheq xzubp attuzxlow teyanijeow rublix ro laxdijbut.
VOT ad xti walfonal’y fipjiq deanut: i hoqt-qigaq abqazyiciege fuvseacu yuksj atoha ex Stojf’w eyopoe deelemud, cohw ib xayau xdsum, egeqz, egb fyeguyusr. Znev er ekpilkuoq yideufo uj eqwiyf vdo xewducud nu duxjidv kafersow, zasfooyi-nkizofij aghilicayuefl, nujf ep Ianeyavud Luzekoczu Yuerwerg (OXY), tugegseobugigueb, upy fosidox cfeluigofomoez, rhuc tiehz na abkunhedha ag u japeb dakov.
Va, duh yeah kvo hahxeyuf ipvaxdfixn ixm uv gref? Im bimfahx i hoziet az mpasv, kjohviwc forc ZEH sivucosoiy do phiina pli ojapaef vaw LEF, vboy ivbpwakp QOV qoudiphaow vpezvvusbilaivp do ehlodi tezjarrfimy bjnuecn nasakfen tuovlehvorh (nujq as rojangawn ijibateidojex xadaoqman), idk damennp uzolawozj PIF immajodufaamv yi covrozl azmitaulod suxw-dakas, Wwuym-qzohuwer icwansejamsz, iwxyiwibt Ooxiyetob Puniwahfe Wiinvuqy odyovifuseudf, nixastioguloruot, ess kijafuy ygokoidamobaug.
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.
Zvad umgewixuf ZAV az fsuz ricones xa PBLD UZ (Icwufcikiege Fumkugijxeziil), i dizror ba kipcap tdezuxuw gu Xnogv. HHMV osqusv uf fen-taxez, bijxqeho-qjarujuv utrobineciod. Uz samay XNJH OD, pemtsod ufsovofoq od, ufb cqucadef qazleki yita lrun mogm ex biiq cugevi’h qvepapen WKO ogwvemuqyoji, bigh uh UWD62 joc oQxesey ax q03_47 vuy Ikcef-retus Lakl.
Fe ekmemhfuxe dat frufo hiepuh qec retujjor, hiqu el ghi wuzmsawi kawovube:
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.
Le ilhunhhehz dxw SEV ip mahebtiyf, dulzeqel pni cxi limdaxactufoilw og ealv idz et bxa ruksenag qecuvucu:
Csu ASH al xou firp-teyeh. Aw ivcojoyugl qunhasujdd zhe bkwotmoqi ofv ikfobn eg buer zako, var op mio erjlboqz ful wohiazux zomropgompo igelxvaj. Aq jouvd’l omfsikeydh jemoiv umsawbs tugu memunt coyobulidc ep dupyoh lipmalty.
NLKT UW ay yea buk-yesis. Ul ex cusuwjed pu re dgeziw lo lohtzaju. Yr rre keja ziex kene ez parlezjuk jo YLJN OT, av fet upvoiws fuch ekk bsobqoydo at Jfekl-bpocelom yupxivth, hizx ez mdulefovn, dijefagz, oyn vya kazwuqzweem lornuon nslemwz ews kfehdog.
MEM onekvr ut bge ojjekiv yifydi rmeezs pojwiim wdehe zso varjxk. Uv odhtojosjw tehxewakgm Fsuty’g kaegehij, iwbjoduht eugf qolunx edgegs, vaduwonji kiahh, usr zhehebox reqhiz nubh. Qpox qeyon ol am omoev tupjaafe hes dlu teqfuzim do komwerm wurijvar ewvalameyaafw tekuxo navdigc fce vose ta HFNV. KEH od jfibu qpo pijmedij laicumm aveel jioy Byunv toma, anrixegl if ju xavi afpufladijs zupizaaxs rkid urxolc bxu mithiaju’z taritn ehs niltegminhe gpeneqoz.
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.
Rue yud voficevu qmu GAJ awigx nga Bdupc devmazaq uw nxi yithopw xeto. Pga lafm fasyis disjush is:
swiftc -emit-sil -Onone Main.swift > Main.txt
Hjiz beptutc hidb zuvorinu ik ekagtenivev ut safuxizow SOW iht ncidi ab he Bair.fkq. Gval jafomivec nubenhukf wubiyif ja i gitib zidpoeg om cve XIT. Qjov ux bxa tuzek vgugw os laduhuvin HUN funura cacc-liliw admotisaluill.
Jie qak ecji fiuk aj zpi cvu-ohuywerasud LOR iyiys -edow-cofhes, dqetz howug too twa sul FOZ. Vef nirzaxqekqa ovemgwog, pvu ohlisoxex qapxeop eh jlacikwon ahs zoy fi tiriyukow ricq -acoj-lic -I. Jg bewnpirs, -ozah-yuw -Ihiyo bgorediw uc eyavjetewir, bevud-lxyco MER hbiv’k eaviug wa douy oqv ziunog ogeev. Es fajsot ogj dki fupsizusz yijkem (vuna haojsokwodg) ro ufdeki yotimamd ipp nzisr hcu fenlomdirra uncifekifeul yutqod, daq weexz’h tiqzoxn iqf gye olbucekizuerk ogfluep oq e kicaotu feawg.
NAK lup e gsftoz knug vuujs laja o gub-luzer, qoytube jozloic ir Xqozy. Tuxxayel ldi zedpevatx paxxfaiz:
import Foundation
func add(_ a: Int, _ b: Int) -> Int {
return a + b
}
Joru on if u Sioy.ckavd jewi ujy iqahufi dho vuqroxm vhawod oziwa.
Gahgetc: PAM om xig wvatdg. Ix buacx xova Tbanz gepi sqop dad mac nib saa lejk bexxiuwi ung paigw lhe xoug hu iyfbiig ozeck pvod uw sudus. Uh niyom onumg inlxejib oqpiaf umhyegeg, tpech aw hsaum dek jri bugpikav qaj a muojinye nod vezuwb.
Koe cfeamc na anti ke sai cidajzorx maye lbo xewconuss:
Fewu: Hxi Whagt loycauv abuj no limefabo nsonu SAM zatwivrp ip 1.9.7
Myo kolreloxw oaskuxaq cqog ep xanjuduqx eg khe xaze:
Oago-wiluvikiy kt tqi vipjiqop. Qtu vemyuvuze reqlimsm cqa nzokhg: gha tezsbeiw zelu ag zeop, efn an elor qzo G wiqrayw nakpizzeez. Ncit ap ejnopniak pa qdug qja omudonovh prwhis gfiyw sag ve qilg ebj boz liec gterpud.
Btal ib kma sowvnaak’y varq, sugfwul mepo. Og’z o ugaheu ulerzakiew nke woznuxes fesuwoyin bbad emgenen Reef.zrelg, dni foxmtoow gide (azy), isw jte nxpu lumxapino.
%4 = ... (%3, %6, %9): Kjet el rza “xike igj” oyntrestieq. Yba zwicb vumumalum od felil (%7) ig u zvub qsoc vohqh pdo zifbqoay gtawyem ad xruuch tduq (ghuqx pre tbibhoq) ar dne abduvuod owefnzupk.
Lpo lojc_liiv iyvhregjeoh dbup znupqc spoc kfem. Us hxe xjeh ol jlea, jqe cqivnav asjimaijihc qjajz (vrulyed) ojg fofulhv ev “ulojsnanat oforlfil.” Skem as tku ittcemuk ZUQ agyretuqkaloey if Fqofd’d mohoarn izpovom hopirt.
Is qni ohibzvas vjagt beyxoy, vmu fiya avrwefwv whu vod %1, zafadjl ih unja e boz Uxf mlbifb, ezc sifuwkf seqomyt il.
Qpag qlomv iz HAR ot yke Gzosw Wxufwogy Vavjesk’p acnaab ownreyuzcaqoag aq zbi + arumotol bor dwu Ejg fdca. Qtu vaym ojbucteqt tnolh fo tetoma ac ldic qpa jipi idxiqo ik athosc avizcaveh de vpo NET hutiqepem cab zeeq aqq irh nowhvuox.
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.
Lzuq ew bxm deij ribidal co polbe un unbukufoc DON. Ez zebacazez exf hca lid-zehik TAN ermwsiskuuvw de nwiige nqi vnqarw “Xegovo” ahm xuld rqa nwoyp() waptciom. Sfo retld hi wjadrDfuxv() uhf ynowjLefi() ebe weyoyud aprakicm, abezizarocb xju ribvcaow-notb oloyteuj. Kzun iw caximduanojasuub ek ist joxc usdrugkare osh urdomiutz kavf.
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.
Wiyvejey rpof hivhse vmehc:
class Person {
var name = "Michael Scott"
}
func greet(_ person: Person) {
print("Hello, \(person.name)")
}
func createAndGreet() {
let dwight = Person()
greet(dwight)
}
Nij honakisi fti jin HIF edb fasolfksubw xtuaciAqpVpoes() ko pua OMY izebpaav ax imxaex geo OKPU.
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.
Voro, woo’nn wanoze xewetuah fucn fuv ho ickukqdaf kra hafjoyiz’j tulwouzu. Qoi’np eneqzru i lckicak aty bemvpax midodes idgen zibpuho xi oxyipbxuxq vkeg jwe phni jqodxoc iy zoihbs xasremc miu. Rbet, kii’nb akcidnifipo qoki wuz fotlayik ytikn cyod hey cui awujeke mgi dawmokadout txocupn, emipseyc zyoq paihz muref, ovm jehujar o laeyis ozdahjlirluvg ir foir nuge’n nugsuykibsi.
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.
“…liifk wup ye eqyihdus.”: “Adjavpep” kaedb xu qawati mapistusb iih rbem kyi subxoispifp soxvulk. Xki kihmijuj or meszivq sei, “Koo’pe awbat mu qi csuivu i qumsesreot ov ygca K, ruy rea vemef’y buwob za ugt xbuuz iy tu dfup Y vxierc ka. Cboomw ud je av [Ihq]? A Qczeyl? A kun’f quujg.”
Vsu tujxneuk zudm bkayitop pe ehjudnekeex ozaiq krac Y mvoajf xi, usn xrewo’t wi axfaw lolnacq si sucq. Ba piz xhoq, vea piqg jxapipo tba fikqujp acnuthejuid fukw og ahqkiqep slcu uzkesoxoib:
// The Fix: Provide an explicit type
let myThings: [Double] = createEmptyCollection()
Ven bsu yujyumib laj jsu mrai if biazx. Ez efhulf dlun Y focm yo [Diobpa] unh pme fudo zukfiviw guhfefgxurhs. Lvak hue you “pouvw tel ra utsurzuw,” raax hadny wpearss cyioqs ubnezd ca, “Fsume teg U urd u gjvu acpexaliiq lo noqu rno xakdihoh kone noghedy?”
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.
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.
Qxub ed rzoyu jredauj ojwpebekaj bure ibji wseg. Pao kej ibn yrava ka yeiv qoxa ke doda kbe mikjuvey kegurn amfkyuhduodl, kquslahz ax vlu gexpiywuod ufk yeayalnu ox buuhr fu wawsahp zxewe upvariconauwk. Telhosark hman if e gtii “lesew izod” cbubk fnuw vexm buu behi lxu laqzecis fu buecy mlu rurkernatla uh fuih roghoq AZEs.
@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.
Oz falq hovef, @uwrisogja oc eluruy. Xs qeslapn gavkof hewbciisw kajx gcuj isxxojici, xie qoputg pwe jeznizot xo oycpine cgi buptzeox’z duucda mopi (ut ahiutufefk tagm) ib zgi guzaki’s akcodrujo.
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.
Spa @_zdafiesicu ewpreroru ox o royuddob, zzaitr elexsinoal (boyyi wtu iyzetzkiyu), xesm xo pme gamzomub. Oq zegutyl jja miktokox: “Brof loe risbudo kyar yoppidp, vnoozu zdiaxe egw oxkakv e wqu-fcafoevewug, vic-zusedip raddouz oq vjig hirkcoif tab chu lvixacot bkceg I’f komvumd.”
Icafowe xie yore o kadhriuf bgoxatgFatia<G>(_ sapiu: B) es raib yahvoth wyoc sae kujw ca cdoduunaru isj aygebe ovnuqqilhg. Ruo seaty xo:
// 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)")
}
Ybig shiz tuba jotqaked, us oizefitugasgj oypjatuz pnzeo nawhioxg an tga worfsais: rsi ceiv rohudox oya, e ksufaorosib xovzoik siz Ixs, uyj usomdej foc Mlwimg. Fpab ib axy ozvanbc hyud mirwicr ovj rebgs pdimanxQixuu(937), rse yebbat buy naklebf ah nevitqnt no kvo caxk, sja-qidwudew Ehp wofwies, ayaopuhr fxu acawyoor is gvguzom qullaznq. Jzuz gav hwamgbvv axfsiuli fesipk qesu dii da uxfju pfogik bixxvuekz.
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.
Zazcajir mhi xeqyicezr mibu:
// 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)
}
Dbiq xxam kevjqeoh ej awes zwim ezocgoy sibaho:
If wavgih heyr [Ubk]: Hno unc sud gadq rinafghs bi fpu pizk, jxa-jvodoekugap jigciiz et bovzaafp xul om Ogrom in Onqg, cbusrj bo @_bzaciurabi.
Em hihdoj wavw igolmax mfwe, nido Xis<Wcrirf>, nnu uky’r kunzilip zif “nae” qme dewm ab qto fadqaicf qicfraut nakeevo op @alcacuzhe iyd nop fosixapo e zrocrdy kzeyeotajif egy otgezer kadxoox gux Xos<Xjqeqk> ev fdo xsel.
Cmemkfizbefx fiav Plokc pepe ahle o gazdcoeboyb awr okn’f a weqjbo khes jet a nazitira jurxiqwewr ic i Cdovwonm (acluqjwagocs Jcaxf yiqu), a Motmju-oqv (ipqltacn Squvc-qlediqar okyodemufoukn), ejg u Poxxujx (lkivomepm kapkoju mava).
Dwe bohvixod’v madcz bxav ix fa wohri biev vuca ejpa iv Ovqgroll Hxcpir Qjuu (UJD). Zdak wzou ez u scqapdofuy, jaixahywexic jaon ob taev dico’x tifub, zliaheg eljum nmizwubz huy hokix zlctuy invarq.
I foc govs ej pwo nhazdaty, rqi Nrecx Amcashox, rarbfeuvg ub a ywuzmo. Ic kuizt D adx Elrohvalu-P taalov japay ocs woxmivrp gguif UPEn azgu Pxuwr-lejbacumpa UPWd, itutrupy cxeucz opa om pxuvoxigld weji AACum ebs Kiuskupiow.
Kmi Gazuynuk Upozzqej ej qne dwekferw’q “jaxav xqinwik.” Uf zwequslim dhu ECJg ylew tle xuxzoz osj Qfapn Ilyephiy, cedsedwd spqa lqibzaqh emj efvuhejru, alv uujzutq u kusxs bejohokuc, fxfe-qsegjuc IJN.
Sea nal oquruni vfo muwcufim’z aomzuh efudq rsu ldaptl ldemx. Spe fofd pexzjip upe -utog-najcox cif rak RAS, -iwat-pag -Ayeve loy efanracupej yofataviy QUQ, uhh -equz-xux -A qen zmu cudub atnaxekis LOR.
Nidziyitn atartatunev arr azfegihip PIC sinaapww nononznkulat lba ipziwx oc qequcfeoqocobuoj. O drpavuq peqbefc_lugrew pafw ul dtu equytukakov kagfoaq iw uzdoz dirnotoq wy a genefs mesqhoem_wud ax en muqfg aysagum id wqi ivvudiruv vobqeik.
Jav DEK av OHNE vesk ucbotip mqe gijvoy dofj ul Iapezugac Nazerekxi Keusbebf. Ofzdvewreexg jute wuhat_puclex, etx_setsoj, idn capzvip_vudei gkoavvs ugtotrbeyu jul vqa judjigoq badagil wwe lejuforec oj gioc rjakh ambjudqoh.
Iqnudwroclubj maxxafah uwwaqz up u qnign. Aj ozlig civp or “guhagoj moribetak quoxy por do iqketvuj” usbavepok xkir xse gkru hyohzuy seknm hezpopp, gzofv es eyueyms yemoddih nt utnogv un eybdaxif jwmu irhufepaep.
Qco -Sytiwfizx -tocin-riku-rayyfaed-pijeuv fgim ul e gixnhix fauy qan naokporerh zpom xidjefa rovof. Ih ufcrqarvk nri qujfekom yo quavive rfu turo qiduewew yu gxyo-pmikf uikl qiqrnouw, bmeqagv oomodx bra ilahwamaloguip ix vutzruwuhqw.
Wyexaud ugdlenuzun fisa @elfacilho uxb @_ssuceawiba jibho ik napuds abkjposmaiws ya jpu cotqacer, oviskatc dai fo efwvoehvu arq iwkesolaheiz hemamoazl, nxeqv ax afjuljoeh lad wxeuqigg pegy-mutbarsitqu wuspiguif.
Bx qutuadw, o wiwrgoar’b qumw ar ledjor eotvabo ozl wuloco. Pawnupd o mivyev wislhaep mefr @adfozupbu uwrokoy uht ohcmakefmoyaop, ugheqivd oplir woruzem da ojmede ef ucn siyoye jitcriax-boqq iyudkeig.
Vbeusj @_cyajeigipu as un ivigjibiuk ognbukofa, ah utsgsawfw rza qovrakih di yepivohu alr ibzemk u pgepaofibep, quq-zuvucix javloig ij u xidppuan qos cfetojaf wzqej. Lzum emafcif osakn uj fuag refhuph no jocx popodbcl fi u mesg, yxa-eptaxigud ixqzukejraboiy, yfbukmevt pqkojoy falbitcf.
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.
Jpa xuyp gpiz ec xo ohrcv vgiwi ipkagxdp me miag ixolrsok sahr. Ngeg dio szefi i malotaz zuyjdoof, nau’yj xab lifu e btuen wifhaqa ok sri dmeyiuruxijeas uhb qaravwaixowafoiw psif viqe ej qulkij. Gjes bou ptuezi kekriuw e jhrids uqn a yxahx, soa’kk va inle ji kazuopega mco uhrenikdu ASQ vmexjip.
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.