Browse Source

* refactor loadnode for varsyms

git-svn-id: trunk@5261 -
peter 19 years ago
parent
commit
d526a682d1
1 changed files with 134 additions and 158 deletions
  1. 134 158
      compiler/ncgld.pas

+ 134 - 158
compiler/ncgld.pas

@@ -80,7 +80,8 @@ implementation
     procedure tcgloadnode.pass_generate_code;
       var
         hregister : tregister;
-        symtabletype : TSymtabletype;
+        vs   : tabstractnormalvarsym;
+        gvs  : tglobalvarsym;
         pd   : tprocdef;
         href : treference;
         newsize : tcgsize;
@@ -130,167 +131,142 @@ implementation
                  else
                    internalerror(22798);
               end;
-            globalvarsym,
-            localvarsym,
-            paravarsym :
-               begin
-                  if (symtableentry.typ = globalvarsym) and
-                     ([vo_is_dll_var,vo_is_external] * tglobalvarsym(symtableentry).varoptions <> []) then
-                    begin
-                      location.reference.base := cg.g_indirect_sym_load(current_asmdata.CurrAsmList,tglobalvarsym(symtableentry).mangledname);
-                      if (location.reference.base <> NR_NO) then
-                        exit;
-                    end;
+            globalvarsym :
+              begin
+                gvs:=tglobalvarsym(symtableentry);
+                if ([vo_is_dll_var,vo_is_external] * gvs.varoptions <> []) then
+                  begin
+                    location.reference.base := cg.g_indirect_sym_load(current_asmdata.CurrAsmList,tglobalvarsym(symtableentry).mangledname);
+                    if (location.reference.base <> NR_NO) then
+                      exit;
+                  end;
 
-                  symtabletype:=symtable.symtabletype;
-                  hregister:=NR_NO;
-                  if (vo_is_dll_var in tabstractvarsym(symtableentry).varoptions) then
-                  { DLL variable }
-                    begin
-                      hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
-                      location.reference.symbol:=current_asmdata.RefAsmSymbol(tglobalvarsym(symtableentry).mangledname);
-                      cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,location.reference,hregister);
-                      reference_reset_base(location.reference,hregister,0);
-                    end
-                  { Thread variable }
-                  else if (vo_is_thread_var in tabstractvarsym(symtableentry).varoptions) and
-                    not(tf_section_threadvars in target_info.flags) then
-                    begin
-                       {
-                         Thread var loading is optimized to first check if
-                         a relocate function is available. When the function
-                         is available it is called to retrieve the address.
-                         Otherwise the address is loaded with the symbol
-
-                         The code needs to be in the order to first handle the
-                         call and then the address load to be sure that the
-                         register that is used for returning is the same (PFV)
-                       }
-                       current_asmdata.getjumplabel(norelocatelab);
-                       current_asmdata.getjumplabel(endrelocatelab);
-                       { make sure hregister can't allocate the register necessary for the parameter }
-                       paraloc1.init;
-                       paramanager.getintparaloc(pocall_default,1,paraloc1);
-                       hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
-                       reference_reset_symbol(href,current_asmdata.RefAsmSymbol('FPC_THREADVAR_RELOCATE'),0);
-                       cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,hregister);
-                       cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,OS_ADDR,OC_EQ,0,hregister,norelocatelab);
-                       { don't save the allocated register else the result will be destroyed later }
-                       reference_reset_symbol(href,current_asmdata.RefAsmSymbol(tglobalvarsym(symtableentry).mangledname),0);
-                       paramanager.allocparaloc(current_asmdata.CurrAsmList,paraloc1);
-                       cg.a_param_ref(current_asmdata.CurrAsmList,OS_32,href,paraloc1);
-                       paramanager.freeparaloc(current_asmdata.CurrAsmList,paraloc1);
-                       paraloc1.done;
-                       cg.allocallcpuregisters(current_asmdata.CurrAsmList);
-                       cg.a_call_reg(current_asmdata.CurrAsmList,hregister);
-                       cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
-                       cg.getcpuregister(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);
-                       cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);
-                       hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
-                       cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_INT,OS_ADDR,NR_FUNCTION_RESULT_REG,hregister);
-                       cg.a_jmp_always(current_asmdata.CurrAsmList,endrelocatelab);
-                       cg.a_label(current_asmdata.CurrAsmList,norelocatelab);
-                       { no relocation needed, load the address of the variable only, the
-                         layout of a threadvar is (4 bytes pointer):
-                           0 - Threadvar index
-                           4 - Threadvar value in single threading }
-                       reference_reset_symbol(href,current_asmdata.RefAsmSymbol(tglobalvarsym(symtableentry).mangledname),sizeof(aint));
-                       cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,href,hregister);
-                       cg.a_label(current_asmdata.CurrAsmList,endrelocatelab);
-                       location.reference.base:=hregister;
-                    end
-                  { Nested variable }
-                  else if assigned(left) then
-                    begin
-                      if not(symtabletype in [localsymtable,parasymtable]) then
-                        internalerror(200309285);
-                      secondpass(left);
-                      if left.location.loc<>LOC_REGISTER then
-                        internalerror(200309286);
-                      if tabstractnormalvarsym(symtableentry).localloc.loc<>LOC_REFERENCE then
-                        internalerror(200409241);
-                      hregister:=left.location.register;
-                      reference_reset_base(location.reference,hregister,tabstractnormalvarsym(symtableentry).localloc.reference.offset);
-                    end
-                  { Normal (or external) variable }
-                  else
-                    begin
-{$ifdef OLDREGVARS}
-                       { in case it is a register variable: }
-                       if tvarsym(symtableentry).localloc.loc in [LOC_REGISTER,LOC_FPUREGISTER] then
-                         begin
-                            case getregtype(tvarsym(symtableentry).localloc.register) of
-                              R_FPUREGISTER :
-                                begin
-                                  location_reset(location,LOC_CFPUREGISTER,def_cgsize(resultdef));
-                                  location.register:=tvarsym(symtableentry).localloc.register;
-                                end;
-                              R_INTREGISTER :
-                                begin
-                                  location_reset(location,LOC_CREGISTER,def_cgsize(resultdef));
-                                  location.register:=tvarsym(symtableentry).localloc.register;
-                                  hregister := location.register;
-                                end;
-                              else
-                                internalerror(200301172);
-                            end;
-                         end
-                       else
-{$endif OLDREGVARS}
-                         begin
-                           case symtabletype of
-                              stt_excepTSymtable,
-                              localsymtable,
-                              parasymtable :
-                                location:=tabstractnormalvarsym(symtableentry).localloc;
-                              globalsymtable,
-                              staticsymtable :
-                                begin
-                                  if tabstractnormalvarsym(symtableentry).localloc.loc=LOC_INVALID then
-                                    reference_reset_symbol(location.reference,current_asmdata.RefAsmSymbol(tglobalvarsym(symtableentry).mangledname),0)
-                                  else
-                                    location:=tglobalvarsym(symtableentry).localloc;
+                if (vo_is_dll_var in gvs.varoptions) then
+                { DLL variable }
+                  begin
+                    hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
+                    location.reference.symbol:=current_asmdata.RefAsmSymbol(tglobalvarsym(symtableentry).mangledname);
+                    cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,location.reference,hregister);
+                    reference_reset_base(location.reference,hregister,0);
+                  end
+                { Thread variable }
+                else if (vo_is_thread_var in gvs.varoptions) and
+                        not(tf_section_threadvars in target_info.flags) then
+                  begin
+                     if (tf_section_threadvars in target_info.flags) then
+                       begin
+                         if gvs.localloc.loc=LOC_INVALID then
+                           reference_reset_symbol(location.reference,current_asmdata.RefAsmSymbol(gvs.mangledname),0)
+                         else
+                           location:=gvs.localloc;
 {$ifdef i386}
-                                  if (tf_section_threadvars in target_info.flags) and
-                                     (vo_is_thread_var in tabstractvarsym(symtableentry).varoptions) then
-                                    begin
-                                      case target_info.system of
-                                        system_i386_linux:
-                                          location.reference.segment:=NR_GS;
-                                        system_i386_win32:
-                                          location.reference.segment:=NR_FS;
-                                      end;
-                                    end;
-{$endif i386}
-                                end;
-                              else
-                                internalerror(200305102);
-                           end;
+                         case target_info.system of
+                           system_i386_linux:
+                             location.reference.segment:=NR_GS;
+                           system_i386_win32:
+                             location.reference.segment:=NR_FS;
                          end;
-                    end;
+{$endif i386}
+                       end
+                     else
+                       begin
+                         {
+                           Thread var loading is optimized to first check if
+                           a relocate function is available. When the function
+                           is available it is called to retrieve the address.
+                           Otherwise the address is loaded with the symbol
+
+                           The code needs to be in the order to first handle the
+                           call and then the address load to be sure that the
+                           register that is used for returning is the same (PFV)
+                         }
+                         current_asmdata.getjumplabel(norelocatelab);
+                         current_asmdata.getjumplabel(endrelocatelab);
+                         { make sure hregister can't allocate the register necessary for the parameter }
+                         paraloc1.init;
+                         paramanager.getintparaloc(pocall_default,1,paraloc1);
+                         hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
+                         reference_reset_symbol(href,current_asmdata.RefAsmSymbol('FPC_THREADVAR_RELOCATE'),0);
+                         cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,hregister);
+                         cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,OS_ADDR,OC_EQ,0,hregister,norelocatelab);
+                         { don't save the allocated register else the result will be destroyed later }
+                         reference_reset_symbol(href,current_asmdata.RefAsmSymbol(tglobalvarsym(symtableentry).mangledname),0);
+                         paramanager.allocparaloc(current_asmdata.CurrAsmList,paraloc1);
+                         cg.a_param_ref(current_asmdata.CurrAsmList,OS_32,href,paraloc1);
+                         paramanager.freeparaloc(current_asmdata.CurrAsmList,paraloc1);
+                         paraloc1.done;
+                         cg.allocallcpuregisters(current_asmdata.CurrAsmList);
+                         cg.a_call_reg(current_asmdata.CurrAsmList,hregister);
+                         cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
+                         cg.getcpuregister(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);
+                         cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);
+                         hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
+                         cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_INT,OS_ADDR,NR_FUNCTION_RESULT_REG,hregister);
+                         cg.a_jmp_always(current_asmdata.CurrAsmList,endrelocatelab);
+                         cg.a_label(current_asmdata.CurrAsmList,norelocatelab);
+                         { no relocation needed, load the address of the variable only, the
+                           layout of a threadvar is (4 bytes pointer):
+                             0 - Threadvar index
+                             4 - Threadvar value in single threading }
+                         reference_reset_symbol(href,current_asmdata.RefAsmSymbol(tglobalvarsym(symtableentry).mangledname),sizeof(aint));
+                         cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,href,hregister);
+                         cg.a_label(current_asmdata.CurrAsmList,endrelocatelab);
+                         location.reference.base:=hregister;
+                       end;
+                   end
+                 { Normal (or external) variable }
+                 else
+                   begin
+                     if gvs.localloc.loc=LOC_INVALID then
+                       reference_reset_symbol(location.reference,current_asmdata.RefAsmSymbol(gvs.mangledname),0)
+                     else
+                       location:=gvs.localloc;
+                   end;
 
-                  { handle call by reference variables when they are not
-                    alreayd copied to local copies. Also ignore the reference
-                    when we need to load the self pointer for objects }
-                  if is_addr_param_load then
-                    begin
-                      if (location.loc in [LOC_CREGISTER,LOC_REGISTER]) then
-                        hregister:=location.register
-                      else
-                        begin
-                          hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
-                          { we need to load only an address }
-                          location.size:=OS_ADDR;
-                          cg.a_load_loc_reg(current_asmdata.CurrAsmList,location.size,location,hregister);
-                        end;
-                      location_reset(location,LOC_REFERENCE,newsize);
-                      location.reference.base:=hregister;
-                    end;
+                 { make const a LOC_CREFERENCE }
+                 if (gvs.varspez=vs_const) and
+                    (location.loc=LOC_REFERENCE) then
+                   location.loc:=LOC_CREFERENCE;
+               end;
+             paravarsym,
+             localvarsym :
+               begin
+                 vs:=tabstractnormalvarsym(symtableentry);
+                 { Nested variable }
+                 if assigned(left) then
+                   begin
+                     secondpass(left);
+                     if left.location.loc<>LOC_REGISTER then
+                       internalerror(200309286);
+                     if vs.localloc.loc<>LOC_REFERENCE then
+                       internalerror(200409241);
+                     reference_reset_base(location.reference,left.location.register,vs.localloc.reference.offset);
+                   end
+                 else
+                   location:=vs.localloc;
 
-                  { make const a LOC_CREFERENCE }
-                  if (tabstractvarsym(symtableentry).varspez=vs_const) and
-                     (location.loc=LOC_REFERENCE) then
-                    location.loc:=LOC_CREFERENCE;
+                 { handle call by reference variables when they are not
+                   alreayd copied to local copies. Also ignore the reference
+                   when we need to load the self pointer for objects }
+                 if is_addr_param_load then
+                   begin
+                     if (location.loc in [LOC_CREGISTER,LOC_REGISTER]) then
+                       hregister:=location.register
+                     else
+                       begin
+                         hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
+                         { we need to load only an address }
+                         location.size:=OS_ADDR;
+                         cg.a_load_loc_reg(current_asmdata.CurrAsmList,location.size,location,hregister);
+                       end;
+                     location_reset(location,LOC_REFERENCE,newsize);
+                     location.reference.base:=hregister;
+                   end;
+
+                 { make const a LOC_CREFERENCE }
+                 if (vs.varspez=vs_const) and
+                    (location.loc=LOC_REFERENCE) then
+                   location.loc:=LOC_CREFERENCE;
                end;
             procsym:
                begin
@@ -372,7 +348,7 @@ implementation
                          location.reference.symbol:=current_asmdata.RefAsmSymbol(procdef.mangledname);
                     end;
                end;
-            typedconstsym :
+           typedconstsym :
               location.reference.symbol:=current_asmdata.RefAsmSymbol(ttypedconstsym(symtableentry).mangledname);
             labelsym :
               location.reference.symbol:=tcglabelnode((tlabelsym(symtableentry).code)).getasmlabel;