Beispiel #1
0
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
}
Beispiel #2
0
func VisitBlocks(mod *ssa.Module, visitFn func(*ssa.Block)) {
	for _, fn := range mod.Functions() {
		for _, block := range fn.Blocks() {
			visitFn(block)
		}
	}
}
Beispiel #3
0
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)
			}
		}
	}
}
Beispiel #4
0
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
}
Beispiel #6
0
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
}
Beispiel #7
0
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
}
Beispiel #8
0
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
}
Beispiel #9
0
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
}
Beispiel #10
0
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
}
Beispiel #11
0
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
}
Beispiel #12
0
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")
	}
}