簡體   English   中英

從 gcc/clang (C++) 中的 function scope 中獲取 label 地址

[英]Get a label address out of the function scope in gcc/clang (C++)


由於本地 label 地址,我正在制作某種解釋器,並且正在計算 static const 跳轉表。
你知道鑽頭, static const int JUMP_TABLE[] = { &&case0 - &&case0, &&case1 - &&case0等等。
由於各種原因,主要是性能,我想在初始化期間將這個表復制/壓縮到 object 中。
我的頭撞牆了,因為我不知道如何逃避 function 的詞匯范圍!

如何以某種方式從另一個 function 引用 &&case0?

有人對此有一個很好的技巧嗎?
提前致謝

我不知道在純 GNU C 中實現這一點的方法,因此下面的方法使用其他機制。

雙編譯

您可以編譯您的 object 文件兩次,在第一次運行時收集偏移量並在第二次運行時使用它們。 例如

int foo(int x) {
#ifdef GENERATE_ADDRESSES
    static __attribute__((section(".foo_offsets"))) unsigned offsets[] = { &&case0 - &&case0, &&case1 - &&case0 };
#endif
    switch (x) {
case0:
        case 0:
            return 1;
case1:
        case 1:
            return 2;
    }
    return 0;
}

現在您可以編譯,從.foo_offsets部分中提取字節,並在第二次運行時將它們嵌入到您的應用程序中

$ gcc tmp.c -c -DGENERATE_ADDRESSES
$ objcopy -j .foo_offsets -O binary tmp.o
$ xxd -i tmp.o | tee offsets.inc
unsigned char tmp_o[] = {
  0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00
};
unsigned int tmp_o_len = 8;

內聯裝配

您可以使用內聯匯編來全球化標簽:

extern char foo_case0[];
extern char foo_case1[];
const void *foo_addresses[] = { &foo_case0[0], &foo_case1[0] };

int foo(int x) {
    switch (x) {
        case 0:
asm("foo_case0:");
            return 1;
        case 1:
asm("foo_case1:");
            return 2;
    }
    return 0;
}

不幸的是,在這種情況下,您只能收集地址(而不是偏移量),因此您需要在啟動時手動計算偏移量。

有時 Goto 只是最好的解決方案。 非常罕見。 多年后它仍然是 c++ 的一部分,這是有充分理由的

所以我所做的是創建一個全局布爾值並在初始化地址數組后設置它。 因此,第一次調用我的解釋器 function 時,它會加載地址結構,因此所有內容都在同一個 function 內。

然后通過對匯編程序 output 的一些研究,我能夠通過如下安排我的代碼來節省一些滴答聲。

if(is_initialized).. ex 命令 else... 初始化東西。 轉到前命令

使用 goto 跳回頂部並執行命令。 我的解釋器使用了近 200 個命令。

使用 switch 語句需要 5-1100 個滴答聲。 取決於命令在列表中的位置

無論命令在列表中的哪個位置,使用 goto functions[command] 都會將其降至 14

這提供了一種純 c++ 但並非所有編譯器都支持的方法

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM