Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/mono/mono/mini/mini-arm.c
Original file line number Diff line number Diff line change
Expand Up @@ -2311,10 +2311,13 @@ mono_arch_get_llvm_call_info (MonoCompile *cfg, MonoMethodSignature *sig)
* in 1 or 2 integer registers.
*/
switch (cinfo->ret.storage) {
case RegTypeGeneral:
case RegTypeNone:
linfo->ret.storage = LLVMArgNone;
break;
case RegTypeGeneral:
case RegTypeFP:
case RegTypeIRegPair:
linfo->ret.storage = LLVMArgNormal;
break;
case RegTypeStructByAddr:
if (sig->pinvoke) {
Expand Down
3 changes: 3 additions & 0 deletions src/mono/mono/mini/mini-arm64.c
Original file line number Diff line number Diff line change
Expand Up @@ -2451,7 +2451,10 @@ mono_arch_get_llvm_call_info (MonoCompile *cfg, MonoMethodSignature *sig)
case ArgInIReg:
case ArgInFReg:
case ArgInFRegR4:
linfo->ret.storage = LLVMArgNormal;
break;
case ArgNone:
linfo->ret.storage = LLVMArgNone;
break;
case ArgVtypeByRef:
linfo->ret.storage = LLVMArgVtypeByRef;
Expand Down
108 changes: 57 additions & 51 deletions src/mono/mono/mini/mini-llvm.c
Original file line number Diff line number Diff line change
Expand Up @@ -5657,46 +5657,65 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)

case OP_SETRET:
switch (linfo->ret.storage) {
case LLVMArgVtypeInReg: {
case LLVMArgNormal:
case LLVMArgVtypeInReg:
case LLVMArgVtypeAsScalar: {
LLVMTypeRef ret_type = LLVMGetReturnType (LLVMGetElementType (LLVMTypeOf (method)));
LLVMValueRef retval = LLVMGetUndef (ret_type);
if (MONO_CLASS_IS_SIMD (ctx->cfg, mono_class_from_mono_type_internal (sig->ret))) {
/* The return type is an LLVM aggregate type, so a bare bitcast cannot be used to do this conversion. */
int width = mono_type_size (sig->ret, NULL);
int elems = width / TARGET_SIZEOF_VOID_P;
/* The return value might not be set if there is a throw */
LLVMValueRef val = lhs ? LLVMBuildBitCast (builder, lhs, LLVMVectorType (IntPtrType (), elems), "") : LLVMConstNull (LLVMVectorType (IntPtrType (), elems));
for (int i = 0; i < elems; ++i) {
LLVMValueRef element = LLVMBuildExtractElement (builder, val, const_int32 (i), "");
retval = LLVMBuildInsertValue (builder, retval, element, i, "setret_simd_vtype_in_reg");
}
} else {
LLVMValueRef addr = LLVMBuildBitCast (builder, addresses [ins->sreg1], LLVMPointerType (ret_type, 0), "");
for (int i = 0; i < 2; ++i) {
if (linfo->ret.pair_storage [i] == LLVMArgInIReg) {
LLVMValueRef indexes [2], part_addr;

indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
indexes [1] = LLVMConstInt (LLVMInt32Type (), i, FALSE);
part_addr = LLVMBuildGEP (builder, addr, indexes, 2, "");

retval = LLVMBuildInsertValue (builder, retval, LLVMBuildLoad (builder, part_addr, ""), i, "");
} else {
g_assert (linfo->ret.pair_storage [i] == LLVMArgNone);
gboolean src_in_reg = FALSE;
gboolean is_simd = MONO_CLASS_IS_SIMD (ctx->cfg, mono_class_from_mono_type_internal (sig->ret));
switch (linfo->ret.storage) {
case LLVMArgNormal: src_in_reg = TRUE; break;
case LLVMArgVtypeInReg: case LLVMArgVtypeAsScalar: src_in_reg = is_simd; break;
}
if (src_in_reg && (!lhs || ctx->is_dead [ins->sreg1])) {
/*
* The method did not set its return value, probably because it
* ends with a throw.
*/
LLVMBuildRet (builder, retval);
break;
}
switch (linfo->ret.storage) {
case LLVMArgNormal:
retval = convert (ctx, lhs, type_to_llvm_type (ctx, sig->ret));
break;
case LLVMArgVtypeInReg:
if (is_simd) {
/* The return type is an LLVM aggregate type, so a bare bitcast cannot be used to do this conversion. */
int width = mono_type_size (sig->ret, NULL);
int elems = width / TARGET_SIZEOF_VOID_P;
/* The return value might not be set if there is a throw */
LLVMValueRef val = LLVMBuildBitCast (builder, lhs, LLVMVectorType (IntPtrType (), elems), "");
for (int i = 0; i < elems; ++i) {
LLVMValueRef element = LLVMBuildExtractElement (builder, val, const_int32 (i), "");
retval = LLVMBuildInsertValue (builder, retval, element, i, "setret_simd_vtype_in_reg");
}
} else {
LLVMValueRef addr = LLVMBuildBitCast (builder, addresses [ins->sreg1], LLVMPointerType (ret_type, 0), "");
for (int i = 0; i < 2; ++i) {
if (linfo->ret.pair_storage [i] == LLVMArgInIReg) {
LLVMValueRef indexes [2], part_addr;

indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
indexes [1] = LLVMConstInt (LLVMInt32Type (), i, FALSE);
part_addr = LLVMBuildGEP (builder, addr, indexes, 2, "");

retval = LLVMBuildInsertValue (builder, retval, LLVMBuildLoad (builder, part_addr, ""), i, "");
} else {
g_assert (linfo->ret.pair_storage [i] == LLVMArgNone);
}
}
}
}
LLVMBuildRet (builder, retval);
break;
}
case LLVMArgVtypeAsScalar: {
LLVMTypeRef ret_type = LLVMGetReturnType (LLVMGetElementType (LLVMTypeOf (method)));
LLVMValueRef retval = NULL;
if (MONO_CLASS_IS_SIMD (ctx->cfg, mono_class_from_mono_type_internal (sig->ret)))
retval = LLVMBuildBitCast (builder, values [ins->sreg1], ret_type, "setret_simd_vtype_as_scalar");
else {
g_assert (addresses [ins->sreg1]);
retval = LLVMBuildLoad (builder, LLVMBuildBitCast (builder, addresses [ins->sreg1], LLVMPointerType (ret_type, 0), ""), "");
break;
case LLVMArgVtypeAsScalar:
if (is_simd) {
retval = LLVMBuildBitCast (builder, values [ins->sreg1], ret_type, "setret_simd_vtype_as_scalar");
} else {
g_assert (addresses [ins->sreg1]);
retval = LLVMBuildLoad (builder, LLVMBuildBitCast (builder, addresses [ins->sreg1], LLVMPointerType (ret_type, 0), ""), "");
}
break;
}
LLVMBuildRet (builder, retval);
break;
Expand Down Expand Up @@ -5742,26 +5761,13 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
break;
}
case LLVMArgNone:
case LLVMArgNormal: {
if (!lhs || ctx->is_dead [ins->sreg1]) {
/*
* The method did not set its return value, probably because it
* ends with a throw.
*/
if (cfg->vret_addr)
LLVMBuildRetVoid (builder);
else
LLVMBuildRet (builder, LLVMConstNull (type_to_llvm_type (ctx, sig->ret)));
} else {
LLVMBuildRet (builder, convert (ctx, lhs, type_to_llvm_type (ctx, sig->ret)));
}
has_terminator = TRUE;
LLVMBuildRetVoid (builder);
break;
}
default:
g_assert_not_reached ();
break;
}
has_terminator = TRUE;
break;
case OP_ICOMPARE:
case OP_FCOMPARE:
Expand Down