示例#1
0
文件: codegen.go 项目: vnev/ark
func (v *Codegen) genIfStat(n *parser.IfStat) {
	// Warning to all who tread here:
	// This function is complicated, but theoretically it should never need to
	// be changed again. God help the soul who has to edit this.

	if !v.inFunction() {
		panic("tried to gen if stat not in function")
	}

	statTerm := semantic.IsNodeTerminating(n)

	var end llvm.BasicBlock
	if !statTerm {
		end = llvm.AddBasicBlock(v.currentLLVMFunction(), "end")
	}

	for i, expr := range n.Exprs {
		cond := v.genExpr(expr)

		ifTrue := llvm.AddBasicBlock(v.currentLLVMFunction(), "if_true")
		ifFalse := llvm.AddBasicBlock(v.currentLLVMFunction(), "if_false")

		v.builder().CreateCondBr(cond, ifTrue, ifFalse)

		v.builder().SetInsertPointAtEnd(ifTrue)
		v.genBlock(n.Bodies[i])

		if !statTerm && !n.Bodies[i].IsTerminating && !isBreakOrNext(n.Bodies[i].LastNode()) {
			v.builder().CreateBr(end)
		}

		v.builder().SetInsertPointAtEnd(ifFalse)

		if !statTerm {
			end.MoveAfter(ifFalse)
		}
	}

	if n.Else != nil {
		v.genBlock(n.Else)
	}

	if !statTerm && (n.Else == nil || (!n.Else.IsTerminating && !isBreakOrNext(n.Else.LastNode()))) {
		v.builder().CreateBr(end)
	}

	if !statTerm {
		v.builder().SetInsertPointAtEnd(end)
	}
}