2011-08-22 13 views
7

में तर्क अग्रेषण मुझे कैली (एलएलवीएम-आईआर में) "फॉरवर्डिंग" तर्कों पर कुछ सलाह चाहिए।एलएलवीएम

मान लीजिए कि मेरे पास फ़ंक्शन है जिसे की शुरुआत में सभी मॉड्यूल में अन्य फ़ंक्शंस में कहा जाता है। F से मुझे अपने तत्काल कॉलर को दिए गए तर्कों को पढ़ने (पढ़ने) की आवश्यकता है।

अभी इस मैं एक struct के अंदर फोन करने वाले के सारे तर्क बॉक्स करते हैं और एक पहचानकर्ता कह जो फोन करने वाले F से बुलाया जा रहा है के साथ, F को struct करने के लिए एक i8* सूचक पारित करने के लिए। F तब एक विशाल स्विच है जो उपयुक्त अनबॉक्सिंग कोड पर शाखाएं हैं। यह किया जाना चाहिए क्योंकि मॉड्यूल में कार्यों में अलग-अलग हस्ताक्षर होते हैं (भिन्न तर्क/वापसी मूल्य गणना और प्रकार; यहां तक ​​कि अलग-अलग कॉलिंग सम्मेलन), लेकिन यह स्पष्ट रूप से उप-विशिष्ट (प्रदर्शन और कोड आकार बिंदु-दृश्य दोनों से) है क्योंकि मैं ढेर पर संरचना आवंटित करने की आवश्यकता है, इसके अंदर तर्कों की प्रतिलिपि बनाएँ, F पर एक अतिरिक्त सूचक पास करना और फिर अनबॉक्सिंग करना।

वहाँ एक बेहतर एक समारोह इसके तत्काल फोन करने वाले के ढेर फ्रेम से पहुंचने का एक तरीका यह करने के लिए जिस तरह से, यानी अगर मैं सोच रहा था (यह जानकर, पहचानकर्ता है, जो फोन करने वाले समारोह से बुलाया गया था करने के लिए धन्यवाद) या , सामान्य रूप से, अपने तत्काल कॉलर में मनमानी मान परिभाषित किया गया है। कोई सुझाव?

नोट: मैं जो काम कर रहा हूं उसका पूरा बिंदु एकल फ़ंक्शन F है जो यह सब करता है; विभाजन/इनलाइनिंग/विशेषज्ञता/टेम्पलेटिंग F एक विकल्प नहीं है।


स्पष्ट करने के लिए, मान लीजिए हम निम्नलिखित कार्य FuncA और FuncB है:

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

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

(नोट! क्या इस प्रकार सिर्फ छद्म सी-कोड, हमेशा याद रखना हम LLVM-आईआर के बारे में बात कर रहे हैं)

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

के रूप में मैं पहले भाग में बताया गया है, अभी मेरी 01,232: मैं क्या जरूरत समारोह F के लिए एक कारगर तरीका निम्न करने के लिए हैइस तरह दिखता है:

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; 
    } 
} 

और दो कार्य बन:

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); 
    // ... 
} 

उत्तर

1

IMHO आप इसे सही किया है। हालांकि मशीनकोड असेंबली में समाधान हैं, मुझे डर है कि एलएलवीएम असेंबली में कोई समाधान नहीं हो सकता है, क्योंकि यह "उच्च स्तर" है। मैं जानता हूँ कि यह प्रत्यक्ष नहीं कर रहा है आप कुछ कार्यों की शुरुआत पर एक समारोह को चलाने के लिए चाहते हैं, तो आप

  • डिबगर स्रोतों (gdb) की तरह
  • बाइनरी इंस्ट्रुमेंटेशन जाँच Valgrind

साथ के बारे में सोचा है जवाब, लेकिन मुझे आशा है कि यह किसी भी तरह से सहायक हो सकता है;)।

+1

dtrace सीएएफएक्सएक्स के वर्णन के समान ही था। – osgx

1

यह सुनिश्चित नहीं करता कि यह मदद करता है, लेकिन मुझे एक ही समस्या थी और इंटरमीडिएट मानों को स्टोर करने के लिए एलएलवीएम वेक्टर का उपयोग कर एलएलवीएम के टीबीएए विश्लेषण की सीमाओं के आसपास हो गया। एलएलवीएम अनुकूलन पास बाद में वेक्टर लोड/स्टोर्स को स्केलर रजिस्टरों में अनुकूलित करने में सक्षम थे।

मुझे याद करते हुए कुछ चेतावनी थीं। अगर आप इस मार्ग का पता लगाते हैं तो मुझे बताएं और मैं कुछ कोड खोद सकता हूं।