From 6331df3c5654135605e9dd266df8124b168032f5 Mon Sep 17 00:00:00 2001 From: imhameed Date: Thu, 9 Dec 2021 07:20:52 -0800 Subject: [PATCH] [mono] Support LLVM inline assembly. (#62558) This change adds a convenience function, named `mono_llvm_inline_asm`, that wraps `LLVMGetInlineAsm` and `LLVMBuildCall2`. Inline assembly isn't used right now for normal code generation. But this can be used to ease debugging and development by inserting easy-to-find markers in the generated code. Towards that end, this change also adds a convenience `LLVMTypeRef`, named `void_func_t`, that denotes a function type that takes no parameters and does not return a value. Example: mono_llvm_inline_asm (builder, void_func_t, "int $$0x3", "", LLVM_ASM_SIDE_EFFECT, NULL, 0, ""); --- src/mono/mono/mini/mini-llvm-cpp.cpp | 23 +++++++++++++++++++++++ src/mono/mono/mini/mini-llvm-cpp.h | 11 +++++++++++ src/mono/mono/mini/mini-llvm.c | 4 ++++ 3 files changed, 38 insertions(+) diff --git a/src/mono/mono/mini/mini-llvm-cpp.cpp b/src/mono/mono/mini/mini-llvm-cpp.cpp index ece236a5350d1a..d2bf4eb7c77421 100644 --- a/src/mono/mono/mini/mini-llvm-cpp.cpp +++ b/src/mono/mono/mini/mini-llvm-cpp.cpp @@ -755,3 +755,26 @@ unsigned int mono_llvm_get_prim_size_bits (LLVMTypeRef type) { return unwrap (type)->getPrimitiveSizeInBits (); } + +/* + * Inserts a call to a fragment of inline assembly. + * + * Return values correspond to output constraints. Parameter values correspond + * to input constraints. Example of use: + * mono_llvm_inline_asm (builder, void_func_t, "int $$0x3", "", LLVM_ASM_SIDE_EFFECT, NULL, 0, ""); + */ +LLVMValueRef +mono_llvm_inline_asm (LLVMBuilderRef builder, LLVMTypeRef type, + const char *asmstr, const char *constraints, + MonoLLVMAsmFlags flags, LLVMValueRef *args, unsigned num_args, + const char *name) +{ + const auto asmstr_len = strlen (asmstr); + const auto constraints_len = strlen (constraints); + const auto asmval = LLVMGetInlineAsm (type, + const_cast(asmstr), asmstr_len, + const_cast(constraints), constraints_len, + (flags & LLVM_ASM_SIDE_EFFECT) != 0, (flags & LLVM_ASM_ALIGN_STACK) != 0, + LLVMInlineAsmDialectATT); + return LLVMBuildCall2 (builder, type, asmval, args, num_args, name); +} diff --git a/src/mono/mono/mini/mini-llvm-cpp.h b/src/mono/mono/mini/mini-llvm-cpp.h index 27f561505d5111..aaf2ef031f30eb 100644 --- a/src/mono/mono/mini/mini-llvm-cpp.h +++ b/src/mono/mono/mini/mini-llvm-cpp.h @@ -220,6 +220,17 @@ mono_llvm_register_overloaded_intrinsic (LLVMModuleRef module, IntrinsicId id, L unsigned int mono_llvm_get_prim_size_bits (LLVMTypeRef type); +typedef enum { + LLVM_ASM_SIDE_EFFECT = 1 << 0, + LLVM_ASM_ALIGN_STACK = 1 << 1, +} MonoLLVMAsmFlags; + +LLVMValueRef +mono_llvm_inline_asm (LLVMBuilderRef builder, LLVMTypeRef type, + const char *asmstr, const char *constraints, + MonoLLVMAsmFlags flags, LLVMValueRef *args, unsigned num_args, + const char *name); + G_END_DECLS #endif /* __MONO_MINI_LLVM_CPP_H__ */ diff --git a/src/mono/mono/mini/mini-llvm.c b/src/mono/mono/mini/mini-llvm.c index 5830c336da380a..4193900b324c53 100644 --- a/src/mono/mono/mini/mini-llvm.c +++ b/src/mono/mono/mini/mini-llvm.c @@ -318,6 +318,8 @@ static LLVMTypeRef sse_i1_t, sse_i2_t, sse_i4_t, sse_i8_t, sse_r4_t, sse_r8_t; static LLVMTypeRef v64_i1_t, v64_i2_t, v64_i4_t, v64_i8_t, v64_r4_t, v64_r8_t; static LLVMTypeRef v128_i1_t, v128_i2_t, v128_i4_t, v128_i8_t, v128_r4_t, v128_r8_t; +static LLVMTypeRef void_func_t; + static MonoLLVMModule *init_jit_module (void); static void emit_dbg_loc (EmitContext *ctx, LLVMBuilderRef builder, const unsigned char *cil_code); @@ -12404,6 +12406,8 @@ mono_llvm_init (gboolean enable_jit) intrins_id_to_intrins = g_hash_table_new (NULL, NULL); + void_func_t = LLVMFunctionType0 (LLVMVoidType (), FALSE); + if (enable_jit) mono_llvm_jit_init (); }