llvmjit: Also copy parameter / return value attributes from template functions.
authorAndres Freund <andres@anarazel.de>
Thu, 15 Oct 2020 20:39:41 +0000 (13:39 -0700)
committerAndres Freund <andres@anarazel.de>
Thu, 15 Oct 2020 22:06:16 +0000 (15:06 -0700)
Previously we only copied the function attributes. That caused problems at
least on s390x: Because we didn't copy the 'zeroext' attribute for
ExecAggTransReparent()'s *IsNull parameters, expressions invoking it didn't
ensure that the upper bytes of the registers were zeroed. In the - relatively
rare - cases where not, ExecAggTransReparent() wrongly ended up in the
newValueIsNull branch due to the register not being zero. Subsequently causing
a crash.

It's quite possible that this would cause problems on other platforms, and in
other places than just ExecAggTransReparent() on s390x.

Thanks to Christoph (and the Debian project) for providing me with access to a
s390x machine, allowing me to debug this.

Reported-By: Christoph Berg
Author: Andres Freund
Discussion: https://postgr.es/m/20201015083246.kie5726xerdt3ael@alap3.anarazel.de
Backpatch: 11-, where JIT was added

src/backend/jit/llvm/llvmjit.c

index 7510698f863a1e7d36eaa0311d1c8cbcbc5ed831..c401a1c5b4859793d37cd4da428b654f75ba4ffa 100644 (file)
@@ -327,26 +327,48 @@ llvm_get_decl(LLVMModuleRef mod, LLVMValueRef v_src)
 }
 
 /*
- * Copy attributes from one function to another.
+ * Copy attributes from one function to another, for a specific index (an
+ * index can reference return value, function and parameter attributes).
  */
-void
-llvm_copy_attributes(LLVMValueRef v_from, LLVMValueRef v_to)
+static void
+llvm_copy_attributes_at_index(LLVMValueRef v_from, LLVMValueRef v_to, uint32 index)
 {
    int         num_attributes;
-   int         attno;
    LLVMAttributeRef *attrs;
+   int         attno;
 
-   num_attributes =
-       LLVMGetAttributeCountAtIndex(v_from, LLVMAttributeFunctionIndex);
+   num_attributes = LLVMGetAttributeCountAtIndex(v_from, index);
 
    attrs = palloc(sizeof(LLVMAttributeRef) * num_attributes);
-   LLVMGetAttributesAtIndex(v_from, LLVMAttributeFunctionIndex, attrs);
+   LLVMGetAttributesAtIndex(v_from, index, attrs);
 
    for (attno = 0; attno < num_attributes; attno++)
-   {
-       LLVMAddAttributeAtIndex(v_to, LLVMAttributeFunctionIndex,
-                               attrs[attno]);
-   }
+       LLVMAddAttributeAtIndex(v_to, index, attrs[attno]);
+
+   pfree(attrs);
+}
+
+/*
+ * Copy all attributes from one function to another. I.e. function, return and
+ * parameters will be copied.
+ */
+void
+llvm_copy_attributes(LLVMValueRef v_from, LLVMValueRef v_to)
+{
+   uint32      param_count;
+   int         paramidx;
+
+   /* copy function attributes */
+   llvm_copy_attributes_at_index(v_from, v_to, LLVMAttributeFunctionIndex);
+
+   /* and the return value attributes */
+   llvm_copy_attributes_at_index(v_from, v_to, LLVMAttributeReturnIndex);
+
+   /* and each function parameter's attribute */
+   param_count = LLVMCountParams(v_from);
+
+   for (paramidx = 1; paramidx <= param_count; paramidx++)
+       llvm_copy_attributes_at_index(v_from, v_to, paramidx);
 }
 
 /*