源文件是指可编译生成目标文件或解释为字节代码的任何文件。目标文件通常包含与源代码中的函数、子例程或方法对应的一个或多个可执行代码区域。分析器分析目标文件,标识每个作为函数的可执行区域,并尝试将其在目标代码中找到的函数映射至与目标代码相关联的源文件中的函数、例程、子例程或方法。当分析器操作成功后,它将在带注释的源文件中对应于在目标代码中找到的函数的第一条指令处添加一个索引行。
带注释的源代码会为每个函数(包括内联函数,即使内联函数没有在“函数”标签中的列表中显示)显示一个索引行。在“源”标签中以红色斜体显示索引行,且索引行中的文本括在尖括号中。类型最简单的索引行与函数的缺省上下文对应。任何函数的缺省源上下文都被定义为该函数的第一条指令所归属的源文件。以下示例显示了 C 函数 icputime 的索引行。
0. 0. 600. int 0. 0. 601. icputime(int k) 0. 0. 602. { 0. 0. <Function: icputime> |
从上面的示例能够看出,索引行紧跟在第一条指令行的后面。对于 C 源代码,第一条指令对应于函数体开头的开型花括号处。在 Fortran 源代码中,各个子例程的索引行跟在包含 subroutine 关键字的行后面。同样,main 函数索引行跟在应用程序启动时执行的第一个 Fortran 源代码指令的后面,如以下示例所示:
0. 0. 1. ! Copyright 02/04/2000 Sun Microsystems, Inc. All Rights Reserved 0. 0. 2. ! 0. 0. 3. ! Synthetic f90 program, used for testing openmp directives and 0. 0. 4. ! the analyzer 0. 0. 5. 0. 0. 6. !$PRAGMA C (gethrtime, gethrvtime) 0. 0. 7. 0. 81.497 [ 8] 9000 format(’X ’, f7.3, 7x, f7.3, 4x, a) 0. 0. <Function: main> |
有时,分析器可能无法将它在目标代码中找到的函数映射至与该目标代码相关联的源文件中的任何编程指令;例如,可能从另一个文件(如某个头文件)执行代码 #included 操作或内联操作。
如果目标代码的源代码不是目标代码中包含的函数的缺省源上下文,那么对应于目标代码的带注释的源代码将包含一个特殊索引行,该索引行交叉引用该函数的缺省源上下文。例如,编译 synprog 演示程序将创建对应于源文件 endcases.c 的目标模块 endcases.o。endcases.c 中的源代码声明函数 inc_func,该函数在头文件 inc_func.h 中定义。头文件通常以这种方式包含内联函数定义。由于 endcases.c 中声明函数 inc_func,但 endcases.c 中没有源代码行与 inc_func 的指令对应,因此 endcases.c 的带注释的源文件的顶部会显示一个特殊的索引行,如下所示:
0.650 0.650 <Function: inc_func, instructions from source file inc_func.h> |
该索引行上的度量指示来自 endcases.o 目标模块的部分代码(在源文件 endcases.c 中)不具有行映射。
此外,分析器还会在带注释的源代码中为定义了 inc_func 函数的 inc_func.h 添加一个标准索引行。
.
0. 0. 2. 0. 0. 3. void 0. 0. 4. inc_func(int n) 0. 0. 5. { 0. 0. <Function: inc_func> |
类似地,如果函数具有替代源上下文,则会在缺省源上下文的带注释的源代码中显示交叉引用该上下文的索引行。
0. 0. 142. inc_body(int n) 0.650 0.650 <Function: inc_body, instructions from source file inc_body.h> 0. 0. 143. { 0. 0. <Function: inc_body> 0. 0. 144. #include "inc_body.h" 0. 0. 145. } |
双击引用另一个源上下文的索引行,将在源代码窗口中显示该源文件的内容。
此外,以红色显示的行还有一些特殊索引行,以及其他一些不是编译器注释的特殊行。例如,由于编译器优化的原因,可能会为目标代码中的某个函数创建一个特殊索引行,但该索引行并不对应在任何源文件中编写的代码。有关详细信息,请参阅“源”、“反汇编”和 "PC" 标签中的特殊行。