336 lines · plain
1; RUN: llc -mtriple=arm64ec-pc-windows-msvc < %s | FileCheck %s2; RUN: llc -mtriple=arm64ec-pc-windows-msvc -filetype=obj -o %t.o < %s3; RUN: llvm-objdump -t %t.o | FileCheck --check-prefix=SYM %s4 5define dso_local ptr @func() hybrid_patchable nounwind {6; SYM: [ 8](sec 4)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000000 #func$hp_target7; CHECK-LABEL: .def "#func$hp_target";8; CHECK: .section .text,"xr",discard,"#func$hp_target"9; CHECK-NEXT: .globl "#func$hp_target" // -- Begin function #func$hp_target10; CHECK-NEXT: .p2align 211; CHECK-NEXT: "#func$hp_target": // @"#func$hp_target"12; CHECK-NEXT: // %bb.0:13; CHECK-NEXT: adrp x0, func14; CHECK-NEXT: add x0, x0, :lo12:func15; CHECK-NEXT: ret16 ret ptr @func17}18 19define void @has_varargs(...) hybrid_patchable nounwind {20; SYM: [11](sec 5)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000000 #has_varargs$hp_target21; CHECK-LABEL: .def "#has_varargs$hp_target";22; CHECK: .section .text,"xr",discard,"#has_varargs$hp_target"23; CHECK-NEXT: .globl "#has_varargs$hp_target" // -- Begin function #has_varargs$hp_target24; CHECK-NEXT: .p2align 225; CHECK-NEXT: "#has_varargs$hp_target": // @"#has_varargs$hp_target"26; CHECK-NEXT: // %bb.0:27; CHECK-NEXT: sub sp, sp, #4828; CHECK-NEXT: stp x0, x1, [x4, #-32]!29; CHECK-NEXT: stp x2, x3, [x4, #16]30; CHECK-NEXT: str x4, [sp, #8]31; CHECK-NEXT: add sp, sp, #4832; CHECK-NEXT: ret33 %valist = alloca ptr34 call void @llvm.va_start(ptr %valist)35 call void @llvm.va_end(ptr %valist)36 ret void37}38 39define void @has_sret(ptr sret([100 x i8])) hybrid_patchable nounwind {40; SYM: [14](sec 6)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000000 #has_sret$hp_target41; CHECK-LABEL: .def "#has_sret$hp_target";42; CHECK: .section .text,"xr",discard,"#has_sret$hp_target"43; CHECK-NEXT: .globl "#has_sret$hp_target" // -- Begin function #has_sret$hp_target44; CHECK-NEXT: .p2align 245; CHECK-NEXT: "#has_sret$hp_target": // @"#has_sret$hp_target"46; CHECK-NEXT: // %bb.0:47; CHECK-NEXT: ret48 ret void49}50 51define dllexport void @exp() hybrid_patchable nounwind {52; CHECK-LABEL: .def "#exp$hp_target";53; CHECK: .section .text,"xr",discard,"#exp$hp_target"54; CHECK-NEXT: .globl "#exp$hp_target" // -- Begin function #exp$hp_target55; CHECK-NEXT: .p2align 256; CHECK-NEXT: "#exp$hp_target": // @"#exp$hp_target"57; CHECK-NEXT: // %bb.0:58; CHECK-NEXT: ret59 ret void60}61 62; hybrid_patchable attribute is ignored on internal functions63define internal i32 @static_func() hybrid_patchable nounwind {64; CHECK-LABEL: .def static_func;65; CHECK: static_func: // @static_func66; CHECK-NEXT: // %bb.0:67; CHECK-NEXT: mov w0, #2 // =0x268; CHECK-NEXT: ret69 ret i32 270}71 72define dso_local void @caller() nounwind {73; CHECK-LABEL: .def "#caller";74; CHECK: .section .text,"xr",discard,"#caller"75; CHECK-NEXT: .globl "#caller" // -- Begin function #caller76; CHECK-NEXT: .p2align 277; CHECK-NEXT: "#caller": // @"#caller"78; CHECK-NEXT: .weak_anti_dep caller79; CHECK-NEXT: caller = "#caller"{{$}}80; CHECK-NEXT: // %bb.0:81; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill82; CHECK-NEXT: bl "#func"83; CHECK-NEXT: bl static_func84; CHECK-NEXT: adrp x8, __os_arm64x_check_icall85; CHECK-NEXT: adrp x11, func86; CHECK-NEXT: add x11, x11, :lo12:func87; CHECK-NEXT: ldr x8, [x8, :lo12:__os_arm64x_check_icall]88; CHECK-NEXT: adrp x10, $iexit_thunk$cdecl$v$v89; CHECK-NEXT: add x10, x10, :lo12:$iexit_thunk$cdecl$v$v90; CHECK-NEXT: str x11, [sp, #8]91; CHECK-NEXT: blr x892; CHECK-NEXT: blr x1193; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload94; CHECK-NEXT: ret95 %1 = call i32 @func()96 %2 = call i32 @static_func()97 %3 = alloca ptr, align 898 store ptr @func, ptr %3, align 899 %4 = load ptr, ptr %3, align 8100 call void %4()101 ret void102}103 104; CHECK-LABEL: def "#func$hybpatch_thunk";105; CHECK: .section .wowthk$aa,"xr",discard,"#func$hybpatch_thunk"106; CHECK-NEXT: .globl "#func$hybpatch_thunk" // -- Begin function #func$hybpatch_thunk107; CHECK-NEXT: .p2align 2108; CHECK-NEXT: "#func$hybpatch_thunk": // @"#func$hybpatch_thunk"109; CHECK-NEXT: .seh_proc "#func$hybpatch_thunk"110; CHECK-NEXT: // %bb.0:111; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill112; CHECK-NEXT: .seh_save_reg_x x30, 16113; CHECK-NEXT: .seh_endprologue114; CHECK-NEXT: adrp x8, __os_arm64x_dispatch_call115; CHECK-NEXT: adrp x11, func116; CHECK-NEXT: add x11, x11, :lo12:func117; CHECK-NEXT: ldr x8, [x8, :lo12:__os_arm64x_dispatch_call]118; CHECK-NEXT: adrp x10, $iexit_thunk$cdecl$i8$v119; CHECK-NEXT: add x10, x10, :lo12:$iexit_thunk$cdecl$i8$v120; CHECK-NEXT: adrp x9, "#func$hp_target"121; CHECK-NEXT: add x9, x9, :lo12:"#func$hp_target"122; CHECK-NEXT: blr x8123; CHECK-NEXT: .seh_startepilogue124; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload125; CHECK-NEXT: .seh_save_reg_x x30, 16126; CHECK-NEXT: .seh_endepilogue127; CHECK-NEXT: br x11128; CHECK-NEXT: .seh_endfunclet129; CHECK-NEXT: .seh_endproc130 131; CHECK-LABEL: .def "#has_varargs$hybpatch_thunk";132; CHECK: .section .wowthk$aa,"xr",discard,"#has_varargs$hybpatch_thunk"133; CHECK-NEXT: .globl "#has_varargs$hybpatch_thunk" // -- Begin function #has_varargs$hybpatch_thunk134; CHECK-NEXT: .p2align 2135; CHECK-NEXT:"#has_varargs$hybpatch_thunk": // @"#has_varargs$hybpatch_thunk"136; CHECK-NEXT:.seh_proc "#has_varargs$hybpatch_thunk"137; CHECK-NEXT:// %bb.0:138; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill139; CHECK-NEXT: .seh_save_reg_x x30, 16140; CHECK-NEXT: .seh_endprologue141; CHECK-NEXT: adrp x8, __os_arm64x_dispatch_call142; CHECK-NEXT: adrp x11, has_varargs143; CHECK-NEXT: add x11, x11, :lo12:has_varargs144; CHECK-NEXT: ldr x8, [x8, :lo12:__os_arm64x_dispatch_call]145; CHECK-NEXT: adrp x10, $iexit_thunk$cdecl$v$varargs146; CHECK-NEXT: add x10, x10, :lo12:$iexit_thunk$cdecl$v$varargs147; CHECK-NEXT: adrp x9, "#has_varargs$hp_target"148; CHECK-NEXT: add x9, x9, :lo12:"#has_varargs$hp_target"149; CHECK-NEXT: blr x8150; CHECK-NEXT: .seh_startepilogue151; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload152; CHECK-NEXT: .seh_save_reg_x x30, 16153; CHECK-NEXT: .seh_endepilogue154; CHECK-NEXT: br x11155; CHECK-NEXT: .seh_endfunclet156; CHECK-NEXT: .seh_endproc157 158; CHECK-LABEL: .def "#has_sret$hybpatch_thunk";159; CHECK: .section .wowthk$aa,"xr",discard,"#has_sret$hybpatch_thunk"160; CHECK-NEXT: .globl "#has_sret$hybpatch_thunk" // -- Begin function #has_sret$hybpatch_thunk161; CHECK-NEXT: .p2align 2162; CHECK-NEXT: "#has_sret$hybpatch_thunk": // @"#has_sret$hybpatch_thunk"163; CHECK-NEXT: .seh_proc "#has_sret$hybpatch_thunk"164; CHECK-NEXT: // %bb.0:165; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill166; CHECK-NEXT: .seh_save_reg_x x30, 16167; CHECK-NEXT: .seh_endprologue168; CHECK-NEXT: adrp x9, __os_arm64x_dispatch_call169; CHECK-NEXT: adrp x11, has_sret170; CHECK-NEXT: add x11, x11, :lo12:has_sret171; CHECK-NEXT: ldr x12, [x9, :lo12:__os_arm64x_dispatch_call]172; CHECK-NEXT: adrp x10, $iexit_thunk$cdecl$m100$v173; CHECK-NEXT: add x10, x10, :lo12:$iexit_thunk$cdecl$m100$v174; CHECK-NEXT: adrp x9, "#has_sret$hp_target"175; CHECK-NEXT: add x9, x9, :lo12:"#has_sret$hp_target"176; CHECK-NEXT: blr x12177; CHECK-NEXT: .seh_startepilogue178; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload179; CHECK-NEXT: .seh_save_reg_x x30, 16180; CHECK-NEXT: .seh_endepilogue181; CHECK-NEXT: br x11182; CHECK-NEXT: .seh_endfunclet183; CHECK-NEXT: .seh_endproc184 185; CHECK-LABEL: .def "#exp$hybpatch_thunk";186; CHECK: .section .wowthk$aa,"xr",discard,"#exp$hybpatch_thunk"187; CHECK-NEXT: .globl "#exp$hybpatch_thunk" // -- Begin function #exp$hybpatch_thunk188; CHECK-NEXT: .p2align 2189; CHECK-NEXT: "#exp$hybpatch_thunk": // @"#exp$hybpatch_thunk"190; CHECK-NEXT: .seh_proc "#exp$hybpatch_thunk"191; CHECK-NEXT: // %bb.0:192; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill193; CHECK-NEXT: .seh_save_reg_x x30, 16194; CHECK-NEXT: .seh_endprologue195; CHECK-NEXT: adrp x8, __os_arm64x_dispatch_call196; CHECK-NEXT: adrp x11, exp197; CHECK-NEXT: add x11, x11, :lo12:exp198; CHECK-NEXT: ldr x8, [x8, :lo12:__os_arm64x_dispatch_call]199; CHECK-NEXT: adrp x10, $iexit_thunk$cdecl$v$v200; CHECK-NEXT: add x10, x10, :lo12:$iexit_thunk$cdecl$v$v201; CHECK-NEXT: adrp x9, "#exp$hp_target"202; CHECK-NEXT: add x9, x9, :lo12:"#exp$hp_target"203; CHECK-NEXT: blr x8204; CHECK-NEXT: .seh_startepilogue205; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload206; CHECK-NEXT: .seh_save_reg_x x30, 16207; CHECK-NEXT: .seh_endepilogue208; CHECK-NEXT: br x11209; CHECK-NEXT: .seh_endfunclet210; CHECK-NEXT: .seh_endproc211 212; Verify the hybrid bitmap213; CHECK-LABEL: .section .hybmp$x,"yi"214; CHECK-NEXT: .symidx "#func$hp_target"215; CHECK-NEXT: .symidx $ientry_thunk$cdecl$i8$v216; CHECK-NEXT: .word 1217; CHECK-NEXT: .symidx "#has_varargs$hp_target"218; CHECK-NEXT: .symidx $ientry_thunk$cdecl$v$varargs219; CHECK-NEXT: .word 1220; CHECK-NEXT: .symidx "#has_sret$hp_target"221; CHECK-NEXT: .symidx $ientry_thunk$cdecl$m100$v222; CHECK-NEXT: .word 1223; CHECK-NEXT: .symidx "#exp$hp_target"224; CHECK-NEXT: .symidx $ientry_thunk$cdecl$v$v225; CHECK-NEXT: .word 1226; CHECK-NEXT: .symidx "#caller"227; CHECK-NEXT: .symidx $ientry_thunk$cdecl$v$v228; CHECK-NEXT: .word 1229; CHECK-NEXT: .symidx func230; CHECK-NEXT: .symidx $iexit_thunk$cdecl$i8$v231; CHECK-NEXT: .word 4232; CHECK-NEXT: .symidx "#func$hybpatch_thunk"233; CHECK-NEXT: .symidx func234; CHECK-NEXT: .word 0235; CHECK-NEXT: .symidx "#has_varargs$hybpatch_thunk"236; CHECK-NEXT: .symidx has_varargs237; CHECK-NEXT: .word 0238; CHECK-NEXT: .symidx "#has_sret$hybpatch_thunk"239; CHECK-NEXT: .symidx has_sret240; CHECK-NEXT: .word 0241; CHECK-NEXT: .symidx "#exp$hybpatch_thunk"242; CHECK-NEXT: .symidx exp243; CHECK-NEXT: .word 0244; CHECK-NEXT: .section .drectve,"yni"245; CHECK-NEXT: .ascii " /EXPORT:exp"246 247; CHECK-NEXT: .def "EXP+#func";248; CHECK-NEXT: .scl 2;249; CHECK-NEXT: .type 32;250; CHECK-NEXT: .endef251; CHECK-NEXT: .def func;252; CHECK-NEXT: .scl 2;253; CHECK-NEXT: .type 32;254; CHECK-NEXT: .endef255; CHECK-NEXT: .weak func256; CHECK-NEXT: func = "EXP+#func"{{$}}257; CHECK-NEXT: .weak "#func"258; CHECK-NEXT: .def "#func";259; CHECK-NEXT: .scl 2;260; CHECK-NEXT: .type 32;261; CHECK-NEXT: .endef262; CHECK-NEXT: "#func" = "#func$hybpatch_thunk"{{$}}263; CHECK-NEXT: .def "EXP+#has_varargs";264; CHECK-NEXT: .scl 2;265; CHECK-NEXT: .type 32;266; CHECK-NEXT: .endef267; CHECK-NEXT: .def has_varargs;268; CHECK-NEXT: .scl 2;269; CHECK-NEXT: .type 32;270; CHECK-NEXT: .endef271; CHECK-NEXT: .weak has_varargs272; CHECK-NEXT: has_varargs = "EXP+#has_varargs"273; CHECK-NEXT: .weak "#has_varargs"274; CHECK-NEXT: .def "#has_varargs";275; CHECK-NEXT: .scl 2;276; CHECK-NEXT: .type 32;277; CHECK-NEXT: .endef278; CHECK-NEXT: "#has_varargs" = "#has_varargs$hybpatch_thunk"279; CHECK-NEXT: .def "EXP+#has_sret";280; CHECK-NEXT: .scl 2;281; CHECK-NEXT: .type 32;282; CHECK-NEXT: .endef283; CHECK-NEXT: .def has_sret;284; CHECK-NEXT: .scl 2;285; CHECK-NEXT: .type 32;286; CHECK-NEXT: .endef287; CHECK-NEXT: .weak has_sret288; CHECK-NEXT: has_sret = "EXP+#has_sret"289; CHECK-NEXT: .weak "#has_sret"290; CHECK-NEXT: .def "#has_sret";291; CHECK-NEXT: .scl 2;292; CHECK-NEXT: .type 32;293; CHECK-NEXT: .endef294; CHECK-NEXT: "#has_sret" = "#has_sret$hybpatch_thunk"295; CHECK-NEXT: .def "EXP+#exp";296; CHECK-NEXT: .scl 2;297; CHECK-NEXT: .type 32;298; CHECK-NEXT: .endef299; CHECK-NEXT: .def exp;300; CHECK-NEXT: .scl 2;301; CHECK-NEXT: .type 32;302; CHECK-NEXT: .endef303; CHECK-NEXT: .weak exp304; CHECK-NEXT: exp = "EXP+#exp"305; CHECK-NEXT: .weak "#exp"306; CHECK-NEXT: .def "#exp";307; CHECK-NEXT: .scl 2;308; CHECK-NEXT: .type 32;309; CHECK-NEXT: .endef310; CHECK-NEXT: "#exp" = "#exp$hybpatch_thunk"311 312; SYM: [53](sec 15)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000000 #func$hybpatch_thunk313; SYM: [58](sec 16)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000000 #has_varargs$hybpatch_thunk314; SYM: [68](sec 18)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000000 #has_sret$hybpatch_thunk315; SYM: [78](sec 20)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000000 #exp$hybpatch_thunk316; SYM: [110](sec 0)(fl 0x00)(ty 0)(scl 69) (nx 1) 0x00000000 func317; SYM-NEXT: AUX indx 112 srch 3318; SYM-NEXT: [112](sec 0)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000000 EXP+#func319; SYM: [116](sec 0)(fl 0x00)(ty 0)(scl 69) (nx 1) 0x00000000 #func320; SYM-NEXT: AUX indx 53 srch 3321; SYM: [122](sec 0)(fl 0x00)(ty 0)(scl 69) (nx 1) 0x00000000 has_varargs322; SYM-NEXT: AUX indx 124 srch 3323; SYM-NEXT: [124](sec 0)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000000 EXP+#has_varargs324; SYM-NEXT: [125](sec 0)(fl 0x00)(ty 0)(scl 69) (nx 1) 0x00000000 has_sret325; SYM-NEXT: AUX indx 127 srch 3326; SYM-NEXT: [127](sec 0)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000000 EXP+#has_sret327; SYM-NEXT: [128](sec 0)(fl 0x00)(ty 0)(scl 69) (nx 1) 0x00000000 exp328; SYM-NEXT: AUX indx 130 srch 3329; SYM-NEXT: [130](sec 0)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000000 EXP+#exp330; SYM-NEXT: [131](sec 0)(fl 0x00)(ty 0)(scl 69) (nx 1) 0x00000000 #has_varargs331; SYM-NEXT: AUX indx 58 srch 3332; SYM-NEXT: [133](sec 0)(fl 0x00)(ty 0)(scl 69) (nx 1) 0x00000000 #has_sret333; SYM-NEXT: AUX indx 68 srch 3334; SYM-NEXT: [135](sec 0)(fl 0x00)(ty 0)(scl 69) (nx 1) 0x00000000 #exp335; SYM-NEXT: AUX indx 78 srch 3336