
#7640: Crash in stg_ap_p_fast on ARM on executable output by registerised/LLVM cross compiler ------------------------------+--------------------------------------------- Reporter: StephenBlackheath | Owner: Type: bug | Status: new Priority: normal | Component: Compiler (LLVM) Version: 7.7 | Keywords: Os: Unknown/Multiple | Architecture: arm Failure: Runtime crash | Blockedby: Blocking: 7623 | Related: ------------------------------+--------------------------------------------- Comment(by StephenBlackheath): The C-- gives a switch with 5 cases + default, but the LL seems to have a jump table with only two cases. The resulting ARM code seems to match the LL (and is shorter than I would expect for the CMM). I don't understand LLVM and C-- very well, but that doesn't seem right. {{{ INFO_TABLE_RET(stg_ap_p, RET_SMALL, W_ info_ptr, gcptr arg1, ) { W_ info; W_ arity; IF_DEBUG(apply,foreign "C" debugBelch("stg_ap_p_ret... "); foreign "C" printClosure(R1 "ptr")); IF_DEBUG(sanity,foreign "C" checkStackFrame(Sp+WDS(2)"ptr")); ASSERT(LOOKS_LIKE_CLOSURE_PTR(Sp(1))); again: if (GETTAG(R1)==1) { Sp_adj(1); jump %GET_ENTRY(R1-1) [R1]; } R1 = UNTAG(R1); info = %INFO_PTR(R1); switch [INVALID_OBJECT .. N_CLOSURE_TYPES] (TO_W_(%INFO_TYPE(%STD_INFO(info)))) { case BCO: { arity = TO_W_(StgBCO_arity(R1)); ASSERT(arity > 0); if (arity == 1) { Sp_adj(1); jump ENTRY_LBL(stg_BCO) [R1]; } else { BUILD_PAP(1,1,stg_ap_p_info,BCO); } } case FUN, FUN_1_0, FUN_0_1, FUN_2_0, FUN_1_1, FUN_0_2, FUN_STATIC: { arity = TO_W_(StgFunInfoExtra_arity(%FUN_INFO(info))); ASSERT(arity > 0); if (arity == 1) { Sp_adj(1); R1 = R1 + 1; jump %GET_ENTRY(UNTAG(R1)) [R1]; } else { if (arity < 4) { R1 = R1 + arity; } BUILD_PAP(1,1,stg_ap_p_info,FUN); } } case PAP: { arity = TO_W_(StgPAP_arity(R1)); ASSERT(arity > 0); if (arity == 1) { Sp_adj(1); R2 = stg_ap_p_info; jump stg_PAP_apply [R1,R2]; } else { NEW_PAP(1,1,stg_ap_p_info,PAP); } } case AP, AP_STACK, BLACKHOLE, WHITEHOLE, THUNK, THUNK_1_0, THUNK_0_1, THUNK_2_0, THUNK_1_1, THUNK_0_2, THUNK_STATIC, THUNK_SELECTOR: { Sp(0) = stg_ap_p_info; jump_SAVE_CCCS(%ENTRY_CODE(info)); } case IND, IND_STATIC, IND_PERM: { R1 = StgInd_indirectee(R1); goto again; } default: { foreign "C" barf("stg_ap_p_ret") never returns; } } } }}} and the ll looks like this: {{{ define cc 10 void @stg_ap_p_fast(i32* noalias nocapture %Base_Arg, i32* noalias nocapture %Sp_Arg, i32* noalias nocapture %Hp_Arg, i32 %R1_Arg, i32 %R2_Arg, i32 %R3_Arg, i32 %R4_Arg, i32 %SpLim_Arg) align 4 nounwind { cCP: %Base_Var = alloca i32*, i32 1 store i32* %Base_Arg, i32** %Base_Var %Sp_Var = alloca i32*, i32 1 store i32* %Sp_Arg, i32** %Sp_Var %Hp_Var = alloca i32*, i32 1 store i32* %Hp_Arg, i32** %Hp_Var %R1_Var = alloca i32, i32 1 store i32 %R1_Arg, i32* %R1_Var %R2_Var = alloca i32, i32 1 store i32 undef, i32* %R2_Var %R3_Var = alloca i32, i32 1 store i32 undef, i32* %R3_Var %R4_Var = alloca i32, i32 1 store i32 undef, i32* %R4_Var %SpLim_Var = alloca i32, i32 1 store i32 %SpLim_Arg, i32* %SpLim_Var %lcD9 = alloca i32, i32 1 %lcD8 = alloca i32, i32 1 %lcDc = alloca i32, i32 1 %lcDb = alloca i32, i32 1 %ln4WG = load i32* %R1_Var %ln4WH = and i32 %ln4WG, 3 %ln4WI = icmp eq i32 %ln4WH, 1 br i1 %ln4WI, label %cD6, label %cD7 cCS: %ln4WJ = load i32** %Sp_Var %ln4WK = ptrtoint i32* %ln4WJ to i32 %ln4WL = inttoptr i32 %ln4WK to i32* store i32* %ln4WL, i32** %Sp_Var %ln4WM = load i32* %R1_Var %ln4WN = add i32 %ln4WM, 1 store i32 %ln4WN, i32* %R1_Var %ln4WO = load i32* %R1_Var %ln4WP = and i32 %ln4WO, -4 %ln4WQ = inttoptr i32 %ln4WP to i32* %ln4WR = load i32* %ln4WQ, !tbaa !5 %ln4WS = inttoptr i32 %ln4WR to void (i32*, i32*, i32*, i32, i32, i32, i32, i32)* %ln4WT = load i32** %Base_Var %ln4WU = load i32** %Sp_Var %ln4WV = load i32** %Hp_Var %ln4WW = load i32* %R1_Var %ln4WX = load i32* %SpLim_Var tail call cc 10 void (i32*,i32*,i32*,i32,i32,i32,i32,i32)* %ln4WS( i32* %ln4WT, i32* %ln4WU, i32* %ln4WV, i32 %ln4WW, i32 undef, i32 undef, i32 undef, i32 %ln4WX ) nounwind ret void cCU: %ln4WY = load i32* %lcD9 %ln4WZ = add i32 %ln4WY, 12 %ln4X0 = load i32* %lcD8 %ln4X1 = shl i32 %ln4X0, 2 %ln4X2 = add i32 %ln4WZ, %ln4X1 %ln4X3 = load i32** %Sp_Var %ln4X4 = ptrtoint i32* %ln4X3 to i32 %ln4X5 = load i32* %lcD8 %ln4X6 = add i32 %ln4X5, 1 %ln4X7 = shl i32 %ln4X6, 2 %ln4X8 = add i32 %ln4X4, %ln4X7 %ln4X9 = inttoptr i32 %ln4X8 to i32* %ln4Xa = load i32* %ln4X9, !tbaa !5 %ln4Xb = inttoptr i32 %ln4X2 to i32* store i32 %ln4Xa, i32* %ln4Xb, !tbaa !5 %ln4Xc = load i32* %lcD8 %ln4Xd = add i32 %ln4Xc, 1 store i32 %ln4Xd, i32* %lcD8 br label %cCW cCV: %ln4Xe = load i32* %lcD9 store i32 %ln4Xe, i32* %R1_Var %ln4Xf = load i32** %Sp_Var %ln4Xg = getelementptr inbounds i32* %ln4Xf, i32 2 %ln4Xh = ptrtoint i32* %ln4Xg to i32 %ln4Xi = inttoptr i32 %ln4Xh to i32* store i32* %ln4Xi, i32** %Sp_Var %ln4Xj = load i32** %Sp_Var %ln4Xk = getelementptr inbounds i32* %ln4Xj, i32 0 %ln4Xl = bitcast i32* %ln4Xk to i32* %ln4Xm = load i32* %ln4Xl, !tbaa !1 %ln4Xn = inttoptr i32 %ln4Xm to void (i32*, i32*, i32*, i32, i32, i32, i32, i32)* %ln4Xo = load i32** %Base_Var %ln4Xp = load i32** %Sp_Var %ln4Xq = load i32** %Hp_Var %ln4Xr = load i32* %R1_Var %ln4Xs = load i32* %SpLim_Var tail call cc 10 void (i32*,i32*,i32*,i32,i32,i32,i32,i32)* %ln4Xn( i32* %ln4Xo, i32* %ln4Xp, i32* %ln4Xq, i32 %ln4Xr, i32 undef, i32 undef, i32 undef, i32 %ln4Xs ) nounwind ret void cCW: %ln4Xt = load i32* %lcD8 %ln4Xu = icmp ult i32 %ln4Xt, 1 br i1 %ln4Xu, label %cCU, label %cCV cCY: %ln4Xv = load i32* %lcDc %ln4Xw = load i32** %Base_Var %ln4Xx = getelementptr inbounds i32* %ln4Xw, i32 39 store i32 %ln4Xv, i32* %ln4Xx, !tbaa !4 %ln4Xy = ptrtoint void (i32*, i32*, i32*, i32, i32, i32, i32, i32)* @stg_ap_p_info to i32 %ln4Xz = load i32** %Sp_Var %ln4XA = getelementptr inbounds i32* %ln4Xz, i32 0 store i32 %ln4Xy, i32* %ln4XA, !tbaa !1 %ln4XB = load i32** %Base_Var %ln4XC = load i32** %Sp_Var %ln4XD = load i32** %Hp_Var %ln4XE = load i32* %R1_Var %ln4XF = load i32* %SpLim_Var tail call cc 10 void (i32*,i32*,i32*,i32,i32,i32,i32,i32)* @__stg_gc_enter_1( i32* %ln4XB, i32* %ln4XC, i32* %ln4XD, i32 %ln4XE, i32 undef, i32 undef, i32 undef, i32 %ln4XF ) nounwind ret void cCZ: %ln4XG = load i32** %Hp_Var %ln4XH = getelementptr inbounds i32* %ln4XG, i32 1 %ln4XI = ptrtoint i32* %ln4XH to i32 %ln4XJ = load i32* %lcDc %ln4XK = sub i32 %ln4XI, %ln4XJ store i32 %ln4XK, i32* %lcD9 %ln4XL = load i32* %lcD9 %ln4XM = ptrtoint [0 x i32]* @stg_PAP_info to i32 %ln4XN = inttoptr i32 %ln4XL to i32* store i32 %ln4XM, i32* %ln4XN, !tbaa !5 %ln4XO = load i32* %lcD9 %ln4XP = add i32 %ln4XO, 4 %ln4XQ = load i32* %lcDb %ln4XR = add i32 %ln4XQ, -1 %ln4XS = trunc i32 %ln4XR to i16 %ln4XT = inttoptr i32 %ln4XP to i16* store i16 %ln4XS, i16* %ln4XT, !tbaa !5 %ln4XU = load i32* %lcD9 %ln4XV = add i32 %ln4XU, 8 %ln4XW = load i32* %R1_Var %ln4XX = inttoptr i32 %ln4XV to i32* store i32 %ln4XW, i32* %ln4XX, !tbaa !5 %ln4XY = load i32* %lcD9 %ln4XZ = add i32 %ln4XY, 6 %ln4Y0 = inttoptr i32 %ln4XZ to i16* store i16 1, i16* %ln4Y0, !tbaa !5 store i32 0, i32* %lcD8 br label %cCW cD0: store i32 16, i32* %lcDc %ln4Y1 = load i32** %Hp_Var %ln4Y2 = ptrtoint i32* %ln4Y1 to i32 %ln4Y3 = load i32* %lcDc %ln4Y4 = add i32 %ln4Y2, %ln4Y3 %ln4Y5 = inttoptr i32 %ln4Y4 to i32* store i32* %ln4Y5, i32** %Hp_Var %ln4Y6 = load i32** %Hp_Var %ln4Y7 = ptrtoint i32* %ln4Y6 to i32 %ln4Y8 = load i32** %Base_Var %ln4Y9 = getelementptr inbounds i32* %ln4Y8, i32 33 %ln4Ya = bitcast i32* %ln4Y9 to i32* %ln4Yb = load i32* %ln4Ya, !tbaa !4 %ln4Yc = icmp ugt i32 %ln4Y7, %ln4Yb br i1 %ln4Yc, label %cCY, label %cCZ cD1: %ln4Yd = load i32* %R1_Var %ln4Ye = load i32* %lcDb %ln4Yf = add i32 %ln4Yd, %ln4Ye store i32 %ln4Yf, i32* %R1_Var br label %cD0 cD3: %ln4Yg = load i32** %Sp_Var %ln4Yh = getelementptr inbounds i32* %ln4Yg, i32 -1 %ln4Yi = ptrtoint i32* %ln4Yh to i32 %ln4Yj = inttoptr i32 %ln4Yi to i32* store i32* %ln4Yj, i32** %Sp_Var %ln4Yk = load i32* %lcDb %ln4Yl = icmp uge i32 %ln4Yk, 4 br i1 %ln4Yl, label %cD0, label %cD1 cD4: %ln4Ym = load i32* %R1_Var %ln4Yn = inttoptr i32 %ln4Ym to i32* %ln4Yo = load i32* %ln4Yn, !tbaa !3 %ln4Yp = add i32 %ln4Yo, -10 %ln4Yq = inttoptr i32 %ln4Yp to i16* %ln4Yr = load i16* %ln4Yq, !tbaa !5 %ln4Ys = sext i16 %ln4Yr to i32 store i32 %ln4Ys, i32* %lcDb %ln4Yt = load i32* %lcDb %ln4Yu = icmp eq i32 %ln4Yt, 1 br i1 %ln4Yu, label %cCS, label %cD3 cD5: %ln4Yv = load i32** %Sp_Var %ln4Yw = getelementptr inbounds i32* %ln4Yv, i32 -1 %ln4Yx = ptrtoint i32* %ln4Yw to i32 %ln4Yy = inttoptr i32 %ln4Yx to i32* store i32* %ln4Yy, i32** %Sp_Var %ln4Yz = load i32** %Base_Var %ln4YA = load i32** %Sp_Var %ln4YB = load i32** %Hp_Var %ln4YC = load i32* %R1_Var %ln4YD = load i32* %SpLim_Var tail call cc 10 void (i32*,i32*,i32*,i32,i32,i32,i32,i32)* @stg_ap_p_info( i32* %ln4Yz, i32* %ln4YA, i32* %ln4YB, i32 %ln4YC, i32 undef, i32 undef, i32 undef, i32 %ln4YD ) nounwind ret void cD6: %ln4YE = load i32** %Sp_Var %ln4YF = ptrtoint i32* %ln4YE to i32 %ln4YG = inttoptr i32 %ln4YF to i32* store i32* %ln4YG, i32** %Sp_Var %ln4YH = load i32* %R1_Var %ln4YI = add i32 %ln4YH, -1 %ln4YJ = inttoptr i32 %ln4YI to i32* %ln4YK = load i32* %ln4YJ, !tbaa !3 %ln4YL = inttoptr i32 %ln4YK to void (i32*, i32*, i32*, i32, i32, i32, i32, i32)* %ln4YM = load i32** %Base_Var %ln4YN = load i32** %Sp_Var %ln4YO = load i32** %Hp_Var %ln4YP = load i32* %R1_Var %ln4YQ = load i32* %SpLim_Var tail call cc 10 void (i32*,i32*,i32*,i32,i32,i32,i32,i32)* %ln4YL( i32* %ln4YM, i32* %ln4YN, i32* %ln4YO, i32 %ln4YP, i32 undef, i32 undef, i32 undef, i32 %ln4YQ ) nounwind ret void cD7: %ln4YR = load i32* %R1_Var %ln4YS = and i32 %ln4YR, -4 store i32 %ln4YS, i32* %R1_Var %ln4YT = load i32* %R1_Var %ln4YU = inttoptr i32 %ln4YT to i32* %ln4YV = load i32* %ln4YU, !tbaa !3 %ln4YW = add i32 %ln4YV, -4 %ln4YX = inttoptr i32 %ln4YW to i16* %ln4YY = load i16* %ln4YX, !tbaa !5 %ln4YZ = sext i16 %ln4YY to i32 switch i32 %ln4YZ, label %cD5 [i32 0, label %cD5 i32 1, label %cD5 i32 2, label %cD5 i32 3, label %cD5 i32 4, label %cD5 i32 5, label %cD5 i32 6, label %cD5 i32 7, label %cD5 i32 8, label %cD5 i32 9, label %cD4 i32 10, label %cD4 i32 11, label %cD4 i32 12, label %cD4 i32 13, label %cD4 i32 14, label %cD4 i32 15, label %cD4 i32 16, label %cD5 i32 17, label %cD5 i32 18, label %cD5 i32 19, label %cD5 i32 20, label %cD5 i32 21, label %cD5 i32 22, label %cD5 i32 23, label %cD5 i32 24, label %cD5 i32 25, label %cD5 i32 26, label %cD5 i32 27, label %cD5 i32 28, label %cD5 i32 29, label %cD5 i32 30, label %cD5 i32 31, label %cD5 i32 32, label %cD5 i32 33, label %cD5 i32 34, label %cD5 i32 35, label %cD5 i32 36, label %cD5 i32 37, label %cD5 i32 38, label %cD5 i32 39, label %cD5 i32 40, label %cD5 i32 41, label %cD5 i32 42, label %cD5 i32 43, label %cD5 i32 44, label %cD5 i32 45, label %cD5 i32 46, label %cD5 i32 47, label %cD5 i32 48, label %cD5 i32 49, label %cD5 i32 50, label %cD5 i32 51, label %cD5 i32 52, label %cD5 i32 53, label %cD5 i32 54, label %cD5 i32 55, label %cD5 i32 56, label %cD5 i32 57, label %cD5 i32 58, label %cD5 i32 59, label %cD5 i32 60, label %cD5 i32 61, label %cD5] } }}} Here are the closure types: {{{ static char *closure_type_names[] = { "INVALID_OBJECT", /* 0 */ "CONSTR", /* 1 */ "CONSTR_1_0", /* 2 */ "CONSTR_0_1", /* 3 */ "CONSTR_2_0", /* 4 */ "CONSTR_1_1", /* 5 */ "CONSTR_0_2", /* 6 */ "CONSTR_INTLIKE", /* 7 */ "CONSTR_CHARLIKE", /* 8 */ "CONSTR_STATIC", /* 9 */ "CONSTR_NOCAF_STATIC", /* 10 */ "FUN", /* 11 */ "FUN_1_0", /* 12 */ "FUN_0_1", /* 13 */ "FUN_2_0", /* 14 */ "FUN_1_1", /* 15 */ "FUN_0_2", /* 16 */ "FUN_STATIC", /* 17 */ "THUNK", /* 18 */ "THUNK_1_0", /* 19 */ "THUNK_0_1", /* 20 */ "THUNK_2_0", /* 21 */ "THUNK_1_1", /* 22 */ "THUNK_0_2", /* 23 */ "THUNK_STATIC", /* 24 */ "THUNK_SELECTOR", /* 25 */ "BCO", /* 26 */ "AP_UPD", /* 27 */ "PAP", /* 28 */ "IND", /* 29 */ "IND_OLDGEN", /* 30 */ "IND_PERM", /* 31 */ "IND_OLDGEN_PERM", /* 32 */ "IND_STATIC", /* 33 */ "CAF_UNENTERED", /* 34 */ "CAF_ENTERED", /* 35 */ "CAF_BLACKHOLE", /* 36 */ "RET_BCO", /* 37 */ "RET_SMALL", /* 38 */ "RET_VEC_SMALL", /* 39 */ "RET_BIG", /* 40 */ "RET_VEC_BIG", /* 41 */ "RET_DYN", /* 42 */ "UPDATE_FRAME", /* 43 */ "CATCH_FRAME", /* 44 */ "STOP_FRAME", /* 45 */ "SEQ_FRAME", /* 46 */ "BLACKHOLE", /* 47 */ "BLACKHOLE_BQ", /* 48 */ "SE_BLACKHOLE", /* 49 */ "SE_CAF_BLACKHOLE", /* 50 */ "MVAR", /* 51 */ "ARR_WORDS", /* 52 */ "MUT_ARR_PTRS", /* 53 */ "MUT_ARR_PTRS_FROZEN", /* 54 */ "MUT_VAR", /* 55 */ "WEAK", /* 56 */ "FOREIGN", /* 57 */ "STABLE_NAME", /* 58 */ "TSO", /* 59 */ "BLOCKED_FETCH", /* 60 */ "FETCH_ME", /* 61 */ "FETCH_ME_BQ", /* 62 */ "RBH", /* 63 */ "EVACUATED", /* 64 */ "REMOTE_REF", /* 65 */ "N_CLOSURE_TYPES" /* 66 */ }; }}} -- Ticket URL: http://hackage.haskell.org/trac/ghc/ticket/7640#comment:4 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler