瀏覽代碼

+ support for subscript nodes in LLVM

git-svn-id: branches/hlcgllvm@26990 -
Jonas Maebe 11 年之前
父節點
當前提交
20a8175bf1
共有 1 個文件被更改,包括 47 次插入1 次删除
  1. 47 1
      compiler/llvm/nllvmmem.pas

+ 47 - 1
compiler/llvm/nllvmmem.pas

@@ -35,6 +35,11 @@ interface
       tllvmloadparentfpnode = class(tcgnestloadparentfpnode)
       end;
 
+      tllvmsubscriptnode = class(tcgsubscriptnode)
+       protected
+        function handle_platform_subscript: boolean; override;
+      end;
+
       tllvmvecnode= class(tcgvecnode)
        private
         constarrayoffset: aint;
@@ -52,10 +57,50 @@ implementation
     uses
       verbose,cutils,
       aasmdata,aasmllvm,
-      symconst,symdef,defutil,
+      symtable,symconst,symdef,defutil,
       nmem,
       cpubase,llvmbase,hlcgobj;
 
+  { tllvmsubscriptnode }
+
+    function tllvmsubscriptnode.handle_platform_subscript: boolean;
+      var
+        llvmfielddef: tdef;
+        newbase: tregister;
+      begin
+        if location.loc<>LOC_REFERENCE then
+          internalerror(2014011905);
+        if is_packed_record_or_object(left.resultdef) then
+          begin
+            { typecast the result to the expected type, but don't actually index
+              (that still has to be done by the generic code, so return false) }
+            newbase:=hlcg.getaddressregister(current_asmdata.CurrAsmList,getpointerdef(resultdef));
+            hlcg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,left.resultdef,getpointerdef(resultdef),location.reference,newbase);
+            reference_reset_base(location.reference,newbase,0,location.reference.alignment);
+            result:=false;
+          end
+        else
+          begin
+            { get the type of the corresponding field in the llvm shadow
+              definition }
+            llvmfielddef:=tabstractrecordsymtable(tabstractrecorddef(left.resultdef).symtable).llvmst[vs.llvmfieldnr].def;
+            { load the address of that shadow field }
+            newbase:=hlcg.getaddressregister(current_asmdata.CurrAsmList,getpointerdef(llvmfielddef));
+            current_asmdata.CurrAsmList.concat(taillvm.getelementptr_reg_size_ref_size_const(newbase,getpointerdef(left.resultdef),location.reference,s32inttype,vs.llvmfieldnr,true));
+            reference_reset_base(location.reference,newbase,vs.offsetfromllvmfield,newalignment(location.reference.alignment,vs.fieldoffset));
+            { if it doesn't match the requested field exactly (variant record),
+              adjust the type of the pointer }
+            if (vs.offsetfromllvmfield<>0) or
+               (llvmfielddef<>resultdef) then
+              begin
+                newbase:=hlcg.getaddressregister(current_asmdata.CurrAsmList,getpointerdef(resultdef));
+                hlcg.a_load_reg_reg(current_asmdata.CurrAsmList,getpointerdef(llvmfielddef),getpointerdef(resultdef),location.reference.base,newbase);
+                location.reference.base:=newbase;
+              end;
+            result:=true;
+          end;
+      end;
+
   { tllvmvecnode }
 
   procedure tllvmvecnode.pass_generate_code;
@@ -214,6 +259,7 @@ implementation
 
 begin
   cloadparentfpnode:=tllvmloadparentfpnode;
+  csubscriptnode:=tllvmsubscriptnode;
   cvecnode:=tllvmvecnode;
 end.