@@ -590,6 +590,45 @@ std::shared_ptr<ExecutableCode> LLVMCodeBuilder::finalize()
590590 break ;
591591 }
592592
593+ case LLVMInstruction::Type::StringChar: {
594+ assert (step.args .size () == 2 );
595+ const auto &arg1 = step.args [0 ];
596+ const auto &arg2 = step.args [1 ];
597+ llvm::Value *str = castValue (arg1.second , arg1.first );
598+ llvm::Value *index = m_builder.CreateFPToSI (castValue (arg2.second , arg2.first ), m_builder.getInt64Ty ());
599+ llvm::PointerType *charPointerType = m_builder.getInt16Ty ()->getPointerTo ();
600+
601+ // Get data ptr and size
602+ llvm::Value *dataField = m_builder.CreateStructGEP (m_stringPtrType, str, 0 );
603+ llvm::Value *data = m_builder.CreateLoad (charPointerType, dataField);
604+ llvm::Value *sizeField = m_builder.CreateStructGEP (m_stringPtrType, str, 1 );
605+ llvm::Value *size = m_builder.CreateLoad (m_builder.getInt64Ty (), sizeField);
606+
607+ // Check range, get character ptr
608+ llvm::Value *inRange = m_builder.CreateAnd (m_builder.CreateICmpSGE (index, m_builder.getInt64 (0 )), m_builder.CreateICmpSLT (index, size));
609+ llvm::Value *charPtr = m_builder.CreateGEP (m_builder.getInt16Ty (), data, index);
610+
611+ // Allocate string
612+ llvm::Value *result = m_builder.CreateCall (resolve_string_pool_new (), m_builder.getInt1 (true ));
613+ freeStringLater (result);
614+ m_builder.CreateCall (resolve_string_alloc (), { result, m_builder.getInt64 (1 ) }); // size 1 to avoid branching
615+
616+ // Get result data ptr
617+ dataField = m_builder.CreateStructGEP (m_stringPtrType, result, 0 );
618+ data = m_builder.CreateLoad (charPointerType, dataField);
619+
620+ // Write result
621+ llvm::Value *char1 = m_builder.CreateGEP (m_builder.getInt16Ty (), data, m_builder.getInt64 (0 ));
622+ llvm::Value *char2 = m_builder.CreateGEP (m_builder.getInt16Ty (), data, m_builder.getInt64 (1 ));
623+ sizeField = m_builder.CreateStructGEP (m_stringPtrType, result, 1 );
624+ m_builder.CreateStore (m_builder.CreateSelect (inRange, m_builder.CreateLoad (m_builder.getInt16Ty (), charPtr), m_builder.getInt16 (0 )), char1);
625+ m_builder.CreateStore (m_builder.getInt16 (0 ), char2);
626+ m_builder.CreateStore (m_builder.CreateSelect (inRange, m_builder.getInt64 (1 ), m_builder.getInt64 (0 )), sizeField);
627+
628+ step.functionReturnReg ->value = result;
629+ break ;
630+ }
631+
593632 case LLVMInstruction::Type::Select: {
594633 assert (step.args .size () == 3 );
595634 const auto &arg1 = step.args [0 ];
@@ -1335,6 +1374,11 @@ CompilerConstant *LLVMCodeBuilder::addConstValue(const Value &value)
13351374 return static_cast <CompilerConstant *>(static_cast <CompilerValue *>(addReg (reg, nullptr )));
13361375}
13371376
1377+ CompilerValue *LLVMCodeBuilder::addStringChar (CompilerValue *string, CompilerValue *index)
1378+ {
1379+ return createOp (LLVMInstruction::Type::StringChar, Compiler::StaticType::String, { Compiler::StaticType::String, Compiler::StaticType::Number }, { string, index });
1380+ }
1381+
13381382CompilerValue *LLVMCodeBuilder::addLoopIndex ()
13391383{
13401384 return createOp (LLVMInstruction::Type::LoopIndex, Compiler::StaticType::Number, {}, {});
0 commit comments