2010-08-12 49 views
3

短表的操作碼我正在做一個小的語言,這是非常相似的HLSL,但僅支持像素着色器。該語言使用reflection.emit構建實現相同功能的點網絡程序集。我目前正在測試我的分支指令「if」的實現,並且在我的一個單元測試中(如果使用內部if else的話,其大小如果失敗,則顯示以下錯誤消息:錯誤與Reflection.Emit的

System.NotSupportedException:Illegal單字節分支在位置:32支要求是:132

我追查問題使用縮寫形式說明我的情況OpCodes.Br_S。該解決方案很簡單,我已經換成OpCodes.Br OpCodes.Br_S但是我有幾個關於這個解決方案的問題:

該解決方案對生成的代碼對性能的影響? 如果我想正確地生成單個字節的Br_S和其他情況下的Br,我該怎麼做?這裏的問題是,我使用的訪問者模式和分支指令,如「如果」我必須首先輸出Br或Br_s,並且在那時我無法知道剩餘的代碼是否將需要多於單個字節跳轉到標籤。爲了更好地說明我的問題,這是我生成以下語句代碼:

我的語言:

int a = -1; if (1>1) { a=1; } else if(2>2) { a=2; }

IL:

.method public virtual final instance int32 Main() cil managed {

.maxstack 4 
.locals init (
    [0] int32 num) 
L_0000: ldc.i4.m1 
L_0001: stloc.0 
L_0002: ldc.i4.1 
L_0003: ldc.i4.1 
L_0004: ble.s L_000a 
L_0006: ldc.i4.1 
L_0007: stloc.0 
L_0008: br.s L_0010 
L_000a: ldc.i4.2 
L_000b: ldc.i4.2 
L_000c: ble.s L_0010 
L_000e: ldc.i4.2 
L_000f: stloc.0 
L_0010: ldloc.0 
L_0011: ret 

}

在這種情況下,我使用兩個簡短形式的指令ble.s和br.s來實現ifs,就像.net編譯器所做的一樣。然而.NET編譯器能夠根據案例選擇br.s或br,我的問題是我該如何做類似的事情?

TNKS

+3

你的IL有點大,沒什麼大不了的。相信JIT編譯器可以做到這一點。這些微型優化不值得你花時間。 – 2010-08-12 18:05:08

+0

我想這樣做,但我需要自己生成IL,因爲例如在silverlight中沒有c#編譯器。我想在Silverlight中以及在沒有編譯器可用的其他環境中使用它... – 2010-08-12 18:07:41

+0

我相信Hans建議您不要打擾簡短形式(您遇到問題)並使用標準的長形式,因爲這種優化將自動與JIT(Silverlight所具有,就像任何其他CLR impl一樣)發生。 – 2010-08-12 23:05:02

回答

6

如果你想做到這一點,你需要產生分支本身之前計算偏移到分支目標,然後確定偏移小到足以在短格式來達到指令。我不認爲使用Reflection.Emit庫有一個特別簡單的方法。

+0

請,我有興趣瞭解這種迴應。我有類似的問題。你有什麼好說的?你能解釋一些插圖。您也可以指向我可以從中受益的其他資源。提前致謝。 – Tebo 2012-09-24 08:00:02

+2

@ColourBlend - 即使'ILGenerator' API允許你傳入一個標籤(並且框架根據放置標籤的位置來計算相關的偏移量),分支指令的目標就是在IL代碼中指定的偏移量, 。 'Br_S'(和其他短指令)要求偏移量可以適合一個字節(即指令流中不超過127字節的偏移量)。這有幫助嗎? – kvb 2012-09-24 14:03:39

+0

謝謝。這很有幫助。在你回覆之前,我已經仔細研究了一下。 DynamicMethod的運行速度是否等於靜態方法(設計時間方法)?將設計時間方法轉換爲MSIL會提高性能嗎? – Tebo 2012-09-24 16:15:40