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