-/*
- * mini-llvm.c: llvm "Backend" for the mono JIT
+/**
+ * \file
+ * llvm "Backend" for the mono JIT
*
* Copyright 2009-2011 Novell Inc (http://www.novell.com)
* Copyright 2011 Xamarin Inc (http://www.xamarin.com)
#include "config.h"
#include <mono/metadata/debug-helpers.h>
-#include <mono/metadata/debug-mono-symfile.h>
+#include <mono/metadata/debug-internals.h>
#include <mono/metadata/mempool-internals.h>
#include <mono/metadata/environment.h>
#include <mono/metadata/object-internals.h>
* This is needed on arm64 where HFAs are returned in
* registers.
*/
+ /* SIMD types have size 16 in mono_class_value_size () */
+ if (klass->simd_type)
+ nfields = 16/ esize;
size = nfields;
eltypes = g_new (LLVMTypeRef, size);
for (i = 0; i < size; ++i)
return LLVMInt16Type ();
case MONO_TYPE_U4:
return LLVMInt32Type ();
- case MONO_TYPE_BOOLEAN:
- return LLVMInt8Type ();
case MONO_TYPE_I8:
case MONO_TYPE_U8:
return LLVMInt64Type ();
- case MONO_TYPE_CHAR:
- return LLVMInt16Type ();
case MONO_TYPE_R4:
return LLVMFloatType ();
case MONO_TYPE_R8:
case MONO_TYPE_U:
return IntPtrType ();
case MONO_TYPE_OBJECT:
- case MONO_TYPE_CLASS:
- case MONO_TYPE_ARRAY:
- case MONO_TYPE_SZARRAY:
- case MONO_TYPE_STRING:
case MONO_TYPE_PTR:
return ObjRefType ();
case MONO_TYPE_VAR:
pindex ++;
break;
case LLVMArgAsIArgs:
- param_types [pindex] = LLVMArrayType (IntPtrType (), ainfo->nslots);
+ if (ainfo->esize == 8)
+ param_types [pindex] = LLVMArrayType (LLVMInt64Type (), ainfo->nslots);
+ else
+ param_types [pindex] = LLVMArrayType (IntPtrType (), ainfo->nslots);
pindex ++;
break;
case LLVMArgVtypeByRef:
}
case LLVMArgAsIArgs:
g_assert (addresses [reg]);
- args [pindex] = LLVMBuildLoad (ctx->builder, convert (ctx, addresses [reg], LLVMPointerType (LLVMArrayType (IntPtrType (), ainfo->nslots), 0)), "");
+ if (ainfo->esize == 8)
+ args [pindex] = LLVMBuildLoad (ctx->builder, convert (ctx, addresses [reg], LLVMPointerType (LLVMArrayType (LLVMInt64Type (), ainfo->nslots), 0)), "");
+ else
+ args [pindex] = LLVMBuildLoad (ctx->builder, convert (ctx, addresses [reg], LLVMPointerType (LLVMArrayType (IntPtrType (), ainfo->nslots), 0)), "");
break;
case LLVMArgVtypeAsScalar:
g_assert_not_reached ();
case OP_X86_LEA: {
LLVMValueRef v1, v2;
+ rhs = LLVMBuildSExt (builder, convert (ctx, rhs, LLVMInt32Type ()), LLVMInt64Type (), "");
+
v1 = LLVMBuildMul (builder, convert (ctx, rhs, IntPtrType ()), LLVMConstInt (IntPtrType (), (1 << ins->backend.shift_amount), FALSE), "");
v2 = LLVMBuildAdd (builder, convert (ctx, lhs, IntPtrType ()), v1, "");
values [ins->dreg] = LLVMBuildAdd (builder, v2, LLVMConstInt (IntPtrType (), ins->inst_imm, FALSE), dname);
break;
#endif
}
+ case OP_TLS_GET: {
+#if (defined(TARGET_AMD64) || defined(TARGET_X86)) && defined(__linux__)
+#ifdef TARGET_AMD64
+ // 257 == FS segment register
+ LLVMTypeRef ptrtype = LLVMPointerType (IntPtrType (), 257);
+#else
+ // 256 == GS segment register
+ LLVMTypeRef ptrtype = LLVMPointerType (IntPtrType (), 256);
+#endif
+ // FIXME: XEN
+ values [ins->dreg] = LLVMBuildLoad (builder, LLVMBuildIntToPtr (builder, LLVMConstInt (IntPtrType (), ins->inst_offset, TRUE), ptrtype, ""), "");
+#elif defined(TARGET_AMD64) && defined(TARGET_OSX)
+ /* See mono_amd64_emit_tls_get () */
+ int offset = mono_amd64_get_tls_gs_offset () + (ins->inst_offset * 8);
+
+ // 256 == GS segment register
+ LLVMTypeRef ptrtype = LLVMPointerType (IntPtrType (), 256);
+ values [ins->dreg] = LLVMBuildLoad (builder, LLVMBuildIntToPtr (builder, LLVMConstInt (IntPtrType (), offset, TRUE), ptrtype, ""), "");
+#else
+ set_failure (ctx, "opcode tls-get");
+ break;
+#endif
+
+ break;
+ }
case OP_GC_SAFE_POINT: {
LLVMValueRef val, cmp, callee;
LLVMBasicBlockRef poll_bb, cont_bb;
values [ins->dreg] = LLVMBuildInsertElement (builder, values [ins->sreg1], convert (ctx, values [ins->sreg2], LLVMDoubleType ()), LLVMConstInt (LLVMInt32Type (), ins->inst_c0, FALSE), dname);
break;
-#if 0
- // Requires a later llvm version
+#if LLVM_API_VERSION > 100
case OP_CVTDQ2PD: {
LLVMValueRef indexes [16];
break;
#endif
+#if LLVM_API_VERSION <= 100
case OP_CVTDQ2PD:
+ case OP_CVTPS2PD:
+ case OP_CVTTPS2DQ:
+#endif
case OP_CVTDQ2PS:
case OP_CVTPD2DQ:
case OP_CVTPS2DQ:
case OP_CVTPD2PS:
- case OP_CVTPS2PD:
case OP_CVTTPD2DQ:
- case OP_CVTTPS2DQ:
case OP_EXTRACT_MASK:
case OP_SQRTPS:
case OP_SQRTPD:
static int count = 0;
count ++;
- if (g_getenv ("LLVM_COUNT")) {
- if (count == atoi (g_getenv ("LLVM_COUNT"))) {
+ char *llvm_count_str = g_getenv ("LLVM_COUNT");
+ if (llvm_count_str) {
+ int lcount = atoi (llvm_count_str);
+ g_free (llvm_count_str);
+ if (count == lcount) {
printf ("LAST: %s\n", mono_method_full_name (cfg->method, TRUE));
fflush (stdout);
last = TRUE;
}
- if (count > atoi (g_getenv ("LLVM_COUNT"))) {
+ if (count > lcount) {
set_failure (ctx, "count");
return;
}
guint32 ei_len, i, nested_len;
gpointer *type_info;
gint32 *table;
+ guint8 *unw_info;
/*
* Decode the one element EH table emitted by the MonoException class
fde = (guint8*)eh_frame + fde_offset;
cie = (guint8*)table;
- mono_unwind_decode_llvm_mono_fde (fde, fde_len, cie, cfg->native_code, &info);
+ /* Compute lengths */
+ mono_unwind_decode_llvm_mono_fde (fde, fde_len, cie, cfg->native_code, &info, NULL, NULL, NULL);
+
+ ei = (MonoJitExceptionInfo *)g_malloc0 (info.ex_info_len * sizeof (MonoJitExceptionInfo));
+ type_info = (gpointer *)g_malloc0 (info.ex_info_len * sizeof (gpointer));
+ unw_info = (guint8*)g_malloc0 (info.unw_info_len);
+
+ mono_unwind_decode_llvm_mono_fde (fde, fde_len, cie, cfg->native_code, &info, ei, type_info, unw_info);
- cfg->encoded_unwind_ops = info.unw_info;
+ cfg->encoded_unwind_ops = unw_info;
cfg->encoded_unwind_ops_len = info.unw_info_len;
if (cfg->verbose_level > 1)
mono_print_unwind_info (cfg->encoded_unwind_ops, cfg->encoded_unwind_ops_len);
cfg->llvm_this_offset = info.this_offset;
}
- ei = info.ex_info;
ei_len = info.ex_info_len;
- type_info = info.type_info;
// Nested clauses are currently disabled
nested_len = 0;
if (!minfo)
return NULL;
- mono_debug_symfile_get_seq_points (minfo, &source_file, NULL, NULL, &sym_seq_points, &n_seq_points);
+ mono_debug_get_seq_points (minfo, &source_file, NULL, NULL, &sym_seq_points, &n_seq_points);
if (!source_file)
source_file = g_strdup ("<unknown>");
dir = g_path_get_dirname (source_file);
MonoDebugSourceLocation *loc;
LLVMValueRef loc_md;
- loc = mono_debug_symfile_lookup_location (ctx->minfo, cil_code - cfg->header->code);
+ loc = mono_debug_method_lookup_location (ctx->minfo, cil_code - cfg->header->code);
if (loc) {
#if LLVM_API_VERSION > 100
loc_md = LLVMMDNode (md_args, nmd_args);
LLVMSetCurrentDebugLocation (builder, loc_md);
#endif
- mono_debug_symfile_free_location (loc);
+ mono_debug_free_source_location (loc);
}
}
}
The mono JIT uses pointer sized iregs/double fregs, while LLVM uses precisely
typed registers, so we have to keep track of the precise LLVM type of each vreg.
This is made easier because the IR is already in SSA form.
- An additional problem is that our IR is not consistent with types, i.e. i32/ia64
+ An additional problem is that our IR is not consistent with types, i.e. i32/i64
types are frequently used incorrectly.
*/