@@ -547,6 +547,49 @@ std::shared_ptr<ExecutableCode> LLVMCodeBuilder::finalize()
547547 break ;
548548 }
549549
550+ case LLVMInstruction::Type::StringConcat: {
551+ assert (step.args .size () == 2 );
552+ const auto &arg1 = step.args [0 ];
553+ const auto &arg2 = step.args [1 ];
554+ llvm::Value *str1 = castValue (arg1.second , arg1.first );
555+ llvm::Value *str2 = castValue (arg2.second , arg2.first );
556+ llvm::PointerType *charPointerType = m_builder.getInt16Ty ()->getPointerTo ();
557+ llvm::Function *memcpyFunc = llvm::Intrinsic::getDeclaration (m_module, llvm::Intrinsic::memcpy_inline, { charPointerType, charPointerType, m_builder.getInt64Ty () });
558+
559+ // StringPtr *result = string_pool_new(true)
560+ llvm::Value *result = m_builder.CreateCall (resolve_string_pool_new (), m_builder.getInt1 (true ));
561+ freeStringLater (result);
562+
563+ // result->size = string1->size + string2->size
564+ llvm::Value *sizeField1 = m_builder.CreateStructGEP (m_stringPtrType, str1, 1 );
565+ llvm::Value *sizeField2 = m_builder.CreateStructGEP (m_stringPtrType, str2, 1 );
566+ llvm::Value *size1 = m_builder.CreateLoad (m_builder.getInt64Ty (), sizeField1);
567+ llvm::Value *size2 = m_builder.CreateLoad (m_builder.getInt64Ty (), sizeField2);
568+ llvm::Value *resultSize = m_builder.CreateAdd (size1, size2);
569+ llvm::Value *resultSizeField = m_builder.CreateStructGEP (m_stringPtrType, result, 1 );
570+ m_builder.CreateStore (resultSize, resultSizeField);
571+
572+ // string_alloc(result, result->size)
573+ m_builder.CreateCall (resolve_string_alloc (), { result, resultSize });
574+
575+ // memcpy(result->data, string1->data, string1->size * sizeof(char16_t))
576+ llvm::Value *dataField1 = m_builder.CreateStructGEP (m_stringPtrType, str1, 0 );
577+ llvm::Value *data1 = m_builder.CreateLoad (charPointerType, dataField1);
578+ llvm::Value *resultDataField = m_builder.CreateStructGEP (m_stringPtrType, result, 0 );
579+ llvm::Value *writePtr = m_builder.CreateLoad (charPointerType, resultDataField);
580+ m_builder.CreateCall (memcpyFunc, { writePtr, data1, m_builder.CreateMul (size1, m_builder.getInt64 (2 )), m_builder.getInt1 (false ) });
581+
582+ // memcpy(result->data + string1->size, string2->data, (string2->size + 1) * sizeof(char16_t))
583+ // +1: null-terminate
584+ llvm::Value *dataField2 = m_builder.CreateStructGEP (m_stringPtrType, str2, 0 );
585+ llvm::Value *data2 = m_builder.CreateLoad (charPointerType, dataField2);
586+ writePtr = m_builder.CreateGEP (m_builder.getInt16Ty (), writePtr, size1);
587+ m_builder.CreateCall (memcpyFunc, { writePtr, data2, m_builder.CreateMul (m_builder.CreateAdd (size2, m_builder.getInt64 (1 )), m_builder.getInt64 (2 )), m_builder.getInt1 (false ) });
588+
589+ step.functionReturnReg ->value = result;
590+ break ;
591+ }
592+
550593 case LLVMInstruction::Type::Select: {
551594 assert (step.args .size () == 3 );
552595 const auto &arg1 = step.args [0 ];
@@ -1556,6 +1599,11 @@ CompilerValue *LLVMCodeBuilder::createExp10(CompilerValue *num)
15561599 return createOp (LLVMInstruction::Type::Exp10, Compiler::StaticType::Number, Compiler::StaticType::Number, { num });
15571600}
15581601
1602+ CompilerValue *LLVMCodeBuilder::createStringConcat (CompilerValue *string1, CompilerValue *string2)
1603+ {
1604+ return createOp (LLVMInstruction::Type::StringConcat, Compiler::StaticType::String, Compiler::StaticType::String, { string1, string2 });
1605+ }
1606+
15591607CompilerValue *LLVMCodeBuilder::createSelect (CompilerValue *cond, CompilerValue *trueValue, CompilerValue *falseValue, Compiler::StaticType valueType)
15601608{
15611609 LLVMRegister *ret = createOp (LLVMInstruction::Type::Select, valueType, { Compiler::StaticType::Bool, valueType, valueType }, { cond, trueValue, falseValue });
@@ -3217,6 +3265,11 @@ llvm::FunctionCallee LLVMCodeBuilder::resolve_string_pool_free()
32173265 return resolveFunction (" string_pool_free" , llvm::FunctionType::get (m_builder.getVoidTy (), { m_stringPtrType->getPointerTo () }, false ));
32183266}
32193267
3268+ llvm::FunctionCallee LLVMCodeBuilder::resolve_string_alloc ()
3269+ {
3270+ return resolveFunction (" string_alloc" , llvm::FunctionType::get (m_builder.getVoidTy (), { m_stringPtrType->getPointerTo (), m_builder.getInt64Ty () }, false ));
3271+ }
3272+
32203273llvm::FunctionCallee LLVMCodeBuilder::resolve_string_compare_case_sensitive ()
32213274{
32223275 llvm::Type *stringPtr = m_stringPtrType->getPointerTo ();
0 commit comments