1//===- executionengine_test.go - Tests for executionengine ----------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file tests bindings for the executionengine component.
11//
12//===----------------------------------------------------------------------===//
13
14package llvm
15
16import (
17	"testing"
18)
19
20func TestFactorial(t *testing.T) {
21	LinkInMCJIT()
22	InitializeNativeTarget()
23	InitializeNativeAsmPrinter()
24
25	mod := NewModule("fac_module")
26
27	fac_args := []Type{Int32Type()}
28	fac_type := FunctionType(Int32Type(), fac_args, false)
29	fac := AddFunction(mod, "fac", fac_type)
30	fac.SetFunctionCallConv(CCallConv)
31	n := fac.Param(0)
32
33	entry := AddBasicBlock(fac, "entry")
34	iftrue := AddBasicBlock(fac, "iftrue")
35	iffalse := AddBasicBlock(fac, "iffalse")
36	end := AddBasicBlock(fac, "end")
37
38	builder := NewBuilder()
39	defer builder.Dispose()
40
41	builder.SetInsertPointAtEnd(entry)
42	If := builder.CreateICmp(IntEQ, n, ConstInt(Int32Type(), 0, false), "cmptmp")
43	builder.CreateCondBr(If, iftrue, iffalse)
44
45	builder.SetInsertPointAtEnd(iftrue)
46	res_iftrue := ConstInt(Int32Type(), 1, false)
47	builder.CreateBr(end)
48
49	builder.SetInsertPointAtEnd(iffalse)
50	n_minus := builder.CreateSub(n, ConstInt(Int32Type(), 1, false), "subtmp")
51	call_fac_args := []Value{n_minus}
52	call_fac := builder.CreateCall(fac, call_fac_args, "calltmp")
53	res_iffalse := builder.CreateMul(n, call_fac, "multmp")
54	builder.CreateBr(end)
55
56	builder.SetInsertPointAtEnd(end)
57	res := builder.CreatePHI(Int32Type(), "result")
58	phi_vals := []Value{res_iftrue, res_iffalse}
59	phi_blocks := []BasicBlock{iftrue, iffalse}
60	res.AddIncoming(phi_vals, phi_blocks)
61	builder.CreateRet(res)
62
63	err := VerifyModule(mod, ReturnStatusAction)
64	if err != nil {
65		t.Errorf("Error verifying module: %s", err)
66		return
67	}
68
69	options := NewMCJITCompilerOptions()
70	options.SetMCJITOptimizationLevel(2)
71	options.SetMCJITEnableFastISel(true)
72	options.SetMCJITNoFramePointerElim(true)
73	options.SetMCJITCodeModel(CodeModelJITDefault)
74	engine, err := NewMCJITCompiler(mod, options)
75	if err != nil {
76		t.Errorf("Error creating JIT: %s", err)
77		return
78	}
79	defer engine.Dispose()
80
81	pass := NewPassManager()
82	defer pass.Dispose()
83
84	pass.Add(engine.TargetData())
85	pass.AddConstantPropagationPass()
86	pass.AddInstructionCombiningPass()
87	pass.AddPromoteMemoryToRegisterPass()
88	pass.AddGVNPass()
89	pass.AddCFGSimplificationPass()
90	pass.Run(mod)
91
92	exec_args := []GenericValue{NewGenericValueFromInt(Int32Type(), 10, false)}
93	exec_res := engine.RunFunction(fac, exec_args)
94	var fac10 uint64 = 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1
95	if exec_res.Int(false) != fac10 {
96		t.Errorf("Expected %d, got %d", fac10, exec_res.Int(false))
97	}
98}
99