Andrew Kelley via llvm-dev
2017-Oct-01 01:49 UTC
[llvm-dev] load with alignment of 1 crashes from being unaligned
Below is attached a full IR module that can reproduce this issue, but the part to notice is this: %Foo96Bits = type <{ i24, i24, i24, i24 }> define internal fastcc i16 @main.0.1() unnamed_addr #2 !dbg !113 { Entry: %value = alloca %Foo96Bits, align 1 %b = alloca i24, align 4 %0 = bitcast %Foo96Bits* %value to i8*, !dbg !129 call void @llvm.memcpy.p0i8.p0i8.i64(i8* %0, i8* bitcast (%Foo96Bits* @4 to i8*), i64 16, i32 1, i1 false), !dbg !129 call void @llvm.dbg.declare(metadata %Foo96Bits* %value, metadata !118, metadata !75), !dbg !129 %1 = getelementptr inbounds %Foo96Bits, %Foo96Bits* %value, i32 0, i32 0, !dbg !130 %2 = load i24, i24* %1, align 1, !dbg !130 store i24 %2, i24* %b, align 4, !dbg !131 call void @llvm.dbg.declare(metadata i24* %b, metadata !127, metadata !75), !dbg !131 ret i16 0, !dbg !132 } Notice that the Foo96Bits struct is allocated with alignment value of 1. Later on there is a load which also has this alignment value of 1. LLVM docs for alignment say: "An alignment of 1 is always safe." ( http://llvm.org/docs/LangRef.html#id189) This program when run crashes with a segfault. However if I change the %value = alloca %Foo96Bits, align 1 to %value = alloca %Foo96Bits, align 32 and the corresponding load %2 = load i24, i24* %1, align 32 Then the program runs fine. I was unable to reproduce the issue with this IR code and clang, because clang doesn't support cross compiling as seamlessly as my frontend: $ clang -o test.exe test.ll -target x86_64-unknown-windows-msvc -fuse-ld=lld -Wl,-entry:_start clang-5.0: warning: unable to find a Visual Studio installation; try running Clang from a developer command prompt [-Wmsvc-not-found] /nix/store/jxm0qg5cazlv8h7f7kp6cgk7ka7ag5kr-lld-5.0.0rc3/bin/lld-link: error: could not open libcmt.lib: No such file or directory clang-5.0: error: linker command failed with exit code 1 (use -v to see invocation) But if you manage to get it linked I am sure this IR would trigger the issue. It even causes the segfault in wine64 in addition to native windows. Can someone confirm this is a bug in llvm? Or is the documentation incorrect? test.ll: ; ModuleID = 'test' source_filename = "test" target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-windows-msvc" %"[]u8" = type { i8*, i64 } %Foo96Bits = type <{ i24, i24, i24, i24 }> @link_libc = internal unnamed_addr constant i1 false, align 1 @want_start_symbol = internal unnamed_addr constant i1 true, align 1 @os = internal unnamed_addr constant i6 15, align 1 @is_windows = internal unnamed_addr constant i1 true, align 1 @user_main_fn = internal unnamed_addr global i16 ()* null, align 8 @0 = internal unnamed_addr constant i8* getelementptr inbounds ([24 x i8], [24 x i8]* @1, i64 0, i64 0), align 8 @1 = internal unnamed_addr constant [24 x i8] c"reached unreachable code", align 1 @2 = internal unnamed_addr constant %"[]u8" { i8* getelementptr inbounds ([24 x i8], [24 x i8]* @1, i64 0, i64 0), i64 24 }, align 8 @3 = internal unnamed_addr constant i16 ()** @user_main_fn, align 8 @4 = internal unnamed_addr constant %Foo96Bits zeroinitializer, align 1 ; Function Attrs: nobuiltin noreturn nounwind define internal fastcc void @panic(%"[]u8"* byval nonnull readonly) unnamed_addr #0 !dbg !60 { Entry: call void @llvm.dbg.declare(metadata %"[]u8"* %0, metadata !74, metadata !75), !dbg !76 br label %WhileCond, !dbg !77 WhileCond: ; preds = %WhileCond, %Entry br label %WhileCond, !dbg !77 } ; Function Attrs: naked nobuiltin noreturn nounwind define void @_start() #1 !dbg !80 { Entry: call fastcc void @windowsCallMainAndExit(), !dbg !84 unreachable, !dbg !84 } ; Function Attrs: nobuiltin nounwind define internal i32 @main.0(i32, i8** nonnull, i8** nonnull) unnamed_addr #2 !dbg !87 { Entry: %c_argc = alloca i32, align 4 %c_argv = alloca i8**, align 8 %c_envp = alloca i8**, align 8 store i32 %0, i32* %c_argc, align 4 call void @llvm.dbg.declare(metadata i32* %c_argc, metadata !94, metadata !75), !dbg !99 store i8** %1, i8*** %c_argv, align 8 call void @llvm.dbg.declare(metadata i8*** %c_argv, metadata !95, metadata !75), !dbg !100 store i8** %2, i8*** %c_envp, align 8 call void @llvm.dbg.declare(metadata i8*** %c_envp, metadata !97, metadata !75), !dbg !101 call fastcc void @panic(%"[]u8"* @2), !dbg !102 unreachable, !dbg !102 } ; Function Attrs: nobuiltin noreturn nounwind define internal fastcc void @windowsCallMainAndExit() unnamed_addr #0 !dbg !106 { Entry: %0 = alloca i16, align 2 store i16 ()* @main.0.1, i16 ()** @user_main_fn, align 8, !dbg !107 %1 = call fastcc i16 @main.0.1(), !dbg !109 store i16 %1, i16* %0, align 2, !dbg !109 %2 = load i16, i16* %0, align 2, !dbg !110 %3 = icmp ne i16 %2, 0, !dbg !110 br i1 %3, label %UnwrapErrError, label %UnwrapErrOk, !dbg !110 UnwrapErrError: ; preds = %Entry call void @ExitProcess(i32 1), !dbg !111 unreachable, !dbg !111 UnwrapErrOk: ; preds = %Entry %4 = load i16, i16* %0, align 2, !dbg !110 br label %UnwrapErrEnd, !dbg !110 UnwrapErrEnd: ; preds = %UnwrapErrOk call void @ExitProcess(i32 0), !dbg !112 unreachable, !dbg !112 } ; Function Attrs: nobuiltin nounwind define internal fastcc i16 @main.0.1() unnamed_addr #2 !dbg !113 { Entry: %value = alloca %Foo96Bits, align 1 %b = alloca i24, align 4 %0 = bitcast %Foo96Bits* %value to i8*, !dbg !129 call void @llvm.memcpy.p0i8.p0i8.i64(i8* %0, i8* bitcast (%Foo96Bits* @4 to i8*), i64 16, i32 1, i1 false), !dbg !129 call void @llvm.dbg.declare(metadata %Foo96Bits* %value, metadata !118, metadata !75), !dbg !129 %1 = getelementptr inbounds %Foo96Bits, %Foo96Bits* %value, i32 0, i32 0, !dbg !130 %2 = load i24, i24* %1, align 1, !dbg !130 store i24 %2, i24* %b, align 4, !dbg !131 call void @llvm.dbg.declare(metadata i24* %b, metadata !127, metadata !75), !dbg !131 ret i16 0, !dbg !132 } ; Function Attrs: nobuiltin noreturn nounwind declare void @ExitProcess(i32) #0 ; Function Attrs: nounwind readnone speculatable declare void @llvm.dbg.declare(metadata, metadata, metadata) #3 ; Function Attrs: argmemonly nounwind declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i32, i1) #4 attributes #0 = { nobuiltin noreturn nounwind "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" } attributes #1 = { naked nobuiltin noreturn nounwind "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" } attributes #2 = { nobuiltin nounwind "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" } attributes #3 = { nounwind readnone speculatable } attributes #4 = { argmemonly nounwind } !llvm.module.flags = !{!0} !llvm.dbg.cu = !{!1} !0 = !{i32 2, !"Debug Info Version", i32 3} !1 = distinct !DICompileUnit(language: DW_LANG_C99, file: !2, producer: "zig 0.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !3, globals: !47) !2 = !DIFile(filename: "test", directory: ".") !3 = !{!4, !40} !4 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "Os", scope: !5, file: !5, line: 1, baseType: !6, size: 8, align: 8, elements: !7) !5 = !DIFile(filename: "builtin.zig", directory: "/home/andy/dev/zig/build/zig-cache") !6 = !DIBasicType(name: "u6", size: 8, encoding: DW_ATE_unsigned) !7 = !{!8, !9, !10, !11, !12, !13, !14, !15, !16, !17, !18, !19, !20, !21, !22, !23, !24, !25, !26, !27, !28, !29, !30, !31, !32, !33, !34, !35, !36, !37, !38, !39} !8 = !DIEnumerator(name: "freestanding", value: 0) !9 = !DIEnumerator(name: "ananas", value: 1) !10 = !DIEnumerator(name: "cloudabi", value: 2) !11 = !DIEnumerator(name: "darwin", value: 3) !12 = !DIEnumerator(name: "dragonfly", value: 4) !13 = !DIEnumerator(name: "freebsd", value: 5) !14 = !DIEnumerator(name: "fuchsia", value: 6) !15 = !DIEnumerator(name: "ios", value: 7) !16 = !DIEnumerator(name: "kfreebsd", value: 8) !17 = !DIEnumerator(name: "linux", value: 9) !18 = !DIEnumerator(name: "lv2", value: 10) !19 = !DIEnumerator(name: "macosx", value: 11) !20 = !DIEnumerator(name: "netbsd", value: 12) !21 = !DIEnumerator(name: "openbsd", value: 13) !22 = !DIEnumerator(name: "solaris", value: 14) !23 = !DIEnumerator(name: "windows", value: 15) !24 = !DIEnumerator(name: "haiku", value: 16) !25 = !DIEnumerator(name: "minix", value: 17) !26 = !DIEnumerator(name: "rtems", value: 18) !27 = !DIEnumerator(name: "nacl", value: 19) !28 = !DIEnumerator(name: "cnk", value: 20) !29 = !DIEnumerator(name: "bitrig", value: 21) !30 = !DIEnumerator(name: "aix", value: 22) !31 = !DIEnumerator(name: "cuda", value: 23) !32 = !DIEnumerator(name: "nvcl", value: 24) !33 = !DIEnumerator(name: "amdhsa", value: 25) !34 = !DIEnumerator(name: "ps4", value: 26) !35 = !DIEnumerator(name: "elfiamcu", value: 27) !36 = !DIEnumerator(name: "tvos", value: 28) !37 = !DIEnumerator(name: "watchos", value: 29) !38 = !DIEnumerator(name: "mesa3d", value: 30) !39 = !DIEnumerator(name: "contiki", value: 31) !40 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "GlobalLinkage", scope: !5, file: !5, line: 138, baseType: !41, size: 8, align: 8, elements: !42) !41 = !DIBasicType(name: "u3", size: 8, encoding: DW_ATE_unsigned) !42 = !{!43, !44, !45, !46} !43 = !DIEnumerator(name: "Internal", value: 0) !44 = !DIEnumerator(name: "Strong", value: 1) !45 = !DIEnumerator(name: "Weak", value: 2) !46 = !DIEnumerator(name: "LinkOnce", value: 3) !47 = !{!48, !51, !54, !56, !58} !48 = !DIGlobalVariableExpression(var: !49) !49 = distinct !DIGlobalVariable(name: "link_libc", linkageName: "link_libc", scope: !5, file: !5, line: 200, type: !50, isLocal: true, isDefinition: true) !50 = !DIBasicType(name: "bool", size: 8, encoding: DW_ATE_boolean) !51 = !DIGlobalVariableExpression(var: !52) !52 = distinct !DIGlobalVariable(name: "want_main_symbol", linkageName: "want_main_symbol", scope: !53, file: !53, line: 8, type: !50, isLocal: true, isDefinition: true) !53 = !DIFile(filename: "bootstrap.zig", directory: "/home/andy/dev/zig/build/lib/zig/std/special") !54 = !DIGlobalVariableExpression(var: !55) !55 = distinct !DIGlobalVariable(name: "want_start_symbol", linkageName: "want_start_symbol", scope: !53, file: !53, line: 9, type: !50, isLocal: true, isDefinition: true) !56 = !DIGlobalVariableExpression(var: !57) !57 = distinct !DIGlobalVariable(name: "os", linkageName: "os", scope: !5, file: !5, line: 195, type: !4, isLocal: true, isDefinition: true) !58 = !DIGlobalVariableExpression(var: !59) !59 = distinct !DIGlobalVariable(name: "is_windows", linkageName: "is_windows", scope: !53, file: !53, line: 13, type: !50, isLocal: true, isDefinition: true) !60 = distinct !DISubprogram(name: "panic", scope: !61, file: !61, line: 47, type: !62, isLocal: true, isDefinition: true, scopeLine: 47, isOptimized: false, unit: !1, variables: !73) !61 = !DIFile(filename: "test.zig", directory: "/home/andy/dev/zig/build") !62 = !DISubroutineType(types: !63) !63 = !{!64, !65} !64 = !DIBasicType(name: "void", encoding: DW_ATE_unsigned) !65 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "&[]const u8", baseType: !66, size: 64, align: 64) !66 = !DICompositeType(tag: DW_TAG_structure_type, name: "[]u8", size: 128, align: 64, elements: !67) !67 = !{!68, !71} !68 = !DIDerivedType(tag: DW_TAG_member, name: "ptr", scope: !66, baseType: !69, size: 64, align: 64) !69 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "&u8", baseType: !70, size: 64, align: 64) !70 = !DIBasicType(name: "u8", size: 8, encoding: DW_ATE_unsigned_char) !71 = !DIDerivedType(tag: DW_TAG_member, name: "len", scope: !66, baseType: !72, size: 64, align: 64, offset: 64) !72 = !DIBasicType(name: "usize", size: 64, encoding: DW_ATE_unsigned) !73 = !{!74} !74 = !DILocalVariable(name: "msg", arg: 1, scope: !60, file: !61, line: 47, type: !66) !75 = !DIExpression() !76 = !DILocation(line: 47, column: 14, scope: !60) !77 = !DILocation(line: 47, column: 45, scope: !78) !78 = distinct !DILexicalBlock(scope: !79, file: !61, line: 47, column: 43) !79 = distinct !DILexicalBlock(scope: !60, file: !61, line: 47, column: 14) !80 = distinct !DISubprogram(name: "_start", scope: !53, file: !53, line: 15, type: !81, isLocal: false, isDefinition: true, scopeLine: 15, isOptimized: false, unit: !1, variables: !83) !81 = !DISubroutineType(types: !82) !82 = !{!64} !83 = !{} !84 = !DILocation(line: 22, column: 31, scope: !85) !85 = distinct !DILexicalBlock(scope: !86, file: !53, line: 21, column: 21) !86 = distinct !DILexicalBlock(scope: !80, file: !53, line: 15, column: 40) !87 = distinct !DISubprogram(name: "main", scope: !53, file: !53, line: 63, type: !88, isLocal: true, isDefinition: true, scopeLine: 63, isOptimized: false, unit: !1, variables: !93) !88 = !DISubroutineType(types: !89) !89 = !{!90, !90, !91, !92} !90 = !DIBasicType(name: "i32", size: 32, encoding: DW_ATE_signed) !91 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "&&u8", baseType: !69, size: 64, align: 64) !92 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "&?&u8", baseType: !69, size: 64, align: 64) !93 = !{!94, !95, !97} !94 = !DILocalVariable(name: "c_argc", arg: 1, scope: !87, file: !53, line: 63, type: !90) !95 = !DILocalVariable(name: "c_argv", arg: 2, scope: !96, file: !53, line: 63, type: !91) !96 = distinct !DILexicalBlock(scope: !87, file: !53, line: 63, column: 16) !97 = !DILocalVariable(name: "c_envp", arg: 3, scope: !98, file: !53, line: 63, type: !92) !98 = distinct !DILexicalBlock(scope: !96, file: !53, line: 63, column: 29) !99 = !DILocation(line: 63, column: 16, scope: !87) !100 = !DILocation(line: 63, column: 29, scope: !96) !101 = !DILocation(line: 63, column: 43, scope: !98) !102 = !DILocation(line: 66, column: 9, scope: !103) !103 = distinct !DILexicalBlock(scope: !104, file: !53, line: 64, column: 28) !104 = distinct !DILexicalBlock(scope: !105, file: !53, line: 63, column: 65) !105 = distinct !DILexicalBlock(scope: !98, file: !53, line: 63, column: 43) !106 = distinct !DISubprogram(name: "windowsCallMainAndExit", scope: !53, file: !53, line: 37, type: !81, isLocal: true, isDefinition: true, scopeLine: 37, isOptimized: false, unit: !1, variables: !83) !107 = !DILocation(line: 38, column: 28, scope: !108) !108 = distinct !DILexicalBlock(scope: !106, file: !53, line: 37, column: 41) !109 = !DILocation(line: 39, column: 14, scope: !108) !110 = !DILocation(line: 39, column: 17, scope: !108) !111 = !DILocation(line: 39, column: 46, scope: !108) !112 = !DILocation(line: 40, column: 31, scope: !108) !113 = distinct !DISubprogram(name: "main", scope: !61, file: !61, line: 14, type: !114, isLocal: true, isDefinition: true, scopeLine: 14, isOptimized: false, unit: !1, variables: !117) !114 = !DISubroutineType(types: !115) !115 = !{!116} !116 = !DIBasicType(name: "u16", size: 16, encoding: DW_ATE_unsigned) !117 = !{!118, !127} !118 = !DILocalVariable(name: "value", scope: !119, file: !61, line: 16, type: !120) !119 = distinct !DILexicalBlock(scope: !113, file: !61, line: 14, column: 24) !120 = !DICompositeType(tag: DW_TAG_structure_type, name: "Foo96Bits", scope: !61, file: !61, line: 7, size: 128, align: 128, elements: !121) !121 = !{!122, !124, !125, !126} !122 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !120, file: !61, line: 8, baseType: !123, size: 24, align: 1) !123 = !DIBasicType(name: "u24", size: 24, encoding: DW_ATE_unsigned) !124 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !120, file: !61, line: 9, baseType: !123, size: 24, align: 1, offset: 32) !125 = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: !120, file: !61, line: 10, baseType: !123, size: 24, align: 1, offset: 64) !126 = !DIDerivedType(tag: DW_TAG_member, name: "d", scope: !120, file: !61, line: 11, baseType: !123, size: 24, align: 1, offset: 96) !127 = !DILocalVariable(name: "b", scope: !128, file: !61, line: 22, type: !123) !128 = distinct !DILexicalBlock(scope: !119, file: !61, line: 16, column: 5) !129 = !DILocation(line: 16, column: 5, scope: !119) !130 = !DILocation(line: 22, column: 20, scope: !128) !131 = !DILocation(line: 22, column: 5, scope: !128) !132 = !DILocation(line: 14, column: 24, scope: !113) -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20170930/ac8fca89/attachment.html>
Andrew Kelley via llvm-dev
2017-Oct-01 02:55 UTC
[llvm-dev] load with alignment of 1 crashes from being unaligned
Forgot to mention. This same IR works fine on Linux and MacOS on the same CPU architecture. On Sat, Sep 30, 2017 at 9:49 PM, Andrew Kelley <superjoe30 at gmail.com> wrote:> Below is attached a full IR module that can reproduce this issue, but the > part to notice is this: > > %Foo96Bits = type <{ i24, i24, i24, i24 }> > > define internal fastcc i16 @main.0.1() unnamed_addr #2 !dbg !113 { > Entry: > %value = alloca %Foo96Bits, align 1 > %b = alloca i24, align 4 > %0 = bitcast %Foo96Bits* %value to i8*, !dbg !129 > call void @llvm.memcpy.p0i8.p0i8.i64(i8* %0, i8* bitcast (%Foo96Bits* @4 > to i8*), i64 16, i32 1, i1 false), !dbg !129 > call void @llvm.dbg.declare(metadata %Foo96Bits* %value, metadata !118, > metadata !75), !dbg !129 > %1 = getelementptr inbounds %Foo96Bits, %Foo96Bits* %value, i32 0, i32 > 0, !dbg !130 > %2 = load i24, i24* %1, align 1, !dbg !130 > store i24 %2, i24* %b, align 4, !dbg !131 > call void @llvm.dbg.declare(metadata i24* %b, metadata !127, metadata > !75), !dbg !131 > ret i16 0, !dbg !132 > } > > Notice that the Foo96Bits struct is allocated with alignment value of 1. > Later on there is a load which also has this alignment value of 1. > > LLVM docs for alignment say: "An alignment of 1 is always safe." ( > http://llvm.org/docs/LangRef.html#id189) > > This program when run crashes with a segfault. > > However if I change the > > %value = alloca %Foo96Bits, align 1 > > to > > %value = alloca %Foo96Bits, align 32 > > and the corresponding load > > %2 = load i24, i24* %1, align 32 > > Then the program runs fine. > > > I was unable to reproduce the issue with this IR code and clang, because > clang doesn't support cross compiling as seamlessly as my frontend: > $ clang -o test.exe test.ll -target x86_64-unknown-windows-msvc > -fuse-ld=lld -Wl,-entry:_start > clang-5.0: warning: unable to find a Visual Studio installation; try > running Clang from a developer command prompt [-Wmsvc-not-found] > /nix/store/jxm0qg5cazlv8h7f7kp6cgk7ka7ag5kr-lld-5.0.0rc3/bin/lld-link: > error: could not open libcmt.lib: No such file or directory > clang-5.0: error: linker command failed with exit code 1 (use -v to see > invocation) > > But if you manage to get it linked I am sure this IR would trigger the > issue. It even causes the segfault in wine64 in addition to native windows. > > > > Can someone confirm this is a bug in llvm? Or is the documentation > incorrect? > > > test.ll: > > ; ModuleID = 'test' > source_filename = "test" > target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" > target triple = "x86_64-unknown-windows-msvc" > > %"[]u8" = type { i8*, i64 } > %Foo96Bits = type <{ i24, i24, i24, i24 }> > > @link_libc = internal unnamed_addr constant i1 false, align 1 > @want_start_symbol = internal unnamed_addr constant i1 true, align 1 > @os = internal unnamed_addr constant i6 15, align 1 > @is_windows = internal unnamed_addr constant i1 true, align 1 > @user_main_fn = internal unnamed_addr global i16 ()* null, align 8 > @0 = internal unnamed_addr constant i8* getelementptr inbounds ([24 x i8], > [24 x i8]* @1, i64 0, i64 0), align 8 > @1 = internal unnamed_addr constant [24 x i8] c"reached unreachable code", > align 1 > @2 = internal unnamed_addr constant %"[]u8" { i8* getelementptr inbounds > ([24 x i8], [24 x i8]* @1, i64 0, i64 0), i64 24 }, align 8 > @3 = internal unnamed_addr constant i16 ()** @user_main_fn, align 8 > @4 = internal unnamed_addr constant %Foo96Bits zeroinitializer, align 1 > > ; Function Attrs: nobuiltin noreturn nounwind > define internal fastcc void @panic(%"[]u8"* byval nonnull readonly) > unnamed_addr #0 !dbg !60 { > Entry: > call void @llvm.dbg.declare(metadata %"[]u8"* %0, metadata !74, metadata > !75), !dbg !76 > br label %WhileCond, !dbg !77 > > WhileCond: ; preds = %WhileCond, > %Entry > br label %WhileCond, !dbg !77 > } > > ; Function Attrs: naked nobuiltin noreturn nounwind > define void @_start() #1 !dbg !80 { > Entry: > call fastcc void @windowsCallMainAndExit(), !dbg !84 > unreachable, !dbg !84 > } > > ; Function Attrs: nobuiltin nounwind > define internal i32 @main.0(i32, i8** nonnull, i8** nonnull) unnamed_addr > #2 !dbg !87 { > Entry: > %c_argc = alloca i32, align 4 > %c_argv = alloca i8**, align 8 > %c_envp = alloca i8**, align 8 > store i32 %0, i32* %c_argc, align 4 > call void @llvm.dbg.declare(metadata i32* %c_argc, metadata !94, > metadata !75), !dbg !99 > store i8** %1, i8*** %c_argv, align 8 > call void @llvm.dbg.declare(metadata i8*** %c_argv, metadata !95, > metadata !75), !dbg !100 > store i8** %2, i8*** %c_envp, align 8 > call void @llvm.dbg.declare(metadata i8*** %c_envp, metadata !97, > metadata !75), !dbg !101 > call fastcc void @panic(%"[]u8"* @2), !dbg !102 > unreachable, !dbg !102 > } > > ; Function Attrs: nobuiltin noreturn nounwind > define internal fastcc void @windowsCallMainAndExit() unnamed_addr #0 !dbg > !106 { > Entry: > %0 = alloca i16, align 2 > store i16 ()* @main.0.1, i16 ()** @user_main_fn, align 8, !dbg !107 > %1 = call fastcc i16 @main.0.1(), !dbg !109 > store i16 %1, i16* %0, align 2, !dbg !109 > %2 = load i16, i16* %0, align 2, !dbg !110 > %3 = icmp ne i16 %2, 0, !dbg !110 > br i1 %3, label %UnwrapErrError, label %UnwrapErrOk, !dbg !110 > > UnwrapErrError: ; preds = %Entry > call void @ExitProcess(i32 1), !dbg !111 > unreachable, !dbg !111 > > UnwrapErrOk: ; preds = %Entry > %4 = load i16, i16* %0, align 2, !dbg !110 > br label %UnwrapErrEnd, !dbg !110 > > UnwrapErrEnd: ; preds = %UnwrapErrOk > call void @ExitProcess(i32 0), !dbg !112 > unreachable, !dbg !112 > } > > ; Function Attrs: nobuiltin nounwind > define internal fastcc i16 @main.0.1() unnamed_addr #2 !dbg !113 { > Entry: > %value = alloca %Foo96Bits, align 1 > %b = alloca i24, align 4 > %0 = bitcast %Foo96Bits* %value to i8*, !dbg !129 > call void @llvm.memcpy.p0i8.p0i8.i64(i8* %0, i8* bitcast (%Foo96Bits* @4 > to i8*), i64 16, i32 1, i1 false), !dbg !129 > call void @llvm.dbg.declare(metadata %Foo96Bits* %value, metadata !118, > metadata !75), !dbg !129 > %1 = getelementptr inbounds %Foo96Bits, %Foo96Bits* %value, i32 0, i32 > 0, !dbg !130 > %2 = load i24, i24* %1, align 1, !dbg !130 > store i24 %2, i24* %b, align 4, !dbg !131 > call void @llvm.dbg.declare(metadata i24* %b, metadata !127, metadata > !75), !dbg !131 > ret i16 0, !dbg !132 > } > > ; Function Attrs: nobuiltin noreturn nounwind > declare void @ExitProcess(i32) #0 > > ; Function Attrs: nounwind readnone speculatable > declare void @llvm.dbg.declare(metadata, metadata, metadata) #3 > > ; Function Attrs: argmemonly nounwind > declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* > nocapture readonly, i64, i32, i1) #4 > > attributes #0 = { nobuiltin noreturn nounwind > "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" } > attributes #1 = { naked nobuiltin noreturn nounwind > "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" } > attributes #2 = { nobuiltin nounwind "no-frame-pointer-elim"="true" > "no-frame-pointer-elim-non-leaf" } > attributes #3 = { nounwind readnone speculatable } > attributes #4 = { argmemonly nounwind } > > !llvm.module.flags = !{!0} > !llvm.dbg.cu = !{!1} > > !0 = !{i32 2, !"Debug Info Version", i32 3} > !1 = distinct !DICompileUnit(language: DW_LANG_C99, file: !2, producer: > "zig 0.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: > FullDebug, enums: !3, globals: !47) > !2 = !DIFile(filename: "test", directory: ".") > !3 = !{!4, !40} > !4 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "Os", scope: !5, > file: !5, line: 1, baseType: !6, size: 8, align: 8, elements: !7) > !5 = !DIFile(filename: "builtin.zig", directory: > "/home/andy/dev/zig/build/zig-cache") > !6 = !DIBasicType(name: "u6", size: 8, encoding: DW_ATE_unsigned) > !7 = !{!8, !9, !10, !11, !12, !13, !14, !15, !16, !17, !18, !19, !20, !21, > !22, !23, !24, !25, !26, !27, !28, !29, !30, !31, !32, !33, !34, !35, !36, > !37, !38, !39} > !8 = !DIEnumerator(name: "freestanding", value: 0) > !9 = !DIEnumerator(name: "ananas", value: 1) > !10 = !DIEnumerator(name: "cloudabi", value: 2) > !11 = !DIEnumerator(name: "darwin", value: 3) > !12 = !DIEnumerator(name: "dragonfly", value: 4) > !13 = !DIEnumerator(name: "freebsd", value: 5) > !14 = !DIEnumerator(name: "fuchsia", value: 6) > !15 = !DIEnumerator(name: "ios", value: 7) > !16 = !DIEnumerator(name: "kfreebsd", value: 8) > !17 = !DIEnumerator(name: "linux", value: 9) > !18 = !DIEnumerator(name: "lv2", value: 10) > !19 = !DIEnumerator(name: "macosx", value: 11) > !20 = !DIEnumerator(name: "netbsd", value: 12) > !21 = !DIEnumerator(name: "openbsd", value: 13) > !22 = !DIEnumerator(name: "solaris", value: 14) > !23 = !DIEnumerator(name: "windows", value: 15) > !24 = !DIEnumerator(name: "haiku", value: 16) > !25 = !DIEnumerator(name: "minix", value: 17) > !26 = !DIEnumerator(name: "rtems", value: 18) > !27 = !DIEnumerator(name: "nacl", value: 19) > !28 = !DIEnumerator(name: "cnk", value: 20) > !29 = !DIEnumerator(name: "bitrig", value: 21) > !30 = !DIEnumerator(name: "aix", value: 22) > !31 = !DIEnumerator(name: "cuda", value: 23) > !32 = !DIEnumerator(name: "nvcl", value: 24) > !33 = !DIEnumerator(name: "amdhsa", value: 25) > !34 = !DIEnumerator(name: "ps4", value: 26) > !35 = !DIEnumerator(name: "elfiamcu", value: 27) > !36 = !DIEnumerator(name: "tvos", value: 28) > !37 = !DIEnumerator(name: "watchos", value: 29) > !38 = !DIEnumerator(name: "mesa3d", value: 30) > !39 = !DIEnumerator(name: "contiki", value: 31) > !40 = !DICompositeType(tag: DW_TAG_enumeration_type, name: > "GlobalLinkage", scope: !5, file: !5, line: 138, baseType: !41, size: 8, > align: 8, elements: !42) > !41 = !DIBasicType(name: "u3", size: 8, encoding: DW_ATE_unsigned) > !42 = !{!43, !44, !45, !46} > !43 = !DIEnumerator(name: "Internal", value: 0) > !44 = !DIEnumerator(name: "Strong", value: 1) > !45 = !DIEnumerator(name: "Weak", value: 2) > !46 = !DIEnumerator(name: "LinkOnce", value: 3) > !47 = !{!48, !51, !54, !56, !58} > !48 = !DIGlobalVariableExpression(var: !49) > !49 = distinct !DIGlobalVariable(name: "link_libc", linkageName: > "link_libc", scope: !5, file: !5, line: 200, type: !50, isLocal: true, > isDefinition: true) > !50 = !DIBasicType(name: "bool", size: 8, encoding: DW_ATE_boolean) > !51 = !DIGlobalVariableExpression(var: !52) > !52 = distinct !DIGlobalVariable(name: "want_main_symbol", linkageName: > "want_main_symbol", scope: !53, file: !53, line: 8, type: !50, isLocal: > true, isDefinition: true) > !53 = !DIFile(filename: "bootstrap.zig", directory: > "/home/andy/dev/zig/build/lib/zig/std/special") > !54 = !DIGlobalVariableExpression(var: !55) > !55 = distinct !DIGlobalVariable(name: "want_start_symbol", linkageName: > "want_start_symbol", scope: !53, file: !53, line: 9, type: !50, isLocal: > true, isDefinition: true) > !56 = !DIGlobalVariableExpression(var: !57) > !57 = distinct !DIGlobalVariable(name: "os", linkageName: "os", scope: !5, > file: !5, line: 195, type: !4, isLocal: true, isDefinition: true) > !58 = !DIGlobalVariableExpression(var: !59) > !59 = distinct !DIGlobalVariable(name: "is_windows", linkageName: > "is_windows", scope: !53, file: !53, line: 13, type: !50, isLocal: true, > isDefinition: true) > !60 = distinct !DISubprogram(name: "panic", scope: !61, file: !61, line: > 47, type: !62, isLocal: true, isDefinition: true, scopeLine: 47, > isOptimized: false, unit: !1, variables: !73) > !61 = !DIFile(filename: "test.zig", directory: "/home/andy/dev/zig/build") > !62 = !DISubroutineType(types: !63) > !63 = !{!64, !65} > !64 = !DIBasicType(name: "void", encoding: DW_ATE_unsigned) > !65 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "&[]const u8", > baseType: !66, size: 64, align: 64) > !66 = !DICompositeType(tag: DW_TAG_structure_type, name: "[]u8", size: > 128, align: 64, elements: !67) > !67 = !{!68, !71} > !68 = !DIDerivedType(tag: DW_TAG_member, name: "ptr", scope: !66, > baseType: !69, size: 64, align: 64) > !69 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "&u8", baseType: !70, > size: 64, align: 64) > !70 = !DIBasicType(name: "u8", size: 8, encoding: DW_ATE_unsigned_char) > !71 = !DIDerivedType(tag: DW_TAG_member, name: "len", scope: !66, > baseType: !72, size: 64, align: 64, offset: 64) > !72 = !DIBasicType(name: "usize", size: 64, encoding: DW_ATE_unsigned) > !73 = !{!74} > !74 = !DILocalVariable(name: "msg", arg: 1, scope: !60, file: !61, line: > 47, type: !66) > !75 = !DIExpression() > !76 = !DILocation(line: 47, column: 14, scope: !60) > !77 = !DILocation(line: 47, column: 45, scope: !78) > !78 = distinct !DILexicalBlock(scope: !79, file: !61, line: 47, column: 43) > !79 = distinct !DILexicalBlock(scope: !60, file: !61, line: 47, column: 14) > !80 = distinct !DISubprogram(name: "_start", scope: !53, file: !53, line: > 15, type: !81, isLocal: false, isDefinition: true, scopeLine: 15, > isOptimized: false, unit: !1, variables: !83) > !81 = !DISubroutineType(types: !82) > !82 = !{!64} > !83 = !{} > !84 = !DILocation(line: 22, column: 31, scope: !85) > !85 = distinct !DILexicalBlock(scope: !86, file: !53, line: 21, column: 21) > !86 = distinct !DILexicalBlock(scope: !80, file: !53, line: 15, column: 40) > !87 = distinct !DISubprogram(name: "main", scope: !53, file: !53, line: > 63, type: !88, isLocal: true, isDefinition: true, scopeLine: 63, > isOptimized: false, unit: !1, variables: !93) > !88 = !DISubroutineType(types: !89) > !89 = !{!90, !90, !91, !92} > !90 = !DIBasicType(name: "i32", size: 32, encoding: DW_ATE_signed) > !91 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "&&u8", baseType: > !69, size: 64, align: 64) > !92 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "&?&u8", baseType: > !69, size: 64, align: 64) > !93 = !{!94, !95, !97} > !94 = !DILocalVariable(name: "c_argc", arg: 1, scope: !87, file: !53, > line: 63, type: !90) > !95 = !DILocalVariable(name: "c_argv", arg: 2, scope: !96, file: !53, > line: 63, type: !91) > !96 = distinct !DILexicalBlock(scope: !87, file: !53, line: 63, column: 16) > !97 = !DILocalVariable(name: "c_envp", arg: 3, scope: !98, file: !53, > line: 63, type: !92) > !98 = distinct !DILexicalBlock(scope: !96, file: !53, line: 63, column: 29) > !99 = !DILocation(line: 63, column: 16, scope: !87) > !100 = !DILocation(line: 63, column: 29, scope: !96) > !101 = !DILocation(line: 63, column: 43, scope: !98) > !102 = !DILocation(line: 66, column: 9, scope: !103) > !103 = distinct !DILexicalBlock(scope: !104, file: !53, line: 64, column: > 28) > !104 = distinct !DILexicalBlock(scope: !105, file: !53, line: 63, column: > 65) > !105 = distinct !DILexicalBlock(scope: !98, file: !53, line: 63, column: > 43) > !106 = distinct !DISubprogram(name: "windowsCallMainAndExit", scope: !53, > file: !53, line: 37, type: !81, isLocal: true, isDefinition: true, > scopeLine: 37, isOptimized: false, unit: !1, variables: !83) > !107 = !DILocation(line: 38, column: 28, scope: !108) > !108 = distinct !DILexicalBlock(scope: !106, file: !53, line: 37, column: > 41) > !109 = !DILocation(line: 39, column: 14, scope: !108) > !110 = !DILocation(line: 39, column: 17, scope: !108) > !111 = !DILocation(line: 39, column: 46, scope: !108) > !112 = !DILocation(line: 40, column: 31, scope: !108) > !113 = distinct !DISubprogram(name: "main", scope: !61, file: !61, line: > 14, type: !114, isLocal: true, isDefinition: true, scopeLine: 14, > isOptimized: false, unit: !1, variables: !117) > !114 = !DISubroutineType(types: !115) > !115 = !{!116} > !116 = !DIBasicType(name: "u16", size: 16, encoding: DW_ATE_unsigned) > !117 = !{!118, !127} > !118 = !DILocalVariable(name: "value", scope: !119, file: !61, line: 16, > type: !120) > !119 = distinct !DILexicalBlock(scope: !113, file: !61, line: 14, column: > 24) > !120 = !DICompositeType(tag: DW_TAG_structure_type, name: "Foo96Bits", > scope: !61, file: !61, line: 7, size: 128, align: 128, elements: !121) > !121 = !{!122, !124, !125, !126} > !122 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !120, file: > !61, line: 8, baseType: !123, size: 24, align: 1) > !123 = !DIBasicType(name: "u24", size: 24, encoding: DW_ATE_unsigned) > !124 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !120, file: > !61, line: 9, baseType: !123, size: 24, align: 1, offset: 32) > !125 = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: !120, file: > !61, line: 10, baseType: !123, size: 24, align: 1, offset: 64) > !126 = !DIDerivedType(tag: DW_TAG_member, name: "d", scope: !120, file: > !61, line: 11, baseType: !123, size: 24, align: 1, offset: 96) > !127 = !DILocalVariable(name: "b", scope: !128, file: !61, line: 22, type: > !123) > !128 = distinct !DILexicalBlock(scope: !119, file: !61, line: 16, column: > 5) > !129 = !DILocation(line: 16, column: 5, scope: !119) > !130 = !DILocation(line: 22, column: 20, scope: !128) > !131 = !DILocation(line: 22, column: 5, scope: !128) > !132 = !DILocation(line: 14, column: 24, scope: !113) > > >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20170930/43392d73/attachment-0001.html>
Friedman, Eli via llvm-dev
2017-Oct-02 19:17 UTC
[llvm-dev] load with alignment of 1 crashes from being unaligned
On 9/30/2017 6:49 PM, Andrew Kelley via llvm-dev wrote:> Below is attached a full IR module that can reproduce this issue, but > the part to notice is this: > > %Foo96Bits = type <{ i24, i24, i24, i24 }> > > define internal fastcc i16 @main.0.1() unnamed_addr #2 !dbg !113 { > Entry: > %value = alloca %Foo96Bits, align 1 > %b = alloca i24, align 4 > %0 = bitcast %Foo96Bits* %value to i8*, !dbg !129 > call void @llvm.memcpy.p0i8.p0i8.i64(i8* %0, i8* bitcast > (%Foo96Bits* @4 to i8*), i64 16, i32 1, i1 false), !dbg !129 > call void @llvm.dbg.declare(metadata %Foo96Bits* %value, metadata > !118, metadata !75), !dbg !129 > %1 = getelementptr inbounds %Foo96Bits, %Foo96Bits* %value, i32 0, > i32 0, !dbg !130 > %2 = load i24, i24* %1, align 1, !dbg !130 > store i24 %2, i24* %b, align 4, !dbg !131 > call void @llvm.dbg.declare(metadata i24* %b, metadata !127, > metadata !75), !dbg !131 > ret i16 0, !dbg !132 > } > > Notice that the Foo96Bits struct is allocated with alignment value of > 1. Later on there is a load which also has this alignment value of 1. > > LLVM docs for alignment say: "An alignment of 1 is always safe." > (http://llvm.org/docs/LangRef.html#id189) > > This program when run crashes with a segfault. > > However if I change the > > %value = alloca %Foo96Bits, align 1 > > to > > %value = alloca %Foo96Bits, align 32 > > and the corresponding load > > %2 = load i24, i24* %1, align 32 > > Then the program runs fine. > > > I was unable to reproduce the issue with this IR code and clang, > because clang doesn't support cross compiling as seamlessly as my > frontend: > $ clang -o test.exe test.ll -target x86_64-unknown-windows-msvc > -fuse-ld=lld -Wl,-entry:_start > clang-5.0: warning: unable to find a Visual Studio installation; try > running Clang from a developer command prompt [-Wmsvc-not-found] > /nix/store/jxm0qg5cazlv8h7f7kp6cgk7ka7ag5kr-lld-5.0.0rc3/bin/lld-link: > error: could not open libcmt.lib: No such file or directory > clang-5.0: error: linker command failed with exit code 1 (use -v to > see invocation) > > But if you manage to get it linked I am sure this IR would trigger the > issue. It even causes the segfault in wine64 in addition to native > windows. > > > > Can someone confirm this is a bug in llvm? Or is the documentation > incorrect?The documentation is correct; LLVM should always find some way to lower an unaligned load to a correct sequence. So probably an LLVM bug, unless you've done something weird like call the function with a misaligned stack. -Eli -- Employee of Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project