Beispiel #1
0
func (v *allocator) allocate(fn *ssa.Function) {
	for _, par := range fn.Parameters() {
		v.allocateValue(par)
	}

	for _, block := range fn.Blocks() {
		for _, instr := range block.Instrs() {
			if val, ok := instr.(ssa.Value); ok {
				v.allocateValue(val)
			}
		}
	}
}
Beispiel #2
0
func (v *CFG) construct(fn *ssa.Function) {
	blocks := fn.Blocks()
	nodes := make([]*CFGNode, len(blocks))
	blocksToNodes := make(map[*ssa.Block]*CFGNode)

	for i, block := range blocks {
		nodes[i] = &CFGNode{
			block: block,
		}
		blocksToNodes[block] = nodes[i]
	}

	for _, node := range nodes {
		switch term := node.block.LastInstr().(type) {
		case *ssa.Br:
			ops := ssa.GetOperands(term)
			node.next = []*CFGNode{
				blocksToNodes[ops[0].(*ssa.Block)],
			}

		case *ssa.CondBr:
			ops := ssa.GetOperands(term)
			node.next = []*CFGNode{
				blocksToNodes[ops[1].(*ssa.Block)],
				blocksToNodes[ops[2].(*ssa.Block)],
			}

		case *ssa.Unreachable, *ssa.Ret:
			// these lead to nowhere

		default:
			panic("unimplemented terminating instruction")
		}

		for _, next := range node.next {
			next.prev = append(next.prev, node)
		}
	}

	v.nodes = nodes
}
Beispiel #3
0
func (v Target) genSaveFunctionParameters(a *allocator, fn *ssa.Function) {
	var vals []ssa.Value
	for _, par := range fn.Parameters() {
		vals = append(vals, par)
	}

	if v.Platform.IsUnixLike() {
		v.sysVCopyFunctionVals(a, vals, fn.Type().(*types.Signature), false)
	} else if v.Platform == platform.Windows {
		v.winSaveFunctionParameters(a, vals, fn.Type().(*types.Signature))
	} else {
		panic("unim")
	}
}
Beispiel #4
0
func (v *Target) genFunction(fn *ssa.Function) {
	if fn.IsPrototype() {
		return
	}

	allocator := newAllocator()
	allocator.allocate(fn)

	blockLabelMap := make(map[*ssa.Block]string)

	for _, block := range fn.Blocks() {
		blockLabelMap[block] = v.nextLabelName()
	}

	v.wnl()
	v.wop(".globl %s", fn.Name())
	v.wop(".align 16, 0x90") // pad with NOPs

	if v.Platform.IsUnixLike() {
		v.wop(".type %s,@function", fn.Name())
	}

	v.wlabel(fn.Name())

	v.wop("pushq #rbp")
	v.wop("pushq #rbx")
	v.wop("pushq #r15")
	v.wop("movq #rsp, #rbp")
	v.wop("subq $%d, #rsp", (allocator.stackSize|0xF)+1)

	retType := fn.Type().(*types.Signature).ReturnType()
	if sysVClassifyType(retType)[0] == sysVClassMEMORY {
		v.wop("movq #rdi, #r15")
	} else if winIsMemory(retType) {
		v.wop("movq #rdx, #r15")
	}

	v.genSaveFunctionParameters(allocator, fn)

	for _, block := range fn.Blocks() {
		v.wlabel(blockLabelMap[block])

		for _, instr := range block.Instrs() {
			v.genInstr(allocator, instr, blockLabelMap)
		}
	}

}