diff --git a/ssa/coro.go b/ssa/coro.go new file mode 100644 index 00000000..d6183f93 --- /dev/null +++ b/ssa/coro.go @@ -0,0 +1,486 @@ +/* + * Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ssa + +import ( + "go/token" + "go/types" +) + +// declare void @llvm.coro.destroy(i8*) +func (p Program) tyCoDestroy() *types.Signature { + if p.coDestroyTy == nil { + i8Ptr := types.NewParam(token.NoPos, nil, "", p.VoidPtr().raw.Type) + params := types.NewTuple(i8Ptr) + p.coDestroyTy = types.NewSignatureType(nil, nil, nil, params, nil, false) + } + return p.coDestroyTy +} + +// declare void @llvm.coro.resume(i8*) +func (p Program) tyCoResume() *types.Signature { + if p.coResumeTy == nil { + i8Ptr := types.NewParam(token.NoPos, nil, "", p.VoidPtr().raw.Type) + params := types.NewTuple(i8Ptr) + p.coResumeTy = types.NewSignatureType(nil, nil, nil, params, nil, false) + } + return p.coResumeTy +} + +// declare i1 @llvm.coro.done(ptr ) +func (p Program) tyCoDone() *types.Signature { + if p.coDoneTy == nil { + i8Ptr := types.NewParam(token.NoPos, nil, "", p.VoidPtr().raw.Type) + params := types.NewTuple(i8Ptr) + results := types.NewTuple(types.NewParam(token.NoPos, nil, "", p.Bool().raw.Type)) + p.coDoneTy = types.NewSignatureType(nil, nil, nil, params, results, false) + } + return p.coDoneTy +} + +// declare ptr @llvm.coro.promise(ptr , i32 , i1 ) +func (p Program) tyCoPromise() *types.Signature { + if p.coPromiseTy == nil { + i8Ptr := types.NewParam(token.NoPos, nil, "", p.VoidPtr().raw.Type) + i32 := types.NewParam(token.NoPos, nil, "", p.Int32().raw.Type) + boolParam := types.NewParam(token.NoPos, nil, "", p.Bool().raw.Type) + params := types.NewTuple(i8Ptr, i32, boolParam) + results := types.NewTuple(i8Ptr) + p.coPromiseTy = types.NewSignatureType(nil, nil, nil, params, results, false) + } + return p.coPromiseTy +} + +// declare i32 @llvm.coro.size.i32() +func (p Program) tyCoSizeI32() *types.Signature { + if p.coSizeI32Ty == nil { + results := types.NewTuple(types.NewParam(token.NoPos, nil, "", p.Int32().raw.Type)) + p.coSizeI32Ty = types.NewSignatureType(nil, nil, nil, nil, results, false) + } + return p.coSizeI32Ty +} + +// declare i32 @llvm.coro.size.i64() +func (p Program) tyCoSizeI64() *types.Signature { + if p.coSizeI64Ty == nil { + results := types.NewTuple(types.NewParam(token.NoPos, nil, "", p.Int64().raw.Type)) + p.coSizeI64Ty = types.NewSignatureType(nil, nil, nil, nil, results, false) + } + return p.coSizeI64Ty +} + +// declare i32 @llvm.coro.align.i32() +func (p Program) tyCoAlignI32() *types.Signature { + if p.coAlignI32Ty == nil { + results := types.NewTuple(types.NewParam(token.NoPos, nil, "", p.Int32().raw.Type)) + p.coAlignI32Ty = types.NewSignatureType(nil, nil, nil, nil, results, false) + } + return p.coAlignI32Ty +} + +// declare i64 @llvm.coro.align.i64() +func (p Program) tyCoAlignI64() *types.Signature { + if p.coAlignI64Ty == nil { + results := types.NewTuple(types.NewParam(token.NoPos, nil, "", p.Int64().raw.Type)) + p.coAlignI64Ty = types.NewSignatureType(nil, nil, nil, nil, results, false) + } + return p.coAlignI64Ty +} + +// declare i8* @llvm.coro.begin(token, i8*) +func (p Program) tyCoBegin() *types.Signature { + if p.coBeginTy == nil { + tokenParam := types.NewParam(token.NoPos, nil, "", p.Token().raw.Type) + i8Ptr := types.NewParam(token.NoPos, nil, "", p.VoidPtr().raw.Type) + params := types.NewTuple(tokenParam, i8Ptr) + results := types.NewTuple(i8Ptr) + p.coBeginTy = types.NewSignatureType(nil, nil, nil, params, results, false) + } + return p.coBeginTy +} + +// declare i8* @llvm.coro.free(token, i8*) +func (p Program) tyCoFree() *types.Signature { + if p.coFreeTy == nil { + tokenParam := types.NewParam(token.NoPos, nil, "", p.Token().raw.Type) + i8Ptr := types.NewParam(token.NoPos, nil, "", p.VoidPtr().raw.Type) + params := types.NewTuple(tokenParam, i8Ptr) + results := types.NewTuple(i8Ptr) + p.coFreeTy = types.NewSignatureType(nil, nil, nil, params, results, false) + } + return p.coFreeTy +} + +// declare i1 @llvm.coro.alloc(token) +func (p Program) tyCoAlloc() *types.Signature { + if p.coAllocTy == nil { + tokenParam := types.NewParam(token.NoPos, nil, "", p.Token().raw.Type) + params := types.NewTuple(tokenParam) + boolParam := types.NewParam(token.NoPos, nil, "", p.Bool().raw.Type) + results := types.NewTuple(boolParam) + p.coAllocTy = types.NewSignatureType(nil, nil, nil, params, results, false) + } + return p.coAllocTy +} + +// declare ptr @llvm.coro.noop() +func (p Program) tyCoNoop() *types.Signature { + if p.coNoopTy == nil { + results := types.NewTuple(types.NewParam(token.NoPos, nil, "", p.VoidPtr().raw.Type)) + p.coNoopTy = types.NewSignatureType(nil, nil, nil, nil, results, false) + } + return p.coNoopTy +} + +// declare ptr @llvm.coro.frame() +func (p Program) tyCoFrame() *types.Signature { + if p.coFrameTy == nil { + results := types.NewTuple(types.NewParam(token.NoPos, nil, "", p.VoidPtr().raw.Type)) + p.coFrameTy = types.NewSignatureType(nil, nil, nil, nil, results, false) + } + return p.coFrameTy +} + +// declare token @llvm.coro.id(i32, i8*, i8*, i8*) +func (p Program) tyCoID() *types.Signature { + if p.coIDTy == nil { + i32 := types.NewParam(token.NoPos, nil, "", p.Int32().raw.Type) + i8Ptr := types.NewParam(token.NoPos, nil, "", p.VoidPtr().raw.Type) + params := types.NewTuple(i32, i8Ptr, i8Ptr, i8Ptr) + tokenParam := types.NewParam(token.NoPos, nil, "", p.Token().raw.Type) + results := types.NewTuple(tokenParam) + p.coIDTy = types.NewSignatureType(nil, nil, nil, params, results, false) + } + return p.coIDTy +} + +// declare token @llvm.coro.id.async(i32 , i32 , ptr , ptr ) +func (p Program) tyCoIDAsync() *types.Signature { + if p.coIDAsyncTy == nil { + i32 := types.NewParam(token.NoPos, nil, "", p.Int32().raw.Type) + i8Ptr := types.NewParam(token.NoPos, nil, "", p.VoidPtr().raw.Type) + params := types.NewTuple(i32, i32, i8Ptr, i8Ptr) + tokenParam := types.NewParam(token.NoPos, nil, "", p.Token().raw.Type) + results := types.NewTuple(tokenParam) + p.coIDAsyncTy = types.NewSignatureType(nil, nil, nil, params, results, false) + } + return p.coIDAsyncTy +} + +// declare token @llvm.coro.id.retcon(i32 , i32 , ptr , ptr , ptr , ptr ) +func (p Program) tyCoIDRetcon() *types.Signature { + if p.coIDRetconTy == nil { + i32 := types.NewParam(token.NoPos, nil, "", p.Int32().raw.Type) + i8Ptr := types.NewParam(token.NoPos, nil, "", p.VoidPtr().raw.Type) + params := types.NewTuple(i32, i32, i8Ptr, i8Ptr, i8Ptr, i8Ptr) + tokenParam := types.NewParam(token.NoPos, nil, "", p.Token().raw.Type) + results := types.NewTuple(tokenParam) + p.coIDRetconTy = types.NewSignatureType(nil, nil, nil, params, results, false) + } + return p.coIDRetconTy +} + +// declare token @llvm.coro.id.retcon.once(i32 , i32 , ptr , ptr , ptr , ptr ) +func (p Program) tyCoIDRetconOnce() *types.Signature { + if p.coIDRetconOnceTy == nil { + i32 := types.NewParam(token.NoPos, nil, "", p.Int32().raw.Type) + i8Ptr := types.NewParam(token.NoPos, nil, "", p.VoidPtr().raw.Type) + params := types.NewTuple(i32, i32, i8Ptr, i8Ptr, i8Ptr, i8Ptr) + tokenParam := types.NewParam(token.NoPos, nil, "", p.Token().raw.Type) + results := types.NewTuple(tokenParam) + p.coIDRetconOnceTy = types.NewSignatureType(nil, nil, nil, params, results, false) + } + return p.coIDRetconOnceTy +} + +// declare i1 @llvm.coro.end(i8*, i1, token) +func (p Program) tyCoEnd() *types.Signature { + if p.coEndTy == nil { + i8Ptr := types.NewParam(token.NoPos, nil, "", p.VoidPtr().raw.Type) + boolParam := types.NewParam(token.NoPos, nil, "", p.Bool().raw.Type) + tokenParam := types.NewParam(token.NoPos, nil, "", p.Token().raw.Type) + params := types.NewTuple(i8Ptr, boolParam, tokenParam) + results := types.NewTuple(boolParam) + p.coEndTy = types.NewSignatureType(nil, nil, nil, params, results, false) + } + return p.coEndTy +} + +// TODO(lijie): varargs +// declare token @llvm.coro.end.results(...) +func (p Program) tyCoEndResults() *types.Signature { + panic("not implemented") +} + +// TODO(lijie): varargs +// declare i1 @llvm.coro.end.async(ptr , i1 , ...) +func (p Program) tyCoEndAsync() *types.Signature { + panic("not implemented") +} + +// declare i8 @llvm.coro.suspend(token , i1 ) +func (p Program) tyCoSuspend() *types.Signature { + if p.coSuspendTy == nil { + tokenParam := types.NewParam(token.NoPos, nil, "", p.Token().raw.Type) + boolParam := types.NewParam(token.NoPos, nil, "", p.Bool().raw.Type) + params := types.NewTuple(tokenParam, boolParam) + paramByte := types.NewParam(token.NoPos, nil, "", p.Byte().raw.Type) + results := types.NewTuple(paramByte) + p.coSuspendTy = types.NewSignatureType(nil, nil, nil, params, results, false) + } + return p.coSuspendTy +} + +// declare token @llvm.coro.save(ptr ) +func (p Program) tyCoSave() *types.Signature { + if p.coSaveTy == nil { + i8Ptr := types.NewParam(token.NoPos, nil, "", p.VoidPtr().raw.Type) + params := types.NewTuple(i8Ptr) + tokenParam := types.NewParam(token.NoPos, nil, "", p.Token().raw.Type) + results := types.NewTuple(tokenParam) + p.coSaveTy = types.NewSignatureType(nil, nil, nil, params, results, false) + } + return p.coSaveTy +} + +// TODO(lijie): varargs +// declare {ptr, ptr, ptr} @llvm.coro.suspend.async(ptr , ptr , ... ... ) +func (p Program) tyCoSuspendAsync() *types.Signature { + panic("not implemented") +} + +// declare ptr @llvm.coro.prepare.async(ptr ) +func (p Program) tyCoPrepareAsync() *types.Signature { + if p.coPrepareAsyncTy == nil { + i8Ptr := types.NewParam(token.NoPos, nil, "", p.VoidPtr().raw.Type) + params := types.NewTuple(i8Ptr) + results := types.NewTuple(i8Ptr) + p.coPrepareAsyncTy = types.NewSignatureType(nil, nil, nil, params, results, false) + } + return p.coPrepareAsyncTy +} + +// declare i1 @llvm.coro.suspend.retcon(...) +func (p Program) tyCoSuspendRetcon() *types.Signature { + panic("not implemented") +} + +// declare void @await_suspend_function(ptr %awaiter, ptr %hdl) +func (p Program) tyCoAwaitSuspendFunction() *types.Signature { + if p.coAwaitSuspendFunctionTy == nil { + i8Ptr := types.NewParam(token.NoPos, nil, "", p.VoidPtr().raw.Type) + params := types.NewTuple(i8Ptr, i8Ptr) + p.coAwaitSuspendFunctionTy = types.NewSignatureType(nil, nil, nil, params, nil, false) + } + return p.coAwaitSuspendFunctionTy +} + +// declare void @llvm.coro.await.suspend.void(ptr , ptr , ptr ) +func (p Program) tyCoAwaitSuspendVoid() *types.Signature { + if p.coAwaitSuspendVoidTy == nil { + i8Ptr := types.NewParam(token.NoPos, nil, "", p.VoidPtr().raw.Type) + params := types.NewTuple(i8Ptr, i8Ptr, i8Ptr) + p.coAwaitSuspendVoidTy = types.NewSignatureType(nil, nil, nil, params, nil, false) + } + return p.coAwaitSuspendVoidTy +} + +// declare i1 @llvm.coro.await.suspend.bool(ptr , ptr , ptr ) +func (p Program) tyCoAwaitSuspendBool() *types.Signature { + if p.coAwaitSuspendBoolTy == nil { + i8Ptr := types.NewParam(token.NoPos, nil, "", p.VoidPtr().raw.Type) + params := types.NewTuple(i8Ptr, i8Ptr, i8Ptr) + results := types.NewTuple(types.NewParam(token.NoPos, nil, "", p.Bool().raw.Type)) + p.coAwaitSuspendBoolTy = types.NewSignatureType(nil, nil, nil, params, results, false) + } + return p.coAwaitSuspendBoolTy +} + +// declare void @llvm.coro.await.suspend.handle(ptr , ptr , ptr ) +func (p Program) tyCoAwaitSuspendHandle() *types.Signature { + if p.coAwaitSuspendHandleTy == nil { + i8Ptr := types.NewParam(token.NoPos, nil, "", p.VoidPtr().raw.Type) + params := types.NewTuple(i8Ptr, i8Ptr, i8Ptr) + p.coAwaitSuspendHandleTy = types.NewSignatureType(nil, nil, nil, params, nil, false) + } + return p.coAwaitSuspendHandleTy +} + +// ----------------------------------------------------------------------------- + +// declare void @llvm.coro.destroy(ptr ) +func (b Builder) CoDestroy(hdl Expr) { + fn := b.Pkg.cFunc("llvm.coro.destroy", b.Prog.tyCoDestroy()) + b.Call(fn, hdl) +} + +// declare void @llvm.coro.resume(ptr ) +func (b Builder) CoResume(hdl Expr) { + fn := b.Pkg.cFunc("llvm.coro.resume", b.Prog.tyCoResume()) + b.Call(fn, hdl) +} + +// declare i1 @llvm.coro.done(ptr ) +func (b Builder) CoDone(hdl Expr) Expr { + fn := b.Pkg.cFunc("llvm.coro.done", b.Prog.tyCoDone()) + return b.Call(fn, hdl) +} + +// declare ptr @llvm.coro.promise(ptr , i32 , i1 ) +func (b Builder) CoPromise(ptr, align, from Expr) Expr { + fn := b.Pkg.cFunc("llvm.coro.promise", b.Prog.tyCoPromise()) + return b.Call(fn, ptr, align, from) +} + +// declare i32 @llvm.coro.size.i32() +func (b Builder) CoSizeI32() Expr { + fn := b.Pkg.cFunc("llvm.coro.size.i32", b.Prog.tyCoSizeI32()) + return b.Call(fn) +} + +// declare i64 @llvm.coro.size.i64() +func (b Builder) CoSizeI64() Expr { + fn := b.Pkg.cFunc("llvm.coro.size.i64", b.Prog.tyCoSizeI64()) + return b.Call(fn) +} + +// declare i32 @llvm.coro.align.i32() +func (b Builder) CoAlignI32() Expr { + fn := b.Pkg.cFunc("llvm.coro.align.i32", b.Prog.tyCoAlignI32()) + return b.Call(fn) +} + +// declare i64 @llvm.coro.align.i64() +func (b Builder) CoAlignI64() Expr { + fn := b.Pkg.cFunc("llvm.coro.align.i64", b.Prog.tyCoAlignI64()) + return b.Call(fn) +} + +// declare ptr @llvm.coro.begin(token , ptr ) +func (b Builder) CoBegin(id, mem Expr) Expr { + fn := b.Pkg.cFunc("llvm.coro.begin", b.Prog.tyCoBegin()) + return b.Call(fn, id, mem) +} + +// declare ptr @llvm.coro.free(token %id, ptr ) +func (b Builder) CoFree(id, frame Expr) Expr { + fn := b.Pkg.cFunc("llvm.coro.free", b.Prog.tyCoFree()) + return b.Call(fn, id, frame) +} + +// declare i1 @llvm.coro.alloc(token ) +func (b Builder) CoAlloc(id Expr) Expr { + fn := b.Pkg.cFunc("llvm.coro.alloc", b.Prog.tyCoAlloc()) + return b.Call(fn, id) +} + +// declare ptr @llvm.coro.noop() +func (b Builder) CoNoop() Expr { + fn := b.Pkg.cFunc("llvm.coro.noop", b.Prog.tyCoNoop()) + return b.Call(fn) +} + +// declare ptr @llvm.coro.frame() +func (b Builder) CoFrame() Expr { + fn := b.Pkg.cFunc("llvm.coro.frame", b.Prog.tyCoFrame()) + return b.Call(fn) +} + +// declare token @llvm.coro.id(i32 , ptr , ptr , ptr ) +func (b Builder) CoID(align Expr, promise, coroAddr, fnAddrs Expr) Expr { + fn := b.Pkg.cFunc("llvm.coro.id", b.Prog.tyCoID()) + return b.Call(fn, align, promise, coroAddr, fnAddrs) +} + +// declare token @llvm.coro.id.async(i32 , i32 , ptr , ptr ) +func (b Builder) CoIDAsync(contextSize, align, contextArg, asyncFnPtr Expr) Expr { + fn := b.Pkg.cFunc("llvm.coro.id.async", b.Prog.tyCoIDAsync()) + return b.Call(fn, contextSize, align, contextArg, asyncFnPtr) +} + +// declare token @llvm.coro.id.retcon(i32 , i32 , ptr , ptr , ptr , ptr ) +func (b Builder) CoIDRetcon(size, align, buffer, contProto, alloc, dealloc Expr) Expr { + fn := b.Pkg.cFunc("llvm.coro.id.retcon", b.Prog.tyCoIDRetcon()) + return b.Call(fn, size, align, buffer, contProto, alloc, dealloc) +} + +// declare token @llvm.coro.id.retcon.once(i32 , i32 , ptr , ptr , ptr , ptr ) +func (b Builder) CoIDRetconOnce(size, align, buffer, prototype, alloc, dealloc Expr) Expr { + fn := b.Pkg.cFunc("llvm.coro.id.retcon.once", b.Prog.tyCoIDRetconOnce()) + return b.Call(fn, size, align, buffer, prototype, alloc, dealloc) +} + +// declare i1 @llvm.coro.end(ptr , i1 , token ) +func (b Builder) CoEnd(hdl Expr, unwind Expr, resultToken Expr) Expr { + fn := b.Pkg.cFunc("llvm.coro.end", b.Prog.tyCoEnd()) + return b.Call(fn, hdl, unwind, resultToken) +} + +// declare token @llvm.coro.end.results(...) +func (b Builder) CoEndResults(args []Expr) Expr { + fn := b.Pkg.cFunc("llvm.coro.end.results", b.Prog.tyCoEndResults()) + return b.Call(fn, args...) +} + +// declare i1 @llvm.coro.end.async(ptr , i1 , ...) +func (b Builder) CoEndAsync(handle, unwind Expr, args ...Expr) Expr { + fn := b.Pkg.cFunc("llvm.coro.end.async", b.Prog.tyCoEndAsync()) + args = append([]Expr{handle, unwind}, args...) + return b.Call(fn, args...) +} + +// declare i8 @llvm.coro.suspend(token , i1 ) +func (b Builder) CoSuspend(save, final Expr) Expr { + fn := b.Pkg.cFunc("llvm.coro.suspend", b.Prog.tyCoSuspend()) + return b.Call(fn, save, final) +} + +// declare token @llvm.coro.save(ptr ) +func (b Builder) CoSave(hdl Expr) Expr { + fn := b.Pkg.cFunc("llvm.coro.save", b.Prog.tyCoSave()) + return b.Call(fn, hdl) +} + +// declare ptr @llvm.coro.prepare.async(ptr ) +func (b Builder) CoPrepareAsync(f Expr) Expr { + fn := b.Pkg.cFunc("llvm.coro.prepare.async", b.Prog.tyCoPrepareAsync()) + return b.Call(fn, f) +} + +// declare i1 @llvm.coro.suspend.retcon(...) +func (b Builder) CoSuspendRetcon(args []Expr) Expr { + fn := b.Pkg.cFunc("llvm.coro.suspend.retcon", b.Prog.tyCoSuspendRetcon()) + return b.Call(fn, args...) +} + +// declare void @llvm.coro.await.suspend.void(ptr , ptr , ptr ) +func (b Builder) CoAwaitSuspendVoid(awaiter, handle, f Expr) { + fn := b.Pkg.cFunc("llvm.coro.await.suspend.void", b.Prog.tyCoAwaitSuspendVoid()) + b.Call(fn, awaiter, handle, f) +} + +// declare i1 @llvm.coro.await.suspend.bool(ptr , ptr , ptr ) +func (b Builder) CoAwaitSuspendBool(awaiter, handle, f Expr) Expr { + fn := b.Pkg.cFunc("llvm.coro.await.suspend.bool", b.Prog.tyCoAwaitSuspendBool()) + return b.Call(fn, awaiter, handle, f) +} + +// declare void @llvm.coro.await.suspend.handle(ptr , ptr , ptr ) +func (b Builder) CoAwaitSuspendHandle(awaiter, handle, f Expr) { + fn := b.Pkg.cFunc("llvm.coro.await.suspend.handle", b.Prog.tyCoAwaitSuspendHandle()) + b.Call(fn, awaiter, handle, f) +} diff --git a/ssa/package.go b/ssa/package.go index 382ef365..7be6d901 100644 --- a/ssa/package.go +++ b/ssa/package.go @@ -135,6 +135,8 @@ type aProgram struct { rtMapTy llvm.Type rtChanTy llvm.Type + tokenType llvm.Type + anyTy Type voidTy Type voidPtr Type @@ -165,6 +167,8 @@ type aProgram struct { deferTy Type deferPtr Type + tokenTy Type + pyImpTy *types.Signature pyNewList *types.Signature pyListSetI *types.Signature @@ -188,6 +192,39 @@ type aProgram struct { sigsetjmpTy *types.Signature sigljmpTy *types.Signature + // coroutine manipulation intrinsics (ordered by LLVM coroutine doc) + coDestroyTy *types.Signature + coResumeTy *types.Signature + coDoneTy *types.Signature + coPromiseTy *types.Signature + + // coroutine structure intrinsics (ordered by LLVM coroutine doc) + coSizeI32Ty *types.Signature + coSizeI64Ty *types.Signature + coAlignI32Ty *types.Signature + coAlignI64Ty *types.Signature + coBeginTy *types.Signature + coFreeTy *types.Signature + coAllocTy *types.Signature + coNoopTy *types.Signature + coFrameTy *types.Signature + coIDTy *types.Signature + coIDAsyncTy *types.Signature + coIDRetconTy *types.Signature + coIDRetconOnceTy *types.Signature + coEndTy *types.Signature + coEndResultsTy *types.Signature + coEndAsyncTy *types.Signature + coSuspendTy *types.Signature + coSaveTy *types.Signature + coSuspendAsyncTy *types.Signature + coPrepareAsyncTy *types.Signature + coSuspendRetconTy *types.Signature + coAwaitSuspendFunctionTy *types.Signature + coAwaitSuspendVoidTy *types.Signature + coAwaitSuspendBoolTy *types.Signature + coAwaitSuspendHandleTy *types.Signature + paramObjPtr_ *types.Var ptrSize int @@ -437,6 +474,13 @@ func (p Program) Any() Type { return p.anyTy } +func (p Program) Token() Type { + if p.tokenTy == nil { + p.tokenTy = &aType{p.tyToken(), rawType{types.Typ[types.Invalid]}, vkInvalid} + } + return p.tokenTy +} + /* // Eface returns the empty interface type. // It is equivalent to Any. diff --git a/ssa/type.go b/ssa/type.go index 5e2dcf88..9ab79f18 100644 --- a/ssa/type.go +++ b/ssa/type.go @@ -58,6 +58,7 @@ const ( vkIface vkStruct vkChan + vkToken ) // ----------------------------------------------------------------------------- @@ -282,6 +283,13 @@ func (p Program) tyInt() llvm.Type { return p.intType } +func (p Program) tyToken() llvm.Type { + if p.tokenType.IsNil() { + p.tokenType = p.ctx.TokenType() + } + return p.tokenType +} + func llvmIntType(ctx llvm.Context, size int) llvm.Type { if size <= 4 { return ctx.Int32Type() @@ -362,6 +370,9 @@ func (p Program) toType(raw types.Type) Type { return &aType{p.rtString(), typ, vkString} case types.UnsafePointer: return &aType{p.tyVoidPtr(), typ, vkPtr} + // TODO(lijie): temporary solution, should be replaced by a proper type + case types.Invalid: + return &aType{p.tyToken(), typ, vkInvalid} } case *types.Pointer: elem := p.rawType(t.Elem()) @@ -444,7 +455,8 @@ func (p Program) toLLVMTypes(t *types.Tuple, n int) (ret []llvm.Type) { if n > 0 { ret = make([]llvm.Type, n) for i := 0; i < n; i++ { - ret[i] = p.rawType(t.At(i).Type()).ll + pt := t.At(i) + ret[i] = p.rawType(pt.Type()).ll } } return