Modern compiling principle--fifth chapter (activity record)

Source: Internet
Author: User

(reprint please indicate source http://www.cnblogs.com/BlackWalnut/p/4559245.html)

The fifth chapter is the most troubling chapter of my current position, not because it is difficult, but because it is not clear to the ultimate purpose. The first half of the chapter introduces a new concept in a very concise language, the activity record, that is, what happens to a call stack when a function call is made. However, in the final coding implementation process, it is not always understood why the author gave these variables? Or, I don't know exactly what the author wants me to do. Tangled for several days, and then simply go back and see if you can find other clues. Until after reading the chapter, the bite-bullet to write half time, just suddenly enlightened. The original author is this intention! So, if you don't know what the end result of this chapter is going to be, it's recommended to read the next chapter, because these two chapters are about different parts of the same thing.

Let's take a look at some theoretical knowledge. First, this activity record is the function call stack in our usual sense, so it's called a stack frame. is an area in memory that contains information such as all parameters in a function, local variables, temporary variables, return values, and so on, if the language also allows nested function declarations, then there is something called a static chain. These things on different target machines correspond to the layout is not the same, the book introduces a standard layout.

So, how does a function go about accessing his own variables? is used (stack pointer + offset), because for the CPU, the addition operation is relatively simple, so, in practice, the stack pointer is located in the low address, the lower bound of the stack, and the frame pointer at a high address, representing the upper bound of the stack. This will find that, in fact, the address of the top of the stack is lower than the bottom of the stack.

In fact, not all parameters are put into the stack (memory), some variables can be placed in the register, which can save a lot of time to visit. However, a program can have multiple functions, but the number of registers is limited. So, when a function calls another function and uses the same register, who is going to save the contents of the original register? If the function that calls the other function is responsible, it becomes the caller protection, and if it is the calling function, then the callee is protected.

In general, we will put the parameters of a function into the register, but, the number of registers is limited, how to do not fit? For example, for the function f (N1, N2, ..., NX), we will put the first k, if K is 4, put in the register, the rest of the x-k we put in the function called function f the end of the stack frame, adjacent to the stack pointer, this x-k area is called the outgoing parameter. However, this x-k block area is called an incoming parameter for the called function F. Think about it, if f goes back to calling other functions? Then the k parameter is removed from the register and placed in an area called the local variable in F, which is next to the outgoing parameter (incoming parameter, to function f).

So, in addition to the variables to be moved out of the register when the above parameter is passed, there are other cases where the parameters in the register need to be placed in memory. For example, in a function definition takes an address of a variable in an external function (this time requires the language support function to define a new function), then this variable will be written back to memory, otherwise, you take the address is a register address, if in the subsequent processing of this variable is removed from the register, Will not find it.

Of course, there are a lot of things to consider, this is not listed here, the Tiger book has been very clear, and, for all the original in the register, and then moved in memory variables called escape. So, how do you take variables of external functions inside a function? This is going to be a chain of things called Static, this thing is to let you in a function inside the clues to find the variables you need, similar to a linked list.

OK, so much to say, let's take a look at the final realization. What this chapter is going to achieve is actually the stack. It is not used to retain a region called scape in the previous data structure, which is a bool variable that uses this variable to mark whether a variable in tiger is escaping. How do you calculate if a variable is escaping? Because these escape messages will only be known after this program has been scanned. Therefore, the obtained abstract syntax tree is scanned two times, the first time to get the escape information of the variable, the second time is to the syntax tree type detection, and generate stack frames.

My Code does not implement the escape variable detection of the abstract syntax, and all of the variables I default to can be escaped. So the main part of this code is frame.h and Frame.cpp, and does not involve the real use of the functions in this frame.h. The part that is used for it will be reflected in the next chapter. The following is the source code:

  

#ifndef Frame_h_#defineFrame_h_#include"Temp.h"#include"util.h"#include"tree.h"Const intF_wordsize =4; typedefstructF_frame_ *f_frame; typedefstructF_access_ *f_access; typedefstructF_accesslist_ *f_accesslist;structF_accesslist_ {f_access head; F_accesslist tail; };typedefstructF_frag_ *F_frag; typedefstructF_fraglist_ *f_fraglist;structf_frame_ {temp_label name;                 intframesize; F_accesslist formals; F_accesslist locals;                 };structF_access_ {enum{inframe, inreg} kind; union{intoffset;                       TEMP_TEMP reg;                  } u; };structF_frag_ {enum{F_stringfrag, f_procfrag} kind; Union {struct{Temp_label label; stringstr;                    } Stringg; struct{t_stm body;                            F_frame frame;                        } proc;                }u; };structf_fraglist_{F_frag Head; F_fraglist tail; }; F_frag F_stringfrag (Temp_label label,stringstr); F_frag F_procfrag (t_stm stm, f_frame frame); F_fraglist f_fraglist (F_frag frag, f_fraglist tail); Temp_temp F_FP (void); Temp_temp F_RV (void) ;f_frame f_newframe (temp_label name, U_boollist formals); F_accesslist F_accesslist (f_access head, f_accesslist tail); Temp_label f_name (F_frame F); F_accesslist f_formals (F_frame F); F_access F_allocloacl (f_frame F,BOOLescape); F_access Inframe (intoffset); F_access inreg (temp_temp reg); T_exp F_exp (f_access acc, t_exp frameptr); T_exp F_externalcall (strings, t_explist explist); T_stm f_procentryexit1 (f_frame frame, t_stm stm);#endif
#include"frame.h"#include"tree.h"Const intoffset =-4 ;StaticTemp_temp fp =NULL;temp_temp f_fp () {if(fp==NULL) {FP=temp_newtemp ();     }    returnFP;}StaticTemp_temp RV =NULL; Temp_temp F_rv () {if(RV = =NULL) {RV=temp_newtemp (); }    returnRV;} F_access F_allocloacl (f_frame F,BOOLescape)    {f_access access; if(Escape = =true) {Access= Inframe (f->framesize); F->framesize-=offset; }    Else{Access=inreg (temp_newtemp ()); } f->locals = f_accesslist (Access, f->locals); returnaccess;} F_access Inframe (intoffset) {f_access tmp= (f_access) checked_malloc (sizeof(*tmp))    ; TMP->kind =F_access_::inframe; TMP->u.offset =offset; returntmp;} F_access inreg (temp_temp reg) {f_access tmp= (f_access) checked_malloc (sizeof(*tmp))    ; TMP->kind =F_access_::inreg; TMP->u.reg =reg; returntmp;} F_frame F_newframe (temp_label name, U_boollist formals) {f_frame frame= (f_frame) checked_malloc (sizeof(*frame))    ; Frame->name =name; Frame->formals =NULL; U_boollist par=formals;    F_access ACC; Frame->framesize =0 ;  while(Par! =NULL) {        if(par->head) {ACC= Inframe (frame->framesize); Frame->framesize-= offset;        }        Else{ACC=inreg (temp_newtemp ()); } Frame->formals = F_accesslist (ACC, frame->formals); Par= par->tail; } Frame->locals =NULL; returnframe;} F_accesslist F_accesslist (f_access head, f_accesslist tail) {f_accesslist tmp= (f_accesslist) checked_malloc (sizeof(*tmp))    ; TMP->head =Head; TMP->tail =tail; returntmp;} T_exp F_exp (f_access acc, t_exp frameptr) {if(Acc->kind = =f_access_::inframe) {        returnT_mem (T_binop (T_plus, Frameptr, T_const (acc->( U.offset))); }    returnT_temp (acc->u.reg);} F_frag F_stringfrag (Temp_label label,stringstr) {F_frag tmp= (F_frag) checked_malloc (sizeof(*tmp))    ; TMP->kind =F_frag_::f_stringfrag; TMP->u.stringg.label =label; TMP->u.stringg.str =str; returntmp;} F_frag F_procfrag (t_stm stm, F_frame frame) {F_frag tmp= (F_frag) checked_malloc (sizeof(*tmp))    ; TMP->kind =F_frag_::f_procfrag; TMP->u.proc.body =STM; TMP->u.proc.frame =frame; returntmp;} F_fraglist f_fraglist (F_frag frag, f_fraglist tail) {f_fraglist tmp= (f_fraglist) checked_malloc (sizeof(*tmp))    ; TMP->head =Frag; TMP->tail =tail; returntmp;} T_stm f_procentryexit1 (f_frame frame, t_stm stm) {returnSTM;} F_accesslist f_formals (F_frame frame) {returnFrame->formals;}

Modern compiling principle--fifth chapter (activity record)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.