Skip to content

Commit 3dd2f69

Browse files
authored
Merge pull request #56 from PipeRift/feature/ir-generation
Generate IR statements
2 parents 41ac386 + 235d329 commit 3dd2f69

25 files changed

Lines changed: 640 additions & 634 deletions

File tree

Libs/Backends/LLVM/Include/LLVMBackend/Components/CIRFunction.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright 2015-2022 Piperift - All rights reserved
22
#pragma once
33

4+
#include <AST/Types.h>
45
#include <llvm/IR/Function.h>
56
#include <Types/Struct.h>
67

@@ -13,7 +14,10 @@ namespace Rift
1314

1415
llvm::Function* instance = nullptr;
1516

17+
TArray<llvm::Value*> inputs;
18+
TArray<AST::Id> inputIds;
1619

17-
CIRFunction(llvm::Function* instance) : instance(instance) {}
20+
21+
CIRFunction() {}
1822
};
1923
} // namespace Rift

Libs/Backends/LLVM/Src/LLVMBackend/IRGeneration.cpp

Lines changed: 102 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -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);

Libs/Core

Submodule Core updated from 5534b59 to b43c438

Libs/Editor/Include/Utils/Properties.h

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,20 @@
22

33
#pragma once
44

5-
#include "AST/Tree.h"
6-
5+
#include <AST/Components/CDeclClass.h>
6+
#include <AST/Components/CDeclFunction.h>
7+
#include <AST/Components/CDeclFunctionLibrary.h>
8+
#include <AST/Components/CDeclNative.h>
9+
#include <AST/Components/CDeclStruct.h>
10+
#include <AST/Components/CDeclVariable.h>
11+
#include <AST/Components/CExprInput.h>
12+
#include <AST/Components/CExprOutputs.h>
13+
#include <AST/Components/CExprType.h>
14+
#include <AST/Components/CIdentifier.h>
15+
#include <AST/Components/CType.h>
16+
#include <AST/Filtering.h>
17+
#include <AST/Tree.h>
18+
#include <AST/Utils/TransactionUtils.h>
719
#include <Strings/StringView.h>
820

921

@@ -17,13 +29,18 @@ namespace Rift
1729
None = 0,
1830
HideValue = 1 << 0
1931
};
32+
33+
using TVariableAccessRef = TAccessRef<TWrite<CDeclVariable>, TWrite<CIdentifier>, CType,
34+
CDeclNative, CDeclStruct, CDeclClass, CParent>;
35+
2036
void DrawField(AST::Tree& ast, CTypeEditor& editor, AST::Id functionId, AST::Id fieldId,
2137
DrawFieldFlags flags = DrawFieldFlags::None);
2238

23-
void DrawVariable(AST::Tree& ast, CTypeEditor& editor, AST::Id variableId);
39+
void DrawVariable(TVariableAccessRef access, CTypeEditor& editor, AST::Id variableId);
2440
void DrawFunction(AST::Tree& ast, CTypeEditor& editor, AST::Id functionId);
2541

26-
void DrawVariables(AST::Tree& ast, CTypeEditor& editor, AST::Id typeId);
42+
void DrawVariables(TVariableAccessRef access, TransactionAccess transAccess,
43+
CTypeEditor& editor, AST::Id typeId);
2744
void DrawFunctions(AST::Tree& ast, CTypeEditor& editor, AST::Id typeId);
2845

2946
void DrawProperties(AST::Tree& ast, AST::Id typeId);

Libs/Editor/Include/Utils/Widgets.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,19 @@
22

33
#pragma once
44

5+
#include <AST/Components/CDeclClass.h>
6+
#include <AST/Components/CDeclNative.h>
7+
#include <AST/Components/CDeclStruct.h>
8+
#include <AST/Components/CType.h>
9+
#include <AST/Filtering.h>
510
#include <AST/Tree.h>
611
#include <Strings/StringView.h>
712

813

914
namespace Rift::Editor
1015
{
11-
bool TypeCombo(AST::Tree& ast, StringView label, AST::Id& selectedTypeId);
16+
bool TypeCombo(TAccessRef<CType, CDeclNative, CDeclStruct, CDeclClass> access, StringView label,
17+
AST::Id& selectedTypeId);
1218

1319
bool InputLiteralValue(AST::Tree& ast, StringView label, AST::Id literalId);
1420
} // namespace Rift::Editor

0 commit comments

Comments
 (0)