OCaml çağrı kuralını bulmaya çalışıyorum, böylece gdb'nin ayrıştırılamadığı yığın izlerini elle yorumlayabiliyorum. Maalesef, genel gözlemler haricinde İngilizce'de hiçbir şey yazılmamış gibi görünüyor. Örneğin, insanlar, bloglarda OCaml'ın kayıtlardaki birçok argümanı geçtiğini söyleyecektir. (Bir yerde İngilizce belgeleri varsa, bir bağlantı çok takdir edilecektir.)OCaml çağrı kuralı: Bu doğru bir özet midir?
Ocamlopt kaynağından çıkarmaya çalışıyorum. Bu tahminlerin doğruluğunu herkes onaylayabilir mi?
Ve eğer ilk on argüman hakkında kayıtlara geçtiysem haklıysam, argümanları genelde bir işlev çağrısına kavuşturmak mümkün olmaz mı? C'de, argümanlar hala bir yere doğru itilirdi, eğer sadece doğru çerçeveye geri dönersem. OCaml'da, kandillerin arayanlarının argümanlarını yok etmekte özgür oldukları görülüyor. ilk 10 tam sayı ve işaretçi argümanlar kayıt rax, RgX RDI, RSI geçirilir
- , OCaml işlevlerini çağrı için
(
/asmcomp/amd64/proc.ml
den)
Kayıt ayırma rxx, rcx, r8, r9, r10 ve r11
- İlk 10 kayan nokta argümanı, xmm0 - xmm9 kayıtlarından geçirilir.
- Ek argümanlar yığının üzerine itilir (En soldaki ilk giren?), mantarlar ve int ve işaretçiler
- tuzak işaretçi (aşağıdaki İstisnalar bakınız) muhtemelen bu blog post tarif edildiği gibi küçük yığın için R14
- ayırma işaretçi (geçirilen) R15
- The geçirilir karışmış bir tamsayı veya işaretçi ise, dönüş değeri geri döndürülürse ve xmm0'de bir float varsa
- Tüm kayıtlar arayan kaydedicidir? Cı işlevlerini çağrı için
, standart amd64'tür Cı kuralı kullanılır:
- ilk altı tam sayı ve işaretçi argümanlar RDI, RSI, RDX RCS, R8 ve R9'un hiçbirinin geçirilir
- ilk sekiz yüzer argümanlar xmm0 geçirilir - xmm7
- ek bağımsız değişkenler yığın bir dönüş değeri rax Lütfen geçirilir
- veya xmm0 itilir
- kayıt, RBP rbx ve R12 - tasarrufu Aranan R15
gönderici adresi birinci işaretçi uygun olarak, çağrı çerçeve içine itilir
(/asmcomp/amd64/emit.mlp
gelen) geri adresi amd64 C sözleşmesi. (Ben tahmin ediyorum ret
talimat bu düzeni varsayar./asmcomp/linearize.ml
itibaren)
İstisnalar()
kod try (...body...) with (...handler...); (...rest...)
böyle doğrusallaştırılmış alır: Sağdaki (hedefleri)
Lsetuptrap .body
(...handler...)
Lbranch .join
Llabel .body
Lpushtrap
(...body...)
Lpoptrap
Llabel .join
(...rest...)
ve sonra böyle montaj olarak yayılan:
call .body
(...handler...)
jmp .join
.body:
pushq %r14
movq %rsp, %r14
(...body...)
popq %r14
addq %rsp, 8
.join:
(...rest...)
Vücudun herhangi bir yerinde doğrusal bir opcode var Lraise
, bu tam montaj olarak gönderilir:
movq %r14, %rsp
popq %r14
ret
Gerçekten temiz! Bu setjmp/longjmp iş yerine, dönüş adresi istisna işleyicisi olan ve yalnızca yerel olan önceki bu kukla çerçeve olan bir kukla çerçeve oluşturuyoruz. /asmcomp/amd64/proc.ml
, "trap işaretçisi" $ r14'ü arayarak bir yorum içerir, bu yüzden bu kukla çerçeveyi tuzak çerçevesine çağıracağım. Bir istisnayı yükseltmek istediğimizde, yığın işaretçisini en son tuzak çerçevesine ayarlıyoruz, tuzak işaretçisini bundan önceki tuzak çerçevesine ayarlıyoruz ve sonra istisna eylemciye "geri dönüyoruz". Ve bahse girerim, istisna eylemcisi bu istisnayı kaldıramazsa, sadece yeniden değerlendirir.
İstisnası% eax.