Пример #1
0
// parseBasicBlock converts the provided LLVM IR basic block into a basic block
// in which the instructions have been translated to Go AST statement nodes but
// the terminator instruction is an unmodified LLVM IR value.
func parseBasicBlock(llBB llvm.BasicBlock) (bb *basicBlock, err error) {
	name, err := getBBName(llBB.AsValue())
	if err != nil {
		return nil, err
	}
	bb = &basicBlock{name: name, phis: make(map[string][]*definition)}
	for inst := llBB.FirstInstruction(); !inst.IsNil(); inst = llvm.NextInstruction(inst) {
		// Handle terminator instruction.
		if inst == llBB.LastInstruction() {
			err = bb.addTerm(inst)
			if err != nil {
				return nil, errutil.Err(err)
			}
			return bb, nil
		}

		// Handle PHI instructions.
		if inst.InstructionOpcode() == llvm.PHI {
			ident, def, err := parsePHIInst(inst)
			if err != nil {
				return nil, errutil.Err(err)
			}
			bb.phis[ident] = def
			continue
		}

		// Handle non-terminator instructions.
		stmt, err := parseInst(inst)
		if err != nil {
			return nil, err
		}
		bb.stmts = append(bb.stmts, stmt)
	}
	return nil, errutil.Newf("invalid basic block %q; contains no instructions", name)
}
Пример #2
0
func (c *Codegen) generateControl(node *parser.IfStmtNode) (ret bool) {
	currFunc := c.module.NamedFunction(c.currFunc)

	tru := llvm.AddBasicBlock(currFunc, "")
	var els llvm.BasicBlock
	if node.Else != nil {
		els = llvm.AddBasicBlock(currFunc, "")
	}
	exit := llvm.AddBasicBlock(currFunc, "")

	cond := c.generateExpression(node.Condition)
	if node.Else != nil {
		c.builder.CreateCondBr(cond, tru, els)
	} else {
		c.builder.CreateCondBr(cond, tru, exit)
	}

	c.builder.SetInsertPoint(tru, tru.LastInstruction())
	if c.generateBlock(node.Body) {
		ret = true
	} else {
		c.builder.CreateBr(exit)
	}

	if node.Else != nil {
		c.builder.SetInsertPoint(els, els.LastInstruction())
		var ok bool
		switch t := node.Else.(type) {
		case *parser.BlockNode:
			ok = c.generateBlock(t)
			ret = ok && ret
		case *parser.IfStmtNode:
			ok = c.generateControl(t)
			ret = ok && ret
		}

		if !ok {
			c.builder.CreateBr(exit)
		}
	}

	c.builder.SetInsertPoint(exit, exit.LastInstruction())
	return
}