[pkg-d-commits] [ldc] 66/211: Add a matching call to llvm.va_end when llvm.va_start was called.

Matthias Klumpp mak at moszumanska.debian.org
Sun Apr 23 22:36:10 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 63fba4efdbb874518bd69d4436b0dd10f278eb94
Author: Johan Engelen <jbc.engelen at gmail.com>
Date:   Mon Sep 5 19:46:26 2016 +0200

    Add a matching call to llvm.va_end when llvm.va_start was called.
    
    Resolves #1744
---
 gen/functions.cpp                    | 22 ++++++++++++++++
 tests/codegen/vastart_vaend_gh1744.d | 50 ++++++++++++++++++++++++++++++++++++
 2 files changed, 72 insertions(+)

diff --git a/gen/functions.cpp b/gen/functions.cpp
index 7d42df5..2a8db89 100644
--- a/gen/functions.cpp
+++ b/gen/functions.cpp
@@ -1011,6 +1011,17 @@ void DtoDefineFunction(FuncDeclaration *fd, bool linkageAvailableExternally) {
     // copy _arguments to a memory location
     irFunc->_arguments =
         DtoAllocaDump(irFunc->_arguments, 0, "_arguments_mem");
+
+    // Push cleanup block that calls va_end to match the va_start call.
+    {
+      auto *vaendBB =
+          llvm::BasicBlock::Create(gIR->context(), "vaend", gIR->topfunc());
+      IRScope saveScope = gIR->scope();
+      gIR->scope() = IRScope(vaendBB);
+      gIR->ir->CreateCall(GET_INTRINSIC_DECL(vaend), llAp);
+      funcGen.scopes.pushCleanup(vaendBB, gIR->scopebb());
+      gIR->scope() = saveScope;
+    }
   }
 
   funcGen.pgo.emitCounterIncrement(fd->fbody);
@@ -1019,6 +1030,17 @@ void DtoDefineFunction(FuncDeclaration *fd, bool linkageAvailableExternally) {
   // output function body
   Statement_toIR(fd->fbody, gIR);
 
+  // D varargs: emit the cleanup block that calls va_end.
+  if (f->linkage == LINKd && f->varargs == 1) {
+    if (!gIR->scopereturned()) {
+      if (!funcGen.retBlock)
+        funcGen.retBlock = gIR->insertBB("return");
+      funcGen.scopes.runCleanups(0, funcGen.retBlock);
+      gIR->scope() = IRScope(funcGen.retBlock);
+    }
+    funcGen.scopes.popCleanups(0);
+  }
+
   llvm::BasicBlock *bb = gIR->scopebb();
   if (pred_begin(bb) == pred_end(bb) &&
       bb != &bb->getParent()->getEntryBlock()) {
diff --git a/tests/codegen/vastart_vaend_gh1744.d b/tests/codegen/vastart_vaend_gh1744.d
new file mode 100644
index 0000000..e4ee02c
--- /dev/null
+++ b/tests/codegen/vastart_vaend_gh1744.d
@@ -0,0 +1,50 @@
+// Test that va_end is called when returning from a variadic function.
+
+// Because the IR is kind of ugly, testing at -O0 is very brittle. Instead we
+// test that at -O3, LLVM was able to analyse the function correctly and
+// optimize-out the va_start and va_end calls and remove the call to
+// return_two (Github #1744).
+// The optimization (removing back-to-back calls to va_start and va_end) only
+// happens from LLVM >= 3.9.
+// REQUIRES: atleast_llvm309
+// RUN: %ldc %s -c -output-ll -O3 -of=%t.O3.ll \
+// RUN:   && FileCheck %s --check-prefix OPT3 < %t.O3.ll
+
+module mod;
+
+// OPT3-LABEL: define {{.*}} @{{.*}}void_three_return_paths
+void void_three_return_paths(int a, ...)
+{
+    // OPT3: call void @llvm.va_start({{.*}} %[[VA:[0-9]+]])
+    // OPT3-NOT: return_two
+    return_two();
+
+    if (a > 0)
+    {
+        throw new Exception("");
+        return;
+    }
+
+    // There are two control paths (normal return, exception resume) that
+    // should call va_end.
+    // OPT3: call void @llvm.va_end({{.*}} %[[VA]])
+    // OPT3: call void @llvm.va_end({{.*}} %[[VA]])
+}
+
+// OPT3-LABEL: define {{.*}} @{{.*}}return_two
+int return_two(...)
+{
+    // OPT3-NOT: va_start
+    // OPT3-NOT: va_end
+    // OPT3: ret i32 2
+    return 2;
+}
+
+// Github #1744:
+// OPT3-LABEL: define {{.*}} @{{.*}}two_four
+int two_four()
+{
+    // OPT3-NOT: return_two
+    // OPT3: ret i32 8
+    return return_two() * 4;
+}

-- 
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