2011-08-10 12 views
6

का उपयोग कर फोन मैं LLVM विधानसभा कि तर्क के रूप में लेता है में एक समारोह को परिभाषित करना चाहते:LLVM विधानसभा: एक समारोह varargs

  • एक उप कार्य करने के लिए एक पहचानकर्ता
  • एक vararg

यह फ़ंक्शन को कुछ प्रीप्रोकैसिंग करना चाहिए, पहचानकर्ता के लिए सही फ़ंक्शन ढूंढें और इसे vararg का उपयोग करके कॉल करें, और इसके परिणाम को वापस कर दें।

कुछ की तरह:

define ??? @1 (i32 %identifier, ...vararg...) 
{ 
    switch i32 %identifier, label %def, i32 1, label %a 
a: 
    %1 = tail call @function_for_a, ...vararg... 
    ret ??? %1 
def: 
    ret void 
} 

यह संभव हो सकता है नहीं लगता है। क्या ऐसा करने का कोई तरीका है? मुझे लगता है कि यह सादे असेंबलर का उपयोग करना संभव होना चाहिए।

यह ऑब्जेक्ट उन्मुख भाषा के लिए एक प्रेषण कार्य होने का इरादा है। मैं इसे तेज़ होना पसंद करूंगा।

  • ढेर से दूसरे कार्य करने के लिए @ 1
  • शाखा द्वारा इस्तेमाल किया पहला तर्क निकालें:

    क्या मैं चाहते हैं के लिए एक रास्ता है।

दूसरा फ़ंक्शन पहले (यह पूंछ कॉल है) के स्थान पर निष्पादित किया जाएगा, लेकिन तर्क की एक सूची के साथ जो पहले फ़ंक्शन (पहले फ़ंक्शन के vararg) के लिए बिल्कुल ज्ञात नहीं है।

+0

क्या सी में ऐसे कोड को लिखने का विकल्प है, इसे क्लैंग/एलएलएमएम-जीसीसी के साथ संकलित करें और '.bc' को अलग करें? – osgx

+0

एक llvm disassembler है: 'llvm-dis'। मैं जो करना चाहता हूं वह सी – Mildred

उत्तर

3

पहले: आप पूंछ कॉल उपयोग नहीं कर सकते अगर आप varargs पास करना चाहते हैं:

http://llvm.org/docs/LangRef.html

  1. वैकल्पिक "पूंछ" मार्कर इंगित करता है कि कॉल प्राप्त करने वाला समारोह किसी भी allocas तक नहीं जाते या कॉलर में varargs।

दूसरा: आपके कॉलिंग सम्मेलन क्या हैं?

तीसरा: varargs (जैसे सी में) आप इसे में va_* कार्यों का उपयोग एक नया va_list बनाने के लिए और सभी मापदंडों को कॉपी करने की जरूरत है संभाल करने के लिए:

http://llvm.org/docs/LangRef.html#int-varargs

अंतिम: हर समारोह है जिसके द्वारा बुलाया जाएगा इस प्रेषक को अपने तर्क प्राप्त करने के लिए va_* फ़ंक्शंस का उपयोग करना चाहिए।

अद्यतन:

आप जो सम्मेलन बुला आप का उपयोग करेगा (क्या डिफ़ॉल्ट है) इससे पहले कि आप समारोह तर्कों के भंडारण के रूप में ढेर के बारे में कहेंगे पता होना चाहिए। फिर। आप va_ * फ़ंक्शंस के बिना "..." तर्क पास नहीं कर सकते हैं, क्योंकि यह एलएलवीएम असेंबली में उन्हें एक्सेस करने का एकमात्र तरीका है।

सी में smth करने का एक तरीका है, यहां printf सभी के साथ vfprintf को कॉल करेगा "..."तर्कों और कितने तर्क पारित करने के लिए

// 3-clause BSD licensed to The Regents of the University of California. 

int 
printf(const char *fmt, ...) 
{ 
     int ret; 
     va_list ap; 

     va_start(ap, fmt); 
     ret = vfprintf(stdout, fmt, ap); 
     va_end(ap); 
     return (ret); 
} 

Vfprintf विशेष तरीके से प्राप्त करने के लिए घोषित किया जाता है जानने के बिना" ... "और इसे से तर्क को निकालने के लिए:

int 
vfprintf(FILE *fp, const char *fmt0, __va_list ap) 
{ 
... 
va_arg(ap, type) //to get next arg of type `type` 
+0

में नहीं किया जा सकता है मैंने पहले से ही यह देखा है ... मैंने अपने प्रश्न को संशोधित करने के लिए संशोधित किया है कि मैं बेहतर क्या चाहता हूं – Mildred

+0

मेरा कॉलिंग सम्मेलन जो भी डिफ़ॉल्ट है। और मैं va_ * फ़ंक्शंस का उपयोग नहीं करना चाहता क्योंकि वे जो भी चाहते हैं वह नहीं कर सकते हैं। – Mildred

+0

osgx आपको अधिक मानसिक होना चाहिए। उस दिमाग को थोड़ा बेहतर काम करने के लिए मिलता है! –

1

(इस के लिए बहुत बड़ा बढ़ी एक टिप्पणी। मुझे डर है कि मेरे पास एलएलवीएम के साथ बहुत व्यावहारिक अनुभव नहीं है, इसलिए इसे नमक के अनाज के साथ लें)

मैं इस बारे में सोच रहा हूं और मुझे संदेह है कि आप लिखने में सक्षम होंगे ऐसा फ़ंक्शन।

सी कॉलिंग सम्मेलन का उपयोग करके x86_64 असेंबलर भाषा में इस फ़ंक्शन को लिखने पर विचार करें, या वास्तव में कोई भी जो varargs का समर्थन करता है (उदाहरण के लिए pg. 20 देखें)। आम तौर पर आप ब्रांचिंग से पहले रजिस्टरों (आरडीआई < -rsi, आरएसआई < -rdx और इसी तरह) को स्थानांतरित करेंगे, लेकिन यदि आप तर्क हैं तो आपको ऐसा नहीं करना चाहिए तैरता है, तो आपको प्रकारों के बारे में जानना होगा! या आपको vfprintf-जैसे फ़ंक्शन का उपयोग करना होगा।

अन्य आर्किटेक्चर के लिए इसी तरह के तर्क मौजूद हैं, इसलिए मैं समस्या को हल करने के किसी अन्य तरीके के बारे में सोचने पर विचार करता हूं। विशेष रूप से आप कॉल को @1 पर एक जंप टेबल में देखकर और %identifier द्वारा निर्दिष्ट फ़ंक्शन पॉइंटर पर एक शाखा को प्रतिस्थापित नहीं कर सकते? इसे एक ऐसे फ़ंक्शन में बनाया जा सकता है जो %identifier जांचता है और सही फ़ंक्शन पॉइंटर देता है और अमान्य पहचानकर्ताओं को उचित रूप से संभालता है।

+0

मुझे लगता है कि आप सही हैं, एलएलवीएम असेंबली में ऐसा करने का कोई तरीका नहीं है, मैं चीजों को करने का एक और तरीका ढूंढने की कोशिश करूंगा। मैं कॉलर के लिए अपारदर्शी रहने के लिए '@ 1' के कार्यान्वयन को चाहता हूं, इसलिए यह संभवतः एक फ़ंक्शन पॉइंटर वापस कर देगा और कॉल करने के लिए कॉलर पर होगा। अगर यह सोचता है कि यह बेहतर है तो मैं एलएलवीएम को इनलाइन कर दूंगा। – Mildred