[PATCH] D61286: [argpromotion] reserve first argument of x86_thiscallcc functions

Bob Haarman via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 29 16:57:27 PDT 2019


inglorion created this revision.
inglorion added reviewers: rnk, eli.friedman.
Herald added a subscriber: hiraditya.
Herald added a project: LLVM.

For functions using the x86_thiscallcc calling convention, the first
parameter (expected to be "this") is passed in the ECX
register. ArgumentPromotion could elide this parameter, which would
cause whatever ended up in the first position to be passed in that
register. If that happened to be an inalloca, code generation would
fail with "cannot use inalloca attribute on a register parameter".
This change stops us from eliding the first parameter of thiscall
functions, avoiding the problem.

Fixes PR41658.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D61286

Files:
  llvm/lib/Transforms/IPO/ArgumentPromotion.cpp
  llvm/test/Transforms/ArgumentPromotion/X86/thiscall.ll


Index: llvm/test/Transforms/ArgumentPromotion/X86/thiscall.ll
===================================================================
--- /dev/null
+++ llvm/test/Transforms/ArgumentPromotion/X86/thiscall.ll
@@ -0,0 +1,35 @@
+; PR41658 happened because we remove parameters from an x86_thiscallcc function
+; and then try to pass an inalloca in a register. This test verifies that we
+; don't do that anymore.
+;
+; RUN: opt -S -argpromotion %s | FileCheck %s
+; CHECK: define internal x86_thiscallcc void @internalfun(%struct.a* %this, <{ %struct.a
+
+target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
+target triple = "i386-pc-windows-msvc19.11.0"
+
+%struct.a = type { i8 }
+
+define internal x86_thiscallcc void @internalfun(%struct.a* %this, <{ %struct.a }>* inalloca) {
+entry:
+  %a = getelementptr inbounds <{ %struct.a }>, <{ %struct.a }>* %0, i32 0, i32 0
+  %argmem = alloca inalloca <{ %struct.a }>, align 4
+  %1 = getelementptr inbounds <{ %struct.a }>, <{ %struct.a }>* %argmem, i32 0, i32 0
+  %call = call x86_thiscallcc %struct.a* @copy_ctor(%struct.a* %1, %struct.a* dereferenceable(1) %a)
+  call void @ext(<{ %struct.a }>* inalloca %argmem)
+  ret void
+}
+
+; This is here to ensure @internalfun is live.
+define void @exportedfun(%struct.a* %a) {
+  %inalloca.save = tail call i8* @llvm.stacksave()
+  %argmem = alloca inalloca <{ %struct.a }>, align 4
+  call x86_thiscallcc void @internalfun(%struct.a* %a, <{ %struct.a }>* inalloca %argmem)
+  call void @llvm.stackrestore(i8* %inalloca.save)
+  ret void
+}
+
+declare x86_thiscallcc %struct.a* @copy_ctor(%struct.a* returned, %struct.a* dereferenceable(1))
+declare void @ext(<{ %struct.a }>* inalloca)
+declare i8* @llvm.stacksave()
+declare void @llvm.stackrestore(i8*)
Index: llvm/lib/Transforms/IPO/ArgumentPromotion.cpp
===================================================================
--- llvm/lib/Transforms/IPO/ArgumentPromotion.cpp
+++ llvm/lib/Transforms/IPO/ArgumentPromotion.cpp
@@ -971,6 +971,12 @@
       ArgsToPromote.insert(PtrArg);
   }
 
+  // Don't promote the first argument to x86 thiscall functions.
+  if (F->getCallingConv() == CallingConv::X86_ThisCall) {
+    assert(!F->arg_empty());
+    ArgsToPromote.erase(F->arg_begin());
+  }
+
   // No promotable pointer arguments.
   if (ArgsToPromote.empty() && ByValArgsToTransform.empty())
     return nullptr;


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D61286.197223.patch
Type: text/x-patch
Size: 2376 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20190429/03bdcbf3/attachment.bin>


More information about the llvm-commits mailing list