Răsfoiți Sursa

+ binary operators for ansi strings

florian 27 ani în urmă
părinte
comite
e4290ba94a
3 a modificat fișierele cu 368 adăugiri și 303 ștergeri
  1. 180 146
      compiler/cg386add.pas
  2. 131 127
      compiler/cg68kadd.pas
  3. 57 30
      compiler/tcadd.pas

+ 180 - 146
compiler/cg386add.pas

@@ -45,6 +45,7 @@ implementation
          flags : tresflags;
       begin
          { remove temporary location if not a set or string }
+         { that's a bad hack (FK) who did this ?            }
          if (p^.left^.resulttype^.deftype<>stringdef) and
             ((p^.left^.resulttype^.deftype<>setdef) or (psetdef(p^.left^.resulttype)^.settype=smallset)) and
             (p^.left^.location.loc in [LOC_MEM,LOC_REFERENCE]) then
@@ -118,158 +119,188 @@ implementation
       begin
         { string operations are not commutative }
         if p^.swaped then
-         swaptree(p);
+          swaptree(p);
+        case pstringdef(p^.left^.resulttype)^.string_typ of
+           st_ansistring:
+             begin
+                case p^.treetype of
+                   addn:
+                     begin
+                        { we do not need destination anymore }
+                        del_reference(p^.left^.location.reference);
+                        del_reference(p^.right^.location.reference);
+                        { concatansistring(p); }
+                     end;
+                   ltn,lten,gtn,gten,
+                   equaln,unequaln:
+                     begin
+                        secondpass(p^.left);
+                        pushed:=maybe_push(p^.right^.registers32,p);
+                        secondpass(p^.right);
+                        if pushed then restore(p);
+                        { release used registers }
+                        case p^.right^.location.loc of
+                          LOC_REFERENCE,LOC_MEM:
+                            del_reference(p^.right^.location.reference);
+                          LOC_REGISTER,LOC_CREGISTER:
+                            ungetregister32(p^.right^.location.register);
+                        end;
+                        case p^.left^.location.loc of
+                          LOC_REFERENCE,LOC_MEM:
+                            del_reference(p^.left^.location.reference);
+                          LOC_REGISTER,LOC_CREGISTER:
+                            ungetregister32(p^.left^.location.register);
+                        end;
+                        { push the still used registers }
+                        pushusedregisters(pushedregs,$ff);
+                        { push data }
+                        case p^.right^.location.loc of
+                          LOC_REFERENCE,LOC_MEM:
+                            emit_push_mem(p^.right^.location.reference);
+                          LOC_REGISTER,LOC_CREGISTER:
+                            exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,p^.right^.location.register)));
+                        end;
+                        case p^.left^.location.loc of
+                          LOC_REFERENCE,LOC_MEM:
+                            emit_push_mem(p^.left^.location.reference);
+                          LOC_REGISTER,LOC_CREGISTER:
+                            exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,p^.left^.location.register)));
+                        end;
+                        emitcall('FPC_ANSICOMPARE',true);
+                        emit_reg_reg(A_OR,S_L,R_EAX,R_EAX);
+                        popusedregisters(pushedregs);
+                        maybe_loadesi;
+                        ungetiftemp(p^.left^.location.reference);
+                        ungetiftemp(p^.right^.location.reference);
+                     end;
+                end;
+             end;
+           st_shortstring:
+             begin
+                case p^.treetype of
+                   addn:
+                     begin
+                        cmpop:=false;
+                        secondpass(p^.left);
+                        { if str_concat is set in expr
+                          s:=s+ ... no need to create a temp string (PM) }
 
-{$ifdef UseAnsiString}
-              if is_ansistring(p^.left^.resulttype) then
-                begin
-                  case p^.treetype of
-                  addn :
-                    begin
-                       { we do not need destination anymore }
-                       del_reference(p^.left^.location.reference);
-                       del_reference(p^.right^.location.reference);
-                       { concatansistring(p); }
-                    end;
-                  ltn,lten,gtn,gten,
-                  equaln,unequaln :
-                    begin
-                       pushusedregisters(pushedregs,$ff);
-                       secondpass(p^.left);
-                       del_reference(p^.left^.location.reference);
-                       emitpushreferenceaddr(exprasmlist,p^.left^.location.reference);
-                       secondpass(p^.right);
-                       del_reference(p^.right^.location.reference);
-                       emitpushreferenceaddr(exprasmlist,p^.right^.location.reference);
-                       emitcall('FPC_ANSISTRCMP',true);
-                       maybe_loadesi;
-                       popusedregisters(pushedregs);
-                    end;
-                  end;
-                end
-              else
-{$endif UseAnsiString}
-       case p^.treetype of
-          addn :
-            begin
-               cmpop:=false;
-               secondpass(p^.left);
-               { if str_concat is set in expr
-                 s:=s+ ... no need to create a temp string (PM) }
-
-               if (p^.left^.treetype<>addn) and not (p^.use_strconcat) then
-                 begin
+                        if (p^.left^.treetype<>addn) and not (p^.use_strconcat) then
+                          begin
 
-                    { can only reference be }
-                    { string in register would be funny    }
-                    { therefore produce a temporary string }
+                             { can only reference be }
+                             { string in register would be funny    }
+                             { therefore produce a temporary string }
 
-                    { release the registers }
-                    del_reference(p^.left^.location.reference);
-                    gettempofsizereference(256,href);
-                    copystring(href,p^.left^.location.reference,255);
-                    ungetiftemp(p^.left^.location.reference);
+                             { release the registers }
+                             del_reference(p^.left^.location.reference);
+                             gettempofsizereference(256,href);
+                             copystring(href,p^.left^.location.reference,255);
+                             ungetiftemp(p^.left^.location.reference);
+
+                             { does not hurt: }
+                             clear_location(p^.left^.location);
+                             p^.left^.location.loc:=LOC_MEM;
+                             p^.left^.location.reference:=href;
+                          end;
 
-                    { does not hurt: }
-                    clear_location(p^.left^.location);
-                    p^.left^.location.loc:=LOC_MEM;
-                    p^.left^.location.reference:=href;
-                 end;
+                        secondpass(p^.right);
 
-               secondpass(p^.right);
+                        { on the right we do not need the register anymore too }
+                        del_reference(p^.right^.location.reference);
+                        {
+                        if p^.right^.resulttype^.deftype=orddef then
+                         begin
+                           pushusedregisters(pushedregs,$ff);
+                           exprasmlist^.concat(new(pai386,op_ref_reg(
+                              A_LEA,S_L,newreference(p^.left^.location.reference),R_EDI)));
+                           exprasmlist^.concat(new(pai386,op_reg_reg(
+                              A_XOR,S_L,R_EBX,R_EBX)));
+                           reset_reference(href);
+                           href.base:=R_EDI;
+                           exprasmlist^.concat(new(pai386,op_ref_reg(
+                              A_MOV,S_B,newreference(href),R_BL)));
+                           exprasmlist^.concat(new(pai386,op_reg(
+                              A_INC,S_L,R_EBX)));
+                           exprasmlist^.concat(new(pai386,op_reg_ref(
+                              A_MOV,S_B,R_BL,newreference(href))));
+                           href.index:=R_EBX;
+                           if p^.right^.treetype=ordconstn then
+                             exprasmlist^.concat(new(pai386,op_const_ref(
+                                A_MOV,S_L,p^.right^.value,newreference(href))))
+                           else
+                            begin
+                              if p^.right^.location.loc in [LOC_CREGISTER,LOC_REGISTER] then
+                               exprasmlist^.concat(new(pai386,op_reg_ref(
+                                 A_MOV,S_B,p^.right^.location.register,newreference(href))))
+                              else
+                               begin
+                                 exprasmlist^.concat(new(pai386,op_ref_reg(
+                                   A_MOV,S_L,newreference(p^.right^.location.reference),R_EAX)));
+                                 exprasmlist^.concat(new(pai386,op_reg_ref(
+                                   A_MOV,S_B,R_AL,newreference(href))));
+                               end;
+                            end;
+                           popusedregisters(pushedregs);
+                         end
+                        else }
+                         begin
+                           pushusedregisters(pushedregs,$ff);
+                           emitpushreferenceaddr(exprasmlist,p^.left^.location.reference);
+                           emitpushreferenceaddr(exprasmlist,p^.right^.location.reference);
+                           emitcall('FPC_STRCONCAT',true);
+                           maybe_loadesi;
+                           popusedregisters(pushedregs);
+                         end;
 
-               { on the right we do not need the register anymore too }
-               del_reference(p^.right^.location.reference);
-{               if p^.right^.resulttype^.deftype=orddef then
-                begin
-                  pushusedregisters(pushedregs,$ff);
-                  exprasmlist^.concat(new(pai386,op_ref_reg(
-                     A_LEA,S_L,newreference(p^.left^.location.reference),R_EDI)));
-                  exprasmlist^.concat(new(pai386,op_reg_reg(
-                     A_XOR,S_L,R_EBX,R_EBX)));
-                  reset_reference(href);
-                  href.base:=R_EDI;
-                  exprasmlist^.concat(new(pai386,op_ref_reg(
-                     A_MOV,S_B,newreference(href),R_BL)));
-                  exprasmlist^.concat(new(pai386,op_reg(
-                     A_INC,S_L,R_EBX)));
-                  exprasmlist^.concat(new(pai386,op_reg_ref(
-                     A_MOV,S_B,R_BL,newreference(href))));
-                  href.index:=R_EBX;
-                  if p^.right^.treetype=ordconstn then
-                    exprasmlist^.concat(new(pai386,op_const_ref(
-                       A_MOV,S_L,p^.right^.value,newreference(href))))
-                  else
-                   begin
-                     if p^.right^.location.loc in [LOC_CREGISTER,LOC_REGISTER] then
-                      exprasmlist^.concat(new(pai386,op_reg_ref(
-                        A_MOV,S_B,p^.right^.location.register,newreference(href))))
-                     else
-                      begin
-                        exprasmlist^.concat(new(pai386,op_ref_reg(
-                          A_MOV,S_L,newreference(p^.right^.location.reference),R_EAX)));
-                        exprasmlist^.concat(new(pai386,op_reg_ref(
-                          A_MOV,S_B,R_AL,newreference(href))));
-                      end;
-                   end;
-                  popusedregisters(pushedregs);
-                end
-               else }
-                begin
-                  pushusedregisters(pushedregs,$ff);
-                  emitpushreferenceaddr(exprasmlist,p^.left^.location.reference);
-                  emitpushreferenceaddr(exprasmlist,p^.right^.location.reference);
-                  emitcall('FPC_STRCONCAT',true);
-                  maybe_loadesi;
-                  popusedregisters(pushedregs);
+                        set_location(p^.location,p^.left^.location);
+                        ungetiftemp(p^.right^.location.reference);
+                     end;
+                   ltn,lten,gtn,gten,
+                   equaln,unequaln :
+                     begin
+                        cmpop:=true;
+                        { generate better code for s='' and s<>'' }
+                        if (p^.treetype in [equaln,unequaln]) and
+                           (((p^.left^.treetype=stringconstn) and (str_length(p^.left)=0)) or
+                            ((p^.right^.treetype=stringconstn) and (str_length(p^.right)=0))) then
+                          begin
+                             secondpass(p^.left);
+                             { are too few registers free? }
+                             pushed:=maybe_push(p^.right^.registers32,p);
+                             secondpass(p^.right);
+                             if pushed then restore(p);
+                             del_reference(p^.right^.location.reference);
+                             del_reference(p^.left^.location.reference);
+                             { only one node can be stringconstn }
+                             { else pass 1 would have evaluted   }
+                             { this node                         }
+                             if p^.left^.treetype=stringconstn then
+                               exprasmlist^.concat(new(pai386,op_const_ref(
+                                 A_CMP,S_B,0,newreference(p^.right^.location.reference))))
+                             else
+                               exprasmlist^.concat(new(pai386,op_const_ref(
+                                 A_CMP,S_B,0,newreference(p^.left^.location.reference))));
+                          end
+                        else
+                          begin
+                             pushusedregisters(pushedregs,$ff);
+                             secondpass(p^.left);
+                             del_reference(p^.left^.location.reference);
+                             emitpushreferenceaddr(exprasmlist,p^.left^.location.reference);
+                             secondpass(p^.right);
+                             del_reference(p^.right^.location.reference);
+                             emitpushreferenceaddr(exprasmlist,p^.right^.location.reference);
+                             emitcall('FPC_STRCMP',true);
+                             maybe_loadesi;
+                             popusedregisters(pushedregs);
+                          end;
+                        ungetiftemp(p^.left^.location.reference);
+                        ungetiftemp(p^.right^.location.reference);
+                     end;
+                   else CGMessage(type_e_mismatch);
                 end;
-
-               set_location(p^.location,p^.left^.location);
-               ungetiftemp(p^.right^.location.reference);
-            end;
-          ltn,lten,gtn,gten,
-          equaln,unequaln :
-            begin
-               cmpop:=true;
-             { generate better code for s='' and s<>'' }
-               if (p^.treetype in [equaln,unequaln]) and
-                  (((p^.left^.treetype=stringconstn) and (str_length(p^.left)=0)) or
-                   ((p^.right^.treetype=stringconstn) and (str_length(p^.right)=0))) then
-                 begin
-                    secondpass(p^.left);
-                    { are too few registers free? }
-                    pushed:=maybe_push(p^.right^.registers32,p);
-                    secondpass(p^.right);
-                    if pushed then restore(p);
-                    del_reference(p^.right^.location.reference);
-                    del_reference(p^.left^.location.reference);
-                    { only one node can be stringconstn }
-                    { else pass 1 would have evaluted   }
-                    { this node                         }
-                    if p^.left^.treetype=stringconstn then
-                      exprasmlist^.concat(new(pai386,op_const_ref(
-                        A_CMP,S_B,0,newreference(p^.right^.location.reference))))
-                    else
-                      exprasmlist^.concat(new(pai386,op_const_ref(
-                        A_CMP,S_B,0,newreference(p^.left^.location.reference))));
-                 end
-               else
-                 begin
-                    pushusedregisters(pushedregs,$ff);
-                    secondpass(p^.left);
-                    del_reference(p^.left^.location.reference);
-                    emitpushreferenceaddr(exprasmlist,p^.left^.location.reference);
-                    secondpass(p^.right);
-                    del_reference(p^.right^.location.reference);
-                    emitpushreferenceaddr(exprasmlist,p^.right^.location.reference);
-                    emitcall('FPC_STRCMP',true);
-                    maybe_loadesi;
-                    popusedregisters(pushedregs);
-                 end;
-               ungetiftemp(p^.left^.location.reference);
-               ungetiftemp(p^.right^.location.reference);
-            end;
-            else CGMessage(type_e_mismatch);
+             end;
           end;
         SetResultLocation(cmpop,true,p);
       end;
@@ -1293,7 +1324,10 @@ implementation
 end.
 {
   $Log$
-  Revision 1.18  1998-10-20 08:06:38  pierre
+  Revision 1.19  1998-10-20 15:09:21  florian
+    + binary operators for ansi strings
+
+  Revision 1.18  1998/10/20 08:06:38  pierre
     * several memory corruptions due to double freemem solved
       => never use p^.loc.location:=p^.left^.loc.location;
     + finally I added now by default

+ 131 - 127
compiler/cg68kadd.pas

@@ -144,6 +144,7 @@ implementation
          flags : tresflags;
       begin
          { remove temporary location if not a set or string }
+         { that's a hack (FK)                               }
          if (p^.left^.resulttype^.deftype<>stringdef) and
             ((p^.left^.resulttype^.deftype<>setdef) or (psetdef(p^.left^.resulttype)^.settype=smallset)) and
             (p^.left^.location.loc in [LOC_MEM,LOC_REFERENCE]) then
@@ -217,135 +218,135 @@ implementation
       begin
         { string operations are not commutative }
         if p^.swaped then
-         swaptree(p);
-
-{$ifdef UseAnsiString}
-              if is_ansistring(p^.left^.resulttype) then
-                begin
-                  case p^.treetype of
-                  addn :
-                    begin
-                       { we do not need destination anymore }
-                       del_reference(p^.left^.location.reference);
-                       del_reference(p^.right^.location.reference);
-                       { concatansistring(p); }
-                    end;
-                  ltn,lten,gtn,gten,
-                  equaln,unequaln :
-                    begin
-                       pushusedregisters(pushedregs,$ff);
-                       secondpass(p^.left);
-                       del_reference(p^.left^.location.reference);
-                       emitpushreferenceaddr(exprasmlist,p^.left^.location.reference);
-                       secondpass(p^.right);
-                       del_reference(p^.right^.location.reference);
-                       emitpushreferenceaddr(exprasmlist,p^.right^.location.reference);
-                       emitcall('FPC_ANSISTRCMP',true);
-                       maybe_loada5;
-                       popusedregisters(pushedregs);
-                    end;
+          swaptree(p);
+        case pstringdef(p^.left^.resulttype)^.string_typ of
+           st_ansistring:
+             begin
+                case p^.treetype of
+                addn :
+                  begin
+                     { we do not need destination anymore }
+                     del_reference(p^.left^.location.reference);
+                     del_reference(p^.right^.location.reference);
+                     { concatansistring(p); }
                   end;
-                end
-              else
-{$endif UseAnsiString}
-
-              case p^.treetype of
-                 addn : begin
-                           cmpop:=false;
-                           secondpass(p^.left);
-                           if (p^.left^.treetype<>addn) then
-                             begin
-                                { can only reference be }
-                                { string in register would be funny    }
-                                { therefore produce a temporary string }
-
-                                { release the registers }
-                                del_reference(p^.left^.location.reference);
-                                gettempofsizereference(256,href);
-                                copystring(href,p^.left^.location.reference,255);
-                                ungetiftemp(p^.left^.location.reference);
-
-                                { does not hurt: }
-                                clear_location(p^.left^.location);
-                                p^.left^.location.loc:=LOC_MEM;
-                                p^.left^.location.reference:=href;
-                             end;
-
-                           secondpass(p^.right);
-
-                           { on the right we do not need the register anymore too }
-                           del_reference(p^.right^.location.reference);
-                           pushusedregisters(pushedregs,$ffff);
-                           { WE INVERSE THE PARAMETERS!!! }
-                           { Because parameters are inversed in the rtl }
-                           emitpushreferenceaddr(exprasmlist,p^.right^.location.reference);
-                           emitpushreferenceaddr(exprasmlist,p^.left^.location.reference);
-                           emitcall('FPC_STRCONCAT',true);
-                           maybe_loadA5;
-                           popusedregisters(pushedregs);
-                           set_location(p^.location,p^.left^.location);
-                           ungetiftemp(p^.right^.location.reference);
-                        end; { this case }
-              ltn,lten,gtn,gten,
+                ltn,lten,gtn,gten,
                 equaln,unequaln :
-                        begin
-                           secondpass(p^.left);
-                           { are too few registers free? }
-                           pushed:=maybe_push(p^.right^.registers32,p);
-                           secondpass(p^.right);
-                           if pushed then restore(p);
-                           cmpop:=true;
-                           del_reference(p^.right^.location.reference);
-                           del_reference(p^.left^.location.reference);
-                           { generates better code }
-                           { s='' and s<>''        }
-                           if (p^.treetype in [equaln,unequaln]) and
-                             (
-                               ((p^.left^.treetype=stringconstn) and
-                                (str_length(p^.left)=0)) or
-                               ((p^.right^.treetype=stringconstn) and
-                                (str_length(p^.right)=0))
-                             ) then
-                             begin
-                                { only one node can be stringconstn }
-                                { else pass 1 would have evaluted   }
-                                { this node                         }
-                                if p^.left^.treetype=stringconstn then
-                                  exprasmlist^.concat(new(pai68k,op_ref(
-                                    A_TST,S_B,newreference(p^.right^.location.reference))))
-                                else
-                                  exprasmlist^.concat(new(pai68k,op_ref(
-                                    A_TST,S_B,newreference(p^.left^.location.reference))));
-                             end
-                           else
-                             begin
-                               pushusedregisters(pushedregs,$ffff);
-
-                               { parameters are directly passed via registers       }
-                               { this has several advantages, no loss of the flags  }
-                               { on exit ,and MUCH faster on m68k machines          }
-                               {  speed difference (68000)                          }
-                               {   normal routine: entry, exit code + push  = 124   }
-                               {   (best case)                                      }
-                               {   assembler routine: param setup (worst case) = 48 }
-
-                               exprasmlist^.concat(new(pai68k,op_ref_reg(
-                                    A_LEA,S_L,newreference(p^.left^.location.reference),R_A0)));
-                               exprasmlist^.concat(new(pai68k,op_ref_reg(
-                                    A_LEA,S_L,newreference(p^.right^.location.reference),R_A1)));
-{
-                               emitpushreferenceaddr(p^.left^.location.reference);
-                               emitpushreferenceaddr(p^.right^.location.reference); }
-                               emitcall('FPC_STRCMP',true);
-                               maybe_loada5;
-                               popusedregisters(pushedregs);
-                          end;
-                           ungetiftemp(p^.left^.location.reference);
-                           ungetiftemp(p^.right^.location.reference);
-                        end; { end this case }
-                else CGMessage(type_e_mismatch);
-              end; { end case }
+                  begin
+                     pushusedregisters(pushedregs,$ff);
+                     secondpass(p^.left);
+                     del_reference(p^.left^.location.reference);
+                     emitpushreferenceaddr(exprasmlist,p^.left^.location.reference);
+                     secondpass(p^.right);
+                     del_reference(p^.right^.location.reference);
+                     emitpushreferenceaddr(exprasmlist,p^.right^.location.reference);
+                     emitcall('FPC_ANSISTRCMP',true);
+                     maybe_loada5;
+                     popusedregisters(pushedregs);
+                  end;
+                end;
+             end;
+           st_shortstring:
+             begin
+                case p^.treetype of
+                   addn : begin
+                             cmpop:=false;
+                             secondpass(p^.left);
+                             if (p^.left^.treetype<>addn) then
+                               begin
+                                  { can only reference be }
+                                  { string in register would be funny    }
+                                  { therefore produce a temporary string }
+
+                                  { release the registers }
+                                  del_reference(p^.left^.location.reference);
+                                  gettempofsizereference(256,href);
+                                  copystring(href,p^.left^.location.reference,255);
+                                  ungetiftemp(p^.left^.location.reference);
+
+                                  { does not hurt: }
+                                  clear_location(p^.left^.location);
+                                  p^.left^.location.loc:=LOC_MEM;
+                                  p^.left^.location.reference:=href;
+                               end;
+
+                             secondpass(p^.right);
 
+                             { on the right we do not need the register anymore too }
+                             del_reference(p^.right^.location.reference);
+                             pushusedregisters(pushedregs,$ffff);
+                             { WE INVERSE THE PARAMETERS!!! }
+                             { Because parameters are inversed in the rtl }
+                             emitpushreferenceaddr(exprasmlist,p^.right^.location.reference);
+                             emitpushreferenceaddr(exprasmlist,p^.left^.location.reference);
+                             emitcall('FPC_STRCONCAT',true);
+                             maybe_loadA5;
+                             popusedregisters(pushedregs);
+                             set_location(p^.location,p^.left^.location);
+                             ungetiftemp(p^.right^.location.reference);
+                          end; { this case }
+                ltn,lten,gtn,gten,
+                  equaln,unequaln :
+                          begin
+                             secondpass(p^.left);
+                             { are too few registers free? }
+                             pushed:=maybe_push(p^.right^.registers32,p);
+                             secondpass(p^.right);
+                             if pushed then restore(p);
+                             cmpop:=true;
+                             del_reference(p^.right^.location.reference);
+                             del_reference(p^.left^.location.reference);
+                             { generates better code }
+                             { s='' and s<>''        }
+                             if (p^.treetype in [equaln,unequaln]) and
+                               (
+                                 ((p^.left^.treetype=stringconstn) and
+                                  (str_length(p^.left)=0)) or
+                                 ((p^.right^.treetype=stringconstn) and
+                                  (str_length(p^.right)=0))
+                               ) then
+                               begin
+                                  { only one node can be stringconstn }
+                                  { else pass 1 would have evaluted   }
+                                  { this node                         }
+                                  if p^.left^.treetype=stringconstn then
+                                    exprasmlist^.concat(new(pai68k,op_ref(
+                                      A_TST,S_B,newreference(p^.right^.location.reference))))
+                                  else
+                                    exprasmlist^.concat(new(pai68k,op_ref(
+                                      A_TST,S_B,newreference(p^.left^.location.reference))));
+                               end
+                             else
+                               begin
+                                 pushusedregisters(pushedregs,$ffff);
+
+                                 { parameters are directly passed via registers       }
+                                 { this has several advantages, no loss of the flags  }
+                                 { on exit ,and MUCH faster on m68k machines          }
+                                 {  speed difference (68000)                          }
+                                 {   normal routine: entry, exit code + push  = 124   }
+                                 {   (best case)                                      }
+                                 {   assembler routine: param setup (worst case) = 48 }
+
+                                 exprasmlist^.concat(new(pai68k,op_ref_reg(
+                                      A_LEA,S_L,newreference(p^.left^.location.reference),R_A0)));
+                                 exprasmlist^.concat(new(pai68k,op_ref_reg(
+                                      A_LEA,S_L,newreference(p^.right^.location.reference),R_A1)));
+                                 {
+                                 emitpushreferenceaddr(p^.left^.location.reference);
+                                 emitpushreferenceaddr(p^.right^.location.reference); }
+                                 emitcall('FPC_STRCMP',true);
+                                 maybe_loada5;
+                                 popusedregisters(pushedregs);
+                            end;
+                             ungetiftemp(p^.left^.location.reference);
+                             ungetiftemp(p^.right^.location.reference);
+                          end; { end this case }
+
+                   else CGMessage(type_e_mismatch);
+                end;
+             end; { end case }
+          end;
         SetResultLocation(cmpop,true,p);
       end;
 
@@ -1279,7 +1280,10 @@ implementation
 end.
 {
   $Log$
-  Revision 1.13  1998-10-20 08:06:43  pierre
+  Revision 1.14  1998-10-20 15:09:23  florian
+    + binary operators for ansi strings
+
+  Revision 1.13  1998/10/20 08:06:43  pierre
     * several memory corruptions due to double freemem solved
       => never use p^.loc.location:=p^.left^.loc.location;
     + finally I added now by default

+ 57 - 30
compiler/tcadd.pas

@@ -377,11 +377,13 @@ implementation
              if is_boolean(ld) and is_boolean(rd) then
               begin
                 case p^.treetype of
-             andn,orn : begin
-                          calcregisters(p,0,0,0);
-                          make_bool_equal_size(p);
-                          p^.location.loc:=LOC_JUMP;
-                        end;
+                  andn,
+                  orn:
+                    begin
+                       calcregisters(p,0,0,0);
+                       make_bool_equal_size(p);
+                       p^.location.loc:=LOC_JUMP;
+                    end;
              unequaln,
           equaln,xorn : begin
                           { this forces a better code generation (TEST }
@@ -437,33 +439,61 @@ implementation
            end
          else
 
-         { is one of the sides a shortstring ? }
+           { is one of the operands a string ? }
            if (rd^.deftype=stringdef) or (ld^.deftype=stringdef) then
             begin
-              {
               if is_widestring(rd) or is_widestring(ld) then
                 begin
+                   if not(is_widestring(rd)) then
+                     p^.right:=gentypeconvnode(p^.right,cwidestringdef);
+                   if not(is_widestring(ld)) then
+                     p^.left:=gentypeconvnode(p^.left,cwidestringdef);
+                   p^.resulttype:=cwidestringdef;
+                   { this is only for add, the comparisaion is handled later }
+                   p^.location.loc:=LOC_REGISTER;
                 end
               else if is_ansistring(rd) or is_ansistring(ld) then
                 begin
+                   if not(is_ansistring(rd)) then
+                     p^.right:=gentypeconvnode(p^.right,cansistringdef);
+                   if not(is_ansistring(ld)) then
+                     p^.left:=gentypeconvnode(p^.left,cansistringdef);
+                   p^.resulttype:=cansistringdef;
+                   { this is only for add, the comparisaion is handled later }
+                   p^.location.loc:=LOC_REGISTER;
                 end
               else if is_longstring(rd) or is_longstring(ld) then
                 begin
+                   if not(is_longstring(rd)) then
+                     p^.right:=gentypeconvnode(p^.right,clongstringdef);
+                   if not(is_longstring(ld)) then
+                     p^.left:=gentypeconvnode(p^.left,clongstringdef);
+                   p^.resulttype:=clongstringdef;
+                   { this is only for add, the comparisaion is handled later }
+                   p^.location.loc:=LOC_MEM;
                 end
-              }
-              if not((rd^.deftype=stringdef) and (ld^.deftype=stringdef)) then
-               begin
-                 if ld^.deftype=stringdef then
-                  p^.right:=gentypeconvnode(p^.right,cstringdef)
-                 else
-                  p^.left:=gentypeconvnode(p^.left,cstringdef);
-                 firstpass(p^.left);
-                 firstpass(p^.right);
-               end;
-            { here we call STRCONCAT or STRCMP or STRCOPY }
+              else
+                begin
+                   if not(is_shortstring(rd)) then
+                     p^.right:=gentypeconvnode(p^.right,cstringdef);
+                   if not(is_shortstring(ld)) then
+                     p^.left:=gentypeconvnode(p^.left,cstringdef);
+                   p^.resulttype:=cstringdef;
+                   { this is only for add, the comparisaion is handled later }
+                   p^.location.loc:=LOC_MEM;
+                end;
+              { only if there is a type cast we need to do again }
+              { the first pass                                   }
+              if p^.left^.treetype=typeconvn then
+                firstpass(p^.left);
+              if p^.right^.treetype=typeconvn then
+                firstpass(p^.right);
+              { here we call STRCONCAT or STRCMP or STRCOPY }
               procinfo.flags:=procinfo.flags or pi_do_call;
-              calcregisters(p,0,0,0);
-              p^.location.loc:=LOC_MEM;
+              if p^.location.loc=LOC_MEM then
+                calcregisters(p,0,0,0)
+              else
+                calcregisters(p,1,0,0);
               convdone:=true;
            end
          else
@@ -875,7 +905,8 @@ implementation
          case p^.treetype of
             ltn,lten,gtn,gten,equaln,unequaln:
               begin
-                 if not assigned(p^.resulttype) then
+                 if (not assigned(p^.resulttype)) or
+                   (p^.resulttype^.deftype=stringdef) then
                    p^.resulttype:=booldef;
                  p^.location.loc:=LOC_FLAGS;
               end;
@@ -891,16 +922,9 @@ implementation
                  if (p^.left^.resulttype^.deftype=stringdef) or
                     (p^.right^.resulttype^.deftype=stringdef) then
                    begin
-{$ifndef UseAnsiString}
                       if not assigned(p^.resulttype) then
                         p^.resulttype:=cstringdef
-{$else UseAnsiString}
-                      if is_ansistring(p^.left^.resulttype) or
-                         is_ansistring(p^.right^.resulttype) then
-                        p^.resulttype:=cansistringdef
-                      else
-                        p^.resulttype:=cstringdef;
-{$endif UseAnsiString}
+                      { the rest is done before }
                    end
                  else
                    if not assigned(p^.resulttype) then
@@ -915,7 +939,10 @@ implementation
 end.
 {
   $Log$
-  Revision 1.5  1998-10-20 08:07:05  pierre
+  Revision 1.6  1998-10-20 15:09:24  florian
+    + binary operators for ansi strings
+
+  Revision 1.5  1998/10/20 08:07:05  pierre
     * several memory corruptions due to double freemem solved
       => never use p^.loc.location:=p^.left^.loc.location;
     + finally I added now by default