[英]How does backpatching work with markers?
一次性代碼生成在為條件生成代碼時存在一個小問題。 典型的if
語句:
if CONDITION then ALTERNATIVE_1 else ALTERNATIVE_2
需要編譯成這樣的東西:
compute CONDITION
JUMP_IF_TRUE label1
JUMP_IF_FALSE label2
label1:
code for ALTERNATIVE_1
JUMP label3
label2:
code for ALTERNATIVE_2
JUMP label3
label3:
next statement
但是當生成CONDITION
的代碼時,不知道label1
和label2
在哪里,並且當生成ALTERNATIVE_1
和ALTERNATIVE_2
的代碼時,不知道label3
在哪里。
一種方法是使用符號名稱作為標簽,如上面的偽代碼,並在知道它們時填寫實際值。 這需要在跳轉語句中存儲符號名稱,這會使數據結構復雜化(特別是,您不能只使用二進制匯編程序代碼)。 它還需要第二次傳球,只是為了填補跳躍目標。
一種(可能)更簡單的方法是只記住跳轉語句的地址,並在知道目標地址時進行補丁。 這稱為“回調”,因為您返回並修補生成的代碼。
事實證明,在許多情況下,您最終會有多個分支到同一個標簽。 典型案例是“短路”布爾值,如C系列的&&
和||
運營商。 例如,擴展原始示例:
if (CONDITION_1 and CONDITION_2) or CONDITION_3 then ALTERNATIVE_1 else ALTERNATIVE_2
compute CONDITION_1
JUMP_IF_TRUE label1
JUMP_IF_FALSE label2
label1:
compute CONDITION_2
JUMP_IF_TRUE label3
JUMP_IF_FALSE label2
label2:
compute CONDITION_3
JUMP_IF_TRUE label3
JUMP_IF_FALSE label4
label3:
code for ALTERNATIVE_1
JUMP label5
label4:
code for ALTERNATIVE_2
JUMP label5
label5:
next statement
事實證明,對於簡單語言,只需要記住兩個不完整的跳轉語句(通常稱為“true”和“false”)。 因為可能有多次跳轉到同一目標,所以這些跳轉實際上是不完整跳轉語句的鏈接列表,其中目標地址用於指向列表中的下一個跳轉。 因此,backpatching遍歷列表,修補正確的目標並使用原始目標查找需要修補的上一個語句。
你所謂的標記 (它是yacc / bison所稱的“中規則制作”的實例)並不與回調真正相關。 它們可用於多種用途。 在一次性代碼生成中,通常需要在規則中間執行某些操作,而回調只是一個示例。
例如,在假設的if
語句中,有必要在解析CONDITION
之前初始化backpatch列表,然后在THEN
和ELSE
子句的開頭進行backpatch。 (另一個backpatch將在整個if
語句的解析結束時觸發,但那個將在規則的finnal操作中。)
在規則中間執行操作的最簡單方法是插入中間規則操作,這相當於使用操作插入空的“標記”生成,如您指向的示例bison文件中所示。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.