272 lines · plain
1; REQUIRES: arm-registered-target2; REQUIRES: aarch64-registered-target3; REQUIRES: x86-registered-target4; RUN: llc -mtriple=i686-windows < %s | FileCheck %s --check-prefixes=CHECK,I686,NOTA325; RUN: llc -mtriple=x86_64-windows < %s | FileCheck %s --check-prefixes=CHECK,X64,NOTA326; RUN: llc -mtriple=aarch64-windows -aarch64-min-jump-table-entries=4 < %s | FileCheck %s --check-prefixes=CHECK,A64,NOTA327; RUN: llc -mtriple=thumbv7a-windows < %s | FileCheck %s --check-prefixes=CHECK,A328; RUN: llc -mtriple=x86_64-windows -filetype=obj < %s | llvm-readobj - --codeview | FileCheck %s --check-prefixes=CV9 10; Generated by clang++ -S -c -std=c++11 -emit-llvm -g from the following C++11 source:11; extern "C" void f1();12; extern "C" void f2();13; extern "C" void f3();14; extern "C" void f4();15; extern "C" void f5();16; extern "C" void func(int i){17; switch (i) {18; case 0: f1(); break;19; case 1: f2(); break;20; case 2: f3(); break;21; case 3: f4(); break;22; }23; switch (i) {24; case 1: f2(); break;25; case 2: f3(); break;26; case 3: f4(); break;27; case 4: f5(); break;28; case 5: f1(); break;29; }30; }31 32; i686 entries are absolute addresses (Base = 0, SwitchType = Pointer).33; x86_64 entries are fixed-size and relative to the jump table (Base = Table,34; SwitchType = Int32).35; aarch64 entries are variable-sized and relative to the first entry's BB if36; compressed (Base = Branch+0x4, SwitchType = UInt8ShiftLeft/UInt16ShiftLeft)37; otherwise relative to the ADR instruction (Base = Branch-0xc, SwitchType =38; Int32).39; thumbv7a entries are either absolute addresses (Base = 0, SwitchType =40; Pointer) OR variable-sized and relative to *after* the branch instruction41; (Base = Branch+0x4, SwitchType = UInt8ShiftLeft/UInt16ShiftLeft/UInt32) but42; there appears to be a bug where the offsets are always 0.43 44; Verify branch labels match what's in the CodeView45; X64: .Ltmp1:46; X64-NEXT: jmpq *%{{.*}}47; X64: .Ltmp4:48; X64-NEXT: jmpq *%{{.*}}49; A32: .LCPI0_0:50; A32-NEXT add pc, r{{.*}}51; NOTE: thumbv7a places the jump tables just after the branch, so verify the other branch below52; A64: .Ltmp1:53; A64-NEXT: br x{{.*}}54; A64: .Ltmp4:55; A64-NEXT: br x{{.*}}56 57; Verify jump table have the same entry size, base offset and shift as what's in the CodeView58; CHECK: {{\.?}}LJTI0_0:59; I686-NEXT: .long LBB0_[[#]]60; X64-NEXT: .long .LBB0_[[#]]-.LJTI0_061; A32-NEXT: .byte ($MBB0_[[#]]-(.LCPI0_0+4))/262; A64-NEXT: .byte (.LBB0_[[FIRSTBLOCK:[0-9]+]]-.LBB0_[[FIRSTBLOCK]])>>263; NOTE: thumbv7a places the jump tables just after the branch, so check for the other branch now64; A32: .LCPI0_1:65; A32-NEXT add pc, r{{.*}}66; CHECK: {{\.?}}LJTI0_1:67; I686-NEXT: .long LBB0_[[#]]68; X64-NEXT: .long .LBB0_[[#]]-.LJTI0_169; A32-NEXT: .byte ($MBB0_[[#]]-(.LCPI0_1+4))/270; A64-NEXT: .byte (.LBB0_[[SECONDBLOCK:[0-9]+]]-.LBB0_[[SECONDBLOCK]])>>271 72; Verify CodeView73; CHECK: [[INT16:\.short|\.hword]] 4441 [[COMMENT:#|//|@]] Record kind: S_ARMSWITCHTABLE74; I686-NEXT: .long 0 [[COMMENT]] Base offset75; I686-NEXT: .short 0 [[COMMENT]] Base section index76; X64-NEXT: .secrel32 .LJTI0_0 [[COMMENT]] Base offset77; X64-NEXT: .secidx .LJTI0_0 [[COMMENT]] Base section index78; A32-NEXT: .secrel32 .LCPI0_0+4 [[COMMENT]] Base offset79; A32-NEXT: .secidx .LCPI0_0 [[COMMENT]] Base section index80; A64-NEXT: .secrel32 .LBB0_[[FIRSTBLOCK]] [[COMMENT]] Base offset81; A64-NEXT: .secidx .LBB0_[[FIRSTBLOCK]] [[COMMENT]] Base section index82; I686-NEXT: .short 6 [[COMMENT]] Switch type83; X64-NEXT: .short 4 [[COMMENT]] Switch type84; A32-NEXT: .short 7 [[COMMENT]] Switch type85; A64-NEXT: .hword 7 [[COMMENT]] Switch type86; NOTA32-NEXT: .secrel32 {{\.?}}Ltmp1 [[COMMENT]] Branch offset87; A32-NEXT: .secrel32 .LCPI0_0 [[COMMENT]] Branch offset88; CHECK-NEXT: .secrel32 {{\.?}}LJTI0_0 [[COMMENT]] Table offset89; NOTA32-NEXT: .secidx {{\.?}}Ltmp1 [[COMMENT]] Branch section index90; A32-NEXT: .secidx .LCPI0_0 [[COMMENT]] Branch section index91; CHECK-NEXT: .secidx {{\.?}}LJTI0_0 [[COMMENT]] Table section index92; CHECK-NEXT: [[INT32:\.long|\.word]] 4 [[COMMENT]] Entries count93; CHECK: [[INT16]] 4441 [[COMMENT]] Record kind: S_ARMSWITCHTABLE94; I686-NEXT: .long 0 [[COMMENT]] Base offset95; I686-NEXT: .short 0 [[COMMENT]] Base section index96; X64-NEXT: .secrel32 .LJTI0_1 [[COMMENT]] Base offset97; X64-NEXT: .secidx .LJTI0_1 [[COMMENT]] Base section index98; A32-NEXT: .secrel32 .LCPI0_1+4 [[COMMENT]] Base offset99; A32-NEXT: .secidx .LCPI0_1 [[COMMENT]] Base section index100; A64-NEXT: .secrel32 .LBB0_[[SECONDBLOCK]] [[COMMENT]] Base offset101; A64-NEXT: .secidx .LBB0_[[SECONDBLOCK]] [[COMMENT]] Base section index102; I686-NEXT: .short 6 [[COMMENT]] Switch type103; X64-NEXT: .short 4 [[COMMENT]] Switch type104; A32-NEXT: .short 7 [[COMMENT]] Switch type105; A64-NEXT: .hword 7 [[COMMENT]] Switch type106; NOTA32-NEXT: .secrel32 {{\.?}}Ltmp4 [[COMMENT]] Branch offset107; A32-NEXT: .secrel32 .LCPI0_1 [[COMMENT]] Branch offset108; CHECK-NEXT: .secrel32 {{\.?}}LJTI0_1 [[COMMENT]] Table offset109; NOTA32-NEXT: .secidx {{\.?}}Ltmp4 [[COMMENT]] Branch section index110; A32-NEXT: .secidx .LCPI0_1 [[COMMENT]] Branch section index111; CHECK-NEXT: .secidx {{\.?}}LJTI0_1 [[COMMENT]] Table section index112; CHECK-NEXT: [[INT32]] 5 [[COMMENT]] Entries count113; CHECK-NOT: [[INT16]] 4441 [[COMMENT]] Record kind: S_ARMSWITCHTABLE114 115; Verify CodeView as dumped by llvm-readobj116; CV: Subsection [117; CV: SubSectionType: Symbols (0xF1)118; CV: GlobalProcIdSym {119; CV: DisplayName: func120; CV-NOT: GlobalProcIdSym121; CV: LabelSym {122; CV-NEXT: Kind: S_LABEL32 (0x1105)123; CV-NEXT: CodeOffset: 0xC0124; CV-NEXT: Segment: 0x0125; CV-NEXT: Flags: 0x0126; CV-NEXT: Flags [ (0x0)127; CV-NEXT: ]128; CV-NEXT: DisplayName:129; CV-NEXT: }130; CV: JumpTableSym {131; CV-NEXT: Kind: S_ARMSWITCHTABLE (0x1159)132; CV-NEXT: BaseOffset: 0x0133; CV-NEXT: BaseSegment: 0134; CV-NEXT: SwitchType: Int32 (0x4)135; CV-NEXT: BranchOffset: 0x23136; CV-NEXT: TableOffset: 0x0137; CV-NEXT: BranchSegment: 0138; CV-NEXT: TableSegment: 0139; CV-NEXT: EntriesCount: 4140; CV-NEXT: }141; CV-NEXT: JumpTableSym {142; CV-NEXT: Kind: S_ARMSWITCHTABLE (0x1159)143; CV-NEXT: BaseOffset: 0x10144; CV-NEXT: BaseSegment: 0145; CV-NEXT: SwitchType: Int32 (0x4)146; CV-NEXT: BranchOffset: 0x5A147; CV-NEXT: TableOffset: 0x10148; CV-NEXT: BranchSegment: 0149; CV-NEXT: TableSegment: 0150; CV-NEXT: EntriesCount: 5151; CV-NEXT: }152; CV-NOT: JumpTableSym {153 154source_filename = ".\\jump-table.cpp"155target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"156target triple = "x86_64-pc-windows-msvc19.35.32216"157 158; Function Attrs: mustprogress noinline optnone uwtable159define dso_local void @func(i32 noundef %0) #0 !dbg !8 {160 %2 = alloca i32, align 4161 store i32 %0, ptr %2, align 4162 call void @llvm.dbg.declare(metadata ptr %2, metadata !14, metadata !DIExpression()), !dbg !15163 %3 = load i32, ptr %2, align 4, !dbg !16164 switch i32 %3, label %8 [165 i32 0, label %4166 i32 1, label %5167 i32 2, label %6168 i32 3, label %7169 ], !dbg !16170 1714: ; preds = %1172 call void @f1(), !dbg !17173 br label %8, !dbg !17174 1755: ; preds = %1176 call void @f2(), !dbg !19177 br label %8, !dbg !19178 1796: ; preds = %1180 call void @f3(), !dbg !20181 br label %8, !dbg !20182 1837: ; preds = %1184 call void @f4(), !dbg !21185 br label %8, !dbg !21186 1878: ; preds = %1, %7, %6, %5, %4188 %9 = load i32, ptr %2, align 4, !dbg !22189 switch i32 %9, label %15 [190 i32 1, label %10191 i32 2, label %11192 i32 3, label %12193 i32 4, label %13194 i32 5, label %14195 ], !dbg !22196 19710: ; preds = %8198 call void @f2(), !dbg !23199 br label %15, !dbg !23200 20111: ; preds = %8202 call void @f3(), !dbg !25203 br label %15, !dbg !25204 20512: ; preds = %8206 call void @f4(), !dbg !26207 br label %15, !dbg !26208 20913: ; preds = %8210 call void @f5(), !dbg !27211 br label %15, !dbg !27212 21314: ; preds = %8214 call void @f1(), !dbg !28215 br label %15, !dbg !28216 21715: ; preds = %8, %14, %13, %12, %11, %10218 ret void, !dbg !29219}220 221; Function Attrs: nocallback nofree nosync nounwind readnone speculatable willreturn222declare void @llvm.dbg.declare(metadata, metadata, metadata) #1223 224declare dso_local void @f1() #2225 226declare dso_local void @f2() #2227 228declare dso_local void @f3() #2229 230declare dso_local void @f4() #2231 232declare dso_local void @f5() #2233 234attributes #0 = { mustprogress noinline optnone uwtable "frame-pointer"="none" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }235attributes #1 = { nocallback nofree nosync nounwind readnone speculatable willreturn }236attributes #2 = { "frame-pointer"="none" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }237 238!llvm.dbg.cu = !{!0}239!llvm.module.flags = !{!2, !3, !4, !5, !6}240!llvm.ident = !{!7}241 242!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_11, file: !1, producer: "clang version 15.0.1", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)243!1 = !DIFile(filename: "jump-table.cpp", directory: "C:\\llvm", checksumkind: CSK_MD5, checksum: "35610c7104c8080f83e2bf6a02dabfc9")244!2 = !{i32 2, !"CodeView", i32 1}245!3 = !{i32 2, !"Debug Info Version", i32 3}246!4 = !{i32 1, !"wchar_size", i32 2}247!5 = !{i32 7, !"PIC Level", i32 2}248!6 = !{i32 7, !"uwtable", i32 2}249!7 = !{!"clang version 15.0.1"}250!8 = distinct !DISubprogram(name: "func", scope: !9, file: !9, line: 6, type: !10, scopeLine: 6, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !13)251!9 = !DIFile(filename: ".\\jump-table.cpp", directory: "C:\\llvm", checksumkind: CSK_MD5, checksum: "35610c7104c8080f83e2bf6a02dabfc9")252!10 = !DISubroutineType(types: !11)253!11 = !{null, !12}254!12 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)255!13 = !{}256!14 = !DILocalVariable(name: "i", arg: 1, scope: !8, file: !9, line: 6, type: !12)257!15 = !DILocation(line: 6, scope: !8)258!16 = !DILocation(line: 7, scope: !8)259!17 = !DILocation(line: 8, scope: !18)260!18 = distinct !DILexicalBlock(scope: !8, file: !9, line: 7)261!19 = !DILocation(line: 9, scope: !18)262!20 = !DILocation(line: 10, scope: !18)263!21 = !DILocation(line: 11, scope: !18)264!22 = !DILocation(line: 13, scope: !8)265!23 = !DILocation(line: 14, scope: !24)266!24 = distinct !DILexicalBlock(scope: !8, file: !9, line: 13)267!25 = !DILocation(line: 15, scope: !24)268!26 = !DILocation(line: 16, scope: !24)269!27 = !DILocation(line: 17, scope: !24)270!28 = !DILocation(line: 18, scope: !24)271!29 = !DILocation(line: 20, scope: !8)272