Skip to content

Commit

Permalink
ir: add Sig to InstCall, TermInvoke and TermCallBr to return the func…
Browse files Browse the repository at this point in the history
…tion signature of the callee

This also simplifies the handling of result cache type of call, invoke
and callbr instructions and terminators.
  • Loading branch information
mewmew committed Dec 16, 2019
1 parent e3e7aa1 commit c56773e
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 76 deletions.
6 changes: 6 additions & 0 deletions asm/inst_other.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,12 @@ func (fgen *funcGen) newCallInst(ident ir.LocalIdent, old *ast.CallInst) (*ir.In
if err != nil {
return nil, errors.WithStack(err)
}
// Resolve return type of variadic functions; e.g.
//
// call void (...) @foo()
if funcType, ok := typ.(*types.FuncType); ok {
typ = funcType.RetType
}
return &ir.InstCall{LocalIdent: ident, Typ: typ}, nil
}

Expand Down
8 changes: 8 additions & 0 deletions asm/term.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ func (fgen *funcGen) newInvokeTerm(ident ir.LocalIdent, old *ast.InvokeTerm) (*i
if err != nil {
return nil, errors.WithStack(err)
}
// Resolve return type of variadic functions.
if funcType, ok := typ.(*types.FuncType); ok {
typ = funcType.RetType
}
return &ir.TermInvoke{LocalIdent: ident, Typ: typ}, nil
}

Expand All @@ -80,6 +84,10 @@ func (fgen *funcGen) newCallBrTerm(ident ir.LocalIdent, old *ast.CallBrTerm) (*i
if err != nil {
return nil, errors.WithStack(err)
}
// Resolve return type of variadic functions.
if funcType, ok := typ.(*types.FuncType); ok {
typ = funcType.RetType
}
return &ir.TermCallBr{LocalIdent: ident, Typ: typ}, nil
}

Expand Down
4 changes: 3 additions & 1 deletion ir/inst_memory.go
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,9 @@ func (inst *InstCmpXchg) String() string {
return fmt.Sprintf("%s %s", inst.Type(), inst.Ident())
}

// Type returns the type of the instruction.
// Type returns the type of the instruction. The result type is a struct type
// with two fields, the first field has the type of the old value and the second
// field has boolean type.
func (inst *InstCmpXchg) Type() types.Type {
// Cache type if not present.
if inst.Typ == nil {
Expand Down
53 changes: 26 additions & 27 deletions ir/inst_other.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ func (inst *InstICmp) String() string {
return fmt.Sprintf("%s %s", inst.Type(), inst.Ident())
}

// Type returns the type of the instruction.
// Type returns the type of the instruction. The result type is either boolean
// type or vector of booleans type.
func (inst *InstICmp) Type() types.Type {
// Cache type if not present.
if inst.Typ == nil {
Expand Down Expand Up @@ -110,7 +111,8 @@ func (inst *InstFCmp) String() string {
return fmt.Sprintf("%s %s", inst.Type(), inst.Ident())
}

// Type returns the type of the instruction.
// Type returns the type of the instruction. The result type is either boolean
// type or vector of booleans type.
func (inst *InstFCmp) Type() types.Type {
// Cache type if not present.
if inst.Typ == nil {
Expand Down Expand Up @@ -174,7 +176,8 @@ func (inst *InstPhi) String() string {
return fmt.Sprintf("%s %s", inst.Type(), inst.Ident())
}

// Type returns the type of the instruction.
// Type returns the type of the instruction. The result type is the type of the
// incoming value.
func (inst *InstPhi) Type() types.Type {
// Cache type if not present.
if inst.Typ == nil {
Expand Down Expand Up @@ -305,8 +308,7 @@ type InstCall struct {

// extra.

// Type of result produced by the instruction, or function signature of the
// callee (as used when callee is variadic).
// Type of result produced by the instruction.
Typ types.Type
// (optional) Tail; zero if not present.
Tail enum.Tail
Expand Down Expand Up @@ -347,22 +349,8 @@ func (inst *InstCall) String() string {
func (inst *InstCall) Type() types.Type {
// Cache type if not present.
if inst.Typ == nil {
t, ok := inst.Callee.Type().(*types.PointerType)
if !ok {
panic(fmt.Errorf("invalid callee type; expected *types.PointerType, got %T", inst.Callee.Type()))
}
sig, ok := t.ElemType.(*types.FuncType)
if !ok {
panic(fmt.Errorf("invalid callee type; expected *types.FuncType, got %T", t.ElemType))
}
if sig.Variadic {
inst.Typ = sig
} else {
inst.Typ = sig.RetType
}
}
if t, ok := inst.Typ.(*types.FuncType); ok {
return t.RetType
sig := inst.Sig()
inst.Typ = sig.RetType
}
return inst.Typ
}
Expand Down Expand Up @@ -395,13 +383,11 @@ func (inst *InstCall) LLString() string {
fmt.Fprintf(buf, " %s", inst.AddrSpace)
}
// Use function signature instead of return type for variadic functions.
typ := inst.Type()
if t, ok := inst.Typ.(*types.FuncType); ok {
if t.Variadic {
typ = t
}
calleeType := inst.Type()
if sig := inst.Sig(); sig.Variadic {
calleeType = sig
}
fmt.Fprintf(buf, " %s %s(", typ, inst.Callee.Ident())
fmt.Fprintf(buf, " %s %s(", calleeType, inst.Callee.Ident())
for i, arg := range inst.Args {
if i != 0 {
buf.WriteString(", ")
Expand All @@ -428,6 +414,19 @@ func (inst *InstCall) LLString() string {
return buf.String()
}

// Sig returns the function signature of the callee.
func (inst *InstCall) Sig() *types.FuncType {
t, ok := inst.Callee.Type().(*types.PointerType)
if !ok {
panic(fmt.Errorf("invalid callee type; expected *types.PointerType, got %T", inst.Callee.Type()))
}
sig, ok := t.ElemType.(*types.FuncType)
if !ok {
panic(fmt.Errorf("invalid callee type; expected *types.FuncType, got %T", t.ElemType))
}
return sig
}

// ~~~ [ va_arg ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

// InstVAArg is an LLVM IR va_arg instruction.
Expand Down
88 changes: 40 additions & 48 deletions ir/terminator.go
Original file line number Diff line number Diff line change
Expand Up @@ -316,8 +316,7 @@ type TermInvoke struct {

// extra.

// Type of result produced by the terminator, or function signature of the
// invokee (as used when invokee is variadic).
// Type of result produced by the terminator.
Typ types.Type
// Successor basic blocks of the terminator.
Successors []*Block
Expand Down Expand Up @@ -357,22 +356,8 @@ func (term *TermInvoke) String() string {
func (term *TermInvoke) Type() types.Type {
// Cache type if not present.
if term.Typ == nil {
t, ok := term.Invokee.Type().(*types.PointerType)
if !ok {
panic(fmt.Errorf("invalid invokee type; expected *types.PointerType, got %T", term.Invokee.Type()))
}
sig, ok := t.ElemType.(*types.FuncType)
if !ok {
panic(fmt.Errorf("invalid invokee type; expected *types.FuncType, got %T", t.ElemType))
}
if sig.Variadic {
term.Typ = sig
} else {
term.Typ = sig.RetType
}
}
if t, ok := term.Typ.(*types.FuncType); ok {
return t.RetType
sig := term.Sig()
term.Typ = sig.RetType
}
return term.Typ
}
Expand Down Expand Up @@ -408,13 +393,11 @@ func (term *TermInvoke) LLString() string {
fmt.Fprintf(buf, " %s", term.AddrSpace)
}
// Use function signature instead of return type for variadic functions.
typ := term.Type()
if t, ok := term.Typ.(*types.FuncType); ok {
if t.Variadic {
typ = t
}
invokeeType := term.Type()
if sig := term.Sig(); sig.Variadic {
invokeeType = sig
}
fmt.Fprintf(buf, " %s %s(", typ, term.Invokee.Ident())
fmt.Fprintf(buf, " %s %s(", invokeeType, term.Invokee.Ident())
for i, arg := range term.Args {
if i != 0 {
buf.WriteString(", ")
Expand Down Expand Up @@ -442,6 +425,19 @@ func (term *TermInvoke) LLString() string {
return buf.String()
}

// Sig returns the function signature of the invokee.
func (term *TermInvoke) Sig() *types.FuncType {
t, ok := term.Invokee.Type().(*types.PointerType)
if !ok {
panic(fmt.Errorf("invalid invokee type; expected *types.PointerType, got %T", term.Invokee.Type()))
}
sig, ok := t.ElemType.(*types.FuncType)
if !ok {
panic(fmt.Errorf("invalid invokee type; expected *types.FuncType, got %T", t.ElemType))
}
return sig
}

// --- [ callbr ] --------------------------------------------------------------

// TermCallBr is an LLVM IR callbr terminator.
Expand All @@ -464,8 +460,7 @@ type TermCallBr struct {

// extra.

// Type of result produced by the terminator, or function signature of the
// callee (as used when callee is variadic).
// Type of result produced by the terminator.
Typ types.Type
// Successor basic blocks of the terminator.
Successors []*Block
Expand Down Expand Up @@ -505,22 +500,8 @@ func (term *TermCallBr) String() string {
func (term *TermCallBr) Type() types.Type {
// Cache type if not present.
if term.Typ == nil {
t, ok := term.Callee.Type().(*types.PointerType)
if !ok {
panic(fmt.Errorf("invalid callee type; expected *types.PointerType, got %T", term.Callee.Type()))
}
sig, ok := t.ElemType.(*types.FuncType)
if !ok {
panic(fmt.Errorf("invalid callee type; expected *types.FuncType, got %T", t.ElemType))
}
if sig.Variadic {
term.Typ = sig
} else {
term.Typ = sig.RetType
}
}
if t, ok := term.Typ.(*types.FuncType); ok {
return t.RetType
sig := term.Sig()
term.Typ = sig.RetType
}
return term.Typ
}
Expand Down Expand Up @@ -557,13 +538,11 @@ func (term *TermCallBr) LLString() string {
fmt.Fprintf(buf, " %s", term.AddrSpace)
}
// Use function signature instead of return type for variadic functions.
typ := term.Type()
if t, ok := term.Typ.(*types.FuncType); ok {
if t.Variadic {
typ = t
}
calleeType := term.Type()
if sig := term.Sig(); sig.Variadic {
calleeType = sig
}
fmt.Fprintf(buf, " %s %s(", typ, term.Callee.Ident())
fmt.Fprintf(buf, " %s %s(", calleeType, term.Callee.Ident())
for i, arg := range term.Args {
if i != 0 {
buf.WriteString(", ")
Expand Down Expand Up @@ -598,6 +577,19 @@ func (term *TermCallBr) LLString() string {
return buf.String()
}

// Sig returns the function signature of the callee.
func (term *TermCallBr) Sig() *types.FuncType {
t, ok := term.Callee.Type().(*types.PointerType)
if !ok {
panic(fmt.Errorf("invalid callee type; expected *types.PointerType, got %T", term.Callee.Type()))
}
sig, ok := t.ElemType.(*types.FuncType)
if !ok {
panic(fmt.Errorf("invalid callee type; expected *types.FuncType, got %T", t.ElemType))
}
return sig
}

// --- [ resume ] --------------------------------------------------------------

// TermResume is an LLVM IR resume terminator.
Expand Down

0 comments on commit c56773e

Please sign in to comment.