88#include < scratchcpp/iengine.h>
99#include < scratchcpp/variable.h>
1010#include < scratchcpp/list.h>
11- #include < scratchcpp/blockprototype.h>
1211#include < scratchcpp/dev/compilerconstant.h>
1312#include < scratchcpp/dev/compilerlocalvariable.h>
1413
@@ -38,6 +37,9 @@ LLVMCodeBuilder::LLVMCodeBuilder(LLVMCompilerContext *ctx, BlockPrototype *proce
3837 initTypes ();
3938 createVariableMap ();
4039 createListMap ();
40+
41+ llvm::FunctionType *funcType = getMainFunctionType (nullptr );
42+ m_defaultArgCount = funcType->getNumParams ();
4143}
4244
4345std::shared_ptr<ExecutableCode> LLVMCodeBuilder::finalize ()
@@ -1030,15 +1032,15 @@ std::shared_ptr<ExecutableCode> LLVMCodeBuilder::finalize()
10301032
10311033 case LLVMInstruction::Type::CallProcedure: {
10321034 assert (step.procedurePrototype );
1035+ assert (step.args .size () == step.procedurePrototype ->argumentTypes ().size ());
10331036 freeScopeHeap ();
10341037 syncVariables (targetVariables);
10351038
10361039 std::string name = getMainFunctionName (step.procedurePrototype );
10371040 llvm::FunctionType *type = getMainFunctionType (step.procedurePrototype );
10381041 std::vector<llvm::Value *> args;
1039- const size_t argCount = type->getNumParams () - 1 - step.procedurePrototype ->argumentTypes ().size (); // omit warp arg and procedure args
10401042
1041- for (size_t i = 0 ; i < argCount ; i++)
1043+ for (size_t i = 0 ; i < m_defaultArgCount ; i++)
10421044 args.push_back (func->getArg (i));
10431045
10441046 // Add warp arg
@@ -1047,7 +1049,14 @@ std::shared_ptr<ExecutableCode> LLVMCodeBuilder::finalize()
10471049 else
10481050 args.push_back (m_procedurePrototype ? warpArg : m_builder.getInt1 (false ));
10491051
1050- // TODO: Add procedure args
1052+ // Add procedure args
1053+ for (const auto &arg : step.args ) {
1054+ if (arg.first == Compiler::StaticType::Unknown)
1055+ args.push_back (createValue (arg.second ));
1056+ else
1057+ args.push_back (castValue (arg.second , arg.first ));
1058+ }
1059+
10511060 llvm::Value *handle = m_builder.CreateCall (resolveFunction (name, type), args);
10521061
10531062 if (!m_warp && !step.procedurePrototype ->warp ()) {
@@ -1068,6 +1077,13 @@ std::shared_ptr<ExecutableCode> LLVMCodeBuilder::finalize()
10681077 reloadLists ();
10691078 break ;
10701079 }
1080+
1081+ case LLVMInstruction::Type::ProcedureArg: {
1082+ assert (m_procedurePrototype);
1083+ llvm::Value *arg = func->getArg (m_defaultArgCount + 1 + step.procedureArgIndex ); // omit warp arg
1084+ step.functionReturnReg ->value = arg;
1085+ break ;
1086+ }
10711087 }
10721088 }
10731089
@@ -1230,6 +1246,31 @@ CompilerValue *LLVMCodeBuilder::addListSize(List *list)
12301246 return createOp (ins, Compiler::StaticType::Number);
12311247}
12321248
1249+ CompilerValue *LLVMCodeBuilder::addProcedureArgument (const std::string &name)
1250+ {
1251+ if (!m_procedurePrototype)
1252+ return addConstValue (Value ());
1253+
1254+ const auto &argNames = m_procedurePrototype->argumentNames ();
1255+ auto it = std::find (argNames.begin (), argNames.end (), name);
1256+
1257+ if (it == argNames.end ()) {
1258+ std::cout << " warning: could not find argument '" << name << " ' in custom block '" << m_procedurePrototype->procCode () << " '" << std::endl;
1259+ return addConstValue (Value ());
1260+ }
1261+
1262+ const auto index = it - argNames.begin ();
1263+ const Compiler::StaticType type = getProcedureArgType (m_procedurePrototype->argumentTypes ()[index]);
1264+ LLVMInstruction ins (LLVMInstruction::Type::ProcedureArg);
1265+ auto ret = std::make_shared<LLVMRegister>(type);
1266+ ret->isRawValue = (type != Compiler::StaticType::Unknown);
1267+ ins.functionReturnReg = ret.get ();
1268+ ins.procedureArgIndex = index;
1269+
1270+ m_instructions.push_back (ins);
1271+ return addReg (ret);
1272+ }
1273+
12331274CompilerValue *LLVMCodeBuilder::createAdd (CompilerValue *operand1, CompilerValue *operand2)
12341275{
12351276 return createOp (LLVMInstruction::Type::Add, Compiler::StaticType::Number, Compiler::StaticType::Number, { operand1, operand2 });
@@ -1502,11 +1543,19 @@ void LLVMCodeBuilder::createStop()
15021543 m_instructions.push_back ({ LLVMInstruction::Type::Stop });
15031544}
15041545
1505- void LLVMCodeBuilder::createProcedureCall (BlockPrototype *prototype)
1546+ void LLVMCodeBuilder::createProcedureCall (BlockPrototype *prototype, const Compiler::Args &args )
15061547{
1548+ assert (prototype);
1549+ assert (prototype->argumentTypes ().size () == args.size ());
1550+ const auto &procedureArgs = prototype->argumentTypes ();
1551+ Compiler::ArgTypes types;
1552+
1553+ for (BlockPrototype::ArgType type : procedureArgs)
1554+ types.push_back (getProcedureArgType (type));
1555+
15071556 LLVMInstruction ins (LLVMInstruction::Type::CallProcedure);
15081557 ins.procedurePrototype = prototype;
1509- m_instructions. push_back (ins);
1558+ createOp (ins, Compiler::StaticType::Void, types, args );
15101559}
15111560
15121561void LLVMCodeBuilder::initTypes ()
@@ -1920,6 +1969,11 @@ llvm::Type *LLVMCodeBuilder::getType(Compiler::StaticType type)
19201969 }
19211970}
19221971
1972+ Compiler::StaticType LLVMCodeBuilder::getProcedureArgType (BlockPrototype::ArgType type)
1973+ {
1974+ return type == BlockPrototype::ArgType::Bool ? Compiler::StaticType::Bool : Compiler::StaticType::Unknown;
1975+ }
1976+
19231977llvm::Value *LLVMCodeBuilder::isNaN (llvm::Value *num)
19241978{
19251979 return m_builder.CreateFCmpUNO (num, num);
0 commit comments