⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chapter 6 assignment and expressions.htm

📁 英文版编译器设计:里面详细介绍啦C编译器的设计
💻 HTM
📖 第 1 页 / 共 5 页
字号:
  _u8, and its block pointer as NULL. This is how we tell a string literal apart 
  from a simple array of characters. The stack is set up in the same way as for 
  an array/record copy. The only difference is that we use function 80h (string 
  N copy). Code for a string copy from a variable to a variable looks like this:
  <P><PRE>       Emit ( LID,RType.getExtra()-&gt;size() );
      Emit ( SYS, 04h, 80h );
</PRE></MENU>
<BLOCKQUOTE dir=ltr style="MARGIN-RIGHT: 0px">
  <P>Since the Block pointer (getExtra()) for string literals is NULL, we have 
  to treat them differently. Fortunately, their size is fixed and can be 
  determined at compilation time. Code for a string copy from a sting literal to 
  a variable looks like this: </P></BLOCKQUOTE>
<MENU><PRE>      Emit ( LID, strlen(....));
      Emit ( MCP );

</PRE>
  <P></P></MENU><B>6.1.3.2 Assigning Simple data types</B><BR>This is done by 
using the <TT>SSx</TT> instructions (i.e., <TT>SSB</TT>, <TT>SSW</TT>, 
<TT>SSD</TT>, and <TT>SSQ</TT>) with an offset of zero. Basically, we already 
have the exact address of where the data is to be stored, so we need no offset, 
and we know that since <TT>LType</TT> is equal to <TT>RType</TT> that the result 
of the expression is the proper size. <PRE>      select LType.subtype from
        case _u8, _s8:
          Emit ( SSB, 0 );
        case _u16, _s16:
          Emit ( SSW, 0 );
        case _u32, _s32, _f32:
          Emit ( SSD, 0 );
        case _u64, _s64, _f64:
          Emit ( SSQ, 0 );
      end select
</PRE>
<P>This is all there is to <TT>RuleAssignment()</TT>. Pseudocode looks like 
this: 
<MENU><B>var</B><BR>
  <MENU>Type LType, RType;<BR></MENU>
  <P>//*** Tell IdentExpr() to make an lvalue<BR>IdentExpr( Local + Follow, 
  false, LType );
  <P>//*** Checking for procedure call<BR><B>if</B> LType.type = notyp 
  <B>and</B> Token.sy = ';' <B>then</B> 
  <MENU>return; </MENU><B>else if</B> Token.sy &lt;&gt; ';' <B>then</B> 
  <MENU>RType := LType;<BR>Expression ( Local + Follow, RType );
    <P><B>if</B> LType.type &lt;&gt; RType.type <B>then</B><BR>
    <MENU>Error "Type mismatch"<BR></MENU><B>else</B> 
    <MENU><B>if</B> LType.IsComplexType() <B>then</B><BR>
      <MENU>Do a mem-copy or a string-copy </MENU><B>else</B> 
      <MENU>Store the result using <TT>SSx 0</TT>. </MENU><B>end if</B> 
    </MENU><B>end if</B> </MENU><B>end if</B><BR></MENU><!----------------------------------------------------------------------------->
<H3>6.2 Evaluating an Expression</TT> </H3><!----------------------------------------------------------------------------->An 
expression consists of all the rules from <TT>RuleExpression()</TT> through 
<TT>RuleUnaryExpression()</TT>. For the most part these rules all follow the 
same pattern, with some noted exceptions. Rule Expression is the root rule for 
<I>any</I> expression (i.e., rvalue) in SAL. Its prototype should look like 
this: <PRE>      void RuleExpression(Set Follow, Type &amp;RType);
</PRE>Prior to calling <TT>RuleExpression()</TT> <I>anywhere in the 
compiler</I>, the fields of <TT>RType</TT> should be initialized to an input 
value. The input value will be used by <TT>RuleIdentExpr()</TT> or 
<TT>RuleFactor()</TT> to resolve the type of any constants encountered. The 
input value will be ignored, otherwise. If there is no discernable type, for 
example with the <TT>write</TT> statement, then the type should be initialized 
to an <TT>inttyp</TT> an subtype should be <TT>_u32s</TT>. As an example, 
considering the following fragment of code: <PRE>      var
        x: int;

      begin
        x:= 1;
</PRE>Before rule Assignment calls Expression, it will initialize a type 
variable to the type of <TT>x</TT>, i.e., <TT>inttyp</TT>, <TT>_u32</TT>. It 
then passes this value into Expression. Rule Expression calls rule 
LandExpression, and so on until rule Factor is called. Rule Factor handles 
literal constants, and rule IdentExpr handles symbolic constants. These two 
rules analyze the size of the number and determine whether or not it 
appropriately fits into the requested value contained in RType. If so, they make 
the constant to be that type. Otherwise they pick a value that is appropriate 
and set RType to be that type. We will talk about this more when we discuss 
<TT>RuleFactor()</TT> in section 6.3.1, when we talk about literal constants. In 
short, <TT>RuleExpression()</TT> requires that its RType parameter be at least 
somewhat initialized (i.e., at least RType.Type). 
<P>Due to the nature of stack-based architectures, a compiler needs to arrange 
computations so that both arguments are on the stack <I>before</I> the operation 
is computed. A simple expression like <PRE>      x + y
</PRE>Needs to be converted to <PRE>      x y +
</PRE>The idea is to load the value of x and the value of y onto the EES and 
then to compute their sum. All operators are binary; in other words, they work 
on only two operands. All binary operators take on the following form in memory: 

<MENU><IMG src="Chapter 6 Assignment and Expressions.files/OPRCOD.gif"> 
  <P><FONT face=arial size=-1><B>Figure {OPRCOD}.</B></FONT> </P></MENU>We can see 
an in the left of figure {OPRCOD} a simple memory map. The code for an operand 
can be as simple as one instruction, or it can be some complex array/record 
access. The importance is the order and the arrangement of the assembly 
instructions. In the center of figure {OPRCOD} we can see a section of code, and 
on the left we have the assembly instructions that the code evaluates to. 
<P>Computation on a stack architecture is always a mixture of loading operands 
onto the EES and then performing the right computations in the right order. Most 
rules from <TT>RuleExpression()</TT> to <TT>RuleMulExpression()</TT> follow one 
general form: 
<MENU><IMG src="Chapter 6 Assignment and Expressions.files/GENEXPR.gif"> 
  <P><FONT face=arial size=-1><B>Figure {GENEXPR}.</B></FONT> </P></MENU>We can 
see the genreal form in pseodocode here: 
<MENU><B>var</B><BR>
  <MENU>LType, RType: Type;<BR>op: Symbol; 
    <P></P></MENU>Rule<I>Next</I>Expression(Follow, RType); 
  <P><B>while</B> Token.sy not in {set of operators for this rule} <B>do</B><BR>
  <MENU>LType:= RType;<BR>op:= Token.sy<BR>NextToken(); 
    <P>Rule<I>Next</I>Expression(Follow, RType); 
    <P><B>if</B> LType.type &lt;&gt; RType.type <B>then</B><BR>
    <MENU>Error "Types not compatible"; (Do not eat tokens) </MENU><B>else</B> 
    <MENU>Emit(<B><I>op</I></B>, LType.subtype, RType.subtype); </MENU><B>end 
    if</B> 
    <P></P></MENU><B>loop;</B> </MENU>At the end of the pseudocode, there is a place 
where we emit code for the operand. The variable <B><I>op</I></B> in this case 
is italicized and in bold to emphasize that we emit the instruction that 
corresponds to the symbol that was found. If the types are the same, then we can 
emit the op code. The op-code's parameters are going to be the subtype of LType 
and RType. In addition, certain operators are only going to be able to work with 
certain operands. For instance, we can not bit-shift a floating point number. We 
can not add two characters. 
<P>
<H3>6.2.1 Rule Expression</TT> </H3><!----------------------------------------------------------------------------->Here 
is our first rule: 
<MENU><IMG src="Chapter 6 Assignment and Expressions.files/RULE34.gif"> 
  <P><FONT face=arial size=-1><B>Figure {RULE34}.</B></FONT> </P></MENU>In this 
rule, we only have one operator, a boolean OR. Notice that in the pseudocode to 
the right, we emit an <TT>ORB</TT> instruction. All boolean values are a single 
byte. 
<H3>6.2.2 Rule LandExpression</TT> </H3><!----------------------------------------------------------------------------->
<MENU><IMG src="Chapter 6 Assignment and Expressions.files/RULE33.gif"> 
  <P><FONT face=arial size=-1><B>Figure {RULE33}.</B></FONT> </P></MENU>Like the 
previous rule, we only have one operator, a boolean AND. Here we also use the 
<TT>ANDB</TT> instruction, specifically, since all boolean values are a single 
byte. 
<H3>6.2.3 Rule CmpExpression</TT> </H3><!----------------------------------------------------------------------------->
<MENU><IMG src="Chapter 6 Assignment and Expressions.files/RULE32.gif"> 
  <P><FONT face=arial size=-1><B>Figure {RULE32}.</B></FONT> </P></MENU>This rule 
compares any two expressions of the same data type and returns a boolean result. 
This rule has a different format; there is no loop. This is because we cannot do 
expressions like <PRE>      if a &lt; b &lt; c then
        . . .
      end if;
</PRE>The reason for this is because the result of the first comparison is a 
boolean, i.e., either a true or a false, which cannot be directly compared to an 
integer or a real. 
<P>Each comparision is comprised of a pair of instructions. The first is, aptly, 
a compare instruction such as <TT>CMPx</TT>, <TT>UCMPx</TT>, or <TT>FCMPx</TT>. 
The comparison instruction works by (internally) performing a subtraction of the 
second number from the first. If the result is negative, the instruction pushes 
a 0FFh onto the EES. If it is positive, it pushes a 01h onto the EES. If the 
result is zero, it pushes a 00h. 
<P>The table below shows the comparison instructions that are to be used whith 
each data type: <PRE>       bool   char   int8   int16  int32  int64  card8  card16 card32 card64 real32 real64
      =====================================================================================
       UCMPB  UCMPB  CMPB   CMPW   CMPD   CMPQ   UCMPB  UCMPW  UCMPD  UCMPQ  FCMPS  FCMPD
</PRE>The second instruction takes the result of the comparison and converts it 
into a boolean value, either a zero or a one depending on the instruction. Here 
is a table of comparison operators, their corresponding VM instructions, and 
their results based on the three input values: <PRE>                             Output From
       Operator:  OpCode:   -1    0    1
      =============================================
          =        EQL       0    1    0
          &lt;&gt;       NEQ       1    0    1
          &lt;        LES       1    0    0
          &lt;=       LEQ       1    1    0
          &gt;        GTR       0    0    1
          &gt;=       GEQ       0    1    1
</PRE>Notice also that prior to exiting, we set RType to <TT>booltyp</TT>. 
<P>
<H3>6.2.4 Rule BorExpression</TT> </H3><!----------------------------------------------------------------------------->
<MENU><IMG src="Chapter 6 Assignment and Expressions.files/RULE31.gif"> 
  <P><FONT face=arial size=-1><B>Figure {RULE31}.</B></FONT> </P></MENU>This rule 
allows for either a bitwise OR, or a bitwise exclusive OR (XOR). This operator 
can only be carried out on integers and cardinals. Here is a table of 
instructions to use: <PRE>      OP |  bool   char   int8   int16  int32  int64  card8  card16 card32 card64 real32 real64
      ===========================================================================================
      |  |   -      -     ORB    ORW    ORD    ORQ    ORB    ORW    ORD    ORQ     -      -
      %  |   -      -     XORB   XORW   XORD   XORQ   XORB   XORW   XORD   XORQ    -      -
</PRE>
<P>
<H3>6.2.5 Rule BandExpression</TT> </H3><!----------------------------------------------------------------------------->
<MENU><IMG src="Chapter 6 Assignment and Expressions.files/RULE30.gif"> 
  <P><FONT face=arial size=-1><B>Figure {RULE30}.</B></FONT> </P></MENU>The 
instructions to be used for a bitwise AND are: <PRE>      OP |  bool   char   int8   int16  int32  int64  card8  card16 card32 card64 real32 real64
      ===========================================================================================
      &amp;  |   -      -     ANDB   ANDW   ANDD   ANDQ   ANDB   ANDW   ANDD   ANDQ    -      -
</PRE>
<P>
<H3>6.2.6 Rule BitwExpression</TT> </H3><!----------------------------------------------------------------------------->
<MENU><IMG src="Chapter 6 Assignment and Expressions.files/RULE29.gif"> 
  <P><FONT face=arial size=-1><B>Figure {RULE29}.</B></FONT> </P></MENU>SAL has a 
fairly robust set of bit-shifting operators. We can do all manner of shifting 
and rotating. This table represents the instructions used for the types of 
operations involved. <PRE>      OP  |  bool   char   int8   int16  int32  int64  card8  card16 card32 card64 real32 real64
      ===========================================================================================
      &gt;&gt;  |   -      -     USHRB  USHRW  USHRD  USHRQ  USHRB  USHRW  USHRD  USHRQ   -      -
      &gt;&gt;&gt; |   -      -     SSHRB  SSHRW  SSHRD  SSHRQ  SSHRB  SSHRW  SSHRD  SSHRQ   -      -
      &lt;&lt;  |   -      -     USHLB  USHLW  USHLD  USHLQ  USHLB  USHLW  USHLD  USHLQ   -      -
      #&gt;  |   -      -     RORB   RORW   RORD   RORQ   RORB   RORW   RORD   RORQ    -      -
      &lt;#  |   -      -     ROLB   ROLW   ROLD   ROLQ   ROLB   ROLW   ROLD   ROLQ    -      -
</PRE>As can be seen by the table, these operators only work on integers and 
cardinals. 
<P>
<H3>6.2.7 Rule AddExpression</TT> </H3><!----------------------------------------------------------------------------->
<MENU><IMG src="Chapter 6 Assignment and Expressions.files/RULE28.gif"> 
  <P><FONT face=arial size=-1><B>Figure {RULE28}.</B></FONT> </P></MENU>Although 
this rule is named after the addition operator, it includes all operators of the 
same precidence: addition and subtraction. <PRE>      OP |  bool   char   int8   int16  int32  int64  card8  card16 card32 card64 real32 real64
      ===========================================================================================
      +  |   -      -     ADDB   ADDW   ADDD   ADDQ   ADDB   ADDW   ADDD   ADDQ   FADDS  FADDD
      -  |   -      -     SUBB   SUBW   SUBD   SUBQ   SUBB   SUBW   SUBD   SUBQ   FSUBS  FSUBD
</PRE>
<P>
<H3>6.2.8 Rule MulExpression</TT> </H3><!----------------------------------------------------------------------------->
<MENU><IMG src="Chapter 6 Assignment and Expressions.files/RULE27.gif"> 
  <P><FONT face=arial size=-1><B>Figure {RULE27}.</B></FONT> </P></MENU>Likewise, 
this rule includes all operators that share precidence with multiplication, 
namely division and modulus. <PRE>      OP  |  bool   char   int8   int16  int32  int64  card8  card16 card32 card64 real32 real64
      ============================================================================================

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -