func checkBranchToEntry(mod *ssa.Module) error { makeError := func(i ssa.Instruction) error { return &InstrError{ Instr: i, Message: fmt.Sprintf("Branch to entry block `%%%s`", i.Block().Name()), } } for _, fn := range mod.Functions() { for _, block := range fn.Blocks() { lastInstr := block.LastInstr() switch i := lastInstr.(type) { case *ssa.Br: if block := ssa.GetOperands(i)[0].(*ssa.Block); block.IsEntry() { return makeError(i) } case *ssa.CondBr: for _, op := range ssa.GetOperands(i)[1:3] { if op.(*ssa.Block).IsEntry() { return makeError(i) } } } } } return nil }
func VisitBlocks(mod *ssa.Module, visitFn func(*ssa.Block)) { for _, fn := range mod.Functions() { for _, block := range fn.Blocks() { visitFn(block) } } }
func VisitInstrs(mod *ssa.Module, visitFn func(ssa.Instruction)) { for _, fn := range mod.Functions() { for _, block := range fn.Blocks() { for _, instr := range block.Instrs() { visitFn(instr) } } } }
func checkEmptyBlock(mod *ssa.Module) error { for _, fn := range mod.Functions() { for _, block := range fn.Blocks() { if len(block.Instrs()) == 0 { return &BlockError{ Block: block, Message: "Empty block", } } } } return nil }
func checkBlockDoesNotTerminate(mod *ssa.Module) error { for _, fn := range mod.Functions() { for _, block := range fn.Blocks() { lastInstr := block.LastInstr() if lastInstr == nil || !lastInstr.IsTerminating() { return &BlockError{ Block: block, Message: "Non-terminating block", } } } } return nil }
func checkIllegalTerminate(mod *ssa.Module) error { for _, fn := range mod.Functions() { for _, block := range fn.Blocks() { instrs := block.Instrs() for _, instr := range instrs[:len(instrs)-1] { if instr.IsTerminating() { return &InstrError{ Instr: instr, Message: "Terminating instruction in middle of block", } } } } } return nil }
func checkEntryPhi(mod *ssa.Module) error { for _, fn := range mod.Functions() { if !fn.IsPrototype() { for _, instr := range fn.EntryBlock().Instrs() { _, ok := instr.(*ssa.Phi) if ok { return InstrError{ Instr: instr, Message: "Phi node in entry block", } } } } } return nil }
func checkInstrs(mod *ssa.Module) error { for _, fn := range mod.Functions() { var blockDomTree *analysis.DominatorTree if !fn.IsPrototype() { blockDomTree = analysis.NewBlockDominatorTree(analysis.NewBlockCFG(fn)) } for _, block := range fn.Blocks() { for _, instr := range block.Instrs() { if err := checkInstr(instr, blockDomTree); err != nil { return err } } } } return nil }
func (v Target) Generate(out io.Writer, mod *ssa.Module) (err error) { if err := validate.Validate(mod); err != nil { return err } mod.UpdateNames() /*defer func() { rec := recover() if rec != nil { err = errors.New(fmt.Sprintf("amd64: %s", rec)) } }()*/ v.out = out v.mod = mod v.gen() return nil }
func checkGlobals(mod *ssa.Module) error { for _, global := range mod.Globals() { init := global.Initialiser() switch init := init.(type) { case *ssa.LiteralInitialiser: litPtr := types.NewPointer(init.Literal().Type()) if err := checkMismatchedTypesGlobal(global.Type(), litPtr, global); err != nil { return err } case *ssa.ZeroInitialiser: // do nothing default: panic("unim") } } return nil }
func checkFunctionNames(mod *ssa.Module) error { seenNames := make(map[string]bool, len(mod.Functions())) for _, fn := range mod.Functions() { if fn.Name() == "" { return &FunctionError{ Function: fn, Message: "Empty function name", } } if seenNames[fn.Name()] { return &FunctionError{ Function: fn, Message: "Duplicate function name `" + fn.Name() + "`", } } seenNames[fn.Name()] = true } return nil }
func PrintValues(mod *ssa.Module, out io.Writer) { printf := func(val string, stuff ...interface{}) { fmt.Fprintf(out, val, stuff...) } printf("Values in module `%s`\n", mod.Name()) printf("\n") printf("Globals:\n") for _, glob := range mod.Globals() { printf(" %s (references: %d)\n", ssa.ValueString(glob), len(glob.References())) } printf("\n") printf("Functions:\n") for _, fn := range mod.Functions() { printf(" %s (references: %d)\n", ssa.ValueString(fn), len(fn.References())) if fn.IsPrototype() { printf("\n") continue } printf(" Parameters:\n") for _, par := range fn.Parameters() { printf(" %s (references: %d)\n", ssa.ValueString(par), len(par.References())) } printf(" Instruction values:\n") for _, block := range fn.Blocks() { for _, instr := range block.Instrs() { if val, ok := instr.(ssa.Value); ok { printf(" %s (references: %d)\n", ssa.ValueString(val), len(val.References())) } } } printf("\n") } }