home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume20 / lcomp < prev    next >
Text File  |  1989-10-26  |  42KB  |  1,691 lines

  1. Subject:  v20i082:  "Cheap dynamic instruction counting"
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Paul Haahr <haahr@princeton.edu>
  7. Posting-number: Volume 20, Issue 82
  8. Archive-name: lcomp
  9.  
  10. [  This is a poor summary of Paul's excellent README; I'm not sure why
  11.    I think it's so great, but I do.  /r$ ]
  12.  
  13. This package is based on Peter Weinberger's "Cheap Dynamic Instruction
  14. Counting" from the AT&T Bell Labs Tech Journal Unix(tm) issue of a
  15. few years ago (Vol 63, No 8, Oct 1984, pp 1815-1826).  These programs
  16. were written for a class taught by David Hanson at Princeton University
  17. in Spring 1988.  (Computer Science 596, Systems Programming Workshop)
  18.  
  19. This code runs on Sun-3s (68020s) and Vaxen (4.3 bsd and ultrix).  The
  20. files 68020.l and vax.l are lex programs that match the instructions in an
  21. assembly program.  I did the 68020 port in about an hour.  If people are
  22. interested, I will maintain a library of machine.l files.
  23.  
  24. paul haahr
  25. princeton!haahr        haahr@princeton.edu
  26.  
  27. # to unbundle, sh this file
  28. # bundled by haahr on elliot at Sun May  8 14:48:31 EDT 1988
  29. echo README 1>&2
  30. sed 's/^-//' > README <<'end of README'
  31. -README for lcomp and lprint
  32. -cheap dynamic instruction counting
  33. -
  34. -This package is based on Peter Weinberger's "Cheap Dynamic Instruction
  35. -Counting" from the AT&T Bell Labs Tech Journal Unix(tm) issue of a
  36. -few years ago (Vol 63, No 8, Oct 1984, pp 1815-1826).  These programs
  37. -were written for a class taught by David Hanson at Princeton University
  38. -in Spring 1988.  (Computer Science 596, Systems Programming Workshop)
  39. -
  40. -This code runs on Sun-3s (68020s) and Vaxen (4.3 bsd and ultrix).  Since it
  41. -works with the assembly language output of compilers, it needs to make
  42. -some assumptions.  The files 68020.l and vax.l are lex programs that match
  43. -the instructions in an assembly program.  For new machines, if the assembler
  44. -is a unix-like assembler and the compiler doesn't do too many strange things,
  45. -it should be possible to easily change one of the included .l files to work
  46. -if you look at the code a bit and know the relevant assembly language.  If
  47. -people are interested, I will maintain a library of machine.l files.
  48. -
  49. -To get this working on a vax or a sun, edit the makefile to set TARGET
  50. -to 68020 or vax, and  change BIN, LIB, and MAN and do a make install.
  51. -BIN, LIB, and MAN may not be the current directory.  If you do not want
  52. -to install the programs, edit lcomp to change the LIB directory to the
  53. -current directory.
  54. -
  55. -See the enclosed manual page (and Weinberger's paper) for how to use
  56. -and interpret the results of these programs.
  57. -
  58. -The interesting thing about this package is the use of lex to drive the
  59. -instruction recognizer.  I like this approach, and would defend it,
  60. -because i did my port to the sun 68020 compiler in less than an hour by
  61. -changing the patterns matched and the inserted assembly code (all in
  62. -the lex source).  Only two small changes had to be made to the machine
  63. -independent code (bb.c) to support the sun, but this was just because
  64. -of a few vax-centrist assumptions I had made when writing the original code.
  65. -See the file INTERNALS for a description of how to write the driver for
  66. -a new machine.
  67. -
  68. -lcomp functions as either cc or f77.  I have not found a case where it
  69. -breaks.  Note that you must use -F when linking fortran .o files if
  70. -there are no .f files listed as arguments.
  71. -
  72. -lprint is modelled on the Ninth Edition manual page for Weinberger's code,
  73. -but I wrote it from memory and confused the meaning of all of his
  74. -options.  Since my lprint and his have different functionality and I
  75. -thought my names made more sense for my program, I kept my version of
  76. -the option names.
  77. -
  78. -For a different approach to writing a package like this, see Sun's tcov,
  79. -which add profiling code to C source rather than compiler output.
  80. -
  81. -
  82. -This code is wholly within the public domain.  It is not copy(right|left)ed
  83. -by anyone or any organization.  Do with it what you wish.
  84. -
  85. -Paul Haahr
  86. -princeton!haahr (haahr@princeton.edu)
  87. end of README
  88. echo makefile 1>&2
  89. sed 's/^-//' > makefile <<'end of makefile'
  90. -CFLAGS    = -O
  91. -LIBS    = -ll
  92. -TARGET    = vax
  93. -GENDEP    = /lib/cpp -M        # on ultrix, use /lib/cpp -Em
  94. -
  95. -SRC    = README makefile INTERNALS lcomp.1 lcomp \
  96. -      bbexit.c bbfile.c \
  97. -      bb.h new.h bool.h \
  98. -      bb.c lprint.c ealloc.c efopen.c \
  99. -      vax.l 68020.l
  100. -
  101. -LPRINT    = lprint.o ealloc.o efopen.o
  102. -BB    = bb.o ealloc.o efopen.o $(TARGET).o
  103. -
  104. -HOME    = /u/haahr
  105. -BIN    = $(HOME)/bin
  106. -LIB    = $(HOME)/lib/bb
  107. -MAN    = $(HOME)/lib/man/man1
  108. -
  109. -# normal targets
  110. -
  111. -all    : bb bbexit.o bbfile.o lprint
  112. -
  113. -bb    : $(BB)
  114. -    $(CC) $(CFLAGS) -o bb $(BB) $(LIBS)
  115. -
  116. -lprint    : $(LPRINT)
  117. -    $(CC) $(CFLAGS) -o lprint $(LPRINT)
  118. -
  119. -
  120. -# c code checking
  121. -
  122. -#    using V8 cyntax
  123. -CYNTAX    = cyntax
  124. -CYN    = O
  125. -CYNLIB    =
  126. -
  127. -#    using sun system V lint
  128. -#CYNTAX    = /usr/5bin/lint
  129. -#CYN    = ln
  130. -#CYNLIB    = -ll
  131. -
  132. -
  133. -CLPRINT    = lprint.$(CYN) ealloc.$(CYN) efopen.$(CYN)
  134. -CBB    = bb.$(CYN) ealloc.$(CYN) efopen.$(CYN) $(TARGET).$(CYN)
  135. -
  136. -.SUFFIXES:    .$(CYN)
  137. -
  138. -.c.$(CYN):
  139. -    -$(CYNTAX) $(CFLAGS) -c $*.c
  140. -
  141. -cyntax    : Cbb Clprint bbexit.$(CYN) bbfile.$(CYN)
  142. -
  143. -Cbb    : $(CBB)
  144. -    -$(CYNTAX) $(CFLAGS) $(CBB) $(CYNLIB)
  145. -
  146. -Clprint    : $(CLPRINT)
  147. -    -$(CYNTAX) $(CFLAGS) $(CLPRINT)
  148. -
  149. -$(TARGET).$(CYN) : $(TARGET).l
  150. -    lex $(LFLAGS) -t $(TARGET).l > $(TARGET).c
  151. -    -$(CYNTAX) $(CFLAGS) -c $(TARGET).c
  152. -    rm -f $(TARGET).c
  153. -
  154. -
  155. -# installation procedure
  156. -
  157. -install        : bin lib man
  158. -bin        : $(BIN)/lprint $(BIN)/lcomp 
  159. -lib        : $(LIB)/bb $(LIB)/bbexit.o $(LIB)/bbfile.o
  160. -man        : $(MAN)/lcomp.1
  161. -
  162. -$(BIN)/lcomp    : lcomp
  163. -        sed 's+^LIB=.*$$+LIB='$(LIB)+ lcomp > $(BIN)/lcomp
  164. -
  165. -$(BIN)/lprint    : lprint
  166. -        cp lprint $(BIN)
  167. -        strip $(BIN)/lprint
  168. -
  169. -$(LIB)/bb    : bb
  170. -        cp bb $(LIB)
  171. -         strip $(LIB)/bb
  172. -
  173. -$(LIB)/bbexit.o    : bbexit.o
  174. -        cp bbexit.o $(LIB)
  175. -
  176. -$(LIB)/bbfile.o    : bbfile.o
  177. -        cp bbfile.o $(LIB)
  178. -
  179. -$(MAN)/lcomp.1    : lcomp.1
  180. -        sed 's+\$$LIB+'$(LIB)+g lcomp.1 > $(MAN)/lcomp.1
  181. -
  182. -bundle    : $(SRC)
  183. -    @bundle $(SRC)
  184. -
  185. -wc    :
  186. -    @wc $(SRC)
  187. -
  188. -delta    : $(SRC)
  189. -    @echo "message for $?"
  190. -    @cat > .cimsg
  191. -    @ci -q -l -m"`cat .cimsg`" $?
  192. -    @rm -f .cimsg
  193. -    @touch delta
  194. -
  195. -clean    :
  196. -    rm -f a.out prof.out bb lprint lex.yy.c makefile.dep *.sL *.[Oos] *%
  197. -
  198. -depend    :
  199. -    sed '/^# --- cut here ---$$/q' makefile > makefile.dep
  200. -    for i in *.[cly]; do $(GENDEP) $$i; done >> makefile.dep
  201. -    mv makefile.dep makefile
  202. -
  203. -# --- cut here ---
  204. -68020.o: 68020.l
  205. -68020.o: /usr/include/stdio.h
  206. -68020.o: /usr/include/ctype.h
  207. -68020.o: /usr/include/string.h
  208. -68020.o: ./bool.h
  209. -68020.o: ./bb.h
  210. -bb.o: bb.c
  211. -bb.o: /usr/include/stdio.h
  212. -bb.o: /usr/include/ctype.h
  213. -bb.o: /usr/include/string.h
  214. -bb.o: ./new.h
  215. -bb.o: ./bool.h
  216. -bb.o: ./bb.h
  217. -bbexit.o: bbexit.c
  218. -bbexit.o: /usr/include/stdio.h
  219. -ealloc.o: ealloc.c
  220. -ealloc.o: /usr/include/stdio.h
  221. -ealloc.o: ./new.h
  222. -ealloc.o: /usr/include/string.h
  223. -efopen.o: efopen.c
  224. -efopen.o: /usr/include/stdio.h
  225. -lprint.o: lprint.c
  226. -lprint.o: /usr/include/stdio.h
  227. -lprint.o: /usr/include/string.h
  228. -lprint.o: ./bool.h
  229. -lprint.o: ./new.h
  230. -max.o: max.c
  231. -panic.o: panic.c
  232. -panic.o: /usr/include/stdio.h
  233. -vax.o: vax.l
  234. -vax.o: /usr/include/stdio.h
  235. -vax.o: /usr/include/ctype.h
  236. -vax.o: /usr/include/string.h
  237. -vax.o: ./bool.h
  238. -vax.o: ./bb.h
  239. end of makefile
  240. echo INTERNALS 1>&2
  241. sed 's/^-//' > INTERNALS <<'end of INTERNALS'
  242. -INTERNALS for lcomp
  243. -(or how to write a driver for a new instruction set)
  244. -
  245. -The driver for lcomp (actually, bb) is a lex program which matches the
  246. -instruction field of a compiler's assembly output.  General machine
  247. -code for most architectures would be very hard to write basic block
  248. -counting code for, as many things that one wants to be able to find are
  249. -hard to identify (for example, can one tell the difference
  250. -between a normal label and the start of a functions).  Therefore, the
  251. -driver for most machines will have to take advantage of the idiosyncratic
  252. -nature of compiler output.
  253. -
  254. -The included drivers both are based on the output from the Portable C
  255. -Compiler (PCC).  68020.l was written for the Sun 3;  it has been tested
  256. -with SunOS 3.3 throught 3.5.  vax.l is for Digital Vaxen;  it has been
  257. -tested on BSD 4.3 and Ultrix 2.0.  I have not tried using either with
  258. -(and assume they will break on) the output of the GNU C compiler, but I
  259. -am sure it would not take long to port from a PCC version to a GNU
  260. -version.  It would be very difficult to port this code to work with a
  261. -compiler that directly generates object code with no provision for
  262. -creating assembler source.  Sorry.
  263. -
  264. -My approach for writing a new driver is to start with one of the
  265. -existing drivers included in this package and modify it appropriately.
  266. -A good way to become familiar with one of these drivers is to examine
  267. -some compiler output for a vax or a sun and compare it with the output
  268. -of bb for that machine.  Reasonable knowledge of the machine you are
  269. -working on and it's function call/return protocol is useful if not
  270. -necessary for porting the driver.
  271. -
  272. -The driver reads one file (a .s file generated by the compiler) and
  273. -generates two (a .s file with block counting code and a .sL file which
  274. -maps basic blocks to line numbers).  The generated code, when executed,
  275. -appends to a file called prof.out which contains a counter for each
  276. -basic block.  (The -r option to lcomp and lprint picks a name other
  277. -than prof.out.  Using an absolute path name can be extremely useful for
  278. -profiling a program that is run from a public bin directory, so that
  279. -users don't get a prof.out file every time they run the program, and
  280. -the developer of the program can get useful profiling data.)
  281. -
  282. -The prof.out file is a series of entries of the form
  283. -    <.sL file> <n>
  284. -    <count for block 0>
  285. -    <count for block 1>
  286. -    .
  287. -    .
  288. -    .
  289. -    <count for block n-1>
  290. -One such entry is written for each file compiled with lcomp.
  291. -
  292. -A .sL file has two parts.  The first part is a set of n (obtained from
  293. -prof.out) lines, one per basic block, each with four whitespace
  294. -separated records, containing the sourcefile name (these should all be
  295. -the same in any one .sL if one does not make too creative use of the C
  296. -preprocessor), first line of the basic block, last line of the block,
  297. -and number of instructions in the block.  This section is followed by a
  298. -line of the form "<m> functions", followed by m lines, one for each
  299. -function in the compilation unit (source file).  Each function line is
  300. -the name of the function and its first basic block.
  301. -
  302. -The .l file must match instructions and generate code to do the
  303. -instruction counting (and link a file's count table with the routine that
  304. -prints counts), and write a .sL file.  Start with the vax or 68020 code
  305. -and modify it appropriately.  The following functions are predefined
  306. -(in bb.c) to handle common cases:
  307. -
  308. -    passline()    -- pass a line through unchanged
  309. -    inst()        -- a normal instruction that does not use
  310. -               the condition codes and does alter them
  311. -    safe()        -- an instruction that uses the condition codes
  312. -               or does not change them
  313. -    branch()    -- a jump or branch (conditional or unconditional)
  314. -               unconditional subroutine call does not go here
  315. -    stabd()        -- handle unix .stabd or .stabn lines
  316. -    stabs()        -- handle unix .stabs lines
  317. -    function(s, n)    -- declare that function named s starts at block n
  318. -    functionmap()    -- write the function map for the end of the .sL file
  319. -
  320. -stabd() and stabs() read the .stab directives put out by the compiler for
  321. -debugger information.  They should work with both dbx and sdb style compiler
  322. -output.
  323. -
  324. -The following functions must be provided by the driver:
  325. -
  326. -    labelstartsblock(label)    -- return a non-zero value if the named label
  327. -                   could be the target of a branch.  if there
  328. -                   is a systematic way of telling that a label
  329. -                   only exists for a debugger, this function
  330. -                   should return false (zero) in that case.
  331. -                   this feature is used in the sun version
  332. -    increment()    -- increment a basic block counter.  output
  333. -               at the beginning of a basic block.
  334. -    safeincrement()    -- same as increment(), but does not change condition
  335. -               codes.  this is normally possible on most machines,
  336. -               but can require tricky code.
  337. -    epilogue()    -- takes one argument, the name of a map file,
  338. -               which must be linked with count information into
  339. -               the counting table.  see bbexit.c.  the structures
  340. -               are normally defined here.
  341. -
  342. -
  343. -There's more to it than what I have described here, but the best way to
  344. -figure it out is to try to write a driver for some machine.  I'll be
  345. -glad to answer questions on how to write a driver.  I will also be
  346. -willing to keep an archive of drivers that other people have written
  347. -for other machines, if there is interest.
  348. -
  349. -paul haahr
  350. -princeton!haahr        haahr@princeton.edu
  351. end of INTERNALS
  352. echo lcomp.1 1>&2
  353. sed 's/^-//' > lcomp.1 <<'end of lcomp.1'
  354. -.TH LCOMP 1 "15 April 1988"
  355. -.SH NAME
  356. -lcomp, lprint \- statement and instruction counting
  357. -.SH SYNOPSIS
  358. -.B lcomp
  359. -[
  360. -.B \-r
  361. -.I prof.out
  362. -file
  363. -]
  364. -[
  365. -.B \-FC
  366. -]
  367. -.I cc
  368. -or
  369. -.I f77
  370. -arguments ...
  371. -.PP
  372. -.B lprint
  373. -[
  374. -.B \-blaipfc
  375. -]
  376. -[
  377. -.B \-r
  378. -.I prof.out
  379. -file
  380. -] [ srcfile ] ...
  381. -.SH DESCRIPTION
  382. -.LP
  383. -.I Lcomp
  384. -compiles a C or \s-2FORTRAN\s0 program into an executable that produces
  385. -instruction counts.  \fILcomp\fP behaves similarly to
  386. -.I cc
  387. -and \fIf77\fP,
  388. -and accepts the same arguments and options as those programs, except that:
  389. -.TP
  390. -.B \-C
  391. -All named .c files are C++ programs and should be compiled with
  392. -.I CC
  393. -instead of
  394. -.I cc .
  395. -.TP
  396. -.B \-F
  397. -Link with \s-2FORTRAN\s0 libraries.  Implied if a named .f file is included,
  398. -but necessary if only object files are listed.
  399. -.TP
  400. -.BI \-r " file"
  401. -Generate code that puts the output in the named file, rather than
  402. -\fIprof.out\fP.
  403. -.LP
  404. -For each .c or .f file named, a .sL file is created, which maps
  405. -basic blocks to line numbers.  The source is compiled into a .o
  406. -file which is instrumented for counting basic blocks.
  407. -.LP
  408. -In the executable file, the function \fI_bbdump\fP(), which is called
  409. -automatically be \fIexit\fP(), writes the
  410. -.I prof.out
  411. -file.  \fI_bbdump\fP() clears it's data structures, so it is safe to
  412. -call from a signal handler (as long as it is safe to I/O from a signal
  413. -handler on your machine).  This is useful for gethering statistics on
  414. -a program that is not supposed to exit.
  415. -.LP
  416. -.I Lprint
  417. -analyzes the results of executing a program compiled with
  418. -.I lcomp .
  419. -The default behavior is to print an execution count in the left margin
  420. -of each named file for the first basic block on that line.
  421. -If no files are listed on the command line,
  422. -all that were executed are printed.
  423. -.SH OPTIONS
  424. -.TP
  425. -.B \-b
  426. -Print counts for basic blocks (default, unless one of
  427. -.B \-ipf
  428. -is selected).
  429. -.TP
  430. -.B \-l
  431. -Print counts for all lines, not just the first line of each basic block.
  432. -.TP
  433. -.B \-a
  434. -Print all basic blocks, not just the first one from a line.
  435. -.TP
  436. -.B \-i
  437. -Print instruction counts.  If a basic block is not executed, the
  438. -number of instructions in that block is printed in parentheses.
  439. -.TP
  440. -.B \-f
  441. -Summarize by file.  For instructions and basic blocks, the number executed,
  442. -the total number in the file, and the number not executed are printed.
  443. -.TP
  444. -.B \-p
  445. -Summarize by function.  As \fB-f\fP, but the number of times each
  446. -function is called is also printed.
  447. -.TP
  448. -.B \-c
  449. -Compresses the
  450. -.I prof.out
  451. -file.  The file grows every time the profile program is executed.
  452. -.TP
  453. -.BI \-r " file"
  454. -Read counting data from the named file, instead of \fIprof.out\fP.
  455. -.SH "EXAMPLES"
  456. -.ta 2.0i
  457. -.nf
  458. -$ lcomp file.c    # compile with counting code
  459. -$ a.out    # generate instruction counts
  460. -$ lprint file.c    # print statement counts for file.c
  461. -.PP
  462. -$ lcomp -o prog *.f    # compile all fortran programs in directory
  463. -$ prog ...    # generate instruction counts
  464. -$ lprint -fp    # print summary information for all files
  465. -.PP
  466. -$ make "CC=lcomp"    # tell make to use count generating compiler
  467. -.fi
  468. -.SH "SEE ALSO"
  469. -cc(1), f77(1), prof(1), gprof(1), exit(2)
  470. -.br
  471. -tcov(1) in SunOS
  472. -.PP
  473. -Peter J. Weinberger, ``Cheap Dynamic Instruction Counting,''
  474. -in \fIAT&T Bell Laboratories Technical Journal\fP,
  475. -Volume 63, No. 8, October 1984.
  476. -.SH FILES
  477. -.PD 0
  478. -.TP 1.5i
  479. -.I file .sL
  480. -mapping from basic blocks to lines and functions
  481. -.TP
  482. -.I prof.out
  483. -default output file for counts
  484. -.TP
  485. -$LIB/bb
  486. -assembly language post-processor to insert statement counts
  487. -.TP
  488. -$LIB/bbexit.o
  489. -exit routine for statement counting
  490. -.TP
  491. -$LIB/bbfile.o
  492. -contains name of file to dump to, normally
  493. -.I prof.out
  494. -.PD
  495. -.SH BUGS
  496. -.LP
  497. -The analyzed program must call
  498. -.I exit (2),
  499. -either explictly or implictly by returning from
  500. -\fImain\fP() for the coverage information to be written to the
  501. -.I prof.out
  502. -file.
  503. -.LP
  504. -The order that \fIlprint\fP prints files in if no names are
  505. -mentioned on the command line is determinate but not too useful.
  506. -.LP
  507. -Profiling the kernel is possible, but some code must be written
  508. -to grab the data out of kernel memory,
  509. -rather than using \fI_bbdump\fP().
  510. end of lcomp.1
  511. echo lcomp 1>&2
  512. sed 's/^-//' > lcomp <<'end of lcomp'
  513. -#! /bin/sh
  514. -
  515. -LIB=$HOME/cs/596/lcomp
  516. -PATH=$LIB:$PATH
  517. -export PATH
  518. -CC=cc
  519. -
  520. -CFILES=
  521. -FFILES=
  522. -SFILES=
  523. -OFILES=
  524. -RMFILES=
  525. -
  526. -LIBS=
  527. -FLIBS=
  528. -PROF=prof.out
  529. -LINK=true
  530. -EXEC=a.out
  531. -FFLAGS='-u _MAIN_'
  532. -FORTRAN='-lF77 -lI77 -lU77 -lm'
  533. -
  534. -while [ $# != 0 ]
  535. -do
  536. -    case "$1" in
  537. -    *.c)    CFILES="$CFILES $1" ;;
  538. -    *.[fF])    FFILES="$FFILES $1" ; FLIBS="$FORTRAN" ;;
  539. -    *.[sS])    SFILES="$SFILES $1" ;;
  540. -    *.o)    OFILES="$OFILES $1" ;;
  541. -    -r)    shift ; PROF=$1 ;;
  542. -    -C)    CC=CC ;;
  543. -    -F)    FLIBS="$FORTRAN" ;;
  544. -    -O)    ;;
  545. -    -c)    LINK=false ;;
  546. -    -o)    shift ; EXEC=$1 ;;
  547. -    -l*|*.a)LIBS="$LIBS $1" ;;
  548. -    -*)    FLAGS="$FLAGS $1" ;;
  549. -    esac
  550. -    shift
  551. -done
  552. -
  553. -for i in $CFILES
  554. -do
  555. -    file=`echo $i | sed 's/\.c$//'`
  556. -    $CC -g -S $FLAGS $file.c    || exit $?
  557. -    bb $file.s            || exit $?
  558. -    SFILES="$SFILES $file.s"
  559. -    RMFILES="$RMFILES $file.s"
  560. -done
  561. -
  562. -for i in $FFILES
  563. -do
  564. -    file=`echo $i | sed 's/\.[fF]$//'`
  565. -    f77 -g -S $FLAGS $i        || exit $?
  566. -    bb $file.s            || exit $?
  567. -    SFILES="$SFILES $file.s"
  568. -    RMFILES="$RMFILES $file.s"
  569. -done
  570. -
  571. -for i in $SFILES
  572. -do
  573. -    file=`echo $i | sed 's/\.[sS]$//'`
  574. -    $CC -c $FLAGS $i        || exit $?
  575. -    OFILES="$OFILES $file.o"
  576. -done
  577. -
  578. -if $LINK
  579. -then
  580. -    if [ "$PROF" = prof.out ]
  581. -    then
  582. -        OFILES="$OFILES $LIB/bbfile.o"
  583. -    else
  584. -        echo "char *_bbfile = \"$PROF\";" > $$bbfile.c
  585. -        $CC -c $$bbfile.c
  586. -        OFILES="$OFILES $$bbfile.o"
  587. -        RMFILES="$RMFILES $$bbfile.c $$bbfile.o"
  588. -    fi
  589. -
  590. -    if [ "$FLIBS" != "" ]
  591. -    then
  592. -        FLAGS="$FLAGS $FFLAGS"
  593. -    fi
  594. -    $CC -o $EXEC $FLAGS $OFILES $LIB/bbexit.o $LIBS $FLIBS || exit $?
  595. -fi
  596. -rm -f $RMFILES
  597. end of lcomp
  598. chmod +x lcomp
  599. echo bbexit.c 1>&2
  600. sed 's/^-//' > bbexit.c <<'end of bbexit.c'
  601. -/* bbexit.c -- exit routine for basic block counting */
  602. -
  603. -#include <stdio.h>
  604. -
  605. -typedef struct Entry Entry;
  606. -struct Entry {
  607. -    Entry    *next;
  608. -    int    len, *counts;
  609. -    char    *mapfile;
  610. -};
  611. -
  612. -Entry *_bblist = NULL;
  613. -extern char *_bbfile;
  614. -
  615. -extern char *malloc();
  616. -
  617. -_bbdump()
  618. -{
  619. -    Entry *e;
  620. -    FILE *fp = fopen(_bbfile, "a");
  621. -    if (fp == NULL) {
  622. -        fprintf(stderr, "couldn't open %s\n", _bbfile);
  623. -        return;
  624. -    }
  625. -    for (e = _bblist; e != NULL; e = e->next) {
  626. -        int i;
  627. -        fprintf(fp, "%s %d\n", e->mapfile, e->len);
  628. -        for (i = 0; i < e->len; i++) {
  629. -            fprintf(fp, "%d\n", e->counts[i]);
  630. -            e->counts[i] = 0;
  631. -        }
  632. -    }
  633. -    fclose(fp);
  634. -}
  635. -
  636. -exit(status)
  637. -    int status;
  638. -{
  639. -    _bbdump();
  640. -    _cleanup();
  641. -    _exit(status);
  642. -}
  643. end of bbexit.c
  644. echo bbfile.c 1>&2
  645. sed 's/^-//' > bbfile.c <<'end of bbfile.c'
  646. -char *_bbfile = "prof.out";
  647. end of bbfile.c
  648. echo bb.h 1>&2
  649. sed 's/^-//' > bb.h <<'end of bb.h'
  650. -/* bb.h -- basic block counting definitions */
  651. -
  652. -#define WORDSIZE    256
  653. -#define    NOPRINT        -1000
  654. -
  655. -#define streq(s, t)    (strcmp((s), (t)) == 0)
  656. -#define    atoi(s)        strtol((s), (char *) NULL, 0)
  657. -
  658. -
  659. -extern    FILE *out;        /* generated .s file */
  660. -extern    FILE *map;        /* generated .sL file */
  661. -
  662. -extern    int lineno;        /* original source line number */
  663. -extern    char filename[];    /* original source filename */
  664. -
  665. -extern    char *yystring;        /* input to lex */
  666. -extern    char *tail;        /* tail of line (everything after opcode) */
  667. -extern    char line[];        /* input line */
  668. -extern    char label[];        /* most recent label */
  669. -
  670. -extern    bool text;        /* in text segment? */
  671. -extern    bool newblock;        /* started new basic block? */
  672. -extern    int block;        /* current basic block number */
  673. -extern    int instructions;    /* counter of instructions */
  674. -extern    int reached;        /* last line reached in basic block */
  675. -
  676. -
  677. -extern    void inst();        /* normal instruction */
  678. -extern    void safe();        /* instruction that uses condition codes */
  679. -extern    void branch();        /* any flow of control */
  680. -extern    void stabd(), stabs();    /* debugger symbol table */
  681. -extern    void passline();    /* no-op */
  682. -
  683. -
  684. -extern    bool labelstartsblock();    /* supplied in $TARGET.l */
  685. -
  686. -
  687. -#ifdef    YYLERR        /* lex */
  688. -
  689. -#undef    output
  690. -#undef    input
  691. -#undef    unput
  692. -
  693. -#define    input()        (*yystring == '\0' ? 0 : *yystring++)
  694. -#define    unput(c)    (*--yystring = (c))
  695. -#define    output(c)    (c)    /* force evaluation */
  696. -
  697. -#endif
  698. end of bb.h
  699. echo new.h 1>&2
  700. sed 's/^-//' > new.h <<'end of new.h'
  701. -/* new.h -- dynamic memory allocation */
  702. -
  703. -extern char *malloc(), *ealloc(), *realloc(), *erealloc(), *strdup();
  704. -extern int free();
  705. -extern void panic();
  706. -
  707. -#ifndef NULL
  708. -#define NULL 0
  709. -#endif
  710. -
  711. -#define    new(t, n)    ((t *) ealloc((n) * sizeof (t)))
  712. -#define renew(t, p, n)    (((p) == NULL) \
  713. -                ? new(t, n) \
  714. -                : ((t *) erealloc((char *) (p), (n) * sizeof (t))))
  715. -#define    delete(p)    (((p) == NULL) ? 0 : free(p))
  716. end of new.h
  717. echo bool.h 1>&2
  718. sed 's/^-//' > bool.h <<'end of bool.h'
  719. -/* bool.h -- boolean type */
  720. -
  721. -typedef int bool;
  722. -#define    FALSE    0
  723. -#define    TRUE    1
  724. -
  725. -#define    strbool(t)    ((t) ? "TRUE" : "FALSE")
  726. end of bool.h
  727. echo bb.c 1>&2
  728. sed 's/^-//' > bb.c <<'end of bb.c'
  729. -/* bb.c -- insert basic block counting code */
  730. -
  731. -#include <stdio.h>
  732. -#include <ctype.h>
  733. -#include <string.h>
  734. -#include "new.h"
  735. -#include "bool.h"
  736. -#include "bb.h"
  737. -
  738. -extern FILE *efopen();
  739. -extern char *memcpy();
  740. -
  741. -char *progname = "bb";
  742. -
  743. -static void usage()
  744. -{
  745. -    fprintf(stderr, "usage: %s file.s ...\n", progname);
  746. -    exit(1);
  747. -}
  748. -
  749. -
  750. -/* globals shared with $TARGET.l */
  751. -
  752. -FILE *out = NULL;        /* generated .s file */
  753. -FILE *map = NULL;        /* generated .sL file */
  754. -
  755. -int lineno = 0;            /* original source line number */
  756. -char filename[WORDSIZE];    /* original source filename */
  757. -
  758. -char *yystring;            /* input to lex */
  759. -char *tail;            /* tail of line (everything after opcode) */
  760. -char line[BUFSIZ];        /* input line */
  761. -char label[WORDSIZE];        /* most recent label */
  762. -
  763. -bool text = TRUE;        /* in text segment? */
  764. -bool newblock = TRUE;        /* started new basic block? */
  765. -int block = 0;            /* current basic block number */
  766. -int instructions = NOPRINT;    /* counter of instructions */
  767. -int reached = 0;        /* last line reached in basic block */
  768. -
  769. -
  770. -/* associate functions with basic blocks*/
  771. -
  772. -#define    MAXFUNC    1000
  773. -int nfunc;
  774. -struct {
  775. -    char *name;
  776. -    int bb;
  777. -} func[MAXFUNC];
  778. -
  779. -function(s, bb)
  780. -    char *s;
  781. -    int bb;
  782. -{
  783. -    if (nfunc >= MAXFUNC)
  784. -        panic("too many functions (>%d), on %s\n", MAXFUNC, s);
  785. -    func[nfunc].name = strdup(s);
  786. -    func[nfunc].bb = bb;
  787. -    nfunc++;
  788. -}
  789. -
  790. -functionmap()
  791. -{
  792. -    int i;
  793. -    fprintf(map, "%d functions\n", nfunc);
  794. -    for (i = 0; i < nfunc; i++) {
  795. -        fprintf(map, "%s %d\n", func[i].name, func[i].bb);
  796. -        free(func[i].name);
  797. -        func[i].name = NULL;
  798. -    }
  799. -    nfunc = 0;
  800. -}
  801. -
  802. -
  803. -/* parse file, pass to yylex from $TARGET.l */
  804. -void bb(infile)
  805. -    char *infile;
  806. -{
  807. -    char outfile[BUFSIZ], mapfile[BUFSIZ];
  808. -    static char pid[10] = "";
  809. -    FILE *in;
  810. -
  811. -    in = efopen(infile, "r");
  812. -
  813. -    strcpy(mapfile, infile);
  814. -    strcat(mapfile, "L");
  815. -    map = efopen(mapfile, "w");
  816. -
  817. -    if (pid[0] == '\0')
  818. -        sprintf(pid, ".%d", getpid());
  819. -    strcpy(outfile, infile);
  820. -    strcat(outfile, pid);
  821. -    out = efopen(outfile, "w");
  822. -
  823. -    lineno = 0;
  824. -    filename[0] = '\0';
  825. -
  826. -    while (fgets(line, sizeof line, in) != NULL) {
  827. -        char *s = line, opcode[WORDSIZE];
  828. -        int i;
  829. -startofline:
  830. -        for (; isspace(*s); s++)
  831. -            ;
  832. -        if (*s == '\0') {
  833. -            fputs(line, out);
  834. -            continue;
  835. -        }
  836. -        for (i = 0; isgraph(s[i]); i++)
  837. -            if (s[i] == ':') {
  838. -                if (text) {
  839. -                    memcpy(label, s, i);
  840. -                    label[i] = '\0';
  841. -                    if (labelstartsblock(label))
  842. -                        newblock = TRUE;
  843. -                }
  844. -                s += i + 1;
  845. -                goto startofline;
  846. -            }
  847. -        tail = s + i;
  848. -        memcpy(opcode, s, i);
  849. -        opcode[i] = '\n';
  850. -        opcode[i + 1] = '\0';
  851. -        yystring = opcode;
  852. -        yylex();
  853. -    }
  854. -
  855. -    epilogue(mapfile);
  856. -    functionmap();
  857. -
  858. -    fclose(in);
  859. -    fclose(out);
  860. -    fclose(map);
  861. -    map = out = NULL;
  862. -
  863. -    if (unlink(infile) == -1)
  864. -        panic("couldn't unlink %s -- output in %s\n", infile, outfile);
  865. -    if (rename(outfile, infile) == -1)
  866. -        panic("couldn't rename %s to %s\n", outfile, infile);
  867. -}
  868. -
  869. -int main(argc, argv)
  870. -    int argc;
  871. -    char *argv[];
  872. -{
  873. -    progname = argv[0];
  874. -    if (argc == 1)
  875. -        usage();
  876. -    for (--argc, ++argv; argc != 0; --argc, ++argv)
  877. -        bb(*argv);
  878. -    return 0;
  879. -}
  880. -
  881. -/* functions for use in $TARGET.l -- common to most machines */
  882. -
  883. -void passline()
  884. -{
  885. -    fputs(line, out);
  886. -}
  887. -
  888. -void inst()
  889. -{
  890. -    if (text) {
  891. -        if (newblock)
  892. -            increment();
  893. -        reached = lineno;
  894. -        instructions++;
  895. -    }
  896. -    passline();
  897. -}
  898. -
  899. -void safe()
  900. -{
  901. -    if (text) {
  902. -        if (newblock)
  903. -            safeincrement();
  904. -        reached = lineno;
  905. -        instructions++;
  906. -    }
  907. -    passline();
  908. -}
  909. -
  910. -void branch()
  911. -{
  912. -    if (text) {
  913. -        if (newblock)
  914. -            safeincrement();
  915. -        reached = lineno;
  916. -        instructions++;
  917. -        newblock = TRUE;
  918. -    }
  919. -    passline();
  920. -}
  921. -
  922. -#define    STAB_LINE    0104    /* N_SLINE from <stab.h> */
  923. -#define    STAB_FILE    0144    /* N_SO from <stab.h> */
  924. -
  925. -void stabd()
  926. -{
  927. -    char *s;
  928. -    passline();
  929. -    if (atoi(tail) != STAB_LINE)
  930. -        return;
  931. -    if ((s = strchr(line, ',')) == NULL || (s = strchr(s + 1, ',')) == NULL)
  932. -        panic("bad directive: .stabn%s", tail);
  933. -    lineno = atoi(s + 1);
  934. -}
  935. -
  936. -void stabs()
  937. -{
  938. -    char *s, *t;
  939. -    int len;
  940. -    passline();
  941. -    if ((s = strchr(tail, ',')) == NULL)
  942. -        panic("bad directive: .stabs%s", tail);
  943. -    if (atoi(s + 1) != STAB_FILE)
  944. -        return;
  945. -    if ((s = strchr(tail, '"')) == NULL || (t = strchr(s + 1, '"')) == NULL)
  946. -        panic("bad directive: .stabs%s", tail);
  947. -    len = t - s - 1;
  948. -    memcpy(filename, s + 1, len);
  949. -    filename[len] = '\0';
  950. -}
  951. end of bb.c
  952. echo lprint.c 1>&2
  953. sed 's/^-//' > lprint.c <<'end of lprint.c'
  954. -/* lprint.c -- print out statement counts */
  955. -
  956. -#include <stdio.h>
  957. -#include <string.h>
  958. -#include "bool.h"
  959. -#include "new.h"
  960. -
  961. -#define    streq(s, t)    (strcmp((s), (t)) == 0)
  962. -
  963. -extern FILE *efopen();
  964. -
  965. -char *progname = "lprint";
  966. -
  967. -void usage()
  968. -{
  969. -    fprintf(stderr, "usage: %s [-blaipf] [-c] [-r file] [file ...]\n", progname);
  970. -    fprintf(stderr, "    -b    print basic block counts (default)\n");
  971. -    fprintf(stderr, "    -l    print counts for all lines\n");
  972. -    fprintf(stderr, "    -a    print all basic blocks\n");
  973. -    fprintf(stderr, "    -i    print instruction counts\n");
  974. -    fprintf(stderr, "    -p    print function summaries\n");
  975. -    fprintf(stderr,    "    -f    print file summaries\n");
  976. -    fprintf(stderr, "    -c    compress prof.out file\n");
  977. -    fprintf(stderr, "    -r    select alternate prof.out file\n");
  978. -    exit(1);
  979. -}
  980. -
  981. -int flags = 0;
  982. -
  983. -#define    BLOCKS    0x01
  984. -#define    LINES    0x02
  985. -#define    ALL    0x04
  986. -#define    INST    0x08
  987. -#define    FILESUM    0x10
  988. -#define    FUNCSUM    0x20
  989. -
  990. -#define    DEFAULT    BLOCKS
  991. -
  992. -typedef struct Mapfile Mapfile;
  993. -typedef struct Mapblock Mapblock;
  994. -typedef struct Sourcefile Sourcefile;
  995. -typedef struct Block Block;
  996. -typedef struct Func Func;
  997. -
  998. -struct Mapfile {
  999. -    char    *name;
  1000. -    int    n, nfunc;
  1001. -    struct Mapblock {
  1002. -        long    count;
  1003. -        int    inst;
  1004. -        Sourcefile *source;
  1005. -    } *block;
  1006. -    Mapfile    *next;
  1007. -};
  1008. -
  1009. -Mapfile *maplist = NULL;
  1010. -
  1011. -struct Block {
  1012. -    int    line, last, inst;
  1013. -    long    count;
  1014. -};
  1015. -
  1016. -struct Sourcefile {
  1017. -    char    *name;
  1018. -    int    nblock, maxblock;
  1019. -    Block    *block;
  1020. -    Sourcefile *next;
  1021. -};
  1022. -Sourcefile *sourcelist = NULL;
  1023. -
  1024. -struct Func {
  1025. -    char    *name;
  1026. -    Mapfile    *map;
  1027. -    int    block;
  1028. -};
  1029. -
  1030. -Func *functab = NULL;
  1031. -int nfunc = 0, maxfunc = 0;
  1032. -
  1033. -void gather(fp)
  1034. -    FILE *fp;
  1035. -{
  1036. -    int i, n;
  1037. -    char name[BUFSIZ];
  1038. -    while (fscanf(fp, "%s %d\n", name, &n) != EOF) {
  1039. -        Mapfile *p;
  1040. -        for (p = maplist; p != NULL; p = p->next)
  1041. -            if (streq(name, p->name)) {
  1042. -                if (n != p->n)
  1043. -                    panic("prof.out: bad counts for %s: %d and %d\n",
  1044. -                          name, p->n, n);
  1045. -                goto found;
  1046. -            }
  1047. -        p = new(Mapfile, 1);
  1048. -        p->next = maplist;
  1049. -        maplist = p;
  1050. -        p->name = strdup(name);
  1051. -        p->n = n;
  1052. -        p->block = new(struct Mapblock, n);
  1053. -        for (i = 0; i < n; i++)
  1054. -            p->block[i].count = 0;
  1055. -    found:
  1056. -        for (i = 0; i < n; i++) {
  1057. -            long count;
  1058. -            if (fscanf(fp, "%ld", &count) == EOF)
  1059. -                panic("prof.out: early EOF\n");
  1060. -            p->block[i].count += count;
  1061. -        }
  1062. -    }
  1063. -}
  1064. -
  1065. -void writeprof(fp)
  1066. -    FILE *fp;
  1067. -{
  1068. -    Mapfile *p;
  1069. -    for (p = maplist; p != NULL; p = p->next) {
  1070. -        int i;
  1071. -        fprintf(fp, "%s %d\n", p->name, p->n);
  1072. -        for (i = 0; i < p->n; i++)
  1073. -            fprintf(fp, "%ld\n", p->block[i].count);
  1074. -    }
  1075. -}
  1076. -
  1077. -Sourcefile *install(name, line, last, inst, count, n)
  1078. -    char    *name;
  1079. -    int    line, last, inst, n;
  1080. -    long    count;
  1081. -{
  1082. -    int i;
  1083. -    static Sourcefile *p = NULL;
  1084. -    if (p != NULL && streq(name, p->name))
  1085. -        goto found;
  1086. -    for (p = sourcelist; p != NULL; p = p->next)
  1087. -        if (streq(name, p->name))
  1088. -            goto found;
  1089. -
  1090. -    p = new(Sourcefile, 1);
  1091. -    p->name        = strdup(name);
  1092. -    p->block    = new(Block, n);
  1093. -    p->maxblock = n;
  1094. -    p->nblock   = 0;
  1095. -    p->next     = sourcelist;
  1096. -    sourcelist  = p;
  1097. -
  1098. -found:
  1099. -    if (p->nblock >= p->maxblock) {
  1100. -        p->maxblock *= 4;
  1101. -        p->block = renew(Block, p->block, p->maxblock);
  1102. -    }
  1103. -
  1104. -    /* insertion sort, but (in practice) very rarely executed */
  1105. -    for (i = p->nblock++; i > 0 && line < p->block[i - 1].line; i--)
  1106. -        p->block[i] = p->block[i - 1];
  1107. -
  1108. -    p->block[i].line  = line;
  1109. -    p->block[i].last  = last;
  1110. -    p->block[i].inst  = inst;
  1111. -    p->block[i].count = count;
  1112. -    return p;
  1113. -}
  1114. -
  1115. -void correlate(map)
  1116. -    Mapfile *map;
  1117. -{
  1118. -    int i;
  1119. -    FILE *fp = efopen(map->name, "r");
  1120. -    for (i = 0; i < map->n; i++) {
  1121. -        char filename[BUFSIZ];
  1122. -        int line, lastline;
  1123. -        if (fscanf(fp, "%s %d %d %d\n", filename,
  1124. -               &line, &lastline, &map->block[i].inst) != 4)
  1125. -            panic("%s, line %d: bad map entry\n", map->name, i + 1);
  1126. -        map->block[i].source = install(filename, line, lastline,
  1127. -                map->block[i].inst, map->block[i].count, map->n);
  1128. -    }
  1129. -    if (fscanf(fp, "%d functions\n", &map->nfunc) != 1)
  1130. -        panic("%s, line %d: bad function line\n", map->name, map->n);
  1131. -    while (nfunc + map->nfunc >= maxfunc) {
  1132. -        if (maxfunc == 0)
  1133. -            maxfunc = 200;
  1134. -        else
  1135. -            maxfunc *= 8;
  1136. -        functab = renew(Func, functab, maxfunc);
  1137. -    }
  1138. -    for (i = 0; i < map->nfunc; i++, nfunc++) {
  1139. -        char name[BUFSIZ];
  1140. -        int block;
  1141. -        if (fscanf(fp, "%s %d\n", name, &block) != 2)
  1142. -            panic("%s, line %d: bad function entry\n",
  1143. -                  map->name, map->n + 1 + 1);
  1144. -        functab[nfunc].name  = strdup(name);
  1145. -        functab[nfunc].map   = map;
  1146. -        functab[nfunc].block = block;
  1147. -    }
  1148. -    fclose(fp);
  1149. -}
  1150. -
  1151. -void printline(s, count, inst)
  1152. -    char    *s;
  1153. -    long    count;
  1154. -    int    inst;
  1155. -{
  1156. -    if (flags & BLOCKS)
  1157. -        printf("%10ld  ", count);
  1158. -    if (flags & INST) {
  1159. -        if (count == 0) {
  1160. -            char buf[20];
  1161. -            sprintf(buf, "(%d)", inst);
  1162. -            printf("%11s ", buf);
  1163. -        } else
  1164. -            printf("%10ld  ", count * inst);
  1165. -    }
  1166. -    printf("%s", s);
  1167. -}
  1168. -
  1169. -void printsource(p)
  1170. -    Sourcefile *p;
  1171. -{
  1172. -    int    line = 0, last = 0, i = 0, inst = 0;
  1173. -    long    count = 0;
  1174. -    char    buf[BUFSIZ];
  1175. -    FILE    *fp = efopen(p->name, "r");
  1176. -
  1177. -    static int fill = 0;
  1178. -    static bool firsttime = TRUE;
  1179. -    if (firsttime) {
  1180. -        firsttime = FALSE;
  1181. -        if (flags & BLOCKS)
  1182. -            fill += 12;
  1183. -        if (flags & INST)
  1184. -            fill += 12;
  1185. -    } else
  1186. -        printf("\f");
  1187. -
  1188. -    while (fgets(buf, sizeof buf, fp) != NULL) {
  1189. -        for (; i < p->nblock && line >= p->block[i].line; i++) {
  1190. -            if (flags & ALL)
  1191. -                printline("\n", p->block[i].count,
  1192. -                        p->block[i].inst);
  1193. -            if (last <= p->block[i].last)
  1194. -                last = p->block[i].last;
  1195. -        }
  1196. -        line++;
  1197. -        if (i < p->nblock && line == p->block[i].line && last < line) {
  1198. -            count = p->block[i].count;
  1199. -            inst  = p->block[i].inst;
  1200. -            last  = p->block[i].last;
  1201. -            printline(buf, count, inst);
  1202. -            while (++i < p->nblock && line == p->block[i].line)
  1203. -                if (flags & ALL)
  1204. -                    printline("\n", p->block[i].count,
  1205. -                            p->block[i].inst);
  1206. -        } else if (flags & LINES)
  1207. -            printline(buf, count, inst);
  1208. -        else
  1209. -            printf("%*s%s", fill, "", buf);
  1210. -    }
  1211. -    fclose(fp);
  1212. -}
  1213. -
  1214. -typedef struct Sum {
  1215. -    long    calls, i, ie, ine, bb, bbe, bbne;
  1216. -} Sum;
  1217. -
  1218. -void printsumline(name, sum, isfunc)
  1219. -    char    *name;
  1220. -    Sum    sum;
  1221. -    bool    isfunc;
  1222. -{
  1223. -    printf("%9ldbbe %4ldbb %4ldbbne ", sum.bbe, sum.bb, sum.bbne);
  1224. -    printf("%9ldie %4ldi %4ldine ", sum.ie, sum.i, sum.ine);
  1225. -    if (isfunc)
  1226. -        printf("%7ldcalls ", sum.calls);
  1227. -    else
  1228. -        printf("%13s", "");
  1229. -    printf(" %s\n", name);
  1230. -}
  1231. -
  1232. -static Sum zerosum = { 0, 0, 0, 0, 0, 0, 0 };
  1233. -
  1234. -void printfunctionsummary(p)
  1235. -    Sourcefile *p;
  1236. -{
  1237. -    Func *func;
  1238. -
  1239. -    for (func = &functab[0]; func < &functab[nfunc]; func++)
  1240. -        if (func->map->block[func->block].source == p) {
  1241. -            Sum sum;
  1242. -            Mapblock *block = func->map->block;
  1243. -            int i, last;
  1244. -            sum = zerosum;
  1245. -            if (func < &functab[nfunc] && func->map == (func + 1)->map)
  1246. -                last = (func + 1)->block;
  1247. -            else
  1248. -                last = func->map->n;
  1249. -            sum.calls += block[func->block].count;
  1250. -            for (i = func->block; i < last; i++) {
  1251. -                Mapblock *b = &block[i];
  1252. -                sum.bb    += 1;
  1253. -                sum.bbe    += b->count;
  1254. -                sum.i    += b->inst;
  1255. -                sum.ie    += b->inst * b->count;
  1256. -                if (b->count == 0) {
  1257. -                    sum.bbne += 1;
  1258. -                    sum.ine  += b->inst;
  1259. -                }
  1260. -            }
  1261. -            printsumline(func->name, sum, TRUE);
  1262. -        }
  1263. -}
  1264. -
  1265. -void printfilesummary(p)
  1266. -    Sourcefile *p;
  1267. -{
  1268. -    Sum sum;
  1269. -    Mapfile *map;
  1270. -    Mapblock *block;
  1271. -
  1272. -    sum = zerosum;
  1273. -    for (map = maplist; map != NULL; map = map->next)
  1274. -        for (block = &map->block[0]; block < &map->block[map->n]; block++)
  1275. -            if (block->source == p) {
  1276. -                sum.bb    += 1;
  1277. -                sum.bbe    += block->count;
  1278. -                sum.i    += block->inst;
  1279. -                sum.ie    += block->inst * block->count;
  1280. -                if (block->count == 0) {
  1281. -                    sum.bbne += 1;
  1282. -                    sum.ine  += block->inst;
  1283. -                }
  1284. -            }
  1285. -    printsumline(p->name, sum, FALSE);
  1286. -}
  1287. -
  1288. -void analyze(name)
  1289. -    char *name;
  1290. -{
  1291. -    Sourcefile *p;
  1292. -    for (p = sourcelist; p == NULL || !streq(p->name, name); p = p->next)
  1293. -        if (p == NULL) {
  1294. -            fprintf(stderr, "%s: not in prof.out\n", name);
  1295. -            return;
  1296. -        }
  1297. -
  1298. -    if (flags & (INST|BLOCKS)) {
  1299. -        printsource(p);
  1300. -        if (flags & (FUNCSUM|FILESUM))
  1301. -            printf("\n\n\n\n");
  1302. -    }
  1303. -    if (flags & FUNCSUM) {
  1304. -        printfunctionsummary(p);
  1305. -        if (flags & FILESUM)
  1306. -            printf("\n");
  1307. -    }
  1308. -    if (flags & FILESUM) {
  1309. -        printfilesummary(p);
  1310. -        if ((flags & FUNCSUM) && (flags & (INST|BLOCKS)) == 0)
  1311. -            printf("\n\n");
  1312. -    }
  1313. -}
  1314. -
  1315. -int main(argc, argv)
  1316. -    int argc;
  1317. -    char *argv[];
  1318. -{
  1319. -    int c;
  1320. -    bool compact = FALSE;
  1321. -    char *prof = "prof.out";
  1322. -    Mapfile *map;
  1323. -
  1324. -    extern int optind;
  1325. -    extern char *optarg;
  1326. -
  1327. -    progname = argv[0];
  1328. -    while ((c = getopt(argc, argv, "blaipfcr:?")) != EOF)
  1329. -        switch(c) {
  1330. -        case 'b':    flags |= BLOCKS;    break;
  1331. -        case 'l':    flags |= LINES;        break;
  1332. -        case 'a':    flags |= ALL;        break;
  1333. -        case 'i':    flags |= INST;        break;
  1334. -        case 'p':    flags |= FUNCSUM;    break;
  1335. -        case 'f':    flags |= FILESUM;    break;
  1336. -        case 'c':    compact = TRUE;        break;
  1337. -        case 'r':    prof = optarg;        break;
  1338. -        case '?':    usage();
  1339. -        }
  1340. -
  1341. -    if (streq(prof, "-"))
  1342. -        gather(stdin);
  1343. -    else {
  1344. -        FILE *fp = efopen(prof, "r");
  1345. -        gather(fp);
  1346. -        fclose(fp);
  1347. -    }
  1348. -    if (compact) {
  1349. -        if (streq(prof, "-"))
  1350. -            writeprof(stdout);
  1351. -        else {
  1352. -            FILE *fp = efopen(prof, "w");
  1353. -            writeprof(fp);
  1354. -            fclose(fp);
  1355. -        }
  1356. -        if (optind == argc && flags == 0)
  1357. -            return 0;
  1358. -    }
  1359. -
  1360. -    if (flags == 0)
  1361. -        flags = DEFAULT;
  1362. -    if ((flags & (ALL|LINES)) && (flags & (INST|BLOCKS)) == 0)
  1363. -        flags |= BLOCKS;
  1364. -
  1365. -    for (map = maplist; map != NULL; map = map->next)
  1366. -        correlate(map);
  1367. -    if (optind == argc) {
  1368. -        Sourcefile *p;
  1369. -        for (p = sourcelist; p != NULL; p = p->next)
  1370. -            analyze(p->name);
  1371. -    } else
  1372. -        for (; optind < argc; optind++)
  1373. -            analyze(argv[optind]);
  1374. -    return 0;
  1375. -}
  1376. end of lprint.c
  1377. echo ealloc.c 1>&2
  1378. sed 's/^-//' > ealloc.c <<'end of ealloc.c'
  1379. -/* ealloc.c -- error checking malloc */
  1380. -
  1381. -#include <stdio.h>
  1382. -#include "new.h"
  1383. -
  1384. -extern char *progname;
  1385. -
  1386. -/* VARARGS1 */  /* PRINTFLIKE0 */
  1387. -void panic(fmt, a, b, c, d, e, f, g, h)
  1388. -    char *fmt;
  1389. -{
  1390. -    fprintf(stderr, "%s: ", progname);
  1391. -    fprintf(stderr, fmt, a, b, c, d, e, f, g, h);
  1392. -    exit(1);
  1393. -}
  1394. -
  1395. -char *ealloc(n)
  1396. -    int n;
  1397. -{
  1398. -    char *p = malloc(n);
  1399. -    if (p == NULL)
  1400. -        panic("malloc(%d) returned 0\n", n);
  1401. -    return p;
  1402. -}
  1403. -
  1404. -char *erealloc(p, n)
  1405. -    char *p;
  1406. -    int n;
  1407. -{
  1408. -    p = realloc(p, n);
  1409. -    if (p == NULL)
  1410. -        panic("realloc(%d) returned 0\n", n);
  1411. -    return p;
  1412. -}
  1413. -
  1414. -#include <string.h>
  1415. -
  1416. -char *strdup(s)
  1417. -    char *s;
  1418. -{
  1419. -    return strcpy(ealloc(strlen(s) + 1), s);
  1420. -}
  1421. end of ealloc.c
  1422. echo efopen.c 1>&2
  1423. sed 's/^-//' > efopen.c <<'end of efopen.c'
  1424. -/* efopen.c -- open stdio file, check for errors */
  1425. -
  1426. -#include <stdio.h>
  1427. -
  1428. -extern char *progname;
  1429. -
  1430. -FILE *efopen(file, mode)
  1431. -    char *file, *mode;
  1432. -{
  1433. -    FILE *fp = fopen(file, mode);
  1434. -    if (fp == NULL) {
  1435. -        fprintf(stderr, "%s: can't open file %s, mode %s\n",
  1436. -            progname, file, mode);
  1437. -        exit(1);
  1438. -    }
  1439. -    return fp;
  1440. -}
  1441. end of efopen.c
  1442. echo vax.l 1>&2
  1443. sed 's/^-//' > vax.l <<'end of vax.l'
  1444. -/* vax.l -- basic block counting driver for vaxen */
  1445. -
  1446. -%{
  1447. -
  1448. -#include <stdio.h>
  1449. -#include <ctype.h>
  1450. -#include <string.h>
  1451. -#include "bool.h"
  1452. -#include "bb.h"
  1453. -
  1454. -extern void panic();
  1455. -
  1456. -bool newfunc = FALSE;        /* started new function? */
  1457. -
  1458. -%}
  1459. -
  1460. -%%
  1461. -
  1462. -\.stab[dn]\n    { stabd(); return; }
  1463. -\.stabs\n    { stabs(); return; }
  1464. -\.word\n    { word(); return; }
  1465. -\.text\n    { text = TRUE;  passline(); return; }
  1466. -\.data\n    { text = FALSE; passline(); return; }
  1467. -\..*\n        { passline(); return; }
  1468. -
  1469. -nop\n        { safe(); return; }
  1470. -movpsl\n    { safe(); return; }
  1471. -adwc\n        { safe(); return; }
  1472. -
  1473. -[as]ob.+\n    { branch(); return; }
  1474. -case[lwb]\n    { branch(); return; }
  1475. -
  1476. -bi[sc]psw\n    { safe(); return; }
  1477. -bi.+\n        { inst(); return; }
  1478. -b.+\n        { safe(); return; }
  1479. -
  1480. -jsb\n        { inst(); return; }
  1481. -jbr\n        { jbr(); return; }
  1482. -j.+\n        { branch(); return; }
  1483. -.+\n        { inst(); return; }
  1484. -\n        { panic("null opcode"); }
  1485. -
  1486. -%%
  1487. -
  1488. -/* ARGSUSED */
  1489. -bool labelstartsblock(s)
  1490. -    char *s;
  1491. -{
  1492. -    return TRUE;
  1493. -}
  1494. -
  1495. -increment()
  1496. -{
  1497. -    if (instructions >= 0)
  1498. -        fprintf(map, "%d %d\n", reached, instructions);
  1499. -    instructions = 0;
  1500. -    fprintf(out, "    incl    bb+%d\n", 4 * block++);
  1501. -    fprintf(map, "%s %d ", filename, lineno);
  1502. -    newblock = FALSE;
  1503. -}
  1504. -
  1505. -safeincrement()
  1506. -{
  1507. -    fputs("    movpsl    -(sp)\n", out);
  1508. -    increment();
  1509. -    fputs("    movw    (sp)+, (sp)\n    bicpsw    $0xf\n    bispsw    (sp)+\n", out);
  1510. -}
  1511. -
  1512. -jbr()
  1513. -{
  1514. -    if (text && newfunc) {
  1515. -        funcprologue();
  1516. -        newfunc = FALSE;
  1517. -        increment();
  1518. -        instructions++;
  1519. -        reached = lineno;
  1520. -        newblock = TRUE;
  1521. -        passline();
  1522. -    } else
  1523. -        branch();
  1524. -}
  1525. -
  1526. -funcprologue()
  1527. -{
  1528. -    function(label, block);
  1529. -    fprintf(out, "    tstl    bb_init\n    jneq    bb_%s\n", label);
  1530. -    fprintf(out, "    calls    $0, bb_init_func\nbb_%s:\n", label);
  1531. -}
  1532. -
  1533. -word()
  1534. -{
  1535. -    if (text && newblock && label[0] == '_')
  1536. -        newfunc = TRUE;
  1537. -    passline();
  1538. -}
  1539. -
  1540. -epilogue(mapfile)
  1541. -    char *mapfile;
  1542. -{
  1543. -    if (instructions >= 0)
  1544. -        fprintf(map, "%d %d\n", reached, instructions);
  1545. -    if (text)
  1546. -        fprintf(out, "    .data\n");
  1547. -    fprintf(out, "    .lcomm bb, %d\n", 4 * block);
  1548. -    fprintf(out, "bb_mapfile:\n");
  1549. -    fprintf(out, "    .asciz    \"%s\"\n", mapfile);
  1550. -    fprintf(out, "bb_init:\n");
  1551. -    fprintf(out, "    .long    0\n");
  1552. -    fprintf(out, "bb_entry:\n");
  1553. -    fprintf(out, "    .long    0\n");            /* next */
  1554. -    fprintf(out, "    .long    %d\n", block);        /* len */
  1555. -    fprintf(out, "    .long    bb\n");            /* count */
  1556. -    fprintf(out, "    .long    bb_mapfile\n");        /* mapfile */
  1557. -    fprintf(out, "    .text\n");
  1558. -    fprintf(out, "bb_init_func:\n");
  1559. -    fprintf(out, "    .word    0\n");
  1560. -    fprintf(out, "    movl    __bblist, bb_entry\n");
  1561. -    fprintf(out, "    movl    $bb_entry, __bblist\n");
  1562. -    fprintf(out, "    incl    bb_init\n");
  1563. -    fprintf(out, "    ret\n");
  1564. -}
  1565. end of vax.l
  1566. echo 68020.l 1>&2
  1567. sed 's/^-//' > 68020.l <<'end of 68020.l'
  1568. -/* 68020.l -- basic block counting driver for motorola 68020s */
  1569. -
  1570. -%{
  1571. -
  1572. -#include <stdio.h>
  1573. -#include <ctype.h>
  1574. -#include <string.h>
  1575. -#include "bool.h"
  1576. -#include "bb.h"
  1577. -
  1578. -extern void panic();
  1579. -
  1580. -%}
  1581. -
  1582. -%%
  1583. -
  1584. -\.stab[dn]\n        { stabd(); return; }
  1585. -\.stabs\n        { stabs(); return; }
  1586. -\.text\n        { text = TRUE;  passline(); return; }
  1587. -\.data\n        { text = FALSE; passline(); return; }
  1588. -\..*\n            { passline(); return; }
  1589. -\|.+\n            { passline(); return; }
  1590. -
  1591. -link\n            { linkprologue(); return; }
  1592. -
  1593. -movem.+\n        { safe(); return; }
  1594. -trap\n            { safe(); return; }
  1595. -pea\n            { safe(); return; }
  1596. -nop\n            { safe(); return; }
  1597. -[ans]bcd\n        { safe(); return; }
  1598. -(add|neg|sub)x\n    { safe(); return; }
  1599. -un.+\n            { safe(); return; }
  1600. -pack\n            { safe(); return; }
  1601. -rox[lr]\n        { safe(); return; }
  1602. -
  1603. -bchg\n            { inst(); return; }
  1604. -btst\n            { inst(); return; }
  1605. -bclr\n            { inst(); return; }
  1606. -bf.+\n            { inst(); return; }
  1607. -bs.+\n            { inst(); return; }
  1608. -b.+\n            { branch(); return; }
  1609. -
  1610. -jbsr\n            { inst(); return; }
  1611. -jsr\n            { inst(); return; }
  1612. -j.+\n            { branch(); }
  1613. -
  1614. -.+\n            { inst(); return; }
  1615. -\n            { panic("null opcode"); }
  1616. -
  1617. -%%
  1618. -
  1619. -increment()
  1620. -{
  1621. -    if (instructions >= 0)
  1622. -        fprintf(map, "%d %d\n", reached, instructions);
  1623. -    instructions = 0;
  1624. -    fprintf(out, "    addql    #1, bb+%d\n", 4 * block++);
  1625. -    fprintf(map, "%s %d ", filename, lineno);
  1626. -    newblock = FALSE;
  1627. -}
  1628. -
  1629. -safeincrement()
  1630. -{
  1631. -    fputs("    movw    cc, sp@-\n", out);
  1632. -    increment();
  1633. -    fputs("    movw    sp@+, cc\n", out);
  1634. -}
  1635. -
  1636. -linkprologue()
  1637. -{
  1638. -    if (text && label[0] == '_') {
  1639. -        funcprologue();
  1640. -        increment();
  1641. -    }
  1642. -    instructions++;
  1643. -    reached = lineno;
  1644. -    passline();
  1645. -}
  1646. -
  1647. -funcprologue()
  1648. -{
  1649. -    function(label, block);
  1650. -    fprintf(out, "    tstl    bb_init\n    jne    Lbb_%s\n", label);
  1651. -    fprintf(out, "    jbsr    bb_init_func\nLbb_%s:\n", label);
  1652. -}
  1653. -
  1654. -bool labelstartsblock(s)
  1655. -    char *s;
  1656. -{
  1657. -    if (s[0] == 'L' && s[1] == 'L')        /* only used by stab */
  1658. -        return FALSE;
  1659. -    return TRUE;
  1660. -}
  1661. -
  1662. -epilogue(mapfile)
  1663. -    char *mapfile;
  1664. -{
  1665. -    if (instructions >= 0)
  1666. -        fprintf(map, "%d %d\n", reached, instructions);
  1667. -    if (text)
  1668. -        fprintf(out, "    .data\n");
  1669. -    fprintf(out, "    .even\n");
  1670. -    fprintf(out, "    .lcomm    bb, %d\n", 4 * block);
  1671. -    fprintf(out, "bb_init:\n");
  1672. -    fprintf(out, "    .long    0\n");
  1673. -    fprintf(out, "bb_map:\n");
  1674. -    fprintf(out, "    .asciz    \"%s\"\n", mapfile);
  1675. -    fprintf(out, "    .even\n");
  1676. -    fprintf(out, "bb_entry:\n");
  1677. -    fprintf(out, "    .long    0\n");            /* next */
  1678. -    fprintf(out, "    .long    %d\n", block);        /* len */
  1679. -    fprintf(out, "    .long    bb\n");            /* count */
  1680. -    fprintf(out, "    .long    bb_map\n");        /* mapfile */
  1681. -    fprintf(out, "    .text\n");
  1682. -    fprintf(out, "bb_init_func:\n");
  1683. -    fprintf(out, "    movl    __bblist, sp@-\n");
  1684. -    fprintf(out, "    movl    sp@+, bb_entry\n");
  1685. -    fprintf(out, "    movl    #bb_entry, __bblist\n");
  1686. -    fprintf(out, "    movl    #1, bb_init\n");
  1687. -    fprintf(out, "    rts\n");
  1688. -}
  1689. end of 68020.l
  1690.  
  1691.