Skip to content

Commit e94e605

Browse files
authored
Merge pull request #642 from scratchcpp/refactor_llvm_code_builder
Refactor LLVMCodeBuilder
2 parents 8f183a2 + 0c65342 commit e94e605

File tree

102 files changed

+31284
-7448
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

102 files changed

+31284
-7448
lines changed

include/scratchcpp/list.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,13 @@ class LIBSCRATCHCPP_EXPORT List : public Entity
4141
void setMonitor(Monitor *monitor);
4242

4343
/*! Returns a pointer to the raw list data. */
44-
inline ValueData *data() const { return m_dataPtr->data(); }
44+
inline ValueData *data() const { return m_rawDataPtr; }
45+
46+
/*!
47+
* Returns a pointer to pointer to the raw list data.
48+
* \note This is used internally by compiled code for various optimizations.
49+
*/
50+
inline ValueData *const *dataPtr() const { return &m_rawDataPtr; }
4551

4652
/*!
4753
* Returns a pointer to the list size.
@@ -247,6 +253,8 @@ class LIBSCRATCHCPP_EXPORT List : public Entity
247253
value_free(&m_dataPtr->back());
248254
m_dataPtr->erase(m_dataPtr->end());
249255
}
256+
257+
m_rawDataPtr = m_dataPtr->data();
250258
}
251259

252260
inline size_t getAllocSize(size_t x)
@@ -264,6 +272,7 @@ class LIBSCRATCHCPP_EXPORT List : public Entity
264272

265273
spimpl::unique_impl_ptr<ListPrivate> impl;
266274
veque::veque<ValueData> *m_dataPtr = nullptr; // NOTE: accessing through pointer is faster! (from benchmarks)
275+
ValueData *m_rawDataPtr = nullptr;
267276
size_t m_size = 0;
268277
};
269278

src/engine/compiler.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ std::shared_ptr<ExecutableCode> Compiler::compile(Block *startBlock, CodeType co
8383
}
8484

8585
impl->block = nullptr;
86-
return impl->builder->finalize();
86+
return impl->builder->build();
8787
}
8888

8989
while (impl->block) {
@@ -122,7 +122,7 @@ std::shared_ptr<ExecutableCode> Compiler::compile(Block *startBlock, CodeType co
122122
impl->substackEnd();
123123
}
124124

125-
return impl->builder->finalize();
125+
return impl->builder->build();
126126
}
127127

128128
/*!

src/engine/internal/engine.cpp

Lines changed: 20 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -528,8 +528,8 @@ void Engine::step()
528528
m_frameActivity = !m_threads.empty();
529529

530530
// Resolve stopped broadcast scripts
531-
std::vector<Broadcast *> resolved;
532-
std::vector<Thread *> resolvedThreads;
531+
std::unordered_map<Broadcast *, Thread *> stoppedBroadcasts; // sender thread
532+
std::unordered_map<Thread *, bool> runningStatus; // sender thread
533533

534534
for (const auto &[broadcast, senderThread] : m_broadcastSenders) {
535535
std::unordered_map<Broadcast *, std::vector<Script *>> *broadcastMap = nullptr;
@@ -544,44 +544,41 @@ void Engine::step()
544544
broadcastMap = &m_broadcastMap;
545545
}
546546

547-
bool found = false;
547+
bool isRunning = false;
548548

549549
if (broadcastMap->find(broadcast) != broadcastMap->cend()) {
550550
const auto &scripts = (*broadcastMap)[broadcast];
551551

552552
for (auto script : scripts) {
553553
if (std::find_if(m_threads.begin(), m_threads.end(), [script](std::shared_ptr<Thread> thread) { return thread->script() == script; }) != m_threads.end()) {
554-
found = true;
554+
isRunning = true;
555555
break;
556556
}
557557
}
558558
}
559559

560-
if (found) {
561-
// If a broadcast with the same name but different case
562-
// was considered stopped before, restore the promise.
563-
if (std::find(resolvedThreads.begin(), resolvedThreads.end(), senderThread) != resolvedThreads.end()) {
564-
senderThread->promise();
565-
resolvedThreads.erase(std::remove(resolvedThreads.begin(), resolvedThreads.end(), senderThread), resolvedThreads.end());
566-
}
567-
} else {
568-
Thread *th = senderThread;
560+
if (runningStatus.find(senderThread) == runningStatus.cend() || isRunning)
561+
runningStatus[senderThread] = isRunning;
569562

570-
if (std::find_if(m_threads.begin(), m_threads.end(), [th](std::shared_ptr<Thread> thread) { return thread.get() == th; }) != m_threads.end()) {
571-
auto promise = th->promise();
563+
if (!isRunning)
564+
stoppedBroadcasts[broadcast] = senderThread;
565+
}
572566

573-
if (promise)
574-
promise->resolve();
575-
}
567+
for (const auto &[broadcast, senderThread] : stoppedBroadcasts) {
568+
m_broadcastSenders.erase(broadcast);
576569

577-
resolved.push_back(broadcast);
578-
resolvedThreads.push_back(th);
570+
// Resolve broadcast promise
571+
Thread *th = senderThread;
572+
573+
if (std::find_if(m_threads.begin(), m_threads.end(), [th](std::shared_ptr<Thread> thread) { return thread.get() == th; }) != m_threads.end()) {
574+
auto promise = th->promise().get();
575+
576+
// Resolve only if all broadcasts of the same name but different case are stopped
577+
if (promise && !runningStatus[senderThread])
578+
promise->resolve();
579579
}
580580
}
581581

582-
for (Broadcast *broadcast : resolved)
583-
m_broadcastSenders.erase(broadcast);
584-
585582
m_redrawRequested = false;
586583

587584
// Step threads

src/engine/internal/icodebuilder.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class ICodeBuilder
1818
public:
1919
virtual ~ICodeBuilder() { }
2020

21-
virtual std::shared_ptr<ExecutableCode> finalize() = 0;
21+
virtual std::shared_ptr<ExecutableCode> build() = 0;
2222

2323
virtual CompilerValue *addFunctionCall(const std::string &functionName, Compiler::StaticType returnType, const Compiler::ArgTypes &argTypes, const Compiler::Args &args) = 0;
2424
virtual CompilerValue *addTargetFunctionCall(const std::string &functionName, Compiler::StaticType returnType, const Compiler::ArgTypes &argTypes, const Compiler::Args &args) = 0;
Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,32 @@
11
target_sources(scratchcpp
22
PRIVATE
3+
llvmbuildutils.cpp
4+
llvmbuildutils.h
35
llvmcodebuilder.cpp
46
llvmcodebuilder.h
57
llvmregister.h
68
llvmconstantregister.h
79
llvminstruction.h
10+
llvminstructionlist.cpp
11+
llvminstructionlist.h
812
llvmifstatement.h
913
llvmloop.h
1014
llvmcoroutine.cpp
1115
llvmcoroutine.h
1216
llvmvariableptr.h
1317
llvmlistptr.h
14-
llvmprocedure.h
1518
llvmtypes.cpp
1619
llvmtypes.h
1720
llvmfunctions.cpp
18-
llvmloopscope.h
21+
llvmfunctions.h
22+
llvmtypeanalyzer.cpp
23+
llvmtypeanalyzer.h
1924
llvmcompilercontext.cpp
2025
llvmcompilercontext.h
2126
llvmexecutablecode.cpp
2227
llvmexecutablecode.h
2328
llvmexecutioncontext.cpp
2429
llvmexecutioncontext.h
2530
)
31+
32+
add_subdirectory(instructions)
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
target_sources(scratchcpp
2+
PRIVATE
3+
instructionbuilder.cpp
4+
instructionbuilder.h
5+
instructiongroup.cpp
6+
instructiongroup.h
7+
processresult.h
8+
)
9+
10+
target_sources(scratchcpp
11+
PRIVATE
12+
functions.cpp
13+
functions.h
14+
math.cpp
15+
math.h
16+
comparison.cpp
17+
comparison.h
18+
string.cpp
19+
string.h
20+
logic.cpp
21+
logic.h
22+
control.cpp
23+
control.h
24+
variables.cpp
25+
variables.h
26+
lists.cpp
27+
lists.h
28+
procedures.cpp
29+
procedures.h
30+
)
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
3+
#include "comparison.h"
4+
#include "../llvminstruction.h"
5+
#include "../llvmbuildutils.h"
6+
7+
using namespace libscratchcpp;
8+
using namespace libscratchcpp::llvmins;
9+
10+
ProcessResult Comparison::process(LLVMInstruction *ins)
11+
{
12+
ProcessResult ret(true, ins);
13+
14+
switch (ins->type) {
15+
case LLVMInstruction::Type::CmpEQ:
16+
ret.next = buildCmpEQ(ins);
17+
break;
18+
19+
case LLVMInstruction::Type::CmpGT:
20+
ret.next = buildCmpGT(ins);
21+
break;
22+
23+
case LLVMInstruction::Type::CmpLT:
24+
ret.next = buildCmpLT(ins);
25+
break;
26+
27+
case LLVMInstruction::Type::StrCmpEQCS:
28+
ret.next = buildStrCmpEQCS(ins);
29+
break;
30+
31+
case LLVMInstruction::Type::StrCmpEQCI:
32+
ret.next = buildStrCmpEQCI(ins);
33+
break;
34+
35+
default:
36+
ret.match = false;
37+
break;
38+
}
39+
40+
return ret;
41+
}
42+
43+
LLVMInstruction *Comparison::buildCmpEQ(LLVMInstruction *ins)
44+
{
45+
assert(ins->args.size() == 2);
46+
const auto &arg1 = ins->args[0].second;
47+
const auto &arg2 = ins->args[1].second;
48+
ins->functionReturnReg->value = m_utils.createComparison(arg1, arg2, LLVMBuildUtils::Comparison::EQ);
49+
50+
return ins->next;
51+
}
52+
53+
LLVMInstruction *Comparison::buildCmpGT(LLVMInstruction *ins)
54+
{
55+
assert(ins->args.size() == 2);
56+
const auto &arg1 = ins->args[0].second;
57+
const auto &arg2 = ins->args[1].second;
58+
ins->functionReturnReg->value = m_utils.createComparison(arg1, arg2, LLVMBuildUtils::Comparison::GT);
59+
60+
return ins->next;
61+
}
62+
63+
LLVMInstruction *Comparison::buildCmpLT(LLVMInstruction *ins)
64+
{
65+
assert(ins->args.size() == 2);
66+
const auto &arg1 = ins->args[0].second;
67+
const auto &arg2 = ins->args[1].second;
68+
ins->functionReturnReg->value = m_utils.createComparison(arg1, arg2, LLVMBuildUtils::Comparison::LT);
69+
70+
return ins->next;
71+
}
72+
73+
LLVMInstruction *Comparison::buildStrCmpEQCS(LLVMInstruction *ins)
74+
{
75+
assert(ins->args.size() == 2);
76+
const auto &arg1 = ins->args[0].second;
77+
const auto &arg2 = ins->args[1].second;
78+
ins->functionReturnReg->value = m_utils.createStringComparison(arg1, arg2, true);
79+
80+
return ins->next;
81+
}
82+
83+
LLVMInstruction *Comparison::buildStrCmpEQCI(LLVMInstruction *ins)
84+
{
85+
assert(ins->args.size() == 2);
86+
const auto &arg1 = ins->args[0].second;
87+
const auto &arg2 = ins->args[1].second;
88+
ins->functionReturnReg->value = m_utils.createStringComparison(arg1, arg2, false);
89+
90+
return ins->next;
91+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
3+
#pragma once
4+
5+
#include "instructiongroup.h"
6+
7+
namespace libscratchcpp::llvmins
8+
{
9+
10+
class Comparison : public InstructionGroup
11+
{
12+
public:
13+
using InstructionGroup::InstructionGroup;
14+
15+
ProcessResult process(LLVMInstruction *ins) override;
16+
17+
private:
18+
LLVMInstruction *buildCmpEQ(LLVMInstruction *ins);
19+
LLVMInstruction *buildCmpGT(LLVMInstruction *ins);
20+
LLVMInstruction *buildCmpLT(LLVMInstruction *ins);
21+
LLVMInstruction *buildStrCmpEQCS(LLVMInstruction *ins);
22+
LLVMInstruction *buildStrCmpEQCI(LLVMInstruction *ins);
23+
};
24+
25+
} // namespace libscratchcpp::llvmins

0 commit comments

Comments
 (0)