llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
27.59k stars 11.34k forks source link

Anonymous functions do not work in MIR #36511

Open arsenm opened 6 years ago

arsenm commented 6 years ago
Bugzilla Link 37163
Version trunk
OS All

Extended Description

Reading a MIR dump produced from an anonymous function does not work.

e.g. run llc -stop-after= on this function (or just copy this into a .ll file in test/CodeGen/X86 and run llvm-lit on it)

; RUN: llc -stop-after=finalize-isel < %s

define void @0() {
  ret void
}

define void @0() {
  ret void
}

produces a function with an empty name. The parser then can't read this in complaining: function '' isn't defined in the provided LLVM IR

llvmbot commented 1 year ago

@llvm/issue-subscribers-good-first-issue

diego-est commented 3 months ago

It seems that the MIR dump now produces the appropriate name for anonymous functions.

file.cc

int main() {
  auto a = [](){};
}

file.ll

; ModuleID = 'file.cc'
source_filename = "file.cc"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

%class.anon = type { i8 }

; Function Attrs: mustprogress noinline norecurse nounwind optnone sspstrong uwtable
define noundef i32 @main() #0 {
  %1 = alloca %class.anon, align 1
  ret i32 0
}

attributes #0 = { mustprogress noinline norecurse nounwind optnone sspstrong uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="4" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }

!llvm.module.flags = !{!0, !1, !2, !3}
!llvm.ident = !{!4}

!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{i32 8, !"PIC Level", i32 2}
!2 = !{i32 7, !"uwtable", i32 2}
!3 = !{i32 7, !"frame-pointer", i32 2}
!4 = !{!"clang version 17.0.6"}

As seen by the %class.anon = type { i8 }.

If I actually use this function, a more specific name is given to it. In this example: _ZZ4mainENK3$_0clEi. file.cc

int main() {
  auto a = [](int x){ return x + 1; };
  return a(1);
}

file.ll

; ModuleID = 'file.cc'
source_filename = "file.cc"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

%class.anon = type { i8 }

; Function Attrs: mustprogress noinline norecurse optnone sspstrong uwtable
define noundef i32 @main() #0 {
  %1 = alloca i32, align 4
  %2 = alloca %class.anon, align 1
  store i32 0, ptr %1, align 4
  %3 = call noundef i32 @"_ZZ4mainENK3$_0clEi"(ptr noundef nonnull align 1 dereferenceable(1) %2, i32 noundef 1)
  ret i32 %3
}

; Function Attrs: mustprogress noinline nounwind optnone sspstrong uwtable
define internal noundef i32 @"_ZZ4mainENK3$_0clEi"(ptr noundef nonnull align 1 dereferenceable(1) %0, i32 noundef %1) #1 align 2 {
  %3 = alloca ptr, align 8
  %4 = alloca i32, align 4
  store ptr %0, ptr %3, align 8
  store i32 %1, ptr %4, align 4
  %5 = load ptr, ptr %3, align 8
  %6 = load i32, ptr %4, align 4
  %7 = add i32 %6, 1
  ret i32 %7
}

attributes #0 = { mustprogress noinline norecurse optnone sspstrong uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="4" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
attributes #1 = { mustprogress noinline nounwind optnone sspstrong uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="4" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }

!llvm.module.flags = !{!0, !1, !2, !3}
!llvm.ident = !{!4}

!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{i32 8, !"PIC Level", i32 2}
!2 = !{i32 7, !"uwtable", i32 2}
!3 = !{i32 7, !"frame-pointer", i32 2}
!4 = !{!"clang version 17.0.6"}

The MIR dump for these files was generated with clang file.cc -S -emit-llvm - -O0

I am new to the LLVM project so if I did anything wrong please let me know immediately!

arsenm commented 3 months ago

I am new to the LLVM project so if I did anything wrong please let me know immediately!

None of these functions are anonymous. The function here has a name, it's @"_ZZ4mainENK3$_0clEi". If it were anonymous, this would look like @0

diego-est commented 3 months ago

I am new to the LLVM project so if I did anything wrong please let me know immediately!

None of these functions are anonymous. The function here has a name, it's @"_ZZ4mainENK3$_0clEi". If it were anonymous, this would look like @0

I see, maybe I am not understanding the part where it says "produced from an anonymous function" how do I do this? I would like to work on this issue so if you have any resources I can read up on I would gladly do so.

arsenm commented 3 months ago

I see, maybe I am not understanding the part where it says "produced from an anonymous function" how do I do this? I would like to work on this issue so if you have any resources I can read up on I would gladly do so.

An IR function does not have to have a name. This has nothing to do with C++ functions, and you cannot write such a function directly in C or C++. See the example IR in the description, anonymous functions are printed as @ and a number

diego-est commented 3 months ago

Oh, thank you for clarifying. I just ran the example IR in the description:

define void @0 {
ret void
}

Copy pasting and running this IR did give me the same error as yours did. But for some reason there is a zero-width blank character in between the @ and 0 that isn't letting it be parsed correctly. Removing it should work.

arsenm commented 3 months ago

Oh, thank you for clarifying. I just ran the example IR in the description:

define void @0 {
ret void
}

Copy pasting and running this IR did give me the same error as yours did. But for some reason there is a zero-width blank character in between the @ and 0 that isn't letting it be parsed correctly. Removing it should work.

This is what happened to all the IR samples in issues imported from bugzilla

diego-est commented 3 months ago

Oh, thank you for clarifying. I just ran the example IR in the description:

define void @0 {
ret void
}

Copy pasting and running this IR did give me the same error as yours did. But for some reason there is a zero-width blank character in between the @ and 0 that isn't letting it be parsed correctly. Removing it should work.

This is what happened to all the IR samples in issues imported from bugzilla

Then that means this issue is resolved? Or is it not?

arsenm commented 3 months ago

Oh, thank you for clarifying. I just ran the example IR in the description:

define void @0 {
ret void
}

Copy pasting and running this IR did give me the same error as yours did. But for some reason there is a zero-width blank character in between the @ and 0 that isn't letting it be parsed correctly. Removing it should work.

This is what happened to all the IR samples in issues imported from bugzilla

Then that means this issue is resolved? Or is it not?

It is not resolved. You just had to fix the zero width thing in the issue description

diego-est commented 3 months ago

I see, thank you for being patient with me. When you say that "the example IR produces a function with an empty name" do you mean that the assembly produced by llc -stop-after= example.ll produces a function that doesn't have a name? The assembly produced by that command does have a name.

As for the second part of the description: "The parser can't read this in complaining: function '' isn't defined in the provided LLVM IR", how can I corroborate this?

arsenm commented 3 months ago

As for the second part of the description: "The parser can't read this in complaining: function '' isn't defined in the provided LLVM IR", how can I corroborate this?

I edited the example to be a valid lit test. You can copy that into test/CodeGen/ and run lit on it, and you will see the error