<html>
    <head>
      <base href="https://bugs.llvm.org/">
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW - Invalid StructType element type {}* for function pointer"
   href="https://bugs.llvm.org/show_bug.cgi?id=47351">47351</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>Invalid StructType element type {}* for function pointer
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>clang
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>10.0
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>PC
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>Linux
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>enhancement
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>Frontend
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedclangbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>roemheld@sec.in.tum.de
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvm-bugs@lists.llvm.org, neeilans@live.com, richard-llvm@metafoo.co.uk
          </td>
        </tr></table>
      <p>
        <div>
        <pre>Created <span class=""><a href="attachment.cgi?id=23904" name="attach_23904" title="Readable LLVM IR of module lkm.ko">attachment 23904</a> <a href="attachment.cgi?id=23904&action=edit" title="Readable LLVM IR of module lkm.ko">[details]</a></span>
Readable LLVM IR of module lkm.ko

I'm not sure where the origin of this issue is, please move this ticket if you
think that it was filed in the wrong category.

When using wllvm with clang build built from source a custom Linux kernel
module LLVM IR seems to be malformed as its IR shows several struct element
types, which are supposed to be function pointers, simply as {}*.

The minimal example looks as follows:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/uaccess.h>
#include <linux/cred.h>
#include <linux/kallsyms.h>

#include <linux/cpu.h>

struct lkm_state {
        struct file_operations lkm_fops;
} __attribute__((packed)) lkm_state;

int lkm_open(struct inode *inode, struct file *file) {
        return 0;
}

static __init int lkm_init(void) {
        lkm_state.lkm_fops.open = lkm_open;

        return 0;
}

static __exit void lkm_exit(void) {

}

module_init(lkm_init);
module_exit(lkm_exit);

MODULE_LICENSE("GPL");

Of the attachment, the example I'm focusing on is the struct.file_operations
(formatted for better readability):

%struct.file_operations = type {
    %struct.module*,
    i64 (%struct.file*, i64, i32)*,
    i64 (%struct.file*, i8*, i64, i64*)*,
    i64 (%struct.file*, i8*, i64, i64*)*,
    i64 (%struct.kiocb*, %struct.iov_iter*)*,
    i64 (%struct.kiocb*, %struct.iov_iter*)*,
    i32 (%struct.kiocb*, i1)*,
    i32 (%struct.file*, %struct.dir_context*)*,
    i32 (%struct.file*, %struct.dir_context*)*,
    i32 (%struct.file*, %struct.poll_table_struct*)*,
    i64 (%struct.file*, i32, i64)*,
    i64 (%struct.file*, i32, i64)*,
    i32 (%struct.file*, %struct.vm_area_struct*)*,
    i64,
    {}*, <-- should be "i32 (%struct.inode*, %struct.file*)*"
[...]
}

In the attachment I sent (lkm.ko.ll, from llvm-dis lkm.ko.bc) there is a single
function pointer assignment to a struct member, but according to the LLVM IR
the type of the struct member is {}*, which is why in the store instruction it
has to use a bitcast in order to perform the store operation (@init_module):

store i32 (%struct.inode*, %struct.file*)* @lkm_open, i32 (%struct.inode*,
%struct.file*)** bitcast ({}** getelementptr inbounds (%struct.lkm_state,
%struct.lkm_state* @lkm_state, i64 0, i32 0, i32 14) to i32 (%struct.inode*,
%struct.file*)**), align 1

This causes problems as I'm trying to determine the type of the struct element
(I have a small code stub that determines if the struct element type is a
function pointer or not). The type of {}* is PointerTypeID, which is correct,
but it is not reported to be a function pointer, which according to the struct
itself it is one.

Clang version: clang version 10.0.0 [...], commit
91827ebf5e3d9eb633ba909e8f50a3d402698cce
LKM built against Linux version 5.4.0</pre>
        </div>
      </p>


      <hr>
      <span>You are receiving this mail because:</span>

      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>