2011-08-22 14 views
7

"İletim" argümanlarının bir arayana (LLVM-IR'de) ilişkin bazı önerilere ihtiyacım var.Bağımsız değişken iletme LLVM

Bir modülde tüm diğer işlevlerinin başında çağrılan bir işlev var F varsayalım. F'dan derhal arayana iletilen argümanlara erişmem gerekiyor. Şu anda

Ben bir yapı içindeki arayan tüm argümanları kutu Bunu yapmak ve arayan F gelen çağrılan bir tanımlayıcı anlatma yanında F için yapı için bir i8* işaretçi geçmek. F, daha sonra uygun kutulama koduna giden dev bir anahtara sahip. Bu, modüldeki işlevlerin farklı imzalara (farklı argüman/dönüş değeri sayısı ve türleri; farklı arama kuralları bile) sahip olduğu için yapılmalıdır, ancak açıkçası (hem performanstan hem de kod boyutunda bir bakış açısından) düşüktür. Yapının yığında ayrılması, içindeki argümanların kopyalanması, F'a ek bir işaretçinin iletilmesi ve sonra kutunun çıkarılması gerekir.

yani yapmak için daha iyi bir yolu, bir fonksiyonun onun hemen arayanın yığın çerçevesi erişmek için bir yol ise I (, işlev çağrılabilir arayan taraf tanımlayıcısı, sayesinde bilerek) merak veya Genel olarak numaralı telefon hattında tanımlanmış keyfi değerler. Baska öneri?

not: üzerinde çalıştıklarımın tüm noktası, tek işlevi olan F işlevini yerine getirmektedir; bölme/satır içi/özelleştirme/şablonlama F bir seçenek değil. netleştirmek için


, biz FuncA ve FuncB aşağıdaki işlevleri olduğunu varsayalım:

Type1 FuncA(Type2 ArgA1) { 
    F(); 
    // ... 
} 

Type3 FuncB(Type4 ArgB1, Type5 ArgB2, Type6 ArgB3) { 
    F(); 
    // ... 
} 

(not! ne şu sadece sözde-C-kodu, her zaman LLVM-IR bahsediyoruz hatırlıyorum olan)

void F() { 
    switch (caller) { 
    case FuncA: 
     // do something with ArgA1 
     break; 
    case FuncB: 
     // do something with ArgB1, ArgB2, ArgB3 
     break; 
    } 
} 

ben ilk bölümde açıklandığı gibi, şu anda benim: ne gerek aşağıdakileri yapmak fonksiyonu F için etkili bir yoldur

struct Args_FuncA { Type2 ArgA1 }; 
struct Args_FuncB { Type4 ArgB1, Type5 ArgB2, Type6 ArgB3 }; 

void F(int callerID, void *args) { 
    switch (callerID) { 
    case ID_FuncA: 
     Args_FuncA *ArgsFuncA = (Args_FuncA*)args; 
     Type2 ArgA1 = ArgsFuncA->ArgA1; 
     // do something with ArgA1 
     break; 
    case ID_FuncB: 
     Args_FuncB *ArgsFuncB = (Args_FuncB*)args; 
     Type4 ArgB1 = ArgsFuncB->ArgB1; 
     Type5 ArgB2 = ArgsFuncB->ArgB2; 
     Type6 ArgB3 = ArgsFuncB->ArgB3; 
     // do something with ArgB1, ArgB2, ArgB3 
     break; 
    } 
} 

ve iki işlev haline:şöyle bunu doğru

Type1 FuncA(Type2 ArgA1) { 
    Args_FuncA args = { ArgA1 }; 
    F(ID_FuncA, (void*)&args); 
    // ... 
} 

Type3 FuncB(Type4 ArgB1, Type5 ArgB2, Type6 ArgB3) { 
    Args_FuncB args = { ArgB1, ArgB2, ArgB3 }; 
    F(ID_FuncB, (void*)&args); 
    // ... 
} 

cevap

1

yaptık IMHO. Makine kodu montajında ​​çözümler olsa da, LLVM montajında ​​“daha ​​yüksek seviye” olduğu için hiçbir çözüm bulunamayacağından korkuyorum. Bazı fonksiyonların başında bir fonksiyonu çalıştırmak için isterseniz Valgrind

ile (gdb gibi)

  • ayıklayıcı kaynakları
  • İkili Enstrümantasyon kontrol düşündün mü bunu doğrudan değil biliyorum cevap, ama umarım bir şekilde yararlı olabilir;).

+1

DTrace çok aynısını yaptı. – osgx

1

emin değil bu yardımcı olur, ama benzer bir sorun vardı ve ara değerleri saklamak için bir LLVM vektörü kullanarak LLVM en tbaa analizinin sınırlamalar var eğer. LLVM optimizasyon geçtiği sonradan sayıl kayıtları içine vektör yük/mağaza optimize başardık. Hatırladığım kadarıyla

birkaç uyarılar vardı. Bu yolu keşfetmek ve bazı kod kazıp eğer bana bildirin. CAFxX olarak tanımladığı