Skip to content

Instantly share code, notes, and snippets.

@pwaller
Last active November 23, 2018 17:13
Show Gist options
  • Save pwaller/255654cd78b77484a02cdfaa6a22237c to your computer and use it in GitHub Desktop.
Save pwaller/255654cd78b77484a02cdfaa6a22237c to your computer and use it in GitHub Desktop.
package ir
import value "github.com/llir/llvm/ir/value"
// Code generated by "llir-gen-ops"; DO NOT EDIT.
// Operands appends the value.Value operands of inst to out.
func Operands(out []value.Value, inst Instruction) []value.Value {
switch inst := inst.(type) {
case *InstAShr:
out = append(out, inst.X)
out = append(out, inst.Y)
return out
case *InstAdd:
out = append(out, inst.X)
out = append(out, inst.Y)
return out
case *InstAddrSpaceCast:
out = append(out, inst.From)
return out
case *InstAlloca:
out = append(out, inst.NElems)
return out
case *InstAnd:
out = append(out, inst.X)
out = append(out, inst.Y)
return out
case *InstAtomicRMW:
out = append(out, inst.Dst)
out = append(out, inst.X)
return out
case *InstBitCast:
out = append(out, inst.From)
return out
case *InstCall:
out = append(out, inst.Callee)
for i := range inst.Args {
out = append(out, inst.Args[i])
}
return out
case *InstCatchPad:
out = append(out, inst.Scope)
for i := range inst.Args {
out = append(out, inst.Args[i])
}
return out
case *InstCleanupPad:
out = append(out, inst.Scope)
for i := range inst.Args {
out = append(out, inst.Args[i])
}
return out
case *InstCmpXchg:
out = append(out, inst.Ptr)
out = append(out, inst.Cmp)
out = append(out, inst.New)
return out
case *InstExtractElement:
out = append(out, inst.X)
out = append(out, inst.Index)
return out
case *InstExtractValue:
out = append(out, inst.X)
return out
case *InstFAdd:
out = append(out, inst.X)
out = append(out, inst.Y)
return out
case *InstFCmp:
out = append(out, inst.X)
out = append(out, inst.Y)
return out
case *InstFDiv:
out = append(out, inst.X)
out = append(out, inst.Y)
return out
case *InstFMul:
out = append(out, inst.X)
out = append(out, inst.Y)
return out
case *InstFPExt:
out = append(out, inst.From)
return out
case *InstFPToSI:
out = append(out, inst.From)
return out
case *InstFPToUI:
out = append(out, inst.From)
return out
case *InstFPTrunc:
out = append(out, inst.From)
return out
case *InstFRem:
out = append(out, inst.X)
out = append(out, inst.Y)
return out
case *InstFSub:
out = append(out, inst.X)
out = append(out, inst.Y)
return out
case *InstFence:
return out
case *InstGetElementPtr:
out = append(out, inst.Src)
for i := range inst.Indices {
out = append(out, inst.Indices[i])
}
return out
case *InstICmp:
out = append(out, inst.X)
out = append(out, inst.Y)
return out
case *InstInsertElement:
out = append(out, inst.X)
out = append(out, inst.Elem)
out = append(out, inst.Index)
return out
case *InstInsertValue:
out = append(out, inst.X)
out = append(out, inst.Elem)
return out
case *InstIntToPtr:
out = append(out, inst.From)
return out
case *InstLShr:
out = append(out, inst.X)
out = append(out, inst.Y)
return out
case *InstLandingPad:
return out
case *InstLoad:
out = append(out, inst.Src)
return out
case *InstMul:
out = append(out, inst.X)
out = append(out, inst.Y)
return out
case *InstOr:
out = append(out, inst.X)
out = append(out, inst.Y)
return out
case *InstPhi:
return out
case *InstPtrToInt:
out = append(out, inst.From)
return out
case *InstSDiv:
out = append(out, inst.X)
out = append(out, inst.Y)
return out
case *InstSExt:
out = append(out, inst.From)
return out
case *InstSIToFP:
out = append(out, inst.From)
return out
case *InstSRem:
out = append(out, inst.X)
out = append(out, inst.Y)
return out
case *InstSelect:
out = append(out, inst.Cond)
out = append(out, inst.X)
out = append(out, inst.Y)
return out
case *InstShl:
out = append(out, inst.X)
out = append(out, inst.Y)
return out
case *InstShuffleVector:
out = append(out, inst.X)
out = append(out, inst.Y)
out = append(out, inst.Mask)
return out
case *InstStore:
out = append(out, inst.Src)
out = append(out, inst.Dst)
return out
case *InstSub:
out = append(out, inst.X)
out = append(out, inst.Y)
return out
case *InstTrunc:
out = append(out, inst.From)
return out
case *InstUDiv:
out = append(out, inst.X)
out = append(out, inst.Y)
return out
case *InstUIToFP:
out = append(out, inst.From)
return out
case *InstURem:
out = append(out, inst.X)
out = append(out, inst.Y)
return out
case *InstVAArg:
out = append(out, inst.ArgList)
return out
case *InstXor:
out = append(out, inst.X)
out = append(out, inst.Y)
return out
case *InstZExt:
out = append(out, inst.From)
return out
default:
panic("unknown type")
}
}
package main
import (
"fmt"
"go/types"
"log"
"github.com/dave/jennifer/jen"
"golang.org/x/tools/go/packages"
)
func main() {
run()
}
func run() {
cfg := &packages.Config{
Mode: packages.LoadAllSyntax,
}
pkgs, err := packages.Load(
cfg,
"github.com/llir/llvm/ir",
"github.com/llir/llvm/ir/value",
)
if err != nil {
log.Fatal(err)
}
for _, p := range pkgs {
if p.IllTyped {
panic(fmt.Errorf("ill typed: %v", p))
}
if len(p.Errors) != 0 {
panic(fmt.Errorf("errors: %v", p.Errors))
}
}
// TODO(pwaller): Hmm, ordering...
pkgIR, pkgValue := pkgs[1], pkgs[0]
scopeIR := pkgIR.Types.Scope()
scopeValue := pkgValue.Types.Scope()
ifaceInstruction := scopeIR.
Lookup("Instruction").
Type().(*types.Named).
Underlying().(*types.Interface)
if ifaceInstruction == nil {
panic("unable to find ir.Instruction type")
}
typeValue, ok := scopeValue.Lookup("Value").Type().(*types.Named)
if !ok {
panic("unable to find value.Value type")
}
ifaceValue, ok := typeValue.Underlying().(*types.Interface)
if !ok {
panic("value.Value not an interface?")
}
var instructions []instructionType
for _, typ := range scopeIR.Names() {
o := scopeIR.Lookup(typ)
if !o.Exported() {
continue
}
// Find named types implementing the instruction interface.
t, ok := o.Type().(*types.Named)
if !ok {
continue
}
ptrToT := types.NewPointer(t)
isInstruction := types.Implements(ptrToT, ifaceInstruction)
if !isInstruction {
continue
}
structType, ok := t.Underlying().(*types.Struct)
if !ok {
continue
}
instructions = append(instructions, instructionType{Name: typ, Type: structType})
}
g := &generator{ifaceValue}
g.emitPackage(instructions)
}
type instructionType struct {
Name string
Type types.Type
}
type generator struct {
ifaceValue *types.Interface // The (llir/llvm/irvalue).Value interace
}
func (g *generator) emitInstruction(
statements []jen.Code,
ctx *jen.Statement,
typ types.Type,
) []jen.Code {
if types.Implements(typ, g.ifaceValue) {
s := jen.Id("out").Op("=").Id("append").Call(jen.Id("out"), jen.Add(ctx))
statements = append(statements, s)
return statements
}
switch typ := typ.(type) {
case *types.Struct:
for i, n := 0, typ.NumFields(); i < n; i++ {
f := typ.Field(i)
statements = g.emitInstruction(
statements,
ctx.Clone().Id(f.Name()),
f.Type(),
)
}
case *types.Slice:
if !types.Implements(typ.Elem(), g.ifaceValue) {
return statements
}
s := jen.For(
// for i := range ctx {
jen.Id("i").Op(":=").Range().Add(ctx.Clone()),
).Block(
// out = append(out, &ctx[i])
g.emitInstruction(nil, ctx.Clone().Index(jen.Id("i")), typ.Elem())...,
)
statements = append(statements, s)
default: // Nothing to do ... ?
}
return statements
}
func (g *generator) emitPackage(instType []instructionType) {
var cases []jen.Code
// Generate one case statement per inst type.
for _, inst := range instType {
var statements []jen.Code
// Case body ...
statements = g.emitInstruction(
statements,
jen.Id("inst").Op("."),
inst.Type,
)
// ... ending in a return statement.
statements = append(statements,
jen.Return(jen.Id("out")),
)
// Case definition.
cases = append(cases,
jen.Case(
jen.Op("*").Id(inst.Name),
).Block(statements...),
)
}
cases = append(cases,
jen.Default().Block(
jen.Panic(jen.Lit("unknown type")),
),
)
f := jen.NewFile("ir")
f.Comment("Code generated by \"llir-gen-ops\"; DO NOT EDIT.")
f.Comment("Operands appends the value.Value operands of inst to out.")
f.ImportName("github.com/llvm/llir/ir/value", "value")
// Generate the Operands function, with a switch over the previously generated cases.
f.Func().
Id("Operands").
Params(
jen.Id("out").Index().Qual("github.com/llir/llvm/ir/value", "Value"),
jen.Id("inst").Id("Instruction"),
).
Index().Qual("github.com/llir/llvm/ir/value", "Value").
Block(
jen.Switch(
jen.Id("inst").Op(":=").Id("inst").Assert(jen.Id("type")),
).Block(
cases...,
),
)
fmt.Printf("%#v", f)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment