1426d2b71SDavid du Colombier.HTML "Plan 9 C Compilers 2219b2ee8SDavid du Colombier.TL 3219b2ee8SDavid du ColombierPlan 9 C Compilers 4219b2ee8SDavid du Colombier.AU 5219b2ee8SDavid du ColombierKen Thompson 67dd7cddfSDavid du Colombierken@plan9.bell-labs.com 7219b2ee8SDavid du Colombier.AB 8219b2ee8SDavid du Colombier.FS 9219b2ee8SDavid du ColombierOriginally appeared, in a different form, in 10219b2ee8SDavid du Colombier.I 11219b2ee8SDavid du ColombierProceedings of the Summer 1990 UKUUG Conference, 12219b2ee8SDavid du Colombier.R 13219b2ee8SDavid du Colombierpp. 41-51, 14219b2ee8SDavid du ColombierLondon, 1990. 15219b2ee8SDavid du Colombier.FE 16219b2ee8SDavid du ColombierThis paper describes the overall structure and function of the Plan 9 C compilers. 17219b2ee8SDavid du ColombierA more detailed implementation document 18219b2ee8SDavid du Colombierfor any one of the compilers 19219b2ee8SDavid du Colombieris yet to be written. 20219b2ee8SDavid du Colombier.AE 21219b2ee8SDavid du Colombier.NH 22219b2ee8SDavid du ColombierIntroduction 23219b2ee8SDavid du Colombier.LP 247dd7cddfSDavid du ColombierThere are many compilers in the series. 25*82f6abeeSDavid du ColombierFive of the compilers (Intel 386, AMD64, PowerPC, PowerPC 64-bit, ARM) 26219b2ee8SDavid du Colombierare considered active and are used to compile 27219b2ee8SDavid du Colombiercurrent versions of Plan 9. 28*82f6abeeSDavid du ColombierFour of the compilers (MIPS 3000, SPARC, DEC Alpha, and Motorola 68020) 29*82f6abeeSDavid du Colombierare maintained but are for older machines 30*82f6abeeSDavid du Colombierfor which we have no current ports of Plan 9; 31*82f6abeeSDavid du Colombierother than the MIPS, we are unlikely to port to any such machines. 32*82f6abeeSDavid du ColombierSeveral others (Motorola 68000, Intel 960, AMD 29000) have had only limited use, such as 337dd7cddfSDavid du Colombierto program peripherals or experimental devices. 34219b2ee8SDavid du Colombier.NH 35219b2ee8SDavid du ColombierStructure 36219b2ee8SDavid du Colombier.LP 37219b2ee8SDavid du ColombierThe compiler is a single program that produces an 38219b2ee8SDavid du Colombierobject file. 39219b2ee8SDavid du ColombierCombined in the compiler are the traditional 40219b2ee8SDavid du Colombierroles of preprocessor, lexical analyzer, parser, code generator, 41219b2ee8SDavid du Colombierlocal optimizer, 42219b2ee8SDavid du Colombierand first half of the assembler. 43219b2ee8SDavid du ColombierThe object files are binary forms of assembly 44219b2ee8SDavid du Colombierlanguage, 45219b2ee8SDavid du Colombiersimilar to what might be passed between 46219b2ee8SDavid du Colombierthe first and second passes of an assembler. 47219b2ee8SDavid du Colombier.LP 48219b2ee8SDavid du ColombierObject files and libraries 49219b2ee8SDavid du Colombierare combined by a loader 50219b2ee8SDavid du Colombierprogram to produce the executable binary. 51219b2ee8SDavid du ColombierThe loader combines the roles of second half 52219b2ee8SDavid du Colombierof the assembler, global optimizer, and loader. 53219b2ee8SDavid du ColombierThe names of the compliers, loaders, and assemblers 54219b2ee8SDavid du Colombierare as follows: 55219b2ee8SDavid du Colombier.DS 56219b2ee8SDavid du Colombier.ta 1.5i 57219b2ee8SDavid du Colombier.de Ta 58219b2ee8SDavid du Colombier\\$1 \f(CW\\$2\fP \f(CW\\$3\fP \f(CW\\$4\fP 59219b2ee8SDavid du Colombier.. 60219b2ee8SDavid du Colombier.Ta SPARC kc kl ka 61*82f6abeeSDavid du Colombier.Ta PowerPC qc ql qa 627dd7cddfSDavid du Colombier.Ta MIPS vc vl va 63*82f6abeeSDavid du Colombier.Ta MIPS\ little-endian 0c 0l 0a 647dd7cddfSDavid du Colombier.Ta Motorola\ 68000 1c 1l 1a 65219b2ee8SDavid du Colombier.Ta Motorola\ 68020 2c 2l 2a 66*82f6abeeSDavid du Colombier.Ta ARM 5c 5l 5a 67*82f6abeeSDavid du Colombier.Ta AMD64 6c 6l 6a 687dd7cddfSDavid du Colombier.Ta DEC\ Alpha 7c 7l 7a 697dd7cddfSDavid du Colombier.Ta Intel\ 386 8c 8l 8a 70*82f6abeeSDavid du Colombier.Ta PowerPC\ 64-bit 9c 9l 9a 71219b2ee8SDavid du Colombier.DE 72219b2ee8SDavid du ColombierThere is a further breakdown 73219b2ee8SDavid du Colombierin the source of the compilers into 74219b2ee8SDavid du Colombierobject-independent and 75219b2ee8SDavid du Colombierobject-dependent 76219b2ee8SDavid du Colombierparts. 77219b2ee8SDavid du ColombierAll of the object-independent parts 78219b2ee8SDavid du Colombierare combined into source files in the 79219b2ee8SDavid du Colombierdirectory 80219b2ee8SDavid du Colombier.CW /sys/src/cmd/cc . 81219b2ee8SDavid du ColombierThe object-dependent parts are collected 82219b2ee8SDavid du Colombierin a separate directory for each compiler, 83219b2ee8SDavid du Colombierfor example 84219b2ee8SDavid du Colombier.CW /sys/src/cmd/vc . 85219b2ee8SDavid du ColombierAll of the code, 86219b2ee8SDavid du Colombierboth object-independent and 87219b2ee8SDavid du Colombierobject-dependent, 88219b2ee8SDavid du Colombieris machine-independent 89219b2ee8SDavid du Colombierand may be cross-compiled and executed on any 90219b2ee8SDavid du Colombierof the architectures. 91219b2ee8SDavid du Colombier.NH 92219b2ee8SDavid du ColombierThe Language 93219b2ee8SDavid du Colombier.LP 94219b2ee8SDavid du ColombierThe compiler implements ANSI C with some 95219b2ee8SDavid du Colombierrestrictions and extensions 96219b2ee8SDavid du Colombier[ANSI90]. 97219b2ee8SDavid du ColombierMost of the restrictions are due to 98219b2ee8SDavid du Colombierpersonal preference, while 99219b2ee8SDavid du Colombiermost of the extensions were to help in 100219b2ee8SDavid du Colombierthe implementation of Plan 9. 101219b2ee8SDavid du ColombierThere are other departures from the standard, 102219b2ee8SDavid du Colombierparticularly in the libraries, 103219b2ee8SDavid du Colombierthat are beyond the scope of this 104219b2ee8SDavid du Colombierpaper. 105219b2ee8SDavid du Colombier.NH 2 106219b2ee8SDavid du ColombierRegister, volatile, const 107219b2ee8SDavid du Colombier.LP 1087dd7cddfSDavid du ColombierThe keyword 1097dd7cddfSDavid du Colombier.CW register 1107dd7cddfSDavid du Colombieris recognized syntactically 1117dd7cddfSDavid du Colombierbut is semantically ignored. 1127dd7cddfSDavid du ColombierThus taking the address of a 1137dd7cddfSDavid du Colombier.CW register 1147dd7cddfSDavid du Colombiervariable is not diagnosed. 1157dd7cddfSDavid du ColombierThe keyword 1167dd7cddfSDavid du Colombier.CW volatile 1177dd7cddfSDavid du Colombierdisables all optimizations, in particular registerization, of the corresponding variable. 1187dd7cddfSDavid du ColombierThe keyword 119219b2ee8SDavid du Colombier.CW const 1207dd7cddfSDavid du Colombiergenerates warnings (if warnings are enabled by the compiler's 1217dd7cddfSDavid du Colombier.CW -w 1227dd7cddfSDavid du Colombieroption) of non-constant use of the variable, 1237dd7cddfSDavid du Colombierbut does not affect the generated code. 124219b2ee8SDavid du Colombier.NH 2 125219b2ee8SDavid du ColombierThe preprocessor 126219b2ee8SDavid du Colombier.LP 127219b2ee8SDavid du ColombierThe C preprocessor is probably the 128219b2ee8SDavid du Colombierbiggest departure from the ANSI standard. 129219b2ee8SDavid du Colombier.LP 130219b2ee8SDavid du ColombierThe preprocessor built into the Plan 9 compilers does not support 131219b2ee8SDavid du Colombier.CW #if , 132219b2ee8SDavid du Colombieralthough it does handle 133219b2ee8SDavid du Colombier.CW #ifdef 134219b2ee8SDavid du Colombierand 135219b2ee8SDavid du Colombier.CW #include . 136219b2ee8SDavid du ColombierIf it is necessary to be more standard, 137219b2ee8SDavid du Colombierthe source text can first be run through the separate ANSI C 138219b2ee8SDavid du Colombierpreprocessor, 139219b2ee8SDavid du Colombier.CW cpp . 140219b2ee8SDavid du Colombier.NH 2 141219b2ee8SDavid du ColombierUnnamed substructures 142219b2ee8SDavid du Colombier.LP 143219b2ee8SDavid du ColombierThe most important and most heavily used of the 144219b2ee8SDavid du Colombierextensions is the declaration of an 145219b2ee8SDavid du Colombierunnamed substructure or subunion. 146219b2ee8SDavid du ColombierFor example: 147219b2ee8SDavid du Colombier.DS 148219b2ee8SDavid du Colombier.CW 149219b2ee8SDavid du Colombier.ta .1i .6i 1.1i 1.6i 150219b2ee8SDavid du Colombier typedef 151219b2ee8SDavid du Colombier struct lock 152219b2ee8SDavid du Colombier { 153219b2ee8SDavid du Colombier int locked; 154219b2ee8SDavid du Colombier } Lock; 155219b2ee8SDavid du Colombier 156219b2ee8SDavid du Colombier typedef 157219b2ee8SDavid du Colombier struct node 158219b2ee8SDavid du Colombier { 159219b2ee8SDavid du Colombier int type; 160219b2ee8SDavid du Colombier union 161219b2ee8SDavid du Colombier { 162219b2ee8SDavid du Colombier double dval; 163219b2ee8SDavid du Colombier float fval; 164219b2ee8SDavid du Colombier long lval; 165219b2ee8SDavid du Colombier }; 166219b2ee8SDavid du Colombier Lock; 167219b2ee8SDavid du Colombier } Node; 168219b2ee8SDavid du Colombier 169219b2ee8SDavid du Colombier Lock* lock; 170219b2ee8SDavid du Colombier Node* node; 171219b2ee8SDavid du Colombier.DE 172219b2ee8SDavid du ColombierThe declaration of 173219b2ee8SDavid du Colombier.CW Node 174219b2ee8SDavid du Colombierhas an unnamed substructure of type 175219b2ee8SDavid du Colombier.CW Lock 176219b2ee8SDavid du Colombierand an unnamed subunion. 177219b2ee8SDavid du ColombierOne use of this feature allows references to elements of the 178219b2ee8SDavid du Colombiersubunit to be accessed as if they were in 179219b2ee8SDavid du Colombierthe outer structure. 180219b2ee8SDavid du ColombierThus 181219b2ee8SDavid du Colombier.CW node->dval 182219b2ee8SDavid du Colombierand 183219b2ee8SDavid du Colombier.CW node->locked 184219b2ee8SDavid du Colombierare legitimate references. 185219b2ee8SDavid du Colombier.LP 186219b2ee8SDavid du ColombierWhen an outer structure is used 187219b2ee8SDavid du Colombierin a context that is only legal for 188219b2ee8SDavid du Colombieran unnamed substructure, 189219b2ee8SDavid du Colombierthe compiler promotes the reference to the 190219b2ee8SDavid du Colombierunnamed substructure. 191219b2ee8SDavid du ColombierThis is true for references to structures and 192219b2ee8SDavid du Colombierto references to pointers to structures. 193219b2ee8SDavid du ColombierThis happens in assignment statements and 194219b2ee8SDavid du Colombierin argument passing where prototypes have been 195219b2ee8SDavid du Colombierdeclared. 196219b2ee8SDavid du ColombierThus, continuing with the example, 197219b2ee8SDavid du Colombier.DS 198219b2ee8SDavid du Colombier.CW 199219b2ee8SDavid du Colombier.ta .1i .6i 1.1i 1.6i 200219b2ee8SDavid du Colombier lock = node; 201219b2ee8SDavid du Colombier.DE 202219b2ee8SDavid du Colombierwould assign a pointer to the unnamed 203219b2ee8SDavid du Colombier.CW Lock 204219b2ee8SDavid du Colombierin 205219b2ee8SDavid du Colombierthe 206219b2ee8SDavid du Colombier.CW Node 207219b2ee8SDavid du Colombierto the variable 208219b2ee8SDavid du Colombier.CW lock . 209219b2ee8SDavid du ColombierAnother example, 210219b2ee8SDavid du Colombier.DS 211219b2ee8SDavid du Colombier.CW 212219b2ee8SDavid du Colombier.ta .1i .6i 1.1i 1.6i 213219b2ee8SDavid du Colombier extern void lock(Lock*); 214219b2ee8SDavid du Colombier func(...) 215219b2ee8SDavid du Colombier { 216219b2ee8SDavid du Colombier ... 217219b2ee8SDavid du Colombier lock(node); 218219b2ee8SDavid du Colombier ... 219219b2ee8SDavid du Colombier } 220219b2ee8SDavid du Colombier.DE 221219b2ee8SDavid du Colombierwill pass a pointer to the 222219b2ee8SDavid du Colombier.CW Lock 223219b2ee8SDavid du Colombiersubstructure. 2247dd7cddfSDavid du Colombier.LP 2257dd7cddfSDavid du ColombierFinally, in places where context is insufficient to identify the unnamed structure, 2267dd7cddfSDavid du Colombierthe type name (it must be a 2277dd7cddfSDavid du Colombier.CW typedef ) 2287dd7cddfSDavid du Colombierof the unnamed structure can be used as an identifier. 2297dd7cddfSDavid du ColombierIn our example, 2307dd7cddfSDavid du Colombier.CW &node->Lock 2317dd7cddfSDavid du Colombiergives the address of the anonymous 2327dd7cddfSDavid du Colombier.CW Lock 2337dd7cddfSDavid du Colombierstructure. 234219b2ee8SDavid du Colombier.NH 2 235219b2ee8SDavid du ColombierStructure displays 236219b2ee8SDavid du Colombier.LP 237219b2ee8SDavid du ColombierA structure cast followed by a list of expressions in braces is 238219b2ee8SDavid du Colombieran expression with the type of the structure and elements assigned from 239219b2ee8SDavid du Colombierthe corresponding list. 240219b2ee8SDavid du ColombierStructures are now almost first-class citizens of the language. 241219b2ee8SDavid du ColombierIt is common to see code like this: 242219b2ee8SDavid du Colombier.DS 243219b2ee8SDavid du Colombier.CW 244219b2ee8SDavid du Colombier.ta .1i 245219b2ee8SDavid du Colombier r = (Rectangle){point1, (Point){x,y+2}}; 246219b2ee8SDavid du Colombier.DE 247219b2ee8SDavid du Colombier.NH 2 248219b2ee8SDavid du ColombierInitialization indexes 249219b2ee8SDavid du Colombier.LP 250219b2ee8SDavid du ColombierIn initializers of arrays, 251219b2ee8SDavid du Colombierone may place a constant expression 252219b2ee8SDavid du Colombierin square brackets before an initializer. 253219b2ee8SDavid du ColombierThis causes the next initializer to assign 254219b2ee8SDavid du Colombierthe indicated element. 255219b2ee8SDavid du ColombierFor example: 256219b2ee8SDavid du Colombier.DS 257219b2ee8SDavid du Colombier.CW 258219b2ee8SDavid du Colombier.ta .1i .6i 1.6i 259219b2ee8SDavid du Colombier enum errors 260219b2ee8SDavid du Colombier { 261219b2ee8SDavid du Colombier Etoobig, 262219b2ee8SDavid du Colombier Ealarm, 263219b2ee8SDavid du Colombier Egreg 264219b2ee8SDavid du Colombier }; 265219b2ee8SDavid du Colombier char* errstrings[] = 266219b2ee8SDavid du Colombier { 267219b2ee8SDavid du Colombier [Ealarm] "Alarm call", 268219b2ee8SDavid du Colombier [Egreg] "Panic: out of mbufs", 269219b2ee8SDavid du Colombier [Etoobig] "Arg list too long", 270219b2ee8SDavid du Colombier }; 271219b2ee8SDavid du Colombier.DE 272219b2ee8SDavid du ColombierIn the same way, 273219b2ee8SDavid du Colombierindividual structures members may 274219b2ee8SDavid du Colombierbe initialized in any order by preceding the initialization with 275219b2ee8SDavid du Colombier.CW .tagname . 276219b2ee8SDavid du ColombierBoth forms allow an optional 277219b2ee8SDavid du Colombier.CW = , 278219b2ee8SDavid du Colombierto be compatible with a proposed 279219b2ee8SDavid du Colombierextension to ANSI C. 280219b2ee8SDavid du Colombier.NH 2 281219b2ee8SDavid du ColombierExternal register 282219b2ee8SDavid du Colombier.LP 283219b2ee8SDavid du ColombierThe declaration 284219b2ee8SDavid du Colombier.CW extern 285219b2ee8SDavid du Colombier.CW register 286219b2ee8SDavid du Colombierwill dedicate a register to 287219b2ee8SDavid du Colombiera variable on a global basis. 288219b2ee8SDavid du ColombierIt can be used only under special circumstances. 289219b2ee8SDavid du ColombierExternal register variables must be identically 290219b2ee8SDavid du Colombierdeclared in all modules and 291219b2ee8SDavid du Colombierlibraries. 292219b2ee8SDavid du ColombierThe feature is not intended for efficiency, 293219b2ee8SDavid du Colombieralthough it can produce efficient code; 294219b2ee8SDavid du Colombierrather it represents a unique storage class that 295219b2ee8SDavid du Colombierwould be hard to get any other way. 296219b2ee8SDavid du ColombierOn a shared-memory multi-processor, 297219b2ee8SDavid du Colombieran external register is 298219b2ee8SDavid du Colombierone-per-processor and neither one-per-procedure (automatic) 299219b2ee8SDavid du Colombieror one-per-system (external). 300219b2ee8SDavid du ColombierIt is used for two variables in the Plan 9 kernel, 301219b2ee8SDavid du Colombier.CW u 302219b2ee8SDavid du Colombierand 303219b2ee8SDavid du Colombier.CW m . 304219b2ee8SDavid du Colombier.CW U 305219b2ee8SDavid du Colombieris a pointer to the structure representing the currently running process 306219b2ee8SDavid du Colombierand 307219b2ee8SDavid du Colombier.CW m 308219b2ee8SDavid du Colombieris a pointer to the per-machine data structure. 309219b2ee8SDavid du Colombier.NH 2 310219b2ee8SDavid du ColombierLong long 311219b2ee8SDavid du Colombier.LP 312219b2ee8SDavid du ColombierThe compilers accept 313219b2ee8SDavid du Colombier.CW long 314219b2ee8SDavid du Colombier.CW long 315219b2ee8SDavid du Colombieras a basic type meaning 64-bit integer. 316219b2ee8SDavid du ColombierOn all of the machines 317219b2ee8SDavid du Colombierthis type is synthesized from 32-bit instructions. 318219b2ee8SDavid du Colombier.NH 2 319219b2ee8SDavid du ColombierPragma 320219b2ee8SDavid du Colombier.LP 321219b2ee8SDavid du ColombierThe compilers accept 322219b2ee8SDavid du Colombier.CW #pragma 323219b2ee8SDavid du Colombier.CW lib 324219b2ee8SDavid du Colombier.I libname 325219b2ee8SDavid du Colombierand pass the 326219b2ee8SDavid du Colombierlibrary name string uninterpreted 327219b2ee8SDavid du Colombierto the loader. 328219b2ee8SDavid du ColombierThe loader uses the library name to 329219b2ee8SDavid du Colombierfind libraries to load. 330219b2ee8SDavid du ColombierIf the name contains 331*82f6abeeSDavid du Colombier.CW $O , 332219b2ee8SDavid du Colombierit is replaced with 333219b2ee8SDavid du Colombierthe single character object type of the compiler 334219b2ee8SDavid du Colombier(e.g., 335219b2ee8SDavid du Colombier.CW v 336219b2ee8SDavid du Colombierfor the MIPS). 337219b2ee8SDavid du ColombierIf the name contains 338*82f6abeeSDavid du Colombier.CW $M , 339219b2ee8SDavid du Colombierit is replaced with 340219b2ee8SDavid du Colombierthe architecture type for the compiler 341219b2ee8SDavid du Colombier(e.g., 342219b2ee8SDavid du Colombier.CW mips 343219b2ee8SDavid du Colombierfor the MIPS). 344219b2ee8SDavid du ColombierIf the name starts with 345219b2ee8SDavid du Colombier.CW / 346219b2ee8SDavid du Colombierit is an absolute pathname; 347219b2ee8SDavid du Colombierif it starts with 348219b2ee8SDavid du Colombier.CW . 349219b2ee8SDavid du Colombierthen it is searched for in the loader's current directory. 350219b2ee8SDavid du ColombierOtherwise, the name is searched from 351*82f6abeeSDavid du Colombier.CW /$M/lib . 352219b2ee8SDavid du ColombierSuch 353219b2ee8SDavid du Colombier.CW #pragma 354219b2ee8SDavid du Colombierstatements in header files guarantee that the correct 355219b2ee8SDavid du Colombierlibraries are always linked with a program without the 356219b2ee8SDavid du Colombierneed to specify them explicitly at link time. 3577dd7cddfSDavid du Colombier.LP 3587dd7cddfSDavid du ColombierThey also accept 3597dd7cddfSDavid du Colombier.CW #pragma 360*82f6abeeSDavid du Colombier.CW packed 3617dd7cddfSDavid du Colombier.CW on 3627dd7cddfSDavid du Colombier(or 3637dd7cddfSDavid du Colombier.CW yes 3647dd7cddfSDavid du Colombieror 3657dd7cddfSDavid du Colombier.CW 1 ) 3667dd7cddfSDavid du Colombierto cause subsequently declared data, until 3677dd7cddfSDavid du Colombier.CW #pragma 368*82f6abeeSDavid du Colombier.CW packed 3697dd7cddfSDavid du Colombier.CW off 3707dd7cddfSDavid du Colombier(or 3717dd7cddfSDavid du Colombier.CW no 3727dd7cddfSDavid du Colombieror 3737dd7cddfSDavid du Colombier.CW 0 ), 3747dd7cddfSDavid du Colombierto be laid out in memory tightly packed in successive bytes, disregarding 3757dd7cddfSDavid du Colombierthe usual alignment rules. 3767dd7cddfSDavid du ColombierAccessing such data can cause faults. 3777dd7cddfSDavid du Colombier.LP 378e288d156SDavid du ColombierSimilarly, 379e288d156SDavid du Colombier.CW #pragma 380e288d156SDavid du Colombier.CW profile 381e288d156SDavid du Colombier.CW off 382e288d156SDavid du Colombier(or 383e288d156SDavid du Colombier.CW no 384e288d156SDavid du Colombieror 385e288d156SDavid du Colombier.CW 0 ) 386e288d156SDavid du Colombiercauses subsequently declared functions, until 387e288d156SDavid du Colombier.CW #pragma 388e288d156SDavid du Colombier.CW profile 389e288d156SDavid du Colombier.CW on 390e288d156SDavid du Colombier(or 391e288d156SDavid du Colombier.CW yes 392e288d156SDavid du Colombieror 393e288d156SDavid du Colombier.CW 1 ), 394e288d156SDavid du Colombierto be marked as unprofiled. 395e288d156SDavid du ColombierSuch functions will not be profiled when 396e288d156SDavid du Colombierprofiling is enabled for the rest of the program. 397e288d156SDavid du Colombier.LP 3987dd7cddfSDavid du ColombierTwo 3997dd7cddfSDavid du Colombier.CW #pragma 4007dd7cddfSDavid du Colombierstatements allow type-checking of 4017dd7cddfSDavid du Colombier.CW print -like 4027dd7cddfSDavid du Colombierfunctions. 4037dd7cddfSDavid du ColombierThe first, of the form 4047dd7cddfSDavid du Colombier.P1 4057dd7cddfSDavid du Colombier#pragma varargck argpos error 2 4067dd7cddfSDavid du Colombier.P2 4077dd7cddfSDavid du Colombiertells the compiler that the second argument to 4087dd7cddfSDavid du Colombier.CW error 4097dd7cddfSDavid du Colombieris a 4107dd7cddfSDavid du Colombier.CW print 4117dd7cddfSDavid du Colombierformat string (see the manual page 4127dd7cddfSDavid du Colombier.I print (2)) 4137dd7cddfSDavid du Colombierthat specifies how to format 4147dd7cddfSDavid du Colombier.CW error 's 4157dd7cddfSDavid du Colombiersubsequent arguments. 4167dd7cddfSDavid du ColombierThe second, of the form 4177dd7cddfSDavid du Colombier.P1 4187dd7cddfSDavid du Colombier#pragma varargck type "s" char* 4197dd7cddfSDavid du Colombier.P2 4207dd7cddfSDavid du Colombiersays that the 4217dd7cddfSDavid du Colombier.CW print 4227dd7cddfSDavid du Colombierformat verb 4237dd7cddfSDavid du Colombier.CW s 4247dd7cddfSDavid du Colombierprocesses an argument of 4257dd7cddfSDavid du Colombiertype 4267dd7cddfSDavid du Colombier.CW char* . 4277dd7cddfSDavid du ColombierIf the compiler's 4287dd7cddfSDavid du Colombier.CW -F 4297dd7cddfSDavid du Colombieroption is enabled, the compiler will use this information 4307dd7cddfSDavid du Colombierto report type violations in the arguments to 4317dd7cddfSDavid du Colombier.CW print , 4327dd7cddfSDavid du Colombier.CW error , 4337dd7cddfSDavid du Colombierand similar routines. 434219b2ee8SDavid du Colombier.NH 435219b2ee8SDavid du ColombierObject module conventions 436219b2ee8SDavid du Colombier.LP 437219b2ee8SDavid du ColombierThe overall conventions of the runtime environment 438219b2ee8SDavid du Colombierare important 439219b2ee8SDavid du Colombierto runtime efficiency. 440219b2ee8SDavid du ColombierIn this section, 441219b2ee8SDavid du Colombierseveral of these conventions are discussed. 442219b2ee8SDavid du Colombier.NH 2 443219b2ee8SDavid du ColombierRegister saving 444219b2ee8SDavid du Colombier.LP 445219b2ee8SDavid du ColombierIn the Plan 9 compilers, 446219b2ee8SDavid du Colombierthe caller of a procedure saves the registers. 447219b2ee8SDavid du ColombierWith caller-saves, 448219b2ee8SDavid du Colombierthe leaf procedures can use all the 449219b2ee8SDavid du Colombierregisters and never save them. 450219b2ee8SDavid du ColombierIf you spend a lot of time at the leaves, 451219b2ee8SDavid du Colombierthis seems preferable. 452219b2ee8SDavid du ColombierWith callee-saves, 453219b2ee8SDavid du Colombierthe saving of the registers is done 454219b2ee8SDavid du Colombierin the single point of entry and return. 455219b2ee8SDavid du ColombierIf you are interested in space, 456219b2ee8SDavid du Colombierthis seems preferable. 457219b2ee8SDavid du ColombierIn both, 458219b2ee8SDavid du Colombierthere is a degree of uncertainty 459219b2ee8SDavid du Colombierabout what registers need to be saved. 460219b2ee8SDavid du ColombierCallee-saved registers make it difficult to 461219b2ee8SDavid du Colombierfind variables in registers in debuggers. 462219b2ee8SDavid du ColombierCallee-saved registers also complicate 463219b2ee8SDavid du Colombierthe implementation of 464219b2ee8SDavid du Colombier.CW longjmp . 465219b2ee8SDavid du ColombierThe convincing argument is 466219b2ee8SDavid du Colombierthat with caller-saves, 467219b2ee8SDavid du Colombierthe decision to registerize a variable 468219b2ee8SDavid du Colombiercan include the cost of saving the register 469219b2ee8SDavid du Colombieracross calls. 470219b2ee8SDavid du ColombierFor a further discussion of caller- vs. callee-saves, 471219b2ee8SDavid du Colombiersee the paper by Davidson and Whalley [Dav91]. 472219b2ee8SDavid du Colombier.LP 473219b2ee8SDavid du ColombierIn the Plan 9 operating system, 474219b2ee8SDavid du Colombiercalls to the kernel look like normal procedure 475219b2ee8SDavid du Colombiercalls, which means 476219b2ee8SDavid du Colombierthe caller 477219b2ee8SDavid du Colombierhas saved the registers and the system 478219b2ee8SDavid du Colombierentry does not have to. 479219b2ee8SDavid du ColombierThis makes system calls considerably faster. 480219b2ee8SDavid du ColombierSince this is a potential security hole, 481219b2ee8SDavid du Colombierand can lead to non-determinism, 482219b2ee8SDavid du Colombierthe system may eventually save the registers 483219b2ee8SDavid du Colombieron entry, 484219b2ee8SDavid du Colombieror more likely clear the registers on return. 485219b2ee8SDavid du Colombier.NH 2 486219b2ee8SDavid du ColombierCalling convention 487219b2ee8SDavid du Colombier.LP 488219b2ee8SDavid du ColombierOlder C compilers maintain a frame pointer, which is at a known constant 489219b2ee8SDavid du Colombieroffset from the stack pointer within each function. 490219b2ee8SDavid du ColombierFor machines where the stack grows towards zero, 491219b2ee8SDavid du Colombierthe argument pointer is at a known constant offset 492219b2ee8SDavid du Colombierfrom the frame pointer. 493219b2ee8SDavid du ColombierSince the stack grows down in Plan 9, 494219b2ee8SDavid du Colombierthe Plan 9 compilers 495219b2ee8SDavid du Colombierkeep neither an 496219b2ee8SDavid du Colombierexplicit frame pointer nor 497219b2ee8SDavid du Colombieran explicit argument pointer; 498219b2ee8SDavid du Colombierinstead they generate addresses relative to the stack pointer. 499219b2ee8SDavid du Colombier.LP 500219b2ee8SDavid du ColombierOn some architectures, the first argument to a subroutine is passed in a register. 501219b2ee8SDavid du Colombier.NH 2 502219b2ee8SDavid du ColombierFunctions returning structures 503219b2ee8SDavid du Colombier.LP 504219b2ee8SDavid du ColombierStructures longer than one word are awkward to implement 505219b2ee8SDavid du Colombiersince they do not fit in registers and must 506219b2ee8SDavid du Colombierbe passed around in memory. 507219b2ee8SDavid du ColombierFunctions that return structures 508219b2ee8SDavid du Colombierare particularly clumsy. 509219b2ee8SDavid du ColombierThe Plan 9 compilers pass the return address of 510219b2ee8SDavid du Colombiera structure as the first argument of a 511219b2ee8SDavid du Colombierfunction that has a structure return value. 512219b2ee8SDavid du ColombierThus 513219b2ee8SDavid du Colombier.DS 514219b2ee8SDavid du Colombier.CW 515219b2ee8SDavid du Colombier.ta .1i .6i 1.1i 1.6i 516219b2ee8SDavid du Colombier x = f(...) 517219b2ee8SDavid du Colombier.DE 518219b2ee8SDavid du Colombieris rewritten as 519219b2ee8SDavid du Colombier.DS 520219b2ee8SDavid du Colombier.CW 521219b2ee8SDavid du Colombier.ta .1i .6i 1.1i 1.6i 522219b2ee8SDavid du Colombier f(&x, ...)\f1. 523219b2ee8SDavid du Colombier.DE 524219b2ee8SDavid du ColombierThis saves a copy and makes the compilation 525219b2ee8SDavid du Colombiermuch less clumsy. 526219b2ee8SDavid du ColombierA disadvantage is that if you call this 527219b2ee8SDavid du Colombierfunction without an assignment, 528219b2ee8SDavid du Colombiera dummy location must be invented. 529219b2ee8SDavid du Colombier.LP 530219b2ee8SDavid du ColombierThere is also a danger of calling a function 531219b2ee8SDavid du Colombierthat returns a structure without declaring 532219b2ee8SDavid du Colombierit as such. 533219b2ee8SDavid du ColombierWith ANSI C function prototypes, 534219b2ee8SDavid du Colombierthis error need never occur. 535219b2ee8SDavid du Colombier.NH 536219b2ee8SDavid du ColombierImplementation 537219b2ee8SDavid du Colombier.LP 538219b2ee8SDavid du ColombierThe compiler is divided internally into 539219b2ee8SDavid du Colombierfour machine-independent passes, 540219b2ee8SDavid du Colombierfour machine-dependent passes, 541219b2ee8SDavid du Colombierand an output pass. 542219b2ee8SDavid du ColombierThe next nine sections describe each pass in order. 543219b2ee8SDavid du Colombier.NH 2 544219b2ee8SDavid du ColombierParsing 545219b2ee8SDavid du Colombier.LP 546219b2ee8SDavid du ColombierThe first pass is a YACC-based parser 547219b2ee8SDavid du Colombier[Joh79]. 548219b2ee8SDavid du ColombierDeclarations are interpreted immediately, 549219b2ee8SDavid du Colombierbuilding a block structured symbol table. 550219b2ee8SDavid du ColombierExecutable statements are put into a parse tree 551219b2ee8SDavid du Colombierand collected, 552219b2ee8SDavid du Colombierwithout interpretation. 553219b2ee8SDavid du ColombierAt the end of each procedure, 554219b2ee8SDavid du Colombierthe parse tree for the function is 555219b2ee8SDavid du Colombierexamined by the other passes of the compiler. 556219b2ee8SDavid du Colombier.LP 557219b2ee8SDavid du ColombierThe input stream of the parser is 558219b2ee8SDavid du Colombiera pushdown list of input activations. 559219b2ee8SDavid du ColombierThe preprocessor 560219b2ee8SDavid du Colombierexpansions of 561219b2ee8SDavid du Colombiermacros 562219b2ee8SDavid du Colombierand 563219b2ee8SDavid du Colombier.CW #include 564219b2ee8SDavid du Colombierare implemented as pushdowns. 565219b2ee8SDavid du ColombierThus there is no separate 566219b2ee8SDavid du Colombierpass for preprocessing. 567219b2ee8SDavid du Colombier.NH 2 568219b2ee8SDavid du ColombierTyping 569219b2ee8SDavid du Colombier.LP 570219b2ee8SDavid du ColombierThe next pass distributes typing information 571219b2ee8SDavid du Colombierto every node of the tree. 572219b2ee8SDavid du ColombierImplicit operations on the tree are added, 573219b2ee8SDavid du Colombiersuch as type promotions and taking the 574219b2ee8SDavid du Colombieraddress of arrays and functions. 575219b2ee8SDavid du Colombier.NH 2 576219b2ee8SDavid du ColombierMachine-independent optimization 577219b2ee8SDavid du Colombier.LP 578219b2ee8SDavid du ColombierThe next pass performs optimizations 579219b2ee8SDavid du Colombierand transformations of the tree, such as converting 580219b2ee8SDavid du Colombier.CW &*x 581219b2ee8SDavid du Colombierand 582219b2ee8SDavid du Colombier.CW *&x 583219b2ee8SDavid du Colombierinto 584219b2ee8SDavid du Colombier.CW x . 585219b2ee8SDavid du ColombierConstant expressions are converted to constants in this pass. 586219b2ee8SDavid du Colombier.NH 2 587219b2ee8SDavid du ColombierArithmetic rewrites 588219b2ee8SDavid du Colombier.LP 589219b2ee8SDavid du ColombierThis is another machine-independent optimization. 590219b2ee8SDavid du ColombierSubtrees of add, subtract, and multiply of integers are 591219b2ee8SDavid du Colombierrewritten for easier compilation. 592219b2ee8SDavid du ColombierThe major transformation is factoring: 593219b2ee8SDavid du Colombier.CW 4+8*a+16*b+5 594219b2ee8SDavid du Colombieris transformed into 595219b2ee8SDavid du Colombier.CW 9+8*(a+2*b) . 596219b2ee8SDavid du ColombierSuch expressions arise from address 597219b2ee8SDavid du Colombiermanipulation and array indexing. 598219b2ee8SDavid du Colombier.NH 2 599219b2ee8SDavid du ColombierAddressability 600219b2ee8SDavid du Colombier.LP 601219b2ee8SDavid du ColombierThis is the first of the machine-dependent passes. 602219b2ee8SDavid du ColombierThe addressability of a processor is defined as the set of 603219b2ee8SDavid du Colombierexpressions that is legal in the address field 604219b2ee8SDavid du Colombierof a machine language instruction. 605219b2ee8SDavid du ColombierThe addressability of different processors varies widely. 606219b2ee8SDavid du ColombierAt one end of the spectrum are the 68020 and VAX, 607219b2ee8SDavid du Colombierwhich allow a complex mix of incrementing, 608219b2ee8SDavid du Colombierdecrementing, 609219b2ee8SDavid du Colombierindexing, and relative addressing. 610219b2ee8SDavid du ColombierAt the other end is the MIPS, 611219b2ee8SDavid du Colombierwhich allows only registers and constant offsets from the 612219b2ee8SDavid du Colombiercontents of a register. 613219b2ee8SDavid du ColombierThe addressability can be different for different instructions 614219b2ee8SDavid du Colombierwithin the same processor. 615219b2ee8SDavid du Colombier.LP 616219b2ee8SDavid du ColombierIt is important to the code generator to know when a 617219b2ee8SDavid du Colombiersubtree represents an address of a particular type. 618219b2ee8SDavid du ColombierThis is done with a bottom-up walk of the tree. 619219b2ee8SDavid du ColombierIn this pass, the leaves are labeled with small integers. 620219b2ee8SDavid du ColombierWhen an internal node is encountered, 621219b2ee8SDavid du Colombierit is labeled by consulting a table indexed by the 622219b2ee8SDavid du Colombierlabels on the left and right subtrees. 623219b2ee8SDavid du ColombierFor example, 624219b2ee8SDavid du Colombieron the 68020 processor, 625219b2ee8SDavid du Colombierit is possible to address an 626219b2ee8SDavid du Colombieroffset from a named location. 627219b2ee8SDavid du ColombierIn C, this is represented by the expression 628219b2ee8SDavid du Colombier.CW *(&name+constant) . 629219b2ee8SDavid du ColombierThis is marked addressable by the following table. 630219b2ee8SDavid du ColombierIn the table, 631219b2ee8SDavid du Colombiera node represented by the left column is marked 632219b2ee8SDavid du Colombierwith a small integer from the right column. 633219b2ee8SDavid du ColombierMarks of the form 634219b2ee8SDavid du Colombier.CW A\s-2\di\u\s0 635219b2ee8SDavid du Colombierare addressable while 636219b2ee8SDavid du Colombiermarks of the form 637219b2ee8SDavid du Colombier.CW N\s-2\di\u\s0 638219b2ee8SDavid du Colombierare not addressable. 639219b2ee8SDavid du Colombier.DS 640219b2ee8SDavid du Colombier.B 641219b2ee8SDavid du Colombier.ta .1i 1.1i 642219b2ee8SDavid du Colombier Node Marked 643219b2ee8SDavid du Colombier.CW 644219b2ee8SDavid du Colombier name A\s-2\d1\u\s0 645219b2ee8SDavid du Colombier const A\s-2\d2\u\s0 646219b2ee8SDavid du Colombier &A\s-2\d1\u\s0 A\s-2\d3\u\s0 647219b2ee8SDavid du Colombier A\s-2\d3\u\s0+A\s-2\d1\u\s0 N\s-2\d1\u\s0 \fR(note that this is not addressable)\fP 648219b2ee8SDavid du Colombier *N\s-2\d1\u\s0 A\s-2\d4\u\s0 649219b2ee8SDavid du Colombier.DE 650219b2ee8SDavid du ColombierHere there is a distinction between 651219b2ee8SDavid du Colombiera node marked 652219b2ee8SDavid du Colombier.CW A\s-2\d1\u\s0 653219b2ee8SDavid du Colombierand a node marked 654219b2ee8SDavid du Colombier.CW A\s-2\d4\u\s0 655219b2ee8SDavid du Colombierbecause the address operator of an 656219b2ee8SDavid du Colombier.CW A\s-2\d4\u\s0 657219b2ee8SDavid du Colombiernode is not addressable. 658219b2ee8SDavid du ColombierSo to extend the table: 659219b2ee8SDavid du Colombier.DS 660219b2ee8SDavid du Colombier.B 661219b2ee8SDavid du Colombier.ta .1i 1.1i 662219b2ee8SDavid du Colombier Node Marked 663219b2ee8SDavid du Colombier.CW 664219b2ee8SDavid du Colombier &A\s-2\d4\u\s0 N\s-2\d2\u\s0 665219b2ee8SDavid du Colombier N\s-2\d2\u\s0+N\s-2\d1\u\s0 N\s-2\d1\u\s0 666219b2ee8SDavid du Colombier.DE 667219b2ee8SDavid du ColombierThe full addressability of the 68020 is expressed 668219b2ee8SDavid du Colombierin 18 rules like this, 669219b2ee8SDavid du Colombierwhile the addressability of the MIPS is expressed 670219b2ee8SDavid du Colombierin 11 rules. 671219b2ee8SDavid du ColombierWhen one ports the compiler, 672219b2ee8SDavid du Colombierthis table is usually initialized 673219b2ee8SDavid du Colombierso that leaves are labeled as addressable and nothing else. 674219b2ee8SDavid du ColombierThe code produced is poor, 675219b2ee8SDavid du Colombierbut porting is easy. 676219b2ee8SDavid du ColombierThe table can be extended later. 677219b2ee8SDavid du Colombier.LP 678219b2ee8SDavid du ColombierThis pass also rewrites some complex operators 679219b2ee8SDavid du Colombierinto procedure calls. 680219b2ee8SDavid du ColombierExamples include 64-bit multiply and divide. 681219b2ee8SDavid du Colombier.LP 682219b2ee8SDavid du ColombierIn the same bottom-up pass of the tree, 683219b2ee8SDavid du Colombierthe nodes are labeled with a Sethi-Ullman complexity 684219b2ee8SDavid du Colombier[Set70]. 685219b2ee8SDavid du ColombierThis number is roughly the number of registers required 686219b2ee8SDavid du Colombierto compile the tree on an ideal machine. 687219b2ee8SDavid du ColombierAn addressable node is marked 0. 688219b2ee8SDavid du ColombierA function call is marked infinite. 689219b2ee8SDavid du ColombierA unary operator is marked as the 690219b2ee8SDavid du Colombiermaximum of 1 and the mark of its subtree. 691219b2ee8SDavid du ColombierA binary operator with equal marks on its subtrees is 692219b2ee8SDavid du Colombiermarked with a subtree mark plus 1. 693219b2ee8SDavid du ColombierA binary operator with unequal marks on its subtrees is 694219b2ee8SDavid du Colombiermarked with the maximum mark of its subtrees. 695219b2ee8SDavid du ColombierThe actual values of the marks are not too important, 696219b2ee8SDavid du Colombierbut the relative values are. 697219b2ee8SDavid du ColombierThe goal is to compile the harder 698219b2ee8SDavid du Colombier(larger mark) 699219b2ee8SDavid du Colombiersubtree first. 700219b2ee8SDavid du Colombier.NH 2 701219b2ee8SDavid du ColombierCode generation 702219b2ee8SDavid du Colombier.LP 703219b2ee8SDavid du ColombierCode is generated by recursive 704219b2ee8SDavid du Colombierdescent. 705219b2ee8SDavid du ColombierThe Sethi-Ullman complexity completely guides the 706219b2ee8SDavid du Colombierorder. 707219b2ee8SDavid du ColombierThe addressability defines the leaves. 708219b2ee8SDavid du ColombierThe only difficult part is compiling a tree 709219b2ee8SDavid du Colombierthat has two infinite (function call) 710219b2ee8SDavid du Colombiersubtrees. 711219b2ee8SDavid du ColombierIn this case, 712219b2ee8SDavid du Colombierone subtree is compiled into the return register 713219b2ee8SDavid du Colombier(usually the most convenient place for a function call) 714219b2ee8SDavid du Colombierand then stored on the stack. 715219b2ee8SDavid du ColombierThe other subtree is compiled into the return register 716219b2ee8SDavid du Colombierand then the operation is compiled with 717219b2ee8SDavid du Colombieroperands from the stack and the return register. 718219b2ee8SDavid du Colombier.LP 719219b2ee8SDavid du ColombierThere is a separate boolean code generator that compiles 720219b2ee8SDavid du Colombierconditional expressions. 721219b2ee8SDavid du ColombierThis is fundamentally different from compiling an arithmetic expression. 722219b2ee8SDavid du ColombierThe result of the boolean code generator is the 723219b2ee8SDavid du Colombierposition of the program counter and not an expression. 724219b2ee8SDavid du ColombierThe boolean code generator makes extensive use of De Morgan's rule. 725219b2ee8SDavid du ColombierThe boolean code generator is an expanded version of that described 726219b2ee8SDavid du Colombierin chapter 8 of Aho, Sethi, and Ullman 727219b2ee8SDavid du Colombier[Aho87]. 728219b2ee8SDavid du Colombier.LP 729219b2ee8SDavid du ColombierThere is a considerable amount of talk in the literature 730219b2ee8SDavid du Colombierabout automating this part of a compiler with a machine 731219b2ee8SDavid du Colombierdescription. 732219b2ee8SDavid du ColombierSince this code generator is so small 733219b2ee8SDavid du Colombier(less than 500 lines of C) 734219b2ee8SDavid du Colombierand easy, 735219b2ee8SDavid du Colombierit hardly seems worth the effort. 736219b2ee8SDavid du Colombier.NH 2 737219b2ee8SDavid du ColombierRegisterization 738219b2ee8SDavid du Colombier.LP 739219b2ee8SDavid du ColombierUp to now, 740219b2ee8SDavid du Colombierthe compiler has operated on syntax trees 741219b2ee8SDavid du Colombierthat are roughly equivalent to the original source language. 742219b2ee8SDavid du ColombierThe previous pass has produced machine language in an internal 743219b2ee8SDavid du Colombierformat. 744219b2ee8SDavid du ColombierThe next two passes operate on the internal machine language 745219b2ee8SDavid du Colombierstructures. 746219b2ee8SDavid du ColombierThe purpose of the next pass is to reintroduce 747219b2ee8SDavid du Colombierregisters for heavily used variables. 748219b2ee8SDavid du Colombier.LP 749219b2ee8SDavid du ColombierAll of the variables that can be 750219b2ee8SDavid du Colombierpotentially registerized within a procedure are 751219b2ee8SDavid du Colombierplaced in a table. 752219b2ee8SDavid du Colombier(Suitable variables are any automatic or external 753219b2ee8SDavid du Colombierscalars that do not have their addresses extracted. 754219b2ee8SDavid du ColombierSome constants that are hard to reference are also 755219b2ee8SDavid du Colombierconsidered for registerization.) 756219b2ee8SDavid du ColombierFour separate data flow equations are evaluated 757219b2ee8SDavid du Colombierover the procedure on all of these variables. 758219b2ee8SDavid du ColombierTwo of the equations are the normal set-behind 759219b2ee8SDavid du Colombierand used-ahead 760219b2ee8SDavid du Colombierbits that define the life of a variable. 761219b2ee8SDavid du ColombierThe two new bits tell if a variable life 762219b2ee8SDavid du Colombiercrosses a function call ahead or behind. 763219b2ee8SDavid du ColombierBy examining a variable over its lifetime, 764219b2ee8SDavid du Colombierit is possible to get a cost 765219b2ee8SDavid du Colombierfor registerizing. 766219b2ee8SDavid du ColombierLoops are detected and the costs are multiplied 767219b2ee8SDavid du Colombierby three for every level of loop nesting. 768219b2ee8SDavid du ColombierCosts are sorted and the variables 769219b2ee8SDavid du Colombierare replaced by available registers on a greedy basis. 770219b2ee8SDavid du Colombier.LP 771219b2ee8SDavid du ColombierThe 68020 has two different 772219b2ee8SDavid du Colombiertypes of registers. 773219b2ee8SDavid du ColombierFor the 68020, 774219b2ee8SDavid du Colombiertwo different costs are calculated for 775219b2ee8SDavid du Colombiereach variable life and the register type that 776219b2ee8SDavid du Colombieraffords the better cost is used. 777219b2ee8SDavid du ColombierTies are broken by counting the number of available 778219b2ee8SDavid du Colombierregisters of each type. 779219b2ee8SDavid du Colombier.LP 780219b2ee8SDavid du ColombierNote that externals are registerized together with automatics. 781219b2ee8SDavid du ColombierThis is done by evaluating the semantics of a ``call'' instruction 782219b2ee8SDavid du Colombierdifferently for externals and automatics. 783219b2ee8SDavid du ColombierSince a call goes outside the local procedure, 784219b2ee8SDavid du Colombierit is assumed that a call references all externals. 785219b2ee8SDavid du ColombierSimilarly, 786219b2ee8SDavid du Colombierexternals are assumed to be set before an ``entry'' instruction 787219b2ee8SDavid du Colombierand assumed to be referenced after a ``return'' instruction. 788219b2ee8SDavid du ColombierThis makes sure that externals are in memory across calls. 789219b2ee8SDavid du Colombier.LP 790219b2ee8SDavid du ColombierThe overall results are satisfactory. 791219b2ee8SDavid du ColombierIt would be nice to be able to do this processing in 792219b2ee8SDavid du Colombiera machine-independent way, 793219b2ee8SDavid du Colombierbut it is impossible to get all of the costs and 794219b2ee8SDavid du Colombierside effects of different choices by examining the parse tree. 795219b2ee8SDavid du Colombier.LP 796219b2ee8SDavid du ColombierMost of the code in the registerization pass is machine-independent. 797219b2ee8SDavid du ColombierThe major machine-dependency is in 798219b2ee8SDavid du Colombierexamining a machine instruction to ask if it sets or references 799219b2ee8SDavid du Colombiera variable. 800219b2ee8SDavid du Colombier.NH 2 801219b2ee8SDavid du ColombierMachine code optimization 802219b2ee8SDavid du Colombier.LP 803219b2ee8SDavid du ColombierThe next pass walks the machine code 804219b2ee8SDavid du Colombierfor opportunistic optimizations. 805219b2ee8SDavid du ColombierFor the most part, 806219b2ee8SDavid du Colombierthis is highly specific to a particular 807219b2ee8SDavid du Colombierprocessor. 808219b2ee8SDavid du ColombierOne optimization that is performed 809219b2ee8SDavid du Colombieron all of the processors is the 810219b2ee8SDavid du Colombierremoval of unnecessary ``move'' 811219b2ee8SDavid du Colombierinstructions. 812219b2ee8SDavid du ColombierIronically, 813219b2ee8SDavid du Colombiermost of these instructions were inserted by 814219b2ee8SDavid du Colombierthe previous pass. 815219b2ee8SDavid du ColombierThere are two patterns that are repetitively 816219b2ee8SDavid du Colombiermatched and replaced until no more matches are 817219b2ee8SDavid du Colombierfound. 818219b2ee8SDavid du ColombierThe first tries to remove ``move'' instructions 819219b2ee8SDavid du Colombierby relabeling variables. 820219b2ee8SDavid du Colombier.LP 821219b2ee8SDavid du ColombierWhen a ``move'' instruction is encountered, 822219b2ee8SDavid du Colombierif the destination variable is set before the 823219b2ee8SDavid du Colombiersource variable is referenced, 824219b2ee8SDavid du Colombierthen all of the references to the destination 825219b2ee8SDavid du Colombiervariable can be renamed to the source and the ``move'' 826219b2ee8SDavid du Colombiercan be deleted. 827219b2ee8SDavid du ColombierThis transformation uses the reverse data flow 828219b2ee8SDavid du Colombierset up in the previous pass. 829219b2ee8SDavid du Colombier.LP 830219b2ee8SDavid du ColombierAn example of this pattern is depicted in the following 831219b2ee8SDavid du Colombiertable. 832219b2ee8SDavid du ColombierThe pattern is in the left column and the 833219b2ee8SDavid du Colombierreplacement action is in the right column. 834219b2ee8SDavid du Colombier.DS 835219b2ee8SDavid du Colombier.CW 836219b2ee8SDavid du Colombier.ta .1i .6i 1.6i 2.1i 2.6i 837219b2ee8SDavid du Colombier MOVE a->b \fR(remove)\fP 838219b2ee8SDavid du Colombier.R 839219b2ee8SDavid du Colombier (sequence with no mention of \f(CWa\fP) 840219b2ee8SDavid du Colombier.CW 841219b2ee8SDavid du Colombier USE b USE a 842219b2ee8SDavid du Colombier.R 843219b2ee8SDavid du Colombier (sequence with no mention of \f(CWa\fP) 844219b2ee8SDavid du Colombier.CW 845219b2ee8SDavid du Colombier SET b SET b 846219b2ee8SDavid du Colombier.DE 847219b2ee8SDavid du Colombier.LP 848219b2ee8SDavid du ColombierExperiments have shown that it is marginally 849219b2ee8SDavid du Colombierworthwhile to rename uses of the destination variable 850219b2ee8SDavid du Colombierwith uses of the source variable up to 851219b2ee8SDavid du Colombierthe first use of the source variable. 852219b2ee8SDavid du Colombier.LP 853219b2ee8SDavid du ColombierThe second transform will do relabeling 854219b2ee8SDavid du Colombierwithout deleting instructions. 855219b2ee8SDavid du ColombierWhen a ``move'' instruction is encountered, 856219b2ee8SDavid du Colombierif the source variable has been set prior 857219b2ee8SDavid du Colombierto the use of the destination variable 858219b2ee8SDavid du Colombierthen all of the references to the source 859219b2ee8SDavid du Colombiervariable are replaced by the destination and 860219b2ee8SDavid du Colombierthe ``move'' is inverted. 861219b2ee8SDavid du ColombierTypically, 862219b2ee8SDavid du Colombierthis transformation will alter two ``move'' 863219b2ee8SDavid du Colombierinstructions and allow the first transformation 864219b2ee8SDavid du Colombieranother chance to remove code. 865219b2ee8SDavid du ColombierThis transformation uses the forward data flow 866219b2ee8SDavid du Colombierset up in the previous pass. 867219b2ee8SDavid du Colombier.LP 868219b2ee8SDavid du ColombierAgain, 869219b2ee8SDavid du Colombierthe following is a depiction of the transformation where 870219b2ee8SDavid du Colombierthe pattern is in the left column and the 871219b2ee8SDavid du Colombierrewrite is in the right column. 872219b2ee8SDavid du Colombier.DS 873219b2ee8SDavid du Colombier.CW 874219b2ee8SDavid du Colombier.ta .1i .6i 1.6i 2.1i 2.6i 875219b2ee8SDavid du Colombier SET a SET b 876219b2ee8SDavid du Colombier.R 877219b2ee8SDavid du Colombier (sequence with no use of \f(CWb\fP) 878219b2ee8SDavid du Colombier.CW 879219b2ee8SDavid du Colombier USE a USE b 880219b2ee8SDavid du Colombier.R 881219b2ee8SDavid du Colombier (sequence with no use of \f(CWb\fP) 882219b2ee8SDavid du Colombier.CW 883219b2ee8SDavid du Colombier MOVE a->b MOVE b->a 884219b2ee8SDavid du Colombier.DE 885219b2ee8SDavid du ColombierIterating these transformations 886219b2ee8SDavid du Colombierwill usually get rid of all redundant ``move'' instructions. 887219b2ee8SDavid du Colombier.LP 888219b2ee8SDavid du ColombierA problem with this organization is that the costs 889219b2ee8SDavid du Colombierof registerization calculated in the previous pass 890219b2ee8SDavid du Colombiermust depend on how well this pass can detect and remove 891219b2ee8SDavid du Colombierredundant instructions. 892219b2ee8SDavid du ColombierOften, 893219b2ee8SDavid du Colombiera fine candidate for registerization is rejected 894219b2ee8SDavid du Colombierbecause of the cost of instructions that are later 895219b2ee8SDavid du Colombierremoved. 896219b2ee8SDavid du Colombier.NH 2 897219b2ee8SDavid du ColombierWriting the object file 898219b2ee8SDavid du Colombier.LP 899219b2ee8SDavid du ColombierThe last pass walks the internal assembly language 900219b2ee8SDavid du Colombierand writes the object file. 901219b2ee8SDavid du ColombierThe object file is reduced in size by about a factor 902219b2ee8SDavid du Colombierof three with simple compression 903219b2ee8SDavid du Colombiertechniques. 904219b2ee8SDavid du ColombierThe most important aspect of the object file 905219b2ee8SDavid du Colombierformat is that it is independent of the compiling machine. 906219b2ee8SDavid du ColombierAll integer and floating numbers in the object 907219b2ee8SDavid du Colombiercode are converted to known formats and byte 908219b2ee8SDavid du Colombierorders. 909219b2ee8SDavid du Colombier.NH 910219b2ee8SDavid du ColombierThe loader 911219b2ee8SDavid du Colombier.LP 912219b2ee8SDavid du ColombierThe loader is a multiple pass program that 913219b2ee8SDavid du Colombierreads object files and libraries and produces 914219b2ee8SDavid du Colombieran executable binary. 915219b2ee8SDavid du ColombierThe loader also does some minimal 916219b2ee8SDavid du Colombieroptimizations and code rewriting. 917219b2ee8SDavid du ColombierMany of the operations performed by the 918219b2ee8SDavid du Colombierloader are machine-dependent. 919219b2ee8SDavid du Colombier.LP 920219b2ee8SDavid du ColombierThe first pass of the loader reads the 921219b2ee8SDavid du Colombierobject modules into an internal data 922219b2ee8SDavid du Colombierstructure that looks like binary assembly language. 923219b2ee8SDavid du ColombierAs the instructions are read, 924219b2ee8SDavid du Colombiercode is reordered to remove 925219b2ee8SDavid du Colombierunconditional branch instructions. 926219b2ee8SDavid du ColombierConditional branch instructions are inverted 927219b2ee8SDavid du Colombierto prevent the insertion of unconditional branches. 928219b2ee8SDavid du ColombierThe loader will also make a copy of a few instructions 929219b2ee8SDavid du Colombierto remove an unconditional branch. 930219b2ee8SDavid du Colombier.LP 931219b2ee8SDavid du ColombierThe next pass allocates addresses for 932219b2ee8SDavid du Colombierall external data. 933219b2ee8SDavid du ColombierTypical of processors is the MIPS, 934219b2ee8SDavid du Colombierwhich can reference ±32K bytes from a 935219b2ee8SDavid du Colombierregister. 936219b2ee8SDavid du ColombierThe loader allocates the register 937219b2ee8SDavid du Colombier.CW R30 938219b2ee8SDavid du Colombieras the static pointer. 939219b2ee8SDavid du ColombierThe value placed in 940219b2ee8SDavid du Colombier.CW R30 941219b2ee8SDavid du Colombieris the base of the data segment plus 32K. 942219b2ee8SDavid du ColombierIt is then cheap to reference all data in the 943219b2ee8SDavid du Colombierfirst 64K of the data segment. 944219b2ee8SDavid du ColombierExternal variables are allocated to 945219b2ee8SDavid du Colombierthe data segment 946219b2ee8SDavid du Colombierwith the smallest variables allocated first. 947219b2ee8SDavid du ColombierIf all of the data cannot fit into the first 948219b2ee8SDavid du Colombier64K of the data segment, 949219b2ee8SDavid du Colombierthen usually only a few large arrays 950219b2ee8SDavid du Colombierneed more expensive addressing modes. 951219b2ee8SDavid du Colombier.LP 952219b2ee8SDavid du ColombierFor the MIPS processor, 953219b2ee8SDavid du Colombierthe loader makes a pass over the internal 954219b2ee8SDavid du Colombierstructures, 955219b2ee8SDavid du Colombierexchanging instructions to try 956219b2ee8SDavid du Colombierto fill ``delay slots'' with useful work. 957219b2ee8SDavid du ColombierIf a useful instruction cannot be found 958219b2ee8SDavid du Colombierto fill a delay slot, 959219b2ee8SDavid du Colombierthe loader will insert 960219b2ee8SDavid du Colombier``noop'' 961219b2ee8SDavid du Colombierinstructions. 962219b2ee8SDavid du ColombierThis pass is very expensive and does not 963219b2ee8SDavid du Colombierdo a good job. 964219b2ee8SDavid du ColombierAbout 40% of all instructions are in 965219b2ee8SDavid du Colombierdelay slots. 966219b2ee8SDavid du ColombierAbout 65% of these are useful instructions and 967219b2ee8SDavid du Colombier35% are ``noops.'' 968219b2ee8SDavid du ColombierThe vendor-supplied assembler does this job 969219b2ee8SDavid du Colombiermore effectively, 970219b2ee8SDavid du Colombierfilling about 80% 971219b2ee8SDavid du Colombierof the delay slots with useful instructions. 972219b2ee8SDavid du Colombier.LP 973219b2ee8SDavid du ColombierOn the 68020 processor, 974219b2ee8SDavid du Colombierbranch instructions come in a variety of 975219b2ee8SDavid du Colombiersizes depending on the relative distance 976219b2ee8SDavid du Colombierof the branch. 977219b2ee8SDavid du ColombierThus the size of branch instructions 978219b2ee8SDavid du Colombiercan be mutually dependent. 979219b2ee8SDavid du ColombierThe loader uses a multiple pass algorithm 980219b2ee8SDavid du Colombierto resolve the branch lengths 981219b2ee8SDavid du Colombier[Szy78]. 982219b2ee8SDavid du ColombierInitially, all branches are assumed minimal length. 983219b2ee8SDavid du ColombierOn each subsequent pass, 984219b2ee8SDavid du Colombierthe branches are reassessed 985219b2ee8SDavid du Colombierand expanded if necessary. 986219b2ee8SDavid du ColombierWhen no more expansions occur, 987219b2ee8SDavid du Colombierthe locations of the instructions in 988219b2ee8SDavid du Colombierthe text segment are known. 989219b2ee8SDavid du Colombier.LP 990219b2ee8SDavid du ColombierOn the MIPS processor, 991219b2ee8SDavid du Colombierall instructions are one size. 992219b2ee8SDavid du ColombierA single pass over the instructions will 993219b2ee8SDavid du Colombierdetermine the locations of all addresses 994219b2ee8SDavid du Colombierin the text segment. 995219b2ee8SDavid du Colombier.LP 996219b2ee8SDavid du ColombierThe last pass of the loader produces the 997219b2ee8SDavid du Colombierexecutable binary. 998219b2ee8SDavid du ColombierA symbol table and other tables are 999219b2ee8SDavid du Colombierproduced to help the debugger to 1000219b2ee8SDavid du Colombierinterpret the binary symbolically. 1001219b2ee8SDavid du Colombier.LP 1002219b2ee8SDavid du ColombierThe loader places absolute source line numbers in the symbol table. 1003219b2ee8SDavid du ColombierThe name and absolute line number of all 1004219b2ee8SDavid du Colombier.CW #include 1005219b2ee8SDavid du Colombierfiles is also placed in the 1006219b2ee8SDavid du Colombiersymbol table so that the debuggers can 1007219b2ee8SDavid du Colombierassociate object code to source files. 1008219b2ee8SDavid du Colombier.NH 1009219b2ee8SDavid du ColombierPerformance 1010219b2ee8SDavid du Colombier.LP 1011219b2ee8SDavid du ColombierThe following is a table of the source size of the MIPS 1012219b2ee8SDavid du Colombiercompiler. 1013219b2ee8SDavid du Colombier.DS 1014219b2ee8SDavid du Colombier.ta .1i .6i 1015219b2ee8SDavid du Colombier lines module 1016219b2ee8SDavid du Colombier \0509 machine-independent headers 1017219b2ee8SDavid du Colombier 1070 machine-independent YACC source 1018219b2ee8SDavid du Colombier 6090 machine-independent C source 1019219b2ee8SDavid du Colombier 1020219b2ee8SDavid du Colombier \0545 machine-dependent headers 1021219b2ee8SDavid du Colombier 6532 machine-dependent C source 1022219b2ee8SDavid du Colombier 1023219b2ee8SDavid du Colombier \0298 loader headers 1024219b2ee8SDavid du Colombier 5215 loader C source 1025219b2ee8SDavid du Colombier.DE 1026219b2ee8SDavid du Colombier.LP 1027219b2ee8SDavid du ColombierThe following table shows timing 1028219b2ee8SDavid du Colombierof a test program 1029219b2ee8SDavid du Colombierthat plays checkers, running on a MIPS R4000. 1030219b2ee8SDavid du ColombierThe test program is 26 files totaling 12600 lines of C. 1031219b2ee8SDavid du ColombierThe execution time does not significantly 1032219b2ee8SDavid du Colombierdepend on library implementation. 1033219b2ee8SDavid du ColombierSince no other compiler runs on Plan 9, 1034219b2ee8SDavid du Colombierthe Plan 9 tests were done with the Plan 9 operating system; 1035219b2ee8SDavid du Colombierthe other tests were done on the vendor's operating system. 1036219b2ee8SDavid du ColombierThe hardware was identical in both cases. 1037219b2ee8SDavid du ColombierThe optimizer in the vendor's compiler 1038219b2ee8SDavid du Colombieris reputed to be extremely good. 1039219b2ee8SDavid du Colombier.DS 1040219b2ee8SDavid du Colombier.ta .1i .9i 1041219b2ee8SDavid du Colombier \0\04.49s Plan 9 \f(CWvc\fP \f(CW-N\fP compile time (opposite of \f(CW-O\fP) 1042219b2ee8SDavid du Colombier \0\01.72s Plan 9 \f(CWvc\fP \f(CW-N\fP load time 1043219b2ee8SDavid du Colombier 148.69s Plan 9 \f(CWvc\fP \f(CW-N\fP run time 1044219b2ee8SDavid du Colombier 1045219b2ee8SDavid du Colombier \015.07s Plan 9 \f(CWvc\fP compile time (\f(CW-O\fP implicit) 1046219b2ee8SDavid du Colombier \0\01.66s Plan 9 \f(CWvc\fP load time 1047219b2ee8SDavid du Colombier \089.96s Plan 9 \f(CWvc\fP run time 1048219b2ee8SDavid du Colombier 1049219b2ee8SDavid du Colombier \014.83s vendor \f(CWcc\fP compile time 1050219b2ee8SDavid du Colombier \0\00.38s vendor \f(CWcc\fP load time 1051219b2ee8SDavid du Colombier 104.75s vendor \f(CWcc\fP run time 1052219b2ee8SDavid du Colombier 1053219b2ee8SDavid du Colombier \043.59s vendor \f(CWcc\fP \f(CW-O\fP compile time 1054219b2ee8SDavid du Colombier \0\00.38s vendor \f(CWcc\fP \f(CW-O\fP load time 1055219b2ee8SDavid du Colombier \076.19s vendor \f(CWcc\fP \f(CW-O\fP run time 1056219b2ee8SDavid du Colombier 1057219b2ee8SDavid du Colombier \0\08.19s vendor \f(CWcc\fP \f(CW-O3\fP compile time 1058219b2ee8SDavid du Colombier \035.97s vendor \f(CWcc\fP \f(CW-O3\fP load time 1059219b2ee8SDavid du Colombier \071.16s vendor \f(CWcc\fP \f(CW-O3\fP run time 1060219b2ee8SDavid du Colombier.DE 1061219b2ee8SDavid du Colombier.LP 1062219b2ee8SDavid du ColombierTo compare the Intel compiler, 1063219b2ee8SDavid du Colombiera program that is about 40% bit manipulation and 1064219b2ee8SDavid du Colombierabout 60% single precision floating point was 1065219b2ee8SDavid du Colombierrun on the same 33 MHz 486, once under Windows 1066219b2ee8SDavid du Colombiercompiled with the Watcom compiler, version 10.0, 1067219b2ee8SDavid du Colombierin 16-bit mode and once under 1068219b2ee8SDavid du ColombierPlan 9 in 32-bit mode. 1069219b2ee8SDavid du ColombierThe Plan 9 execution time was 27 sec while the Windows 1070219b2ee8SDavid du Colombierexecution time was 31 sec. 1071219b2ee8SDavid du Colombier.NH 1072219b2ee8SDavid du ColombierConclusions 1073219b2ee8SDavid du Colombier.LP 1074219b2ee8SDavid du ColombierThe new compilers compile 1075219b2ee8SDavid du Colombierquickly, 1076219b2ee8SDavid du Colombierload slowly, 1077219b2ee8SDavid du Colombierand produce 1078219b2ee8SDavid du Colombiermedium quality 1079219b2ee8SDavid du Colombierobject code. 1080219b2ee8SDavid du ColombierThe compilers are relatively 1081219b2ee8SDavid du Colombierportable, 1082219b2ee8SDavid du Colombierrequiring but a couple of weeks' work to 1083219b2ee8SDavid du Colombierproduce a compiler for a different computer. 1084219b2ee8SDavid du ColombierFor Plan 9, 1085219b2ee8SDavid du Colombierwhere we needed several compilers 1086219b2ee8SDavid du Colombierwith specialized features and 1087219b2ee8SDavid du Colombierour own object formats, 1088219b2ee8SDavid du Colombierthis project was indispensable. 1089219b2ee8SDavid du ColombierIt is also necessary for us to 1090219b2ee8SDavid du Colombierbe able to freely distribute our compilers 1091219b2ee8SDavid du Colombierwith the Plan 9 distribution. 1092219b2ee8SDavid du Colombier.LP 1093219b2ee8SDavid du ColombierTwo problems have come up in retrospect. 1094219b2ee8SDavid du ColombierThe first has to do with the 1095219b2ee8SDavid du Colombierdivision of labor between compiler and loader. 1096219b2ee8SDavid du ColombierPlan 9 runs on multi-processors and as such 1097219b2ee8SDavid du Colombiercompilations are often done in parallel. 1098219b2ee8SDavid du ColombierUnfortunately, 1099219b2ee8SDavid du Colombierall compilations must be complete before loading 1100219b2ee8SDavid du Colombiercan begin. 1101219b2ee8SDavid du ColombierThe load is then single-threaded. 1102219b2ee8SDavid du ColombierWith this model, 1103219b2ee8SDavid du Colombierany shift of work from compile to load 1104219b2ee8SDavid du Colombierresults in a significant increase in real time. 1105219b2ee8SDavid du ColombierThe same is true of libraries that are compiled 1106219b2ee8SDavid du Colombierinfrequently and loaded often. 1107219b2ee8SDavid du ColombierIn the future, 1108219b2ee8SDavid du Colombierwe may try to put some of the loader work 1109219b2ee8SDavid du Colombierback into the compiler. 1110219b2ee8SDavid du Colombier.LP 1111219b2ee8SDavid du ColombierThe second problem comes from 1112219b2ee8SDavid du Colombierthe various optimizations performed over several 1113219b2ee8SDavid du Colombierpasses. 1114219b2ee8SDavid du ColombierOften optimizations in different passes depend 1115219b2ee8SDavid du Colombieron each other. 1116219b2ee8SDavid du ColombierIterating the passes could compromise efficiency, 1117219b2ee8SDavid du Colombieror even loop. 1118219b2ee8SDavid du ColombierWe see no real solution to this problem. 1119219b2ee8SDavid du Colombier.NH 1120219b2ee8SDavid du ColombierReferences 1121219b2ee8SDavid du Colombier.LP 1122219b2ee8SDavid du Colombier[Aho87] A. V. Aho, R. Sethi, and J. D. Ullman, 1123219b2ee8SDavid du Colombier.I 1124219b2ee8SDavid du ColombierCompilers \- Principles, Techniques, and Tools, 1125219b2ee8SDavid du Colombier.R 1126219b2ee8SDavid du ColombierAddison Wesley, 1127219b2ee8SDavid du ColombierReading, MA, 1128219b2ee8SDavid du Colombier1987. 1129219b2ee8SDavid du Colombier.LP 1130219b2ee8SDavid du Colombier[ANSI90] \f2American National Standard for Information Systems \- 1131219b2ee8SDavid du ColombierProgramming Language C\f1, American National Standards Institute, Inc., 1132219b2ee8SDavid du ColombierNew York, 1990. 1133219b2ee8SDavid du Colombier.LP 1134219b2ee8SDavid du Colombier[Dav91] J. W. Davidson and D. B. Whalley, 1135219b2ee8SDavid du Colombier``Methods for Saving and Restoring Register Values across Function Calls'', 1136219b2ee8SDavid du Colombier.I 1137219b2ee8SDavid du ColombierSoftware\-Practice and Experience, 1138219b2ee8SDavid du Colombier.R 1139219b2ee8SDavid du ColombierVol 21(2), pp. 149-165, February 1991. 1140219b2ee8SDavid du Colombier.LP 1141219b2ee8SDavid du Colombier[Joh79] S. C. Johnson, 1142219b2ee8SDavid du Colombier``YACC \- Yet Another Compiler Compiler'', 1143219b2ee8SDavid du Colombier.I 1144219b2ee8SDavid du ColombierUNIX Programmer's Manual, Seventh Ed., Vol. 2A, 1145219b2ee8SDavid du Colombier.R 1146219b2ee8SDavid du ColombierAT&T Bell Laboratories, 1147219b2ee8SDavid du ColombierMurray Hill, NJ, 1148219b2ee8SDavid du Colombier1979. 1149219b2ee8SDavid du Colombier.LP 1150219b2ee8SDavid du Colombier[Set70] R. Sethi and J. D. Ullman, 1151219b2ee8SDavid du Colombier``The Generation of Optimal Code for Arithmetic Expressions'', 1152219b2ee8SDavid du Colombier.I 1153219b2ee8SDavid du ColombierJournal of the ACM, 1154219b2ee8SDavid du Colombier.R 1155219b2ee8SDavid du ColombierVol 17(4), pp. 715-728, 1970. 1156219b2ee8SDavid du Colombier.LP 1157219b2ee8SDavid du Colombier[Szy78] T. G. Szymanski, 1158219b2ee8SDavid du Colombier``Assembling Code for Machines with Span-dependent Instructions'', 1159219b2ee8SDavid du Colombier.I 1160219b2ee8SDavid du ColombierCommunications of the ACM, 1161219b2ee8SDavid du Colombier.R 1162219b2ee8SDavid du ColombierVol 21(4), pp. 300-308, 1978. 1163