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
5 changes: 5 additions & 0 deletions IRBindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "IRBindings.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/Function.h"
Expand All @@ -27,6 +28,10 @@ LLVMMetadataRef LLVMConstantAsMetadata(LLVMValueRef C) {
return wrap(ConstantAsMetadata::get(unwrap<Constant>(C)));
}

LLVMValueRef LLVMGoConstTokenNone(LLVMContextRef C) {
return wrap(ConstantTokenNone::get(*unwrap(C)));
}

LLVMMetadataRef LLVMMDString2(LLVMContextRef C, const char *Str, unsigned SLen) {
return wrap(MDString::get(*unwrap(C), StringRef(Str, SLen)));
}
Expand Down
2 changes: 2 additions & 0 deletions IRBindings.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ struct LLVMDebugLocMetadata{

LLVMMetadataRef LLVMConstantAsMetadata(LLVMValueRef Val);

LLVMValueRef LLVMGoConstTokenNone(LLVMContextRef C);

LLVMMetadataRef LLVMMDString2(LLVMContextRef C, const char *Str, unsigned SLen);
LLVMMetadataRef LLVMMDNode2(LLVMContextRef C, LLVMMetadataRef *MDs,
unsigned Count);
Expand Down
6 changes: 6 additions & 0 deletions ir.go
Original file line number Diff line number Diff line change
Expand Up @@ -829,6 +829,12 @@ func (v Value) SetOperand(i int, op Value) { C.LLVMSetOperand(v.C, C.unsigned(i)
func (v Value) OperandsCount() int { return int(C.LLVMGetNumOperands(v.C)) }

// Operations on constants of any type
// ConstTokenNone returns the empty token constant owned by c.
func (c Context) ConstTokenNone() (v Value) {
v.C = C.LLVMGoConstTokenNone(c.C)
return
}

func ConstNull(t Type) (v Value) { v.C = C.LLVMConstNull(t.C); return }
func ConstAllOnes(t Type) (v Value) { v.C = C.LLVMConstAllOnes(t.C); return }
func Undef(t Type) (v Value) { v.C = C.LLVMGetUndef(t.C); return }
Expand Down
71 changes: 71 additions & 0 deletions ir_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,77 @@ func TestIntrinsicBindings(t *testing.T) {
}
}

func TestConstTokenNoneWithCoroutineIntrinsics(t *testing.T) {
ctx := NewContext()
defer ctx.Dispose()

none := ctx.ConstTokenNone()
if none.IsNil() {
t.Fatal("ConstTokenNone returned a nil value")
}
if got := none.Type(); got != ctx.TokenType() || got.TypeKind() != TokenTypeKind {
t.Fatalf("ConstTokenNone type = %v (kind %v), want token", got, got.TypeKind())
}
if got := strings.TrimSpace(none.String()); got != "token none" {
t.Fatalf("ConstTokenNone string = %q, want %q", got, "token none")
}

majorVersion, err := strconv.Atoi(strings.SplitN(Version, ".", 2)[0])
if err != nil {
t.Fatalf("could not parse LLVM version: %v", err)
}

mod := ctx.NewModule("coro-token-none")
defer mod.Dispose()
builder := ctx.NewBuilder()
defer builder.Dispose()

ptrTy := PointerType(ctx.Int8Type(), 0)
fn := AddFunction(mod, "use_token_none", FunctionType(ctx.VoidType(), []Type{ptrTy}, false))
builder.SetInsertPointAtEnd(ctx.AddBasicBlock(fn, "entry"))
falseValue := ConstInt(ctx.Int1Type(), 0, false)

suspendID := LookupIntrinsicID("llvm.coro.suspend")
if suspendID == 0 {
t.Fatal("could not look up llvm.coro.suspend intrinsic")
}
suspend := builder.CreateIntrinsic(ctx.Int8Type(), suspendID, []Value{none, falseValue}, "suspend")
if suspend.IsNil() {
t.Fatal("could not construct llvm.coro.suspend with token none")
}

// LLVM 18 added the unwind token operand to llvm.coro.end. LLVM 22
// subsequently changed only its result type from i1 to void.
if majorVersion >= 18 {
endID := LookupIntrinsicID("llvm.coro.end")
if endID == 0 {
t.Fatal("could not look up llvm.coro.end intrinsic")
}
endType := ctx.Int1Type()
endName := "end"
if majorVersion >= 22 {
endType = ctx.VoidType()
endName = ""
}
end := builder.CreateIntrinsic(endType, endID, []Value{fn.Param(0), falseValue, none}, endName)
if end.IsNil() {
t.Fatal("could not construct llvm.coro.end with token none")
}
}
builder.CreateRetVoid()

if err := VerifyModule(mod, ReturnStatusAction); err != nil {
t.Fatalf("module with token-none coroutine operands should verify: %v\n%s", err, mod.String())
}
text := mod.String()
if !strings.Contains(text, "@llvm.coro.suspend(token none, i1 false)") {
t.Fatalf("llvm.coro.suspend did not print token none:\n%s", text)
}
if majorVersion >= 18 && !strings.Contains(text, "i1 false, token none)") {
t.Fatalf("llvm.coro.end did not print token none:\n%s", text)
}
}

func TestSubtypes(t *testing.T) {
cont := NewContext()
defer cont.Dispose()
Expand Down
Loading