[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