@@ -41,6 +41,17 @@ namespace Rift::Compiler::LLVM
4141 using namespace llvm ;
4242
4343
44+ using BlockAccessRef = TAccessRef<CStmtOutput, CStmtOutputs, CStmtIf, CExprCallId, CIRFunction>;
45+
46+ // Forward declarations
47+ void AddStmtBlock (Context& context, LLVMContext& llvm, IRBuilder<>& builder,
48+ BlockAccessRef access, AST::Id firstStmtId, BasicBlock* block, const CIRFunction& function);
49+ BasicBlock* AddIf (Context& context, LLVMContext& llvm, IRBuilder<>& builder,
50+ BlockAccessRef access, AST::Id id, const CIRFunction& function);
51+ void AddCall (Context& context, LLVMContext& llvm, IRBuilder<>& builder, const CExprCallId& call,
52+ BlockAccessRef access);
53+
54+
4455 void BindNativeTypes (LLVMContext& llvm, TAccessRef<CType, TWrite<CIRType>> access)
4556 {
4657 const auto & nativeTypes = access.GetAST ().GetNativeTypes ();
@@ -104,38 +115,6 @@ namespace Rift::Compiler::LLVM
104115 }
105116 }
106117
107- void DefineFunctions (Context& context, LLVMContext& llvm, IRBuilder<>& builder,
108- TAccessRef<CIRFunction, CStmtOutputs, CExprCall, CStmtIf, CStmtReturn, CIRInstruction>
109- access,
110- TSpan<AST::Id> ids, Module& irModule)
111- {
112- ZoneScoped;
113- for (AST::Id id : ids)
114- {
115- const auto & irFunction = access.Get <const CIRFunction>(id);
116- BasicBlock* bb = BasicBlock::Create (llvm, " entry" , irFunction.instance );
117- builder.SetInsertPoint (bb);
118-
119- TArray<AST::Id> stmtIds{id};
120-
121- // Scan function statement chain and cache it
122- TArray<AST::Id> stmtsToCheck{id};
123- TArray<AST::Id> lastStmtOutputs;
124- while (!stmtsToCheck.IsEmpty ())
125- {
126- AST::Statements::GetConnectedToOutputs (access, stmtsToCheck, lastStmtOutputs);
127- lastStmtOutputs.RemoveIf ([&access](AST::Id id) {
128- return !access.IsValid (id);
129- });
130- stmtIds.Append (lastStmtOutputs);
131- stmtsToCheck = lastStmtOutputs;
132- lastStmtOutputs.Empty (false );
133- }
134-
135- verifyFunction (*irFunction.instance );
136- }
137- }
138-
139118 void DeclareFunctions (Context& context, LLVMContext& llvm, IRBuilder<>& builder,
140119 TAccessRef<TWrite<CIRFunction>, CIdentifier, CExprType, CExprOutputs, CIRType, CParent>
141120 access,
@@ -146,9 +125,9 @@ namespace Rift::Compiler::LLVM
146125 TArray<llvm::Type*> inputTypes;
147126 for (AST::Id id : ids)
148127 {
128+ auto & functionComp = access.Add <CIRFunction>(id);
129+
149130 // Gather arguments
150- inputIds.Empty (false );
151- inputTypes.Empty (false );
152131 AST::Hierarchy::GetChildren (access, id, inputIds);
153132 AST::RemoveIfNot<CExprOutputs>(access, inputIds);
154133 AST::RemoveIfNot<CExprType>(access, inputIds);
@@ -175,59 +154,116 @@ namespace Rift::Compiler::LLVM
175154 // Create function
176155 const CIdentifier& ident = access.Get <const CIdentifier>(id);
177156 auto * functionType = FunctionType::get (builder.getVoidTy (), ToLLVM (inputTypes), false );
178- auto * function = Function::Create (
179- functionType, Function::ExternalLinkage, ToLLVM (ident.name ), &irModule);
157+ functionComp. instance = Function::Create (
158+ functionType, Function::ExternalLinkage, ToLLVM (ident.name ), &irModule);
180159
181160 // Set argument names
182- i32 i = 0 ;
183- for (auto & arg : function->args ())
161+ i32 i = 0 ;
162+ const auto & args = functionComp.instance ->args ();
163+ for (auto & arg : args)
184164 {
185165 Name name = Names::GetName (access, inputIds[i++]);
186166 arg.setName (ToLLVM (name));
187167 }
188- access.Add <CIRFunction>(id, {function});
168+
169+ // Cache final inputs
170+ functionComp.inputs = {args.begin (), args.end ()};
171+ functionComp.inputIds = inputIds;
172+ inputIds.Empty (false );
173+ inputTypes.Empty (false );
189174 }
190175 }
191176
192- void AddExprCalls (Context& context, LLVMContext& llvm, IRBuilder<>& builder,
193- TAccessRef<CExprCallId, CIRFunction, TWrite<CIRInstruction>> access )
177+ void AddStmtBlock (Context& context, LLVMContext& llvm, IRBuilder<>& builder,
178+ BlockAccessRef access, AST::Id firstStmtId, BasicBlock* block, const CIRFunction& function )
194179 {
195180 ZoneScoped;
196- for (AST::Id id : AST::ListAll<CExprCallId>(access))
181+ builder.SetInsertPoint (block);
182+
183+ AST::Id splitId = AST::NoId;
184+ TArray<AST::Id> stmtIds;
185+ AST::Statements::GetChain (access, firstStmtId, stmtIds, splitId);
186+
187+ for (AST::Id id : stmtIds)
197188 {
198- const AST::Id functionId = access.Get <const CExprCallId>(id).functionId ;
199- if (!access.IsValid (functionId))
189+ if (const auto * call = access.TryGet <const CExprCallId>(id))
200190 {
201- context.AddError (" Call to an unknown function" );
202- continue ;
191+ AddCall (context, llvm, builder, *call, access);
203192 }
204- const auto * function = access.TryGet <const CIRFunction>(functionId);
205- if (!Ensure (function))
193+ }
194+
195+ if (splitId != AST::NoId)
196+ {
197+ if (access.Has <const CStmtIf>(splitId))
206198 {
207- context.AddError (" Call to an invalid function" );
208- continue ;
199+ AddIf (context, llvm, builder, access, splitId, function);
209200 }
201+ }
202+ // TODO: Resolve continuation block and generate it
203+ }
204+
205+ BasicBlock* AddIf (Context& context, LLVMContext& llvm, IRBuilder<>& builder,
206+ BlockAccessRef access, AST::Id id, const CIRFunction& function)
207+ {
208+ const auto & outputs = access.Get <const CStmtOutputs>(id);
209+ const auto & connectedIds = outputs.linkInputNodes ;
210+ Check (connectedIds.Size () == 2 );
210211
211- // TODO: Make sure arguments match
212- // if (CalleeF->arg_size() != Args.size())
213- // context.AddError("Incorrect number of arguments provided");
212+ // Temporarily using value false until we have expressions
213+ Value* condV = ConstantInt::get (llvm, APInt (1 , false , true ));
214214
215- TArray<Value*> args;
216- access.Add <CIRInstruction>(
217- id, {CallInst::Create (function->instance , ToLLVM (args), " calltmp" )});
215+ BasicBlock* thenBlock = BasicBlock::Create (llvm, " then" );
216+ BasicBlock* elseBlock = BasicBlock::Create (llvm, " else" );
217+ BasicBlock* contBlock = BasicBlock::Create (llvm, " continue" );
218+ builder.CreateCondBr (condV, thenBlock, elseBlock);
219+
220+ function.instance ->getBasicBlockList ().push_back (thenBlock);
221+ AddStmtBlock (context, llvm, builder, access, connectedIds[0 ], thenBlock, function);
222+ builder.CreateBr (contBlock);
223+
224+ function.instance ->getBasicBlockList ().push_back (elseBlock);
225+ AddStmtBlock (context, llvm, builder, access, connectedIds[1 ], elseBlock, function);
226+ builder.CreateBr (contBlock);
227+
228+ function.instance ->getBasicBlockList ().push_back (contBlock);
229+ return contBlock;
230+ }
231+
232+ void AddCall (Context& context, LLVMContext& llvm, IRBuilder<>& builder, const CExprCallId& call,
233+ BlockAccessRef access)
234+ {
235+ const AST::Id functionId = call.functionId ;
236+ if (!access.IsValid (functionId))
237+ {
238+ context.AddError (" Call to an unknown function" );
239+ return ;
218240 }
241+ const auto * function = access.TryGet <const CIRFunction>(functionId);
242+ if (!Ensure (function))
243+ {
244+ context.AddError (" Call to an invalid function" );
245+ return ;
246+ }
247+
248+ TArray<Value*> args;
249+ // TODO: Pass arguments
250+ builder.CreateCall (function->instance , ToLLVM (args));
219251 }
220252
221- Value* AddIf (TAccessRef<CStmtIf> access, AST::Id id, AST::Id valueId)
253+ void DefineFunctions (Context& context, LLVMContext& llvm, IRBuilder<>& builder,
254+ BlockAccessRef access, TSpan<AST::Id> ids, Module& irModule)
222255 {
223- // Value* condV = value;
224- // Convert condition to a bool by comparing non-equal to 0.0.
225- // condV = builder.CreateFCmpONE(condV, ConstantFP::get(llvm, APFloat(0.0)), "ifcond");
226- // BasicBlock* thenBlock = BasicBlock::Create(llvm, "then", function);
227- // BasicBlock* elseBlock = BasicBlock::Create(llvm, "else");
228- // BasicBlock* mergeBlock = BasicBlock::Create(llvm, "ifcont");
229- // builder.CreateCondBr(condV, thenBlock, elseBlock);
230- return nullptr ;
256+ ZoneScoped;
257+ for (AST::Id id : ids)
258+ {
259+ const auto & irFunction = access.Get <const CIRFunction>(id);
260+ BasicBlock* block = BasicBlock::Create (llvm, " entry" , irFunction.instance );
261+
262+ const auto & output = access.Get <const CStmtOutput>(id);
263+ AddStmtBlock (context, llvm, builder, access, output.linkInputNode , block, irFunction);
264+
265+ verifyFunction (*irFunction.instance );
266+ }
231267 }
232268
233269
@@ -250,7 +286,7 @@ namespace Rift::Compiler::LLVM
250286 for (AST::Id id : AST::ListAll<CLiteralBool>(access))
251287 {
252288 const auto & boolean = access.Get <const CLiteralBool>(id);
253- Value* value = ConstantInt::get (llvm, APInt (8 , boolean.value , true ));
289+ Value* value = ConstantInt::get (llvm, APInt (1 , boolean.value , true ));
254290 access.Add <CIRValue>(id, value);
255291 }
256292 for (AST::Id id : AST::ListAll<CLiteralIntegral>(access))
@@ -296,7 +332,6 @@ namespace Rift::Compiler::LLVM
296332 AST::RemoveIfNot<CDeclStruct>(ast, structIds);
297333 AST::RemoveIfNot<CDeclClass>(ast, classIds);
298334
299-
300335 DeclareStructs (llvm, ast, structIds, false );
301336 DeclareStructs (llvm, ast, classIds, true ); // Declare classes
302337
@@ -305,9 +340,6 @@ namespace Rift::Compiler::LLVM
305340 AST::RemoveIfNot<CDeclFunction>(ast, functionIds);
306341 DeclareFunctions (context, llvm, builder, ast, functionIds, irModule);
307342
308- // Generate expressions
309- AddExprCalls (context, llvm, builder, ast);
310-
311343 DefineStructs (context, llvm, ast, structIds, false );
312344 DefineStructs (context, llvm, ast, classIds, true ); // Define classes
313345 DefineFunctions (context, llvm, builder, ast, functionIds, irModule);
0 commit comments