Skip to content

Commit 6da284f

Browse files
authored
fix the factorial example (#7)
closes #6 --------- Co-authored-by: junyucao1024 <[email protected]>
1 parent d3874fb commit 6da284f

File tree

1 file changed

+66
-20
lines changed

1 file changed

+66
-20
lines changed

examples/factorial_module.zig

Lines changed: 66 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -25,37 +25,83 @@ pub fn main() void {
2525
const factorialFunc: types.LLVMValueRef = core.LLVMAddFunction(module, "factorial", factorialFuncType);
2626

2727
// Set up the function body
28-
const entryBlock: types.LLVMBasicBlockRef = core.LLVMAppendBasicBlock(factorialFunc, "entry");
28+
const entryBlock = core.LLVMAppendBasicBlock(factorialFunc, "entry");
29+
const initBlock = core.LLVMAppendBasicBlock(factorialFunc, "init");
30+
const condBlock = core.LLVMAppendBasicBlock(factorialFunc, "cond");
31+
const bodyBlock = core.LLVMAppendBasicBlock(factorialFunc, "body");
32+
const endBlock = core.LLVMAppendBasicBlock(factorialFunc, "end");
33+
34+
// Start entryBlock
2935
core.LLVMPositionBuilderAtEnd(builder, entryBlock);
36+
const n = core.LLVMGetParam(factorialFunc, 0);
3037

31-
const n: types.LLVMValueRef = core.LLVMGetParam(factorialFunc, 0);
32-
const loopBlock: types.LLVMBasicBlockRef = core.LLVMAppendBasicBlock(factorialFunc, "loop");
33-
const endBlock: types.LLVMBasicBlockRef = core.LLVMAppendBasicBlock(factorialFunc, "end");
38+
// allocate space to store values
39+
// with pointers as return values
40+
const result_ptr = core.LLVMBuildAlloca(builder, returnType, "result_ptr");
41+
const n_ptr = core.LLVMBuildAlloca(builder, returnType, "n_ptr");
42+
// End entryBlock
3443

35-
_ = core.LLVMBuildBr(builder, loopBlock);
36-
core.LLVMPositionBuilderAtEnd(builder, loopBlock);
37-
const nIsZero: types.LLVMValueRef = core.LLVMBuildICmp(builder, types.LLVMIntPredicate.LLVMIntEQ, n, core.LLVMConstInt(core.LLVMInt32Type(), 0, 0), "nIsZero");
44+
// Start initBlock, do some initialization
45+
_ = core.LLVMBuildBr(builder, initBlock);
46+
core.LLVMPositionBuilderAtEnd(builder, initBlock);
47+
48+
// Set n_ptr.* = n, result.* = 1
49+
_ = core.LLVMBuildStore(builder, core.LLVMConstInt(returnType, 1, 0), result_ptr);
50+
_ = core.LLVMBuildStore(builder, n, n_ptr);
51+
// End initBlock
3852

39-
_ = core.LLVMBuildCondBr(builder, nIsZero, endBlock, loopBlock);
40-
core.LLVMPositionBuilderAtEnd(builder, endBlock);
41-
const result: types.LLVMValueRef = core.LLVMBuildPhi(builder, returnType, "result");
42-
const resultValue: types.LLVMValueRef = core.LLVMBuildPhi(builder, returnType, "result_value");
43-
const resultPlusN: types.LLVMValueRef = core.LLVMBuildAdd(builder, resultValue, n, "result_plus_n");
53+
// Start condBlock, set control flow
54+
_ = core.LLVMBuildBr(builder, condBlock);
55+
core.LLVMPositionBuilderAtEnd(builder, condBlock);
4456

45-
_ = core.LLVMBuildStore(builder, resultPlusN, result);
46-
const nIsOne: types.LLVMValueRef = core.LLVMBuildICmp(builder, types.LLVMIntPredicate.LLVMIntEQ, n, core.LLVMConstInt(core.LLVMInt32Type(), 1, 0), "nIsOne");
47-
const newResult: types.LLVMValueRef = core.LLVMBuildSelect(builder, nIsOne, resultPlusN, resultValue, "newResult");
57+
const n_val = core.LLVMBuildLoad2(builder, returnType, n_ptr, "n_val");
58+
const isZero = core.LLVMBuildICmp(
59+
builder,
60+
types.LLVMIntPredicate.LLVMIntEQ,
61+
n_val,
62+
core.LLVMConstInt(returnType, 0, 0),
63+
"n_is_zero",
64+
);
65+
_ = core.LLVMBuildCondBr(builder, isZero, endBlock, bodyBlock);
66+
// If n_ptr.* = 0 then goto endBlock
67+
// else goto bodyBlock
68+
// End condBlock
4869

49-
_ = core.LLVMBuildStore(builder, newResult, resultValue);
50-
_ = core.LLVMBuildCondBr(builder, nIsOne, endBlock, loopBlock);
70+
// Start bodyBlock:
71+
// factorial *= n; n -= 1
72+
core.LLVMPositionBuilderAtEnd(builder, bodyBlock);
73+
const result_val = core.LLVMBuildLoad2(builder, returnType, result_ptr, "res");
74+
const new_result = core.LLVMBuildMul(builder, result_val, n_val, "new_res");
75+
_ = core.LLVMBuildStore(builder, new_result, result_ptr);
5176

77+
const new_n = core.LLVMBuildSub(
78+
builder,
79+
n_val,
80+
core.LLVMConstInt(returnType, 1, 0),
81+
"new_n",
82+
);
83+
_ = core.LLVMBuildStore(builder, new_n, n_ptr);
84+
_ = core.LLVMBuildBr(builder, condBlock);
85+
// goto condBlock
86+
// End bodyBlock
87+
88+
// Start endBlock
5289
core.LLVMPositionBuilderAtEnd(builder, endBlock);
53-
_ = core.LLVMBuildRet(builder, resultValue);
90+
const final_result = core.LLVMBuildLoad2(builder, returnType, result_ptr, "final");
91+
_ = core.LLVMBuildRet(builder, final_result);
92+
// End endBlock
93+
// Program ends
5494

5595
// Verify the module
5696
var errMsg: ?[*:0]u8 = null;
57-
_ = analysis.LLVMVerifyModule(module, types.LLVMVerifierFailureAction.LLVMPrintMessageAction, @ptrCast(&errMsg));
58-
if (errMsg) |msg| {
97+
const failed: types.LLVMBool = analysis.LLVMVerifyModule(
98+
module,
99+
types.LLVMVerifierFailureAction.LLVMReturnStatusAction,
100+
@ptrCast(&errMsg),
101+
);
102+
103+
if (failed != 0 and errMsg != null){
104+
const msg: [*:0]u8 = errMsg.?;
59105
@panic(std.mem.span(msg));
60106
// core.LLVMDisposeMessage(msg);
61107
// std.os.exit(1);

0 commit comments

Comments
 (0)