From 42606782799174644855b10b5c5d78ea7b72d619 Mon Sep 17 00:00:00 2001 From: Imran Hameed Date: Wed, 25 Dec 2019 14:17:15 -0800 Subject: [PATCH] Use byte-aligned LLVM loads and stores for unaligned mini IR loads and stores. Should fix https://github.com/mono/mono/issues/18221. --- mono/mini/mini-llvm.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/mono/mini/mini-llvm.c b/mono/mini/mini-llvm.c index da8e6d7fc679..e9d350da6fd6 100644 --- a/mono/mini/mini-llvm.c +++ b/mono/mini/mini-llvm.c @@ -5761,6 +5761,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) gboolean sext = FALSE, zext = FALSE; gboolean is_faulting = (ins->flags & MONO_INST_FAULT) != 0; gboolean is_volatile = (ins->flags & MONO_INST_VOLATILE) != 0; + gboolean is_unaligned = (ins->flags & MONO_INST_UNALIGNED) != 0; t = load_store_to_llvm_type (ins->opcode, &size, &sext, &zext); @@ -5793,7 +5794,10 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) addr = convert (ctx, addr, LLVMPointerType (t, 0)); - values [ins->dreg] = emit_load (ctx, bb, &builder, size, addr, base, dname, is_faulting, is_volatile, LLVM_BARRIER_NONE); + if (is_unaligned) + values [ins->dreg] = mono_llvm_build_aligned_load (builder, addr, dname, is_volatile, 1); + else + values [ins->dreg] = emit_load (ctx, bb, &builder, size, addr, base, dname, is_faulting, is_volatile, LLVM_BARRIER_NONE); if (!(is_faulting || is_volatile) && (ins->flags & MONO_INST_INVARIANT_LOAD)) { /* @@ -5811,7 +5815,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) values [ins->dreg] = LLVMBuildFPExt (builder, values [ins->dreg], LLVMDoubleType (), dname); break; } - + case OP_STOREI1_MEMBASE_REG: case OP_STOREI2_MEMBASE_REG: case OP_STOREI4_MEMBASE_REG: @@ -5825,6 +5829,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) gboolean sext = FALSE, zext = FALSE; gboolean is_faulting = (ins->flags & MONO_INST_FAULT) != 0; gboolean is_volatile = (ins->flags & MONO_INST_VOLATILE) != 0; + gboolean is_unaligned = (ins->flags & MONO_INST_UNALIGNED) != 0; if (!values [ins->inst_destbasereg]) { set_failure (ctx, "inst_destbasereg"); @@ -5842,13 +5847,19 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset, FALSE); addr = LLVMBuildGEP (builder, convert (ctx, base, LLVMPointerType (LLVMInt8Type (), 0)), &index, 1, ""); } else { - index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset / size, FALSE); + index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset / size, FALSE); addr = LLVMBuildGEP (builder, convert (ctx, base, LLVMPointerType (t, 0)), &index, 1, ""); } if (is_volatile && LLVMGetInstructionOpcode (base) == LLVMAlloca && !(ins->flags & MONO_INST_VOLATILE)) /* Storing to an alloca cannot fail */ is_volatile = FALSE; - emit_store (ctx, bb, &builder, size, convert (ctx, values [ins->sreg1], t), convert (ctx, addr, LLVMPointerType (t, 0)), base, is_faulting, is_volatile); + LLVMValueRef srcval = convert (ctx, values [ins->sreg1], t); + LLVMValueRef ptrdst = convert (ctx, addr, LLVMPointerType (t, 0)); + + if (is_unaligned) + mono_llvm_build_aligned_store (builder, srcval, ptrdst, is_volatile, 1); + else + emit_store (ctx, bb, &builder, size, srcval, ptrdst, base, is_faulting, is_volatile); break; } @@ -5863,6 +5874,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) gboolean sext = FALSE, zext = FALSE; gboolean is_faulting = (ins->flags & MONO_INST_FAULT) != 0; gboolean is_volatile = (ins->flags & MONO_INST_VOLATILE) != 0; + gboolean is_unaligned = (ins->flags & MONO_INST_UNALIGNED) != 0; t = load_store_to_llvm_type (ins->opcode, &size, &sext, &zext); @@ -5875,10 +5887,15 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset, FALSE); addr = LLVMBuildGEP (builder, convert (ctx, base, LLVMPointerType (LLVMInt8Type (), 0)), &index, 1, ""); } else { - index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset / size, FALSE); + index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset / size, FALSE); addr = LLVMBuildGEP (builder, convert (ctx, base, LLVMPointerType (t, 0)), &index, 1, ""); } - emit_store (ctx, bb, &builder, size, convert (ctx, LLVMConstInt (IntPtrType (), ins->inst_imm, FALSE), t), convert (ctx, addr, LLVMPointerType (t, 0)), base, is_faulting, is_volatile); + LLVMValueRef srcval = convert (ctx, LLVMConstInt (IntPtrType (), ins->inst_imm, FALSE), t); + LLVMValueRef ptrdst = convert (ctx, addr, LLVMPointerType (t, 0)); + if (is_unaligned) + mono_llvm_build_aligned_store (builder, srcval, ptrdst, is_volatile, 1); + else + emit_store (ctx, bb, &builder, size, srcval, ptrdst, base, is_faulting, is_volatile); break; }