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

📄 chapter 14 pointers.htm

📁 英文版编译器设计:里面详细介绍啦C编译器的设计
💻 HTM
📖 第 1 页 / 共 3 页
字号:
up your plev checks within rule ident expression. If there is an ampersand you 
can set a boolean flag and at the very end of ruleIdentExpr if that flag is set 
increment rtype's plev. </P>
<H3>14.6.5 Summary of <TT>RuleIdentExpr()</TT></H3><!-----------------------------------------------------------------------------><PRE>In just a recap, we have talked about how <TT>RuleIdentExpr()</TT> operates.  This rule operates
on anything in SAL that is an identifier.  For the most part it generates rvalues, however, it
can also generate lvalues with variables.  The flag, <TT>MakeRValue</TT> tells it which case
it needs to do.  If <TT>RuleIdentExpr()</TT> is told to make an lvalue from a constant or a
type conversion, then it should report an error (don't eat tokens, just report an error).</PRE><PRE>
This rule also has an in/out parameter that is used for resolving constant types.  If possible,
the constant should be matched as closely as possible to the type that is passed in.  The rule
should then choose a final type and then return that to the caller.  <TT>RuleIdentExpr()</TT>
also takes a sign parameter that is useful for setting the sign.  This is also used in setting
the final constant's type.</PRE><PRE>
In all cases, the <TT>RType</TT> (return type) should be set to whatever the ident's type turned
out to be.  In any event, the skeleton code for <TT>RuleIdentExpr()</TT> would look like this:
</PRE><PRE>var
  Ident *ident;

begin
  ident:= RuleQualIdent ( local+follow );

  if ident =  null then
      RType.Init(notyp,nosubtyp);
      return;
  else if ident-&gt;obj&lt;&gt;  constobj then
      RType.Init(ident);
  end if;
  
  if ident-&gt;obj = constobj then
      if MakeRValue =  false
        then Error: "Can't take lvalue of a constant"
      end if
      //*** Generate a constant based on RType's setings and the
      //*** value in Sign (Set Sign to zero afterwards).
 
  else if ident-&gt;obj =   varobj
      then ifrval-&gt;isComplexType()
          // handle records/arrays/classes 
      else if MakeRValue then
          //*** Make an rvalue
      else
         //*** Make an lvalue
      end if;
  else if ident-&gt;obj = typeobj then
      RuleTypeConvert( local+follow, RType);
      if MakeRValue =  false
        then Error: "Can't take lvalue of a type-conversion"
      endif;
      // Dereference Pointers 
  else if ident-&gt;obj =  funcobj orident-&gt;obj = procobj then
      RuleProcFuncCall();
      // Dereference Pointers 
  end if;

</PRE>
<H2>14.7 RuleDesignator</H2>Once again to make a long story short, we have to 
handle Rec.field^^^ and arr[5]^^^ and the like. We do this in rule designator 
like this: <PRE>
	do {
		Check(local+follow, "Designator expected");
        ....
		
		<FONT color=green>deref = RuleGetPointerLevel(follow, last);
		if (deref) {
			if(deref &gt; rval-&gt;getPlev())
				SemanticErrorMsg("Pointer error");
			rval-&gt;setPlev(rval-&gt;getPlev() - deref);
			while(deref--) {
				Emit(xLSD, 0);
			}
		</FONT>	
		}
		
	} while (TestToken(FirstMemberField) || TestToken(FirstArrayIndexing) );
	
	if (makerval &amp;&amp; !procFuncCall) {   //* resolve lvalue to an rvalue
		<FONT color=green>if(rval-&gt;getPlev())
			Emit(xLSD, 0);	</FONT>	
		else if (rval-&gt;IsSimpleType())
			EmitLoad(_LS_, GET_TYPE_BYTE_SIZE(rval-&gt;subtype) , 0);
	}


</PRE>
<H2>14.8 RuleCmpExpr</H2>Do determine whether a pointer is null or if two 
pointers are the same, we need to be able to compare pointers. This entails some 
adjusting to RuleCmpExpression. In it when we out put the code for a comparison 
if what we are comparing is pointers, we need to do the right size 
comparison.<BR>To make a long story short here are the changes that need to be 
made: <PRE>		<FONT color=green>if(rtype-&gt;getPlev()) { 
			Emit (xUCMPD);
		} else </FONT> if(rtype-&gt;type ==  booltyp)
			{ Emit(xUCMPB); }
			 else if(rtype-&gt;type ==  realtyp){
			  Emit(xFCMP_ +	subtype);
			 } else if(rtype-&gt;type == inttyp) {
			  Emit(xCMP_ + subtype);

</PRE>
<H2>14.9 Memory Management</H2>There eventually will be some theory here, but 
for now, here is how you implement Rules new and delete<PRE></PRE></FONT>
<H3>14.9.1 New </H3>
<P>The&nbsp;basic idea for Rule new is that it is an intrinsic function that 
takes a type as a parameter and allocates the size of the type on the heap and 
returns the pointer to that allocated area. This is simply done by getting the 
size of the type passed in by parameter and calling the VM syscall MALLOC. This 
instruction allocates the specified amount of memory on the heap and leaves a 4 
byte pointer on the stack to that allocated memory. Actually this chapter 
normally comes before the classes chapter, so you would not need to worry about 
classes and meta-constructors, but you do here. So, make sure if the type needs 
to have the meta constructor called, call it. You can implement new like 
follows: </P><PRE>
void Parser531::RuleNew(Set &amp;follow, Type* rtype)
var
	Token la;
	bool dummy := true;
	Ident *temp;
	Type ptyp;
	
        Set local (FirstExpression + commasy +  scopesy + rparentsy);
	
begin
	LookAhead(la);
	if la.sy = atsy then
		la := token;
		Accept( identsy, follow + atsy + scopesy + commasy, "Missing type identifier");
		NextToken();

		if token.sy = identsy then
			temp := table.findInModule( la.data.id, token.data.id);
		else
			temp := table.findInModule( la.data.id);
                end if;

		if temp = NULL || temp-&gt;getObj() &lt;&gt; typeobj then
			SemanticErrorMsg( "Invalid or undeclared type");
                end if;

		Accept( identsy, follow + scopesy + commasy, "Missing module identifier");
	else 
		if  token.sy = identsy then
			temp := table.getCurrentBlock()-&gt;Find_Backward( token.data.id, dummy, true);
		end if;

                if  temp = NULL || temp-&gt;getObj() &lt;&gt; typeobj then
			SemanticErrorMsg( "Invalid or undeclared type");
                end if;

		Accept( identsy, follow + scopesy + commasy, "Missing type identifier");
	end if;

	if temp = NULL then
		return;
        end if;

	ptyp.Init( cardtyp, _u32s);
	Emit( xLID, temp-&gt;getSize());

	if temp-&gt;getExtra() &amp;&amp; temp-&gt;getExtra()-&gt;getMetaCtorProcNum() then
		Check( follow + rparentsy + commasy + scopesy + FirstExpression, "Syntax Error");
		if temp-&gt;getType()-&gt;getType() = classtyp then

			Emit( xSYS, 0x04, MALLOC);
			Emit( xCOPT, 4);

			Check( local + follow, "Syntax Error");
			if token.sy = scopesy then
	       		        Emit( xCOPT, 4);
    			        NewonItem( temp, FALSE);
				
                                NextToken();
				Ident *cons := NULL;
				
                                if  token.sy = identsy &amp;&amp; temp-&gt;getExtra() &amp;&amp; temp-&gt;getExtra()-&gt;toClassBlock() then
					cons := temp-&gt;getExtra()-&gt;toClassBlock()-&gt;GetAMember( token.data.id);
				end if;

                                NextToken();
				
                                if  !cons || !cons-&gt;toFunctionIdent() || ! cons-&gt;toFunctionIdent()-&gt;getIsConstructor() then
					SemanticErrorMsg( "Invalid or missing constructor name");
				else
					Type temp := *(cons-&gt;getType());
					Type temp2 := *(cons-&gt;getType());
					
					RuleProcFuncCall(follow + rparentsy, lparentsy, cons, &amp;temp, &amp;temp);
				end if;
			else
		
				NewonItem( temp, TRUE);
			end if;

		else 
			Emit( xSYS, 0x04, MALLOC);
			Emit( xCOPT, 4);
			NewonItem( temp, TRUE);
		end if;
		
         else 
              if  temp-&gt;getType()-&gt;getType() == proctyp || temp-&gt;getType()-&gt;getType() == functyp then
		  SemanticErrorMsg( "Cannot allocate memory for procedures and functions");
	      else 
		  Emit( xSYS, 0x04, MALLOC);  // Allocate memory for simple types
	      end if;
         end if;
	
        rtype-&gt;Init(temp);
	rtype-&gt;setPlev(++(rtype-&gt;getPlev()));
   endif;
end;


</PRE>
<H3>14.9.2 Delete</H3>
<P></P>Delete is pretty similar, but it takes a variable as a parameter and 
issues a FREE SYS call, to free the memory. And for later if we are destryoing a 
class we need to call the correct destructor if it exists. <BR>You can implement 
rule delete like follows: 
<P></P><PRE>void Parser531::RuleDelete(Set &amp;follow, Type* rtype) 

var
    int sign := 0;

begin	
    RuleIdentExpr( follow + rparentsy, lparentsy, rtype, true, sign);
    if rtype-&gt;getPlev() &lt; 1 then
	SemanticErrorMsg( "Can only delete pointers");
    end if;
    
    Emit( xCOPT, 4);

    if rtype-&gt;getExtra() &amp;&amp; rtype-&gt;getExtra()-&gt;getMetaDtorProcNum() then
		Emit( xCOPT, 4);
		DeleteItem( rtype-&gt;getExtra()-&gt;getParent());
		
		// If we are destroying a class, we need to find out if our 
		// pointer references the whole class, and not a base class.
		if rtype-&gt;getType() = classtyp &amp;&amp; rtype-&gt;getPlev()  then	// If this is a class
			ClassBlock *cblock := rtype-&gt;getExtra()-&gt;toClassBlock();
			FunctionIdent *dident := cblock-&gt;getDestructor();
			
                        if dident &amp;&amp;						// If this class has a destructor
				dident-&gt;isVirtualFunc() then			// And finally, if this class's destructor is virtual
			
                             	DWORD vprocnum =: dident-&gt;getVProcNum();
				Emit (xCOPT, 4);	 			// Copy the pointer to self
				Emit (xLSD, 0); 				// Load the vtable pointer (always at offset 0).
				
				Emit (xLID, 0xFFFFFFFF);               		// if (*vtable == 0xFFFFFFFF) goto Skip; (Class has no virtual functions).
				Emit (xUCMPD);		
				Emit1(xJPZ);
				DWORD Skip := ForwardJump();
				
				Emit (xCOPT, 4);	 			// Copy the pointer to self
				Emit (xLSD, 0); 				// Load the vtable pointer (always at offset 0).
				Emit (xLSD, vprocnum*8 + 4);	                // Get the self fixup.
				Emit (xADDD);					// Add the two
				
				JumpFix(Skip);					// Skip:
			end if;
		end if;
     end if;
	Emit( xSYS, 0x04, MFREE);  
	Emit( xLID, 0);
	Emit( xSSD, 0);
	rtype-&gt;Init( proctyp, nosubtyp);
	
end;
</PRE>
<H2>14.10</H2>In init vars remember you do not call the meta constructor on a 
variable if it is a pointer. </BODY></HTML>

⌨️ 快捷键说明

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