From d611ed143065455f328d73b399706044415c8679 Mon Sep 17 00:00:00 2001 From: Li Jie Date: Sat, 1 Aug 2026 16:49:07 +0800 Subject: [PATCH 1/2] llvm: expose inline assembly properties --- IRBindings.cpp | 29 +++++++++++++++++++++++++++++ IRBindings.h | 7 +++++++ ir.go | 40 ++++++++++++++++++++++++++++++++++++++++ ir_test.go | 29 +++++++++++++++++++++++++++++ 4 files changed, 105 insertions(+) diff --git a/IRBindings.cpp b/IRBindings.cpp index 27dd35c..4852a00 100644 --- a/IRBindings.cpp +++ b/IRBindings.cpp @@ -18,6 +18,7 @@ #include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/Function.h" #include "llvm/IR/IRBuilder.h" +#include "llvm/IR/InlineAsm.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" @@ -93,6 +94,34 @@ LLVMValueRef LLVMGoGetInlineAsm(LLVMTypeRef Ty, char *AsmString, Dialect, CanThrow); } +const char *LLVMGoGetInlineAsmAsmString(LLVMValueRef Asm, size_t *Size) { + const std::string &String = unwrap(Asm)->getAsmString(); + *Size = String.size(); + return String.data(); +} + +const char *LLVMGoGetInlineAsmConstraintString(LLVMValueRef Asm, size_t *Size) { + const std::string &String = unwrap(Asm)->getConstraintString(); + *Size = String.size(); + return String.data(); +} + +LLVMBool LLVMGoInlineAsmHasSideEffects(LLVMValueRef Asm) { + return unwrap(Asm)->hasSideEffects(); +} + +LLVMBool LLVMGoInlineAsmNeedsAlignedStack(LLVMValueRef Asm) { + return unwrap(Asm)->isAlignStack(); +} + +LLVMInlineAsmDialect LLVMGoGetInlineAsmDialect(LLVMValueRef Asm) { + return static_cast(unwrap(Asm)->getDialect()); +} + +LLVMBool LLVMGoInlineAsmCanThrow(LLVMValueRef Asm) { + return unwrap(Asm)->canThrow(); +} + LLVMValueRef LLVMGoBuildIntrinsicCall(LLVMBuilderRef B, LLVMTypeRef RetTy, unsigned ID, LLVMValueRef *Args, unsigned Count, const char *Name) { diff --git a/IRBindings.h b/IRBindings.h index b2356e4..f9d1eb7 100644 --- a/IRBindings.h +++ b/IRBindings.h @@ -57,6 +57,13 @@ LLVMValueRef LLVMGoGetInlineAsm(LLVMTypeRef Ty, char *AsmString, LLVMBool IsAlignStack, LLVMInlineAsmDialect Dialect, LLVMBool CanThrow); +const char *LLVMGoGetInlineAsmAsmString(LLVMValueRef Asm, size_t *Size); +const char *LLVMGoGetInlineAsmConstraintString(LLVMValueRef Asm, size_t *Size); +LLVMBool LLVMGoInlineAsmHasSideEffects(LLVMValueRef Asm); +LLVMBool LLVMGoInlineAsmNeedsAlignedStack(LLVMValueRef Asm); +LLVMInlineAsmDialect LLVMGoGetInlineAsmDialect(LLVMValueRef Asm); +LLVMBool LLVMGoInlineAsmCanThrow(LLVMValueRef Asm); + LLVMValueRef LLVMGoBuildIntrinsicCall(LLVMBuilderRef B, LLVMTypeRef RetTy, unsigned ID, LLVMValueRef *Args, unsigned Count, const char *Name); diff --git a/ir.go b/ir.go index 99a0921..fc94b53 100644 --- a/ir.go +++ b/ir.go @@ -1381,6 +1381,46 @@ func InlineAsm(t Type, asmString, constraints string, hasSideEffects, isAlignSta return } +// InlineAsmString returns the assembly template of an inline-assembly value. +// The receiver must be an inline-assembly value. +func (v Value) InlineAsmString() string { + var size C.size_t + data := C.LLVMGoGetInlineAsmAsmString(v.C, &size) + return C.GoStringN(data, C.int(size)) +} + +// InlineAsmConstraintString returns the constraint string of an +// inline-assembly value. The receiver must be an inline-assembly value. +func (v Value) InlineAsmConstraintString() string { + var size C.size_t + data := C.LLVMGoGetInlineAsmConstraintString(v.C, &size) + return C.GoStringN(data, C.int(size)) +} + +// InlineAsmHasSideEffects reports whether an inline-assembly value is marked +// as having side effects. The receiver must be an inline-assembly value. +func (v Value) InlineAsmHasSideEffects() bool { + return C.LLVMGoInlineAsmHasSideEffects(v.C) != 0 +} + +// InlineAsmNeedsAlignedStack reports whether an inline-assembly value requires +// stack alignment. The receiver must be an inline-assembly value. +func (v Value) InlineAsmNeedsAlignedStack() bool { + return C.LLVMGoInlineAsmNeedsAlignedStack(v.C) != 0 +} + +// InlineAsmDialect returns the dialect of an inline-assembly value. The +// receiver must be an inline-assembly value. +func (v Value) InlineAsmDialect() InlineAsmDialect { + return InlineAsmDialect(C.LLVMGoGetInlineAsmDialect(v.C)) +} + +// InlineAsmCanThrow reports whether an inline-assembly value may unwind. The +// receiver must be an inline-assembly value. +func (v Value) InlineAsmCanThrow() bool { + return C.LLVMGoInlineAsmCanThrow(v.C) != 0 +} + // Operations on aggregates func (v Value) Indices() []uint32 { num := C.LLVMGetNumIndices(v.C) diff --git a/ir_test.go b/ir_test.go index cf70902..82b8208 100644 --- a/ir_test.go +++ b/ir_test.go @@ -175,6 +175,35 @@ func TestIntrinsicBindings(t *testing.T) { } } +func TestInlineAsmIntrospection(t *testing.T) { + ctx := NewContext() + defer ctx.Dispose() + + fnType := FunctionType(ctx.VoidType(), []Type{ctx.Int64Type()}, false) + asm := InlineAsm(fnType, "nop $0", "r,~{memory}", true, true, InlineAsmDialectIntel, true) + if asm.IsAInlineAsm().IsNil() { + t.Fatal("InlineAsm did not produce an inline-assembly value") + } + if got, want := asm.InlineAsmString(), "nop $0"; got != want { + t.Fatalf("InlineAsmString() = %q, want %q", got, want) + } + if got, want := asm.InlineAsmConstraintString(), "r,~{memory}"; got != want { + t.Fatalf("InlineAsmConstraintString() = %q, want %q", got, want) + } + if !asm.InlineAsmHasSideEffects() { + t.Fatal("InlineAsmHasSideEffects() = false, want true") + } + if !asm.InlineAsmNeedsAlignedStack() { + t.Fatal("InlineAsmNeedsAlignedStack() = false, want true") + } + if got, want := asm.InlineAsmDialect(), InlineAsmDialectIntel; got != want { + t.Fatalf("InlineAsmDialect() = %v, want %v", got, want) + } + if !asm.InlineAsmCanThrow() { + t.Fatal("InlineAsmCanThrow() = false, want true") + } +} + func TestConstTokenNoneWithCoroutineIntrinsics(t *testing.T) { ctx := NewContext() defer ctx.Dispose() From 9e7761330bf1e5e483436d051c640bf4196d5d68 Mon Sep 17 00:00:00 2001 From: Li Jie Date: Sat, 1 Aug 2026 16:57:39 +0800 Subject: [PATCH 2/2] llvm: support StringRef inline asm accessors --- IRBindings.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/IRBindings.cpp b/IRBindings.cpp index 4852a00..5b7bb3a 100644 --- a/IRBindings.cpp +++ b/IRBindings.cpp @@ -95,13 +95,13 @@ LLVMValueRef LLVMGoGetInlineAsm(LLVMTypeRef Ty, char *AsmString, } const char *LLVMGoGetInlineAsmAsmString(LLVMValueRef Asm, size_t *Size) { - const std::string &String = unwrap(Asm)->getAsmString(); + StringRef String = unwrap(Asm)->getAsmString(); *Size = String.size(); return String.data(); } const char *LLVMGoGetInlineAsmConstraintString(LLVMValueRef Asm, size_t *Size) { - const std::string &String = unwrap(Asm)->getConstraintString(); + StringRef String = unwrap(Asm)->getConstraintString(); *Size = String.size(); return String.data(); }