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