GCC 3
Section: GNU Tools (1)
Updated: 2003/12/05
-
調試選項(DEBUGGING OPTION)
GNU CC擁有許多特別選項,既可以調試用戶的程序,也可以對GCC排錯:
- -g
- 以操作系統的本地格式(stabs, COFF, XCOFF,或DWARF).產生調試信息. GDB能夠使用這些調試信息.
在大多數使用stabs格式的系統上, `-g'選項啟動只有GDB才使用的額外調試信息;這些信息使GDB 調試效果更好,但是有可能導致其他調試器崩潰,或拒絕讀入程序.如果你確定要控制是否生成額外的信息, 使用`-gstabs+', `-gstabs', `-gxcoff+', `-gxcoff', `-gdwarf+',或`-gdwarf' (見下文).
和大多數C編譯器不同, GNU CC允許結合使用`-g'和`-O'選項.優化的代碼偶爾制造 一些驚異的結果:某些聲明過的變量根本不存在;控制流程直接跑到沒有預料到的地方;某些語句因為計算結果是常量或已經確定而 沒有執行;某些語句在其他地方執行,因為他們被移到循環外面了.
然而它證明了調試優化的輸出是可能的.對可能含有錯誤的程序使用優化器是合理的.
如果GNU CC支持輸出多種調試信息,下面的選項則非常有用.
- -ggdb
- 以本地格式(如果支持)輸出調試信息,盡可能包括GDB擴展.
- -gstabs
- 以stabs格式(如果支持)輸出調試信息,不包括GDB擴展.這是大多數BSD系統上DBX使用的格式.
- -gstabs+
- 以stabs格式(如果支持)輸出調試信息,使用只有GNU調試器(GDB)理解的GNU擴展.使用這些擴展有可能導致 其他調試器崩潰或拒絕讀入程序.
- -gcoff
- 以COFF格式(如果支持)輸出調試信息.這是在System V第四版以前的大多數System V系統上SDB使用的 格式.
- -gxcoff
- 以XCOFF格式(如果支持)輸出調試信息.這是IBM RS/6000系統上DBX調試器使用的格式.
- -gxcoff+
- 以XCOFF格式(如果支持)輸出調試信息,使用只有GNU調試器(GDB)理解的GNU擴展.使用這些擴展有可能導致 其他調試器崩潰或拒絕讀入程序.
- -gdwarf
- 以DWARF格式(如果支持)輸出調試信息.這是大多數System V第四版系統上SDB使用的格式.
- -gdwarf+
- 以DWARF格式(如果支持)輸出調試信息,使用只有GNU調試器(GDB)理解的GNU擴展.使用這些擴展有可能導致 其他調試器崩潰或拒絕讀入程序.
-glevel
-ggdblevel
-gstabslevel
-gcofflevel -gxcofflevel
- -gdwarflevel
- 請求生成調試信息,同時用level指出需要多少信息.默認的level值是2.
Level 1輸出最少量的信息,僅夠在不打算調試的程序段內backtrace.包括函數和外部變量的描述,但是 沒有局部變量和行號信息.
Level 3包含更多的信息,如程序中出現的所有宏定義.當使用`-g3'選項的時候,某些調試器支持 宏擴展.
- -p
- 產生額外代碼,用于輸出profile信息,供分析程序prof使用.
- -pg
- 產生額外代碼,用于輸出profile信息,供分析程序gprof使用.
- -a
- 產生額外代碼,用于輸出基本塊(basic block)的profile信息,它記錄各個基本塊的執行次數,供諸如 tcov此類的程序分析.但是注意,這個數據格式并非tcov期待的.最終GNU gprof 將處理這些數據.
- -ax
- 產生額外代碼,用于從'bb.in'文件讀取基本塊的profile參數,把profile的結果寫到'bb.out' 文件. `bb.in'包含一張函數列表.一旦進入列表中的某個函數, profile操作就開始,離開最外層的函數后, profile操作就結束.以`-'為前綴名的函數排除在profile操作之外.如果函數名不是唯一的,它可以寫成 `/path/filename.d:functionname'來澄清. `bb.out'將列出一些有效的文件名.這四個函數名具有 特殊含義: `__bb_jumps__'導致跳轉(jump)頻率寫進`bb.out'. `__bb_trace__'導致基本塊序列通過 管道傳到`gzip',輸出`bbtrace.gz'文件. `__bb_hidecall__'導致從跟蹤(trace)中排除call 指令. `__bb_showret__'導致在跟蹤中包括返回指令.
- -dletters
- 編譯的時候,在letters指定的時刻做調試轉儲(dump).用于調試編譯器.大多數轉儲的文件名 通過源文件名添加字詞獲得(例如`foo.c.rtl'或`foo.c.jump').
- -dM
- 預處理結束的時候轉儲所有的宏定義,不輸出到文件.
- -dN
- 預處理結束的時候轉儲所有的宏名.
- -dD
- 預處理結束的時候轉儲所有的宏定義,同時進行正常輸出.
- -dy
- 語法分析(parse)的時候在標準錯誤轉儲調試信息.
- -dr
- RTL階段后轉儲到`file.rtl'.
- -dx
- 僅對函數生成RTL,而不是編譯.通常和`r'聯用.
- -dj
- 第一次跳轉優化后轉儲到`file.jump'.
- -ds
- CSE (包括有時候跟在CSE后面的跳轉優化)后轉儲到`file.cse'.
- -dL
- 循環優化后轉儲到`file.loop'.
- -dt
- 第二次CSE處理(包括有時候跟在CSE后面的跳轉優化)后轉儲到`file.cse2'.
- -df
- 流程分析(flow analysis)后轉儲到`file.flow'.
- -dc
- 指令組合(instruction combination)后轉儲到`file.combine'.
- -dS
- 第一次指令安排(instruction schedule)后轉儲到`file.sched'.
- -dl
- 局部寄存器分配后轉儲到`file.lreg'.
- -dg
- 全局寄存器分配后轉儲到`file.greg'.
- -dR
- 第二次指令安排(instruction schedule)后轉儲到`file.sched2'.
- -dJ
- 最后一次跳轉優化后轉儲到`file.jump2'.
- -dd
- 推遲分支調度(delayed branch scheduling)后轉儲到`file.dbr'.
- -dk
- 寄存器-堆棧轉換后轉儲到`file.stack'.
- -da
- 產生以上所有的轉儲.
- -dm
- 運行結束后,在標準錯誤顯示內存使用統計.
- -dp
- 在匯編輸出加注指明使用了哪些模式(pattern)及其替代模式.
- -fpretend-float
- 交叉編譯的時候,假定目標機和宿主機使用同樣的浮點格式.它導致輸出錯誤的浮點常數,但是在目標機上運行的時候, 真實的指令序列有可能和GNU CC希望的一樣.
- -save-temps
- 保存那些通常是``臨時''的中間文件;置于當前目錄下,并且根據源文件命名.因此,用`-c -save-temps'選項編譯`foo.c '會生成` foo.cpp'和`foo.s' 以及`foo.o'文件.
- -print-file-name=library
- 顯示庫文件library的全路徑名,連接時會使用這個庫---其他什么事情都不作.根據這個選項, GNU CC既不編譯,也不連接,僅僅顯示文件名.
- -print-libgcc-file-name
- 和`-print-file-name=libgcc.a'一樣.
- -print-prog-name=program
- 類似于`-print-file-name',但是查找程序program如`cpp'.
優化選項(OPTIMIZATION OPTION)
這些選項控制多種優化措施:
- -O
-
- -O1
- 優化.對于大函數,優化編譯占用稍微多的時間和相當大的內存.
不使用`-O'選項時,編譯器的目標是減少編譯的開銷,使編譯結果能夠調試.語句是獨立的:如果在 兩條語句之間用斷點中止程序,你可以對任何變量重新賦值,或者在函數體內把程序計數器指到其他語句,以及從源程序中 精確地獲取你期待的結果.
不使用`-O'選項時,只有聲明了register的變量才分配使用寄存器.編譯結果比不用 `-O'選項的PCC要略遜一籌.
使用了`-O'選項,編譯器會試圖減少目標碼的大小和執行時間.
如果指定了`-O'選項, `-fthread-jumps'和`-fdefer-pop'選項將被 打開.在有delay slot的機器上, `-fdelayed-branch'選項將被打開.在即使沒有幀指針 (frame pointer)也支持調試的機器上, `-fomit-frame-pointer'選項將被打開.某些機器上 還可能會打開其他選項.
- -O2
- 多優化一些.除了涉及空間和速度交換的優化選項,執行幾乎所有的優化工作.例如不進行循環展開(loop unrolling)和函數內嵌(inlining).和-O選項比較,這個選項既增加了編譯時間,也提高了生成代碼的 運行效果.
- -O3
- 優化的更多.除了打開-O2所做的一切,它還打開了-finline-functions選項.
- -O0
- 不優化.
如果指定了多個-O選項,不管帶不帶數字,最后一個選項才是生效的選項.
諸如`-fflag'此類的選項描述一些機器無關的開關.大多數開關具有肯定和否定兩種格式; `-ffoo'開關選項的否定格式應該是`-fno-foo'.下面的列表只展示了一種格式---那個不是 默認選項的格式.你可以通過去掉或添加`no-'構造出另一種格式.
- -ffloat-store
- 不要在寄存器中存放浮點變量.這樣可以防止某些機器上不希望的過高精度,如68000的浮點寄存器(來自 68881)保存的精度超過了double應該具有的精度.
對于大多數程序,過高精度只有好處.但是有些程序嚴格依賴于IEEE浮點數的定義.對這樣的程序可以使用 `-ffloat-store'選項.
- -fmemoize-lookups
-
- -fsave-memoized
- 使用探索法(heuristic)進行更快的編譯(僅對C++).默認情況下不使用探索法.由于探索法只對某些輸入文件 有效,其他程序的編譯速度會變得更慢.
第一次編譯器必須對成員函數(或對成員數據的引用)建立一個調用.它必須(1)判斷出這個類是否實現了那個名字的 成員函數; (2)決定調用哪個成員函數(涉及到推測需要做哪種類型轉換); (3)檢查成員函數對調用者是否可見.所有這些構成 更慢的編譯.一般情形,第二次對成員函數(或對成員數據的引用)建立的調用,必須再次經過相同長度的處理.這意味著象 這樣的代碼
cout << "This " << p << " has " << n << " legs.\n";
對整個三步驟要做六次遍歷.通過使用軟件緩存, ``命中''能夠顯著地減少這種代價.然而不幸的是,使用這種緩存 必須實現其他機制,帶來了它自己的開銷. `-fmemoize-lookups'選項打開軟件緩存.
因為函數的正文環境不同,函數對成員和成員函數的訪問權(可見性)也可能不同, g++可能需要刷新緩存. 使用`-fmemoize-lookups'選項,每編譯完一個函數就刷新緩存.而`-fsave-memoized'選項 也啟用同樣的緩存,但是當編譯器發覺最后編譯的函數的正文環境產生的訪問權和下一個待編譯的函數相同,編譯器就 保留緩存內容.這對某個類定義許多成員函數時非常有用:除了某些其他類的友函數,每個成員函數擁有和其他成員函數完全一樣 的訪問權,因而無需刷新緩存.
- -fno-default-inline
- 默認為不要把成員函數內嵌,因為它們定義在類的作用域內(僅C++).
- -fno-defer-pop
- 一旦函數返回,參數就立即彈出.對于那些調用函數后必須彈出參數的機器,編譯器一般情況下讓幾次函數調用的參數 堆積在棧上,然后一次全部彈出.
- -fforce-mem
- 做數學運算前把將要使用的內存操作數送入寄存器.通過把內存訪問轉換成潛在的公共子表達式,它可能產生較好的目標碼. 如果它們不是公共子表達式,指令組合應該消除各自的寄存器載荷.我樂意傾聽不同意見.
- -fforce-addr
- 做數學運算前把將要使用的內存地址常數送入寄存器.它可能和`-fforce-mem'一樣產生較好的 目標碼.我樂意傾聽不同意見.
- -fomit-frame-pointer
- 對于不需要幀指針(frame pointer)的函數,不要在寄存器中保存幀指針.這樣能夠避免保存,設置和恢復 幀指針的指令;同時對許多函數提供一個額外的寄存器. 但是在大多數機器上將無法調試.
某些機器上,如Vax,這個選項無效,因為標準調用序列自動處理幀指針,通過假裝不存在而不保存任何東西.機器描述宏 FRAME_POINTER_REQUIRED控制目標機是否支持這個選項.
- -finline-functions
- 把所有簡單的函數集成進調用者.編譯器探索式地決定哪些函數足夠簡單,值得這種集成.
如果集成了所有給定函數的調用,而且函數聲明為static,那么一般說來GCC有權不按匯編代碼輸出函數.
- -fcaller-saves
- 允許在寄存器里分配數值,但是這個方案通常受到各個函數調用的沖擊,因此GCC生成額外的代碼,在函數調用的 前后保存和復原寄存器內容.僅當生成代碼看上去優于反之結果時才實現這樣的分配.
某些機器上該選項默認為允許,通常這些機器沒有調用保護寄存器代替使用.
- -fkeep-inline-functions
- 即使集成了某個函數的所有調用,而且該函數聲明為static,仍然輸出這個函數一個獨立的,運行時可調用 的版本.
- -fno-function-cse
- 不要把函數地址存入寄存器;讓調用固定函數的指令顯式給出函數地址.
這個選項產生效率較低的目標碼,但是如果不用這個選項,某些不尋常的hack,改變匯編器的輸出,可能因優化而帶來 困惑.
- -fno-peephole
- 禁止任何機器相關的peephole優化.
- -ffast-math
- 這個選項出于速度優化,允許GCC違反某些ANSI或IEEE規則/規格.例如,它允許編譯器假設sqrt 函數的參數是非負數.
這個選項不被任何`-O'選項打開,因為對于嚴格依靠IEEE或ANSI規則/規格實現的數學函數,程序可能 會產生錯誤的結果.
下列選項控制特定的優化. `-O2'選項打開下面的大多數優化項,除了`-funroll-loops'和 `-funroll-all-loops'項.
而`-O'選項通常打開`-fthread-jumps'和`-fdelayed-branch' 優化項,但是特定的機器上的默認優化項有可能改變.
如果特別情況下非常需要``微調''優化,你可以使用下面的選項.
- -fstrength-reduce
- 執行循環強度縮小(loop strength reduction)優化,并且消除重復變量.
- -fthread-jumps
- 執行優化的地點是,如果某個跳轉分支的目的地存在另一個條件比較,而且該條件比較包含在前一個比較語句之內,那么 執行優化.根據條件是true或者false,前面那條分支重定向到第二條分支的目的地或者緊跟在第二條分支后面.
- -funroll-loops
- 執行循環展開(loop unrolling)優化.僅對循環次數能夠在編譯時或運行時確定的循環實行.
- -funroll-all-loops
- 執行循環展開(loop unrolling)優化.對所有循環實行.通常使程序運行的更慢.
- -fcse-follow-jumps
- 在公共子表達式消元(common subexpression elimination)的時候,如果沒有其他路徑到達某個跳轉的 目的地,就掃過這條jump指令.例如,如果CSE遇到帶有else從句的if語句,當條件測試為 false時, CSE就跟在jump后面.
- -fcse-skip-blocks
- 它類似于`-fcse-follow-jumps'選項,但是CSE跟在條件跳轉后面,條件跳轉跳過了 語句塊(block).如果CSE遇到一條簡單的if語句,不帶else從句, `-fcse-skip-blocks'選項將導致CSE跟在if產生的跳轉后面.
- -frerun-cse-after-loop
- 執行循環優化后,重新進行公共子表達式消元.
- -felide-constructors
- 如果看上去合理就省略構造子(僅C++).根據這個選項,對于下面的代碼, GNU C++直接從調用foo 初始化y,而無需通過臨時變量:
A foo (); A y = foo ();
如果沒有這個選項, GNU C++首先通過調用類型A 合適的構造子初始化y;然后把 foo的結果賦給臨時變量;最后,用臨時變量替換`y'的初始值.
ANSI C++標準草案規定了默認行為(`-fno-elide-constructors').如果程序的構造子存在 副效應, `-felide-constructors'選項能夠使程序有不同的表現,因為可能忽略一些構造子的調用.
- -fexpensive-optimizations
- 執行一些相對開銷較大的次要優化.
- -fdelayed-branch
- 如果對目標機支持這個功能,它試圖重新排列指令,以便利用延遲分支(delayed branch)指令后面的指令空隙.
- -fschedule-insns
- 如果對目標機支持這個功能,它試圖重新排列指令,以便消除因數據未緒造成的執行停頓.這可以幫助浮點運算或內存訪問 較慢的機器調取指令,允許其他指令先執行,直到調取指令或浮點運算完成.
- -fschedule-insns2
- 類似于`-fschedule-insns'選項,但是在寄存器分配完成后,需要一個額外的指令調度過程.對于 寄存器數目相對較少,而且取內存指令大于一個周期的機器,這個選項特別有用.
目標機選項(TARGET OPTION)
缺省情況下, GNU CC編譯出本機類型的目標碼.然而也可以把他安裝成交叉編譯器, 為其他機型編譯程序.事實上,針對不同的目標機,可以同時安裝GNU CC相應的配置.然后用`-b'選項指定 目標機種.
順便提一下,新版本和舊版本的GNU CC可以共存.其中一個版本(可能是最新的那個)為缺省版本,但是有時候你希望使用 其他版本.
- -b machine
- 參數machine指出編譯的目標機種.這個選項用于安裝為交叉編譯器的GNU CC.
參數machine的值和配置GNU CC交叉編譯器時設置的機器類型一樣.例如,如果交叉編譯器配置有 `configure i386v',意思是編譯80386上的System V目標碼,那么你可以通過`-b i386v'運行交叉編譯器.
如果沒有指定`-b'選項,通常指編譯本機目標碼.
- -V version
- 參數version指出運行哪個版本的GNU CC.這個選項用于安裝了多個版本的GCC.例如,如果 version是`2.0',意味著運行GNU CC 2.0版.
如果沒有指定`-V'選項,缺省版本取決于GNU CC的安裝方式,一般說來推薦使用通用版本.