[pkg-d-commits] [ldc] 79/211: Fix in-place construction of structs returned by inline assembly

Matthias Klumpp mak at moszumanska.debian.org
Sun Apr 23 22:36:11 UTC 2017


This is an automated email from the git hooks/post-receive script.

mak pushed a commit to annotated tag v1.1.0
in repository ldc.

commit 7a0bba00d9282d82313a9b371b4f80696c63afcd
Author: Martin <noone at nowhere.com>
Date:   Tue Oct 11 21:10:23 2016 +0200

    Fix in-place construction of structs returned by inline assembly
    
    Fixes #1823.
---
 gen/inlineir.cpp                       | 15 ++++++++++-----
 gen/inlineir.h                         |  4 +++-
 gen/llvmhelpers.h                      |  3 ++-
 gen/naked.cpp                          | 19 ++++++++++++-------
 gen/toir.cpp                           |  4 ++--
 tests/codegen/in_place_construct_asm.d | 14 ++++++++++++++
 6 files changed, 43 insertions(+), 16 deletions(-)

diff --git a/gen/inlineir.cpp b/gen/inlineir.cpp
index 31928ac..f6f2e41 100644
--- a/gen/inlineir.cpp
+++ b/gen/inlineir.cpp
@@ -43,7 +43,7 @@ void copyFnAttributes(llvm::Function *wannabe, llvm::Function *idol) {
 } // anonymous namespace
 
 DValue *DtoInlineIRExpr(Loc &loc, FuncDeclaration *fdecl,
-                        Expressions *arguments) {
+                        Expressions *arguments, LLValue *sretPointer) {
   IF_LOG Logger::println("DtoInlineIRExpr @ %s", loc.toChars());
   LOG_SCOPE;
 
@@ -172,17 +172,22 @@ DValue *DtoInlineIRExpr(Loc &loc, FuncDeclaration *fdecl,
     }
 
     llvm::Value *rv = gIR->ir->CreateCall(fun, args);
+    Type *type = fdecl->type->nextOf();
+
+    if (sretPointer) {
+      DtoStore(rv, DtoBitCast(sretPointer, getPtrToType(rv->getType())));
+      return new DLValue(type, sretPointer);
+    }
 
     // work around missing tuple support for users of the return value
-    Type *type = fdecl->type->nextOf()->toBasetype();
-    if (type->ty == Tstruct) {
+    if (type->toBasetype()->ty == Tstruct) {
       // make a copy
       llvm::Value *mem = DtoAlloca(type, ".__ir_tuple_ret");
       DtoStore(rv, DtoBitCast(mem, getPtrToType(rv->getType())));
-      return new DLValue(fdecl->type->nextOf(), mem);
+      return new DLValue(type, mem);
     }
 
     // return call as im value
-    return new DImValue(fdecl->type->nextOf(), rv);
+    return new DImValue(type, rv);
   }
 }
diff --git a/gen/inlineir.h b/gen/inlineir.h
index 8806e6a..d260dcc 100644
--- a/gen/inlineir.h
+++ b/gen/inlineir.h
@@ -22,9 +22,11 @@ struct Loc;
 
 namespace llvm {
 class Function;
+class Value;
 }
 
 DValue *DtoInlineIRExpr(Loc &loc, FuncDeclaration *fdecl,
-                        Expressions *arguments);
+                        Expressions *arguments,
+                        llvm::Value *sretPointer = nullptr);
 
 #endif
diff --git a/gen/llvmhelpers.h b/gen/llvmhelpers.h
index deac7ce..db9435d 100644
--- a/gen/llvmhelpers.h
+++ b/gen/llvmhelpers.h
@@ -148,7 +148,8 @@ LLValue *DtoIndexAggregate(LLValue *src, AggregateDeclaration *ad,
 unsigned getFieldGEPIndex(AggregateDeclaration *ad, VarDeclaration *vd);
 
 ///
-DValue *DtoInlineAsmExpr(Loc &loc, FuncDeclaration *fd, Expressions *arguments);
+DValue *DtoInlineAsmExpr(Loc &loc, FuncDeclaration *fd, Expressions *arguments,
+                         LLValue *sretPointer = nullptr);
 
 /// Returns the size the LLVM type for a member variable of the given type will
 /// take up in a struct (in bytes). This does not include padding in any way.
diff --git a/gen/naked.cpp b/gen/naked.cpp
index e9a37a1..887d9dd 100644
--- a/gen/naked.cpp
+++ b/gen/naked.cpp
@@ -387,8 +387,8 @@ void emitABIReturnAsmStmt(IRAsmBlock *asmblock, Loc &loc,
 
 // sort of kinda related to naked ...
 
-DValue *DtoInlineAsmExpr(Loc &loc, FuncDeclaration *fd,
-                         Expressions *arguments) {
+DValue *DtoInlineAsmExpr(Loc &loc, FuncDeclaration *fd, Expressions *arguments,
+                         LLValue *sretPointer) {
   IF_LOG Logger::println("DtoInlineAsmExpr @ %s", loc.toChars());
   LOG_SCOPE;
 
@@ -431,8 +431,8 @@ DValue *DtoInlineAsmExpr(Loc &loc, FuncDeclaration *fd,
   }
 
   // build asm function type
-  Type *type = fd->type->nextOf()->toBasetype();
-  LLType *ret_type = DtoType(type);
+  Type *type = fd->type->nextOf();
+  LLType *ret_type = DtoType(type->toBasetype());
   llvm::FunctionType *FT = llvm::FunctionType::get(ret_type, argtypes, false);
 
   // build asm call
@@ -441,14 +441,19 @@ DValue *DtoInlineAsmExpr(Loc &loc, FuncDeclaration *fd,
 
   llvm::Value *rv = gIR->ir->CreateCall(ia, args, "");
 
+  if (sretPointer) {
+    DtoStore(rv, DtoBitCast(sretPointer, getPtrToType(ret_type)));
+    return new DLValue(type, sretPointer);
+  }
+
   // work around missing tuple support for users of the return value
   if (type->ty == Tstruct) {
     // make a copy
     llvm::Value *mem = DtoAlloca(type, ".__asm_tuple_ret");
-    DtoStore(rv, DtoBitCast(mem, getPtrToType(rv->getType())));
-    return new DLValue(fd->type->nextOf(), mem);
+    DtoStore(rv, DtoBitCast(mem, getPtrToType(ret_type)));
+    return new DLValue(type, mem);
   }
 
   // return call as im value
-  return new DImValue(fd->type->nextOf(), rv);
+  return new DImValue(type, rv);
 }
diff --git a/gen/toir.cpp b/gen/toir.cpp
index 8f5ef6d..821f852 100644
--- a/gen/toir.cpp
+++ b/gen/toir.cpp
@@ -654,10 +654,10 @@ public:
       VarExp *ve = static_cast<VarExp *>(e->e1);
       if (FuncDeclaration *fd = ve->var->isFuncDeclaration()) {
         if (fd->llvmInternal == LLVMinline_asm) {
-          return DtoInlineAsmExpr(e->loc, fd, e->arguments);
+          return DtoInlineAsmExpr(e->loc, fd, e->arguments, sretPointer);
         }
         if (fd->llvmInternal == LLVMinline_ir) {
-          return DtoInlineIRExpr(e->loc, fd, e->arguments);
+          return DtoInlineIRExpr(e->loc, fd, e->arguments, sretPointer);
         }
       }
     }
diff --git a/tests/codegen/in_place_construct_asm.d b/tests/codegen/in_place_construct_asm.d
new file mode 100644
index 0000000..bd9c970
--- /dev/null
+++ b/tests/codegen/in_place_construct_asm.d
@@ -0,0 +1,14 @@
+// Tests in-place construction of structs returned by inline assembly (issue #1823).
+
+// Target Win64 for simplicity (e.g., 4x32-bit struct not returned in memory for non-Windows x64).
+// RUN: %ldc -mtriple=x86_64-pc-windows-msvc -c -output-ll -of=%t.ll %s && FileCheck %s < %t.ll
+
+import ldc.llvmasm;
+
+// CHECK-LABEL: define{{.*}} @{{.*}}_D22in_place_construct_asm14inlineAssemblyFkkZv
+void inlineAssembly(uint eax, uint ecx)
+{
+    // CHECK: store %"ldc.llvmasm.__asmtuple_t!(uint, uint, uint, uint).__asmtuple_t" %3, %"ldc.llvmasm.__asmtuple_t!(uint, uint, uint, uint).__asmtuple_t"* %r
+    auto r = __asmtuple!(uint, uint, uint, uint) ("cpuid",
+        "={eax},={ebx},={ecx},={edx},{eax},{ecx}", eax, ecx);
+}

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-d/ldc.git



More information about the pkg-d-commits mailing list