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
29 changes: 29 additions & 0 deletions IRBindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -93,6 +94,34 @@ LLVMValueRef LLVMGoGetInlineAsm(LLVMTypeRef Ty, char *AsmString,
Dialect, CanThrow);
}

const char *LLVMGoGetInlineAsmAsmString(LLVMValueRef Asm, size_t *Size) {
StringRef String = unwrap<InlineAsm>(Asm)->getAsmString();
*Size = String.size();
return String.data();
}

const char *LLVMGoGetInlineAsmConstraintString(LLVMValueRef Asm, size_t *Size) {
StringRef String = unwrap<InlineAsm>(Asm)->getConstraintString();
*Size = String.size();
return String.data();
}

LLVMBool LLVMGoInlineAsmHasSideEffects(LLVMValueRef Asm) {
return unwrap<InlineAsm>(Asm)->hasSideEffects();
}

LLVMBool LLVMGoInlineAsmNeedsAlignedStack(LLVMValueRef Asm) {
return unwrap<InlineAsm>(Asm)->isAlignStack();
}

LLVMInlineAsmDialect LLVMGoGetInlineAsmDialect(LLVMValueRef Asm) {
return static_cast<LLVMInlineAsmDialect>(unwrap<InlineAsm>(Asm)->getDialect());
}

LLVMBool LLVMGoInlineAsmCanThrow(LLVMValueRef Asm) {
return unwrap<InlineAsm>(Asm)->canThrow();
}

LLVMValueRef LLVMGoBuildIntrinsicCall(LLVMBuilderRef B, LLVMTypeRef RetTy,
unsigned ID, LLVMValueRef *Args,
unsigned Count, const char *Name) {
Expand Down
7 changes: 7 additions & 0 deletions IRBindings.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
40 changes: 40 additions & 0 deletions ir.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
29 changes: 29 additions & 0 deletions ir_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
Loading