From 40e0286a45c2ff2f08323a53bc0a9e40490facf3 Mon Sep 17 00:00:00 2001 From: Quinton Miller Date: Sun, 28 Jan 2024 13:06:33 +0800 Subject: [PATCH 1/4] Support inline x86 assembly using Intel syntax --- spec/compiler/codegen/asm_spec.cr | 8 ++++++++ src/compiler/crystal/codegen/asm.cr | 2 +- src/llvm/type.cr | 6 +++--- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/spec/compiler/codegen/asm_spec.cr b/spec/compiler/codegen/asm_spec.cr index 2c6b0707699e..289c1455741e 100644 --- a/spec/compiler/codegen/asm_spec.cr +++ b/spec/compiler/codegen/asm_spec.cr @@ -44,5 +44,13 @@ describe "Code gen: asm" do c )).to_i.should eq(42) end + + it "codegens with intel dialect" do + run(<<-CRYSTAL).to_i.should eq(1234) + dst = uninitialized Int32 + asm("mov dword ptr [$0], 1234" :: "r"(pointerof(dst)) :: "intel") + dst + CRYSTAL + end {% end %} end diff --git a/src/compiler/crystal/codegen/asm.cr b/src/compiler/crystal/codegen/asm.cr index f0b3e2f088ab..f0b0a77a9634 100644 --- a/src/compiler/crystal/codegen/asm.cr +++ b/src/compiler/crystal/codegen/asm.cr @@ -53,7 +53,7 @@ class Crystal::CodeGenVisitor fun_type = LLVM::Type.function(input_types, output_type) constraints = constraints.to_s - value = fun_type.inline_asm(node.text, constraints, node.volatile?, node.alignstack?, node.can_throw?) + value = fun_type.inline_asm(node.text, constraints, node.volatile?, node.alignstack?, node.intel?, node.can_throw?) value = LLVM::Function.from_value(value) asm_value = call LLVMTypedFunction.new(fun_type, value), input_values diff --git a/src/llvm/type.cr b/src/llvm/type.cr index 06c36ff5796d..3dd5156c5c60 100644 --- a/src/llvm/type.cr +++ b/src/llvm/type.cr @@ -173,7 +173,7 @@ struct LLVM::Type Value.new LibLLVM.const_array(self, (values.to_unsafe.as(LibLLVM::ValueRef*)), values.size) end - def inline_asm(asm_string, constraints, has_side_effects = false, is_align_stack = false, can_throw = false) + def inline_asm(asm_string, constraints, has_side_effects = false, is_align_stack = false, intel_dialect = false, can_throw = false) value = {% if LibLLVM::IS_LT_130 %} LibLLVM.get_inline_asm( @@ -184,7 +184,7 @@ struct LLVM::Type constraints.size, (has_side_effects ? 1 : 0), (is_align_stack ? 1 : 0), - LibLLVM::InlineAsmDialect::ATT + (intel_dialect ? LibLLVM::InlineAsmDialect::Intel : LibLLVM::InlineAsmDialect::ATT) ) {% else %} LibLLVM.get_inline_asm( @@ -195,7 +195,7 @@ struct LLVM::Type constraints.size, (has_side_effects ? 1 : 0), (is_align_stack ? 1 : 0), - LibLLVM::InlineAsmDialect::ATT, + (intel_dialect ? LibLLVM::InlineAsmDialect::Intel : LibLLVM::InlineAsmDialect::ATT), (can_throw ? 1 : 0) ) {% end %} From 1826e8a71a5cdbf850514b4335063b2703dbecb1 Mon Sep 17 00:00:00 2001 From: Quinton Miller Date: Sun, 28 Jan 2024 20:18:51 +0800 Subject: [PATCH 2/4] Update src/llvm/type.cr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Johannes Müller --- src/llvm/type.cr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llvm/type.cr b/src/llvm/type.cr index 3dd5156c5c60..0f87803b60c2 100644 --- a/src/llvm/type.cr +++ b/src/llvm/type.cr @@ -173,7 +173,7 @@ struct LLVM::Type Value.new LibLLVM.const_array(self, (values.to_unsafe.as(LibLLVM::ValueRef*)), values.size) end - def inline_asm(asm_string, constraints, has_side_effects = false, is_align_stack = false, intel_dialect = false, can_throw = false) + def inline_asm(asm_string, constraints, has_side_effects = false, is_align_stack = false, can_throw = false, *, intel_dialect = false) value = {% if LibLLVM::IS_LT_130 %} LibLLVM.get_inline_asm( From 5ac29fde3febb04ddfe22d6a47e78f3c4440d304 Mon Sep 17 00:00:00 2001 From: Quinton Miller Date: Sun, 28 Jan 2024 20:19:36 +0800 Subject: [PATCH 3/4] Update asm.cr --- src/compiler/crystal/codegen/asm.cr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/crystal/codegen/asm.cr b/src/compiler/crystal/codegen/asm.cr index f0b0a77a9634..d667d7ccc276 100644 --- a/src/compiler/crystal/codegen/asm.cr +++ b/src/compiler/crystal/codegen/asm.cr @@ -53,7 +53,7 @@ class Crystal::CodeGenVisitor fun_type = LLVM::Type.function(input_types, output_type) constraints = constraints.to_s - value = fun_type.inline_asm(node.text, constraints, node.volatile?, node.alignstack?, node.intel?, node.can_throw?) + value = fun_type.inline_asm(node.text, constraints, node.volatile?, node.alignstack?, node.can_throw?, intel_dialect: node.intel?) value = LLVM::Function.from_value(value) asm_value = call LLVMTypedFunction.new(fun_type, value), input_values From c1bc294cf13558e15a8dd201ca263bcf6ec7eeeb Mon Sep 17 00:00:00 2001 From: Quinton Miller Date: Mon, 29 Jan 2024 04:51:14 +0800 Subject: [PATCH 4/4] fixup --- src/compiler/crystal/codegen/asm.cr | 2 +- src/compiler/crystal/codegen/ast.cr | 6 ++++++ src/llvm/enums.cr | 5 +++++ src/llvm/lib_llvm/core.cr | 9 ++------- src/llvm/type.cr | 6 +++--- 5 files changed, 17 insertions(+), 11 deletions(-) diff --git a/src/compiler/crystal/codegen/asm.cr b/src/compiler/crystal/codegen/asm.cr index d667d7ccc276..107d63f19ecf 100644 --- a/src/compiler/crystal/codegen/asm.cr +++ b/src/compiler/crystal/codegen/asm.cr @@ -53,7 +53,7 @@ class Crystal::CodeGenVisitor fun_type = LLVM::Type.function(input_types, output_type) constraints = constraints.to_s - value = fun_type.inline_asm(node.text, constraints, node.volatile?, node.alignstack?, node.can_throw?, intel_dialect: node.intel?) + value = fun_type.inline_asm(node.text, constraints, node.volatile?, node.alignstack?, node.can_throw?, node.dialect) value = LLVM::Function.from_value(value) asm_value = call LLVMTypedFunction.new(fun_type, value), input_values diff --git a/src/compiler/crystal/codegen/ast.cr b/src/compiler/crystal/codegen/ast.cr index 816958844dd9..ab4fa76d4e16 100644 --- a/src/compiler/crystal/codegen/ast.cr +++ b/src/compiler/crystal/codegen/ast.cr @@ -138,4 +138,10 @@ module Crystal found_extern end end + + class Asm + def dialect : LLVM::InlineAsmDialect + intel? ? LLVM::InlineAsmDialect::Intel : LLVM::InlineAsmDialect::ATT + end + end end diff --git a/src/llvm/enums.cr b/src/llvm/enums.cr index b8e06fb46f89..ac23fa711560 100644 --- a/src/llvm/enums.cr +++ b/src/llvm/enums.cr @@ -440,6 +440,11 @@ module LLVM LittleEndian = 1 << 28 end + enum InlineAsmDialect + ATT + Intel + end + struct Value enum Kind Argument diff --git a/src/llvm/lib_llvm/core.cr b/src/llvm/lib_llvm/core.cr index 20f10c7e6e62..c865baaa55a5 100644 --- a/src/llvm/lib_llvm/core.cr +++ b/src/llvm/lib_llvm/core.cr @@ -4,11 +4,6 @@ lib LibLLVM # NOTE: the following C enums usually have different values from their C++ # counterparts (e.g. `LLVMModuleFlagBehavior` v.s. `LLVM::Module::ModFlagBehavior`) - enum InlineAsmDialect - ATT - Intel - end - enum ModuleFlagBehavior Warning = 1 end @@ -39,9 +34,9 @@ lib LibLLVM fun print_module_to_file = LLVMPrintModuleToFile(m : ModuleRef, filename : Char*, error_message : Char**) : Bool fun print_module_to_string = LLVMPrintModuleToString(m : ModuleRef) : Char* {% if !LibLLVM::IS_LT_130 %} - fun get_inline_asm = LLVMGetInlineAsm(ty : TypeRef, asm_string : Char*, asm_string_size : SizeT, constraints : Char*, constraints_size : SizeT, has_side_effects : Bool, is_align_stack : Bool, dialect : InlineAsmDialect, can_throw : Bool) : ValueRef + fun get_inline_asm = LLVMGetInlineAsm(ty : TypeRef, asm_string : Char*, asm_string_size : SizeT, constraints : Char*, constraints_size : SizeT, has_side_effects : Bool, is_align_stack : Bool, dialect : LLVM::InlineAsmDialect, can_throw : Bool) : ValueRef {% else %} - fun get_inline_asm = LLVMGetInlineAsm(t : TypeRef, asm_string : Char*, asm_string_size : SizeT, constraints : Char*, constraints_size : SizeT, has_side_effects : Bool, is_align_stack : Bool, dialect : InlineAsmDialect) : ValueRef + fun get_inline_asm = LLVMGetInlineAsm(t : TypeRef, asm_string : Char*, asm_string_size : SizeT, constraints : Char*, constraints_size : SizeT, has_side_effects : Bool, is_align_stack : Bool, dialect : LLVM::InlineAsmDialect) : ValueRef {% end %} fun get_module_context = LLVMGetModuleContext(m : ModuleRef) : ContextRef diff --git a/src/llvm/type.cr b/src/llvm/type.cr index 0f87803b60c2..c391019aef83 100644 --- a/src/llvm/type.cr +++ b/src/llvm/type.cr @@ -173,7 +173,7 @@ struct LLVM::Type Value.new LibLLVM.const_array(self, (values.to_unsafe.as(LibLLVM::ValueRef*)), values.size) end - def inline_asm(asm_string, constraints, has_side_effects = false, is_align_stack = false, can_throw = false, *, intel_dialect = false) + def inline_asm(asm_string, constraints, has_side_effects = false, is_align_stack = false, can_throw = false, dialect : InlineAsmDialect = InlineAsmDialect::ATT) value = {% if LibLLVM::IS_LT_130 %} LibLLVM.get_inline_asm( @@ -184,7 +184,7 @@ struct LLVM::Type constraints.size, (has_side_effects ? 1 : 0), (is_align_stack ? 1 : 0), - (intel_dialect ? LibLLVM::InlineAsmDialect::Intel : LibLLVM::InlineAsmDialect::ATT) + dialect, ) {% else %} LibLLVM.get_inline_asm( @@ -195,7 +195,7 @@ struct LLVM::Type constraints.size, (has_side_effects ? 1 : 0), (is_align_stack ? 1 : 0), - (intel_dialect ? LibLLVM::InlineAsmDialect::Intel : LibLLVM::InlineAsmDialect::ATT), + dialect, (can_throw ? 1 : 0) ) {% end %}