Browse Source

* implement concatcopy for complex types by calling the llvm.memcpy()
intrinsic. This may insert actual calls to a function called memcpy with
the signature of the libc function, but llvm optimizers are free to
insert such calls by themselves already. This means that for non-libc
targets, we will have to add weak symbols for memcpy/memmove/memset
that call through to move/fillchar when using LLVM, so that these
implementation are used when not linking to libc

git-svn-id: trunk@31408 -

Jonas Maebe 10 years ago
parent
commit
be9d2b1c26
1 changed files with 40 additions and 2 deletions
  1. 40 2
      compiler/llvm/hlcgllvm.pas

+ 40 - 2
compiler/llvm/hlcgllvm.pas

@@ -915,8 +915,46 @@ implementation
 
 
   procedure thlcgllvm.g_concatcopy(list: TAsmList; size: tdef; const source, dest: treference);
-    begin
-      a_load_ref_ref(list,size,size,source,dest);
+    var
+      pd: tprocdef;
+      sourcepara, destpara, sizepara, alignpara, volatilepara: tcgpara;
+      maxalign: longint;
+    begin
+      { perform small copies directly; not larger ones, because then llvm
+        will try to load the entire large datastructure into registers and
+        starts spilling like crazy; too small copies must not be done via
+        llvm.memcpy either, because then you get crashes in llvm }
+      if (size.typ in [orddef,floatdef,enumdef]) or
+         (size.size<=2*sizeof(aint)) then
+        begin
+          a_load_ref_ref(list,size,size,source,dest);
+          exit;
+        end;
+      pd:=search_system_proc('llvm_memcpy64');
+      sourcepara.init;
+      destpara.init;
+      sizepara.init;
+      alignpara.init;
+      volatilepara.init;
+      paramanager.getintparaloc(list,pd,1,sourcepara);
+      paramanager.getintparaloc(list,pd,2,destpara);
+      paramanager.getintparaloc(list,pd,3,sizepara);
+      paramanager.getintparaloc(list,pd,4,alignpara);
+      paramanager.getintparaloc(list,pd,5,volatilepara);
+      a_loadaddr_ref_cgpara(list,size,source,sourcepara);
+      a_loadaddr_ref_cgpara(list,size,dest,destpara);
+      a_load_const_cgpara(list,u64inttype,size.size,sizepara);
+      maxalign:=newalignment(source.alignment,dest.alignment);
+      a_load_const_cgpara(list,u32inttype,maxalign,alignpara);
+      { we don't know anything about volatility here, should become an extra
+        parameter to g_concatcopy }
+      a_load_const_cgpara(list,pasbool8type,0,volatilepara);
+      g_call_system_proc(list,pd,[@sourcepara,@destpara,@sizepara,@alignpara,@volatilepara],nil).resetiftemp;
+      sourcepara.done;
+      destpara.done;
+      sizepara.done;
+      alignpara.done;
+      volatilepara.done;
     end;