home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / compsrcs / unix / volume20 / lcomp < prev    next >
Encoding:
Internet Message Format  |  1989-10-27  |  41.5 KB

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