This is an archive of the discontinued LLVM Phabricator instance.

[Coroutines] Define __coro_frame_ty in function scope
ClosedPublic

Authored by hoy on Jun 25 2021, 11:40 AM.

Details

Summary

Types should be defined in function scope instead of a local lexical scope. Field types should be defined inside in its parent type scope.

We were seeing a type defined in a local scope causing trouble to the dwarf emitter where a context is required to be a funciton scope, a namespace or a global scope.

Diff Detail

Event Timeline

hoy created this revision.Jun 25 2021, 11:40 AM
hoy requested review of this revision.Jun 25 2021, 11:40 AM
Herald added a project: Restricted Project. · View Herald TranscriptJun 25 2021, 11:40 AM
aprantl accepted this revision.Jun 25 2021, 12:15 PM
This revision is now accepted and ready to land.Jun 25 2021, 12:15 PM
This revision was automatically updated to reflect the committed changes.

We were seeing a type defined in a local scope causing trouble to the dwarf emitter where a context is required to be a funciton scope, a namespace or a global scope.

Could you describe this in more detail? It's possible there's a bug somewhere there that should be fixed instead of avoiding that situation?

hoy added a comment.Jun 28 2021, 1:43 PM

We were seeing a type defined in a local scope causing trouble to the dwarf emitter where a context is required to be a funciton scope, a namespace or a global scope.

Could you describe this in more detail? It's possible there's a bug somewhere there that should be fixed instead of avoiding that situation?

We have encountered an assert failure at the following line, i.e, the getOrCreateContextDIE call.
https://github.com/llvm/llvm-project/blob/main/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp#L619

Looking into that function (https://github.com/llvm/llvm-project/blob/main/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp#L538) , I'm not seeing a local scope is supposed to have a DIE created for it. I guess that's by design and dwarf spec.

We were seeing a type defined in a local scope causing trouble to the dwarf emitter where a context is required to be a funciton scope, a namespace or a global scope.

Could you describe this in more detail? It's possible there's a bug somewhere there that should be fixed instead of avoiding that situation?

We have encountered an assert failure at the following line, i.e, the getOrCreateContextDIE call.
https://github.com/llvm/llvm-project/blob/main/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp#L619

Looking into that function (https://github.com/llvm/llvm-project/blob/main/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp#L538) , I'm not seeing a local scope is supposed to have a DIE created for it. I guess that's by design and dwarf spec.

If by local scopes you mean DILexicalBlock/DW_TAG_lexical_block, those do get DIEs:

$ cat > scope.cpp
int main() {
  int i = 3;
  {
    int j = 7;
    {
      int k = 42;
    }
  }
}
blaikie@blaikie-linux2:~/dev/scratch$ clang++-tot scope.cpp -g -c && llvm-dwarfdump-tot scope.o
scope.o:        file format elf64-x86-64

.debug_info contents:
0x00000000: Compile Unit: length = 0x0000008e, format = DWARF32, version = 0x0004, abbr_offset = 0x0000, addr_size = 0x08 (next unit at 0x00000092)

0x0000000b: DW_TAG_compile_unit
              DW_AT_producer    ("clang version 13.0.0 (git@github.com:llvm/llvm-project.git 9aa951e80e72decd95c7d972e1e0dde24260d336)")
              DW_AT_language    (DW_LANG_C_plus_plus_14)
              DW_AT_name        ("scope.cpp")
              DW_AT_stmt_list   (0x00000000)
              DW_AT_comp_dir    ("/usr/local/google/home/blaikie/dev/scratch")
              DW_AT_low_pc      (0x0000000000000000)
              DW_AT_high_pc     (0x000000000000001d)

0x0000002a:   DW_TAG_subprogram
                DW_AT_low_pc    (0x0000000000000000)
                DW_AT_high_pc   (0x000000000000001d)
                DW_AT_frame_base        (DW_OP_reg6 RBP)
                DW_AT_name      ("main")
                DW_AT_decl_file ("/usr/local/google/home/blaikie/dev/scratch/scope.cpp")
                DW_AT_decl_line (1)
                DW_AT_type      (0x0000008a "int")
                DW_AT_external  (true)

0x00000043:     DW_TAG_variable
                  DW_AT_location        (DW_OP_fbreg -4)
                  DW_AT_name    ("i")
                  DW_AT_decl_file       ("/usr/local/google/home/blaikie/dev/scratch/scope.cpp")
                  DW_AT_decl_line       (2)
                  DW_AT_type    (0x0000008a "int")

0x00000051:     DW_TAG_lexical_block
                  DW_AT_low_pc  (0x000000000000000b)
                  DW_AT_high_pc (0x0000000000000019)

0x0000005e:       DW_TAG_variable
                    DW_AT_location      (DW_OP_fbreg -8)
                    DW_AT_name  ("j")
                    DW_AT_decl_file     ("/usr/local/google/home/blaikie/dev/scratch/scope.cpp")
                    DW_AT_decl_line     (4)
                    DW_AT_type  (0x0000008a "int")

0x0000006c:       DW_TAG_lexical_block
                    DW_AT_low_pc        (0x0000000000000012)
                    DW_AT_high_pc       (0x0000000000000019)

0x00000079:         DW_TAG_variable
                      DW_AT_location    (DW_OP_fbreg -12)
                      DW_AT_name        ("k")
                      DW_AT_decl_file   ("/usr/local/google/home/blaikie/dev/scratch/scope.cpp")
                      DW_AT_decl_line   (6)
                      DW_AT_type        (0x0000008a "int")

0x00000087:         NULL

0x00000088:       NULL

0x00000089:     NULL

0x0000008a:   DW_TAG_base_type
                DW_AT_name      ("int")
                DW_AT_encoding  (DW_ATE_signed)
                DW_AT_byte_size (0x04)

0x00000091:   NULL

But if I recall correctly the path to create them is a bit different, because they're created more dynamically, based on the instructions and DebugLocs on those instructions.

But, yes, for local types and local static variables I don't think we currently track their lexical scope info (eg: if you put a named struct in one of the {} in the above example it still appears at the top level of the function and in the LLVM IR the DICompositeType's scope member points to the DISubprogram) - so, yeah, this is a long-standing limitation/bug/etc. Glad to understand this is another case of that. Thanks for the details!