<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                LLVM平臺,短短幾年間,改變了眾多編程語言的走向,也催生了一大批具有特色的編程語言的出現,不愧為編譯器架構的王者,也榮獲2012年ACM軟件系統獎 —— 題記 版權聲明:本文為 西風逍遙游 原創文章,轉載請注明出處 西風世界 [http://blog.csdn.net/xfxyy_sxfancy](http://blog.csdn.net/xfxyy_sxfancy) # 函數的調用及基本運算符 之前我們提到了函數的定義,那么,定義好的函數如何調用才行呢?今天我們就來了解一下,函數的調用。 ### 函數調用的宏形式 我們去讀之前對函數調用的語法樹翻譯形式: ~~~ printf("%d\n", y); ~~~ 會被翻譯為: ~~~ Node String call String printf String %d\n ID y ~~~ 這個宏的名字是call,是個不定參數的: ~~~ (call 函數名 參數表... ) ~~~ 于是我們就需要掃描參數表,獲取全部調用參數。 ### 調用宏的基本形式 調用宏其實很簡單,就是不斷循環判斷有多少參數即可。 ~~~ static Value* call_macro(CodeGenContext* context, Node* node) { // 參數一 函數名 // 其余參數 要傳入的參數 for (Node* p = node->getNext(); p != NULL; p = p->getNext()) { // 循環獲取參數 } } ~~~ 另外我們查閱一下LLVM的文檔,找到其中CallInst這個指令,LLVM的指令都派生自Instruction,可以發現構建的方法很簡單: ~~~ static CallInst * Create (Value *Func, ArrayRef< Value * > Args, const Twine &NameStr, BasicBlock *InsertAtEnd) ~~~ 但是我們發現,Value中要傳輸的是一個Function對象,如何獲取呢?當然還是從符號表中獲取,我們下次會講符號表的實現,這次也和上節一樣,將接口先寫出來。 ~~~ // 參數一 函數名 Value* func = context->getFunction(node); if (func == NULL) { errs() << "找不到函數的定義:"; errs() << node->getStr().c_str() << "\n"; exit(1); } ~~~ 函數調用在生成時,如果這個函數還沒有被掃描到,那么在生成時會報函數定義找不到的問題,這就是我們為什么要用多遍掃描。只有充分的多次掃描語法樹,才能獲取每個函數后面的函數定義。雖然像C語言那樣強制聲明也可以,但我個人不大喜歡這種風格。 至于參數的獲取,就十分簡單的,但有一點要注意,參數是遞歸生成的,例如: ~~~ printf("%d", add(3, 5)); ~~~ 這時,我們在獲取參數時,就會發現,其中一個參數是表達式,那么我們就要先對其進行處理: ~~~ // 其余參數 要傳入的參數 std::vector<Value*> args; for (Node* p = node->getNext(); p != NULL; p = p->getNext()) { Value* v = p->codeGen(context); // 遞歸地生成參數 if (v != NULL) args.push_back(v); } ~~~ Node類下面有實現codeGen方法,其作用就是重新調用了完整的對當前節點的代碼生成,方便遞歸調用: ~~~ Value* Node::codeGen(CodeGenContext* context) { return context->MacroMake(this); // MacroMake是核心的代碼生成接口 } ~~~ 于是我們遞歸地生成了這些代碼,就可以產生一條Call語句,那么別忘記將其返回給上一層: ~~~ static Value* call_macro(CodeGenContext* context, Node* node) { // 參數一 函數名 Value* func = context->getFunction(node); if (func == NULL) { errs() << "找不到函數的定義:"; errs() << node->getStr().c_str() << "\n"; exit(1); } // 其余參數 要傳入的參數 std::vector<Value*> args; for (Node* p = node->getNext(); p != NULL; p = p->getNext()) { Value* v = p->codeGen(context); if (v != NULL) args.push_back(v); } CallInst *call = CallInst::Create(func, args, "", context->getNowBlock()); return call; } ~~~ ### 簡單運算符計算 對于計算機,加減乘除這些基本運算,就是幾個指令而已,但對于編譯器,卻也要分好幾種情況討論,因為,全部的運算符有這么多: ~~~ // Standard binary operators... FIRST_BINARY_INST( 8) HANDLE_BINARY_INST( 8, Add , BinaryOperator) HANDLE_BINARY_INST( 9, FAdd , BinaryOperator) HANDLE_BINARY_INST(10, Sub , BinaryOperator) HANDLE_BINARY_INST(11, FSub , BinaryOperator) HANDLE_BINARY_INST(12, Mul , BinaryOperator) HANDLE_BINARY_INST(13, FMul , BinaryOperator) HANDLE_BINARY_INST(14, UDiv , BinaryOperator) HANDLE_BINARY_INST(15, SDiv , BinaryOperator) HANDLE_BINARY_INST(16, FDiv , BinaryOperator) HANDLE_BINARY_INST(17, URem , BinaryOperator) HANDLE_BINARY_INST(18, SRem , BinaryOperator) HANDLE_BINARY_INST(19, FRem , BinaryOperator) // Logical operators (integer operands) HANDLE_BINARY_INST(20, Shl , BinaryOperator) // Shift left (logical) HANDLE_BINARY_INST(21, LShr , BinaryOperator) // Shift right (logical) HANDLE_BINARY_INST(22, AShr , BinaryOperator) // Shift right (arithmetic) HANDLE_BINARY_INST(23, And , BinaryOperator) HANDLE_BINARY_INST(24, Or , BinaryOperator) HANDLE_BINARY_INST(25, Xor , BinaryOperator) ~~~ 這些定義很難找,在文檔中并沒有真正寫出來,而是在頭文件的`llvm/IR/Instruction.def`里面,這是宏定義的專屬部分。 這些還僅僅是數值運算,還不算比較運算的部分呢。 當然,這和計算機體系結構有關,浮點數的運算和整數肯定是不一樣的,而我們知道,右移位也分算數右移和邏輯右移。所以必然,會有大量不同的運算符。 創建指令則很簡單: ~~~ static BinaryOperator * Create (BinaryOps Op, Value *S1, Value *S2, const Twine &Name, BasicBlock *InsertAtEnd) ~~~ 兩個運算數,可以是常量,也可以是變量load出值后,還可以是表達式返回值,只要兩個Value調用getType,符合運算規則,就可以。 注意,浮點數不能直接和整數運算,必須先將整形轉為浮點才可以。 于是以下是簡單的運算符操作,我只寫了整數的運算操作: ~~~ static Value* opt2_macro(CodeGenContext* context, Node* node) { std::string opt = node->getStr(); Node* op1 = (node = node->getNext()); if (node == NULL) return NULL; Node* op2 = (node = node->getNext()); if (node == NULL) return NULL; Instruction::BinaryOps instr; if (opt == "+") { instr = Instruction::Add; goto binOper; } if (opt == "-") { instr = Instruction::Sub; goto binOper; } if (opt == "*") { instr = Instruction::Mul; goto binOper; } if (opt == "/") { instr = Instruction::SDiv; goto binOper; } // 未知運算符 return NULL; binOper: return BinaryOperator::Create(instr, op1->codeGen(context), op2->codeGen(context), "", context->getNowBlock()); ~~~ ### 附:文檔參考及源代碼 [CallInst類參考](http://llvm.org/doxygen/classllvm_1_1CallInst.html) [BinaryOperator類參考](http://llvm.org/doxygen/classllvm_1_1BinaryOperator.html) [github源碼-函數調用及基本運算符](https://github.com/sunxfancy/RedApple/blob/master/src/Macro/Functions.cpp)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看