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

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                LLVM平臺,短短幾年間,改變了眾多編程語言的走向,也催生了一大批具有特色的編程語言的出現,不愧為編譯器架構的王者,也榮獲2012年ACM軟件系統獎 —— 題記 版權聲明:本文為 西風逍遙游 原創文章,轉載請注明出處 西風世界 [http://blog.csdn.net/xfxyy_sxfancy](http://blog.csdn.net/xfxyy_sxfancy) # 變量的存儲與讀取 變量是一款編程語言中的核心,說編譯語言是一種符號處理工具,其實是有些道理的。棧式符號表可以方便的記錄編譯過程中的變量和語法符號,我們上節已經了解了其中的實現方法。那么,還有沒有其他的辦法能夠簡單的實現變量的存取呢? ### LLVM的內置符號表 其實LLVM還提供了一個內部符號表,這個和我們的符號表不一樣,它的符號是以函數為界的,函數內的是局部符號,外面的是全局符號。這個符號表的作用,主要是供LLVM找到各個底層的語法元素而設計的,所以它的功能較為有限。 例如下面這段字節碼: ~~~ define void @print(i64 %k1) { entry: ... } ~~~ 我們可以通過符號表,找到k1這個元素。 這個符號表的獲取也很簡單,只要你有basicblock,你就能夠找到這個符號表的指針: ~~~ BasicBlock* bb = context->getNowBlock(); ValueSymbolTable* st = bb->getValueSymbolTable(); Value* v = st->lookup(value); ~~~ ### 棧上變量空間的分配,AllocaInst語句 AllocaInst是LLVM的一條標準語句,負責棧上空間的分配,你無需考慮棧的增長的操作,它會自動幫你完成,并返回給你對應空間的指針。 千萬不要認為這個語句能夠動態分配堆內存,堆內存實際上是通過調用Malloc語句來分配的。 ~~~ %k = alloca i64 ~~~ 以上語句,會讓k的類型變為你分配類型的指針。 這個語句的C++接口非常的好用,像這樣: ~~~ AllocaInst *alloc = new AllocaInst(t, var_name, context->getNowBlock()); ~~~ t對應分配的類型,var_name對應語句返回的那個變量名(上面的‘k’),最后一個參數當然是插入的basicblock。 這時,返回的語句,就代表k這個指針了。 ### 變量的存儲 LLVM中,變量的存儲,都需要知道要存儲地址的指針,注意,一定是指針,而不是值。 原型: ~~~ StoreInst (Value *Val, Value *Ptr, bool isVolatile, BasicBlock *InsertAtEnd) ~~~ 使用示例: ~~~ new StoreInst(value2, value1, false, context->getNowBlock()); ~~~ 這個value1,就是目標的存儲指針,而value2則是要放入的值。false表示不是易變的,這個參數相當與C語言中的volatile關鍵字,主要是防止這個變量在重復讀取時的編譯器優化。因為一般的編譯器優化,都會將一個變量在沒有改變情況下的多次讀取,認為取到同一個值,雖然這在多線程和硬中斷的環境下并不成立。 ### 變量的讀取 變量的讀取,就用Load語句: ~~~ LoadInst (Value *Ptr, const Twine &NameStr, bool isVolatile, unsigned Align, BasicBlock *InsertAtEnd) ~~~ 使用示例: ~~~ new LoadInst(v, "", false, bb); ~~~ 我們這里暫時沒有考慮內存對齊的問題,當然,一般在Clang中,都是4字節對齊的。我們注意到,其實Load語句也是從指針中取值的,返回的則是一個值類型。 ### 打造一個賦值語句 賦值語句其實是一個挺尷尬的語句,左邊要賦值的,應該是一個指針地址,而右邊的部分,則應該是一個獲取到的值。而之前我們的運算,函數調用等等,絕大部分都是依賴值類型的。 我們先要為變量實現一個值的獲取,這部分因為很通用,我們放到IDNode節點的代碼生成中: ~~~ Value* IDNode::codeGen(CodeGenContext* context) { BasicBlock* bb = context->getNowBlock(); ValueSymbolTable* st = bb->getValueSymbolTable(); Value* v = st->lookup(value); if (v == NULL || v->hasName() == false) { errs() << "undeclared variable " << value << "\n"; return NULL; } Value* load = new LoadInst(v, "", false, bb); return load; } ~~~ value是我們類的成員變量,記錄的是變量名。 然而賦值語句有時還會要求獲取到的是指針,不是值,現在我們要為賦值語句實現一個符號指針的獲取: ~~~ Value* IDNode::codeGen(CodeGenContext* context) { BasicBlock* bb = context->getNowBlock(); ValueSymbolTable* st = bb->getValueSymbolTable(); Value* v = st->lookup(value); if (v == NULL || v->hasName() == false) { errs() << "undeclared variable " << value << "\n"; return NULL; } if (context->isSave()) return v; // 我們在上下文類中記錄了一個變量,看當前狀態是存還是取 Value* load = new LoadInst(v, "", false, bb); return load; } ~~~ 那么我們在調用時,只需要這樣做: ~~~ 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; if (opt == "=") { context->setIsSave(true); // 這兩句設置的目前是為下面的節點解析時,返回指針而不是load后的值 Value* ans1 = op1->codeGen(context); context->setIsSave(false); Value* ans2 = op2->codeGen(context); return new StoreInst(ans2, ans1, false, context->getNowBlock()); } ... } ~~~ 其實我們這里也可以單獨實現一個函數來處理這個功能,但由于兩個函數功能太像,所以也不怎么想添加一個類似的函數了。 這個部分暫時先這樣處理一下,待整體結構完善后,應該有更好的實現方法。
                  <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>

                              哎呀哎呀视频在线观看