@@ -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