Skip to content

Commit

Permalink
ir: Add support for aggregate instructions.
Browse files Browse the repository at this point in the history
Updates #15.
  • Loading branch information
mewmew committed Apr 4, 2017
1 parent bb69914 commit 5ff35bb
Show file tree
Hide file tree
Showing 8 changed files with 406 additions and 4 deletions.
9 changes: 9 additions & 0 deletions asm/internal/ast/astutil/walk.go
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,10 @@ func (w *walker) walkBeforeAfter(x interface{}, before, after func(interface{}))
w.walkBeforeAfter(*n, before, after)
case **ast.InstShuffleVector:
w.walkBeforeAfter(*n, before, after)
case **ast.InstExtractValue:
w.walkBeforeAfter(*n, before, after)
case **ast.InstInsertValue:
w.walkBeforeAfter(*n, before, after)
case **ast.InstAlloca:
w.walkBeforeAfter(*n, before, after)
case **ast.InstLoad:
Expand Down Expand Up @@ -705,6 +709,11 @@ func (w *walker) walkBeforeAfter(x interface{}, before, after func(interface{}))
w.walkBeforeAfter(&n.X, before, after)
w.walkBeforeAfter(&n.Y, before, after)
w.walkBeforeAfter(&n.Mask, before, after)
case *ast.InstExtractValue:
w.walkBeforeAfter(&n.X, before, after)
case *ast.InstInsertValue:
w.walkBeforeAfter(&n.X, before, after)
w.walkBeforeAfter(&n.Elem, before, after)
case *ast.InstAlloca:
w.walkBeforeAfter(&n.Elem, before, after)
if n.NElems != nil {
Expand Down
72 changes: 72 additions & 0 deletions asm/internal/ast/inst_aggregate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// === [ Aggregate instructions ] ==============================================
//
// References:
// http://llvm.org/docs/LangRef.html#aggregate-operations

package ast

// --- [ extractvalue ] ------------------------------------------------------

// InstExtractValue represents an extract value instruction.
//
// References:
// http://llvm.org/docs/LangRef.html#extractvalue-instruction
type InstExtractValue struct {
// Name of the local variable associated with the instruction.
Name string
// Aggregate value.
X Value
// Indices.
Indices []int64
}

// GetName returns the name of the value.
func (inst *InstExtractValue) GetName() string {
return inst.Name
}

// SetName sets the name of the value.
func (inst *InstExtractValue) SetName(name string) {
inst.Name = name
}

// isValue ensures that only values can be assigned to the ast.Value interface.
func (*InstExtractValue) isValue() {}

// isInst ensures that only instructions can be assigned to the ast.Instruction
// interface.
func (*InstExtractValue) isInst() {}

// --- [ insertvalue ] -------------------------------------------------------

// InstInsertValue represents an insert value instruction.
//
// References:
// http://llvm.org/docs/LangRef.html#insertvalue-instruction
type InstInsertValue struct {
// Name of the local variable associated with the instruction.
Name string
// Aggregate value.
X Value
// Element to insert.
Elem Value
// Indices.
Indices []int64
}

// GetName returns the name of the value.
func (inst *InstInsertValue) GetName() string {
return inst.Name
}

// SetName sets the name of the value.
func (inst *InstInsertValue) SetName(name string) {
inst.Name = name
}

// isValue ensures that only values can be assigned to the ast.Value interface.
func (*InstInsertValue) isValue() {}

// isInst ensures that only instructions can be assigned to the ast.Instruction
// interface.
func (*InstInsertValue) isInst() {}
63 changes: 63 additions & 0 deletions asm/internal/astx/astx.go
Original file line number Diff line number Diff line change
Expand Up @@ -1899,6 +1899,69 @@ func NewShuffleVectorInst(xTyp, xVal, yTyp, yVal, maskTyp, maskVal interface{})
return &ast.InstShuffleVector{X: x, Y: y, Mask: mask}, nil
}

// --- [ Aggregate instructions ] ----------------------------------------------

// NewExtractValueInst returns a new extractvalue instruction based on the
// given aggregate value and indices.
func NewExtractValueInst(xTyp, xVal, indices interface{}) (*ast.InstExtractValue, error) {
x, err := NewValue(xTyp, xVal)
if err != nil {
return nil, errors.WithStack(err)
}
is, ok := indices.([]int64)
if !ok {
return nil, errors.Errorf("invalid indices type; expected []int64, got %T", indices)
}
if len(is) < 1 {
return nil, errors.Errorf("invalid indices length; expected > 0, got %d", len(is))
}
return &ast.InstExtractValue{X: x, Indices: is}, nil
}

// NewIntLitList returns a new integer literal list based on the given integer
// literal.
func NewIntLitList(i interface{}) ([]int64, error) {
x, err := getInt64(i)
if err != nil {
return nil, errors.WithStack(err)
}
return []int64{x}, nil
}

// AppendIntLit appends the given integer literal to the integer literal list.
func AppendIntLit(is, i interface{}) ([]int64, error) {
xs, ok := is.([]int64)
if !ok {
return nil, errors.Errorf("invalid integer literal list type; expected []int64, got %T", is)
}
x, err := getInt64(i)
if err != nil {
return nil, errors.WithStack(err)
}
return append(xs, x), nil
}

// NewInsertValueInst returns a new insertvalue instruction based on the
// given aggregate value, element and indices.
func NewInsertValueInst(xTyp, xVal, elemTyp, elemVal, indices interface{}) (*ast.InstInsertValue, error) {
x, err := NewValue(xTyp, xVal)
if err != nil {
return nil, errors.WithStack(err)
}
elem, err := NewValue(elemTyp, elemVal)
if err != nil {
return nil, errors.WithStack(err)
}
is, ok := indices.([]int64)
if !ok {
return nil, errors.Errorf("invalid indices type; expected []int64, got %T", indices)
}
if len(is) < 1 {
return nil, errors.Errorf("invalid indices length; expected > 0, got %d", len(is))
}
return &ast.InstInsertValue{X: x, Elem: elem, Indices: is}, nil
}

// --- [ Memory instructions ] -------------------------------------------------

// NewAllocaInst returns a new alloca instruction based on the given element
Expand Down
32 changes: 32 additions & 0 deletions asm/internal/irx/translate.go
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,18 @@ func (m *Module) funcDecl(oldFunc *ast.Function) {
Name: oldInst.Name,
}

// Aggregate instructions
case *ast.InstExtractValue:
inst = &ir.InstExtractValue{
Parent: block,
Name: oldInst.Name,
}
case *ast.InstInsertValue:
inst = &ir.InstInsertValue{
Parent: block,
Name: oldInst.Name,
}

// Memory instructions
case *ast.InstAlloca:
inst = &ir.InstAlloca{
Expand Down Expand Up @@ -745,6 +757,26 @@ func (m *Module) basicBlock(oldBlock *ast.BasicBlock, block *ir.BasicBlock) {
inst.Y = m.irValue(oldInst.Y)
inst.Mask = m.irValue(oldInst.Mask)

// Aggregate instructions
case *ast.InstExtractValue:
inst, ok := v.(*ir.InstExtractValue)
if !ok {
panic(fmt.Errorf("invalid instruction type; expected *ir.InstExtractValue, got %T", v))
}
x := m.irValue(oldInst.X)
typ := aggregateElemType(x.Type(), oldInst.Indices)
inst.Typ = typ
inst.X = x
inst.Indices = oldInst.Indices
case *ast.InstInsertValue:
inst, ok := v.(*ir.InstInsertValue)
if !ok {
panic(fmt.Errorf("invalid instruction type; expected *ir.InstInsertValue, got %T", v))
}
inst.X = m.irValue(oldInst.X)
inst.Elem = m.irValue(oldInst.Elem)
inst.Indices = oldInst.Indices

// Memory instructions
case *ast.InstAlloca:
inst, ok := v.(*ir.InstAlloca)
Expand Down
23 changes: 23 additions & 0 deletions asm/internal/irx/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,26 @@ func (m *Module) irType(old ast.Type) types.Type {
panic(fmt.Errorf("support for %T not yet implemented", old))
}
}

// aggregateElemType returns the element type of the given aggregate type, based
// on the specified indices.
func aggregateElemType(t types.Type, indices []int64) types.Type {
if len(indices) == 0 {
return t
}
index := indices[0]
switch t := t.(type) {
case *types.ArrayType:
if index >= t.Len {
panic(fmt.Errorf("invalid index (%d); exceeds array length (%d)", index, t.Len))
}
return aggregateElemType(t.Elem, indices[1:])
case *types.StructType:
if index >= int64(len(t.Fields)) {
panic(fmt.Errorf("invalid index (%d); exceeds struct field count (%d)", index, len(t.Fields)))
}
return aggregateElemType(t.Fields[index], indices[1:])
default:
panic(fmt.Errorf("invalid aggregate value type; expected *types.ArrayType or *types.StructType, got %T", t))
}
}
8 changes: 4 additions & 4 deletions asm/internal/ll.bnf
Original file line number Diff line number Diff line change
Expand Up @@ -1236,18 +1236,18 @@ ShuffleVectorInst
// ~~~ [ extractvalue ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

ExtractValueInst
: "extractvalue" FirstClassType Value "," IntLitList << nil, nil >>
: "extractvalue" FirstClassType Value "," IntLitList << astx.NewExtractValueInst($1, $2, $4) >>
;

IntLitList
: IntLit
| IntLitList "," IntLit
: IntLit << astx.NewIntLitList($0) >>
| IntLitList "," IntLit << astx.AppendIntLit($0, $2) >>
;

// ~~~ [ insertvalue ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

InsertValueInst
: "insertvalue" FirstClassType Value "," FirstClassType Value "," IntLitList << nil, nil >>
: "insertvalue" FirstClassType Value "," FirstClassType Value "," IntLitList << astx.NewInsertValueInst($1, $2, $4, $5, $7) >>
;

// --- [ Memory instructions ] -------------------------------------------------
Expand Down
Loading

0 comments on commit 5ff35bb

Please sign in to comment.