@@ -414,86 +414,293 @@ llvm::Value *LLVMBuildUtils::castValue(LLVMRegister *reg, Compiler::StaticType t
414414 assert (reg->type () != Compiler::StaticType::Void && targetType != Compiler::StaticType::Void);
415415
416416 switch (targetType) {
417- case Compiler::StaticType::Number:
418- switch (reg->type ()) {
419- case Compiler::StaticType::Number: {
420- // Read number directly
417+ case Compiler::StaticType::Number: {
418+ Compiler::StaticType type = reg->type ();
419+ bool singleType = isSingleType (type);
420+
421+ if (singleType) {
422+ // Handle single type cases directly
423+ switch (type) {
424+ case Compiler::StaticType::Number: {
425+ // Read number directly
426+ llvm::Value *ptr = m_builder.CreateStructGEP (m_valueDataType, reg->value , 0 );
427+ return m_builder.CreateLoad (m_builder.getDoubleTy (), ptr);
428+ }
429+
430+ case Compiler::StaticType::Bool: {
431+ // Read boolean and cast to double
432+ llvm::Value *ptr = m_builder.CreateStructGEP (m_valueDataType, reg->value , 0 );
433+ llvm::Value *boolValue = m_builder.CreateLoad (m_builder.getInt1Ty (), ptr);
434+ return m_builder.CreateUIToFP (boolValue, m_builder.getDoubleTy ());
435+ }
436+
437+ case Compiler::StaticType::String:
438+ // Convert to double
439+ // TODO: Use value_stringToDouble()
440+ return m_builder.CreateCall (m_functions.resolve_value_toDouble (), reg->value );
441+
442+ default :
443+ assert (false );
444+ return nullptr ;
445+ }
446+ } else {
447+ // Handle multiple type cases with runtime switch
448+ llvm::Value *typePtr = m_builder.CreateStructGEP (m_valueDataType, reg->value , 1 );
449+ llvm::Value *loadedType = m_builder.CreateLoad (m_builder.getInt32Ty (), typePtr);
450+
451+ llvm::BasicBlock *mergeBlock = llvm::BasicBlock::Create (m_llvmCtx, " merge" , m_function);
452+ llvm::BasicBlock *defaultBlock = llvm::BasicBlock::Create (m_llvmCtx, " default" , m_function);
453+
454+ llvm::SwitchInst *sw = m_builder.CreateSwitch (loadedType, defaultBlock, 4 );
455+
456+ std::vector<std::pair<llvm::BasicBlock *, llvm::Value *>> results;
457+
458+ // Number case
459+ if ((type & Compiler::StaticType::Number) == Compiler::StaticType::Number) {
460+ llvm::BasicBlock *numberBlock = llvm::BasicBlock::Create (m_llvmCtx, " number" , m_function);
461+ sw->addCase (m_builder.getInt32 (static_cast <uint32_t >(ValueType::Number)), numberBlock);
462+
463+ m_builder.SetInsertPoint (numberBlock);
421464 llvm::Value *ptr = m_builder.CreateStructGEP (m_valueDataType, reg->value , 0 );
422- return m_builder.CreateLoad (m_builder.getDoubleTy (), ptr);
465+ llvm::Value *numberResult = m_builder.CreateLoad (m_builder.getDoubleTy (), ptr);
466+ m_builder.CreateBr (mergeBlock);
467+ results.push_back ({ numberBlock, numberResult });
423468 }
424469
425- case Compiler::StaticType::Bool: {
426- // Read boolean and cast to double
470+ // Bool case
471+ if ((type & Compiler::StaticType::Bool) == Compiler::StaticType::Bool) {
472+ llvm::BasicBlock *boolBlock = llvm::BasicBlock::Create (m_llvmCtx, " bool" , m_function);
473+ sw->addCase (m_builder.getInt32 (static_cast <uint32_t >(ValueType::Bool)), boolBlock);
474+
475+ m_builder.SetInsertPoint (boolBlock);
427476 llvm::Value *ptr = m_builder.CreateStructGEP (m_valueDataType, reg->value , 0 );
428477 llvm::Value *boolValue = m_builder.CreateLoad (m_builder.getInt1Ty (), ptr);
429- return m_builder.CreateSIToFP (boolValue, m_builder.getDoubleTy ());
478+ llvm::Value *boolResult = m_builder.CreateUIToFP (boolValue, m_builder.getDoubleTy ());
479+ m_builder.CreateBr (mergeBlock);
480+ results.push_back ({ boolBlock, boolResult });
430481 }
431482
432- case Compiler::StaticType::String:
433- case Compiler::StaticType::Unknown: {
434- // Convert to double
435- return m_builder.CreateCall (m_functions.resolve_value_toDouble (), reg->value );
483+ // String case
484+ if ((type & Compiler::StaticType::String) == Compiler::StaticType::String) {
485+ llvm::BasicBlock *stringBlock = llvm::BasicBlock::Create (m_llvmCtx, " string" , m_function);
486+ sw->addCase (m_builder.getInt32 (static_cast <uint32_t >(ValueType::String)), stringBlock);
487+
488+ m_builder.SetInsertPoint (stringBlock);
489+ // TODO: Use value_stringToDouble()
490+ llvm::Value *stringResult = m_builder.CreateCall (m_functions.resolve_value_toDouble (), reg->value );
491+ m_builder.CreateBr (mergeBlock);
492+ results.push_back ({ stringBlock, stringResult });
436493 }
437494
438- default :
439- assert (false );
440- return nullptr ;
495+ // Default case
496+ m_builder.SetInsertPoint (defaultBlock);
497+
498+ // All possible types are covered, mark as unreachable
499+ m_builder.CreateUnreachable ();
500+
501+ // Create phi node to merge results
502+ m_builder.SetInsertPoint (mergeBlock);
503+ llvm::PHINode *result = m_builder.CreatePHI (m_builder.getDoubleTy (), results.size ());
504+
505+ for (auto &pair : results)
506+ result->addIncoming (pair.second , pair.first );
507+
508+ return result;
441509 }
510+ }
442511
443- case Compiler::StaticType::Bool:
444- switch (reg->type ()) {
445- case Compiler::StaticType::Number: {
446- // True if != 0
512+ case Compiler::StaticType::Bool: {
513+ Compiler::StaticType type = reg->type ();
514+ bool singleType = isSingleType (type);
515+
516+ if (singleType) {
517+ // Handle single type cases directly
518+ switch (type) {
519+ case Compiler::StaticType::Number: {
520+ // True if != 0
521+ llvm::Value *ptr = m_builder.CreateStructGEP (m_valueDataType, reg->value , 0 );
522+ llvm::Value *numberValue = m_builder.CreateLoad (m_builder.getDoubleTy (), ptr);
523+ return m_builder.CreateFCmpONE (numberValue, llvm::ConstantFP::get (m_llvmCtx, llvm::APFloat (0.0 )));
524+ }
525+
526+ case Compiler::StaticType::Bool: {
527+ // Read boolean directly
528+ llvm::Value *ptr = m_builder.CreateStructGEP (m_valueDataType, reg->value , 0 );
529+ return m_builder.CreateLoad (m_builder.getInt1Ty (), ptr);
530+ }
531+
532+ case Compiler::StaticType::String:
533+ // Convert to bool
534+ // TODO: Use value_stringToBool()
535+ return m_builder.CreateCall (m_functions.resolve_value_toBool (), reg->value );
536+
537+ default :
538+ assert (false );
539+ return nullptr ;
540+ }
541+ } else {
542+ // Handle multiple type cases with runtime switch
543+ llvm::Value *typePtr = m_builder.CreateStructGEP (m_valueDataType, reg->value , 1 );
544+ llvm::Value *loadedType = m_builder.CreateLoad (m_builder.getInt32Ty (), typePtr);
545+
546+ llvm::BasicBlock *mergeBlock = llvm::BasicBlock::Create (m_llvmCtx, " merge" , m_function);
547+ llvm::BasicBlock *defaultBlock = llvm::BasicBlock::Create (m_llvmCtx, " default" , m_function);
548+
549+ llvm::SwitchInst *sw = m_builder.CreateSwitch (loadedType, defaultBlock, 4 );
550+
551+ std::vector<std::pair<llvm::BasicBlock *, llvm::Value *>> results;
552+
553+ // Number case
554+ if ((type & Compiler::StaticType::Number) == Compiler::StaticType::Number) {
555+ llvm::BasicBlock *numberBlock = llvm::BasicBlock::Create (m_llvmCtx, " number" , m_function);
556+ sw->addCase (m_builder.getInt32 (static_cast <uint32_t >(ValueType::Number)), numberBlock);
557+
558+ m_builder.SetInsertPoint (numberBlock);
447559 llvm::Value *ptr = m_builder.CreateStructGEP (m_valueDataType, reg->value , 0 );
448560 llvm::Value *numberValue = m_builder.CreateLoad (m_builder.getDoubleTy (), ptr);
449- return m_builder.CreateFCmpONE (numberValue, llvm::ConstantFP::get (m_llvmCtx, llvm::APFloat (0.0 )));
561+ llvm::Value *numberResult = m_builder.CreateFCmpONE (numberValue, llvm::ConstantFP::get (m_llvmCtx, llvm::APFloat (0.0 )));
562+ m_builder.CreateBr (mergeBlock);
563+ results.push_back ({ numberBlock, numberResult });
450564 }
451565
452- case Compiler::StaticType::Bool: {
453- // Read boolean directly
566+ // Bool case
567+ if ((type & Compiler::StaticType::Bool) == Compiler::StaticType::Bool) {
568+ llvm::BasicBlock *boolBlock = llvm::BasicBlock::Create (m_llvmCtx, " bool" , m_function);
569+ sw->addCase (m_builder.getInt32 (static_cast <uint32_t >(ValueType::Bool)), boolBlock);
570+
571+ m_builder.SetInsertPoint (boolBlock);
454572 llvm::Value *ptr = m_builder.CreateStructGEP (m_valueDataType, reg->value , 0 );
455- return m_builder.CreateLoad (m_builder.getInt1Ty (), ptr);
573+ llvm::Value *boolResult = m_builder.CreateLoad (m_builder.getInt1Ty (), ptr);
574+ m_builder.CreateBr (mergeBlock);
575+ results.push_back ({ boolBlock, boolResult });
456576 }
457577
458- case Compiler::StaticType:: String:
459- case Compiler::StaticType::Unknown:
460- // Convert to bool
461- return m_builder.CreateCall (m_functions. resolve_value_toBool (), reg-> value );
578+ // String case
579+ if ((type & Compiler::StaticType::String) == Compiler::StaticType::String) {
580+ llvm::BasicBlock *stringBlock = llvm::BasicBlock::Create (m_llvmCtx, " string " , m_function);
581+ sw-> addCase ( m_builder.getInt32 ( static_cast < uint32_t >(ValueType::String)), stringBlock );
462582
463- default :
464- assert (false );
465- return nullptr ;
583+ m_builder.SetInsertPoint (stringBlock);
584+ // TODO: Use value_stringToBool()
585+ llvm::Value *stringResult = m_builder.CreateCall (m_functions.resolve_value_toBool (), reg->value );
586+ m_builder.CreateBr (mergeBlock);
587+ results.push_back ({ stringBlock, stringResult });
588+ }
589+
590+ // Default case
591+ m_builder.SetInsertPoint (defaultBlock);
592+
593+ // All possible types are covered, mark as unreachable
594+ m_builder.CreateUnreachable ();
595+
596+ // Create phi node to merge results
597+ m_builder.SetInsertPoint (mergeBlock);
598+ llvm::PHINode *result = m_builder.CreatePHI (m_builder.getInt1Ty (), results.size ());
599+
600+ for (auto &pair : results)
601+ result->addIncoming (pair.second , pair.first );
602+
603+ return result;
466604 }
605+ }
467606
468- case Compiler::StaticType::String:
469- switch (reg->type ()) {
470- case Compiler::StaticType::Number:
471- case Compiler::StaticType::Bool:
472- case Compiler::StaticType::Unknown: {
473- // Cast to string
474- // TODO: Use value_stringToDouble() and value_stringToBool()
475- llvm::Value *ptr = m_builder.CreateCall (m_functions.resolve_value_toStringPtr (), reg->value );
476- freeStringLater (ptr);
477- return ptr;
607+ case Compiler::StaticType::String: {
608+ Compiler::StaticType type = reg->type ();
609+ bool singleType = isSingleType (type);
610+
611+ if (singleType) {
612+ // Handle single type cases directly
613+ switch (type) {
614+ case Compiler::StaticType::Number:
615+ case Compiler::StaticType::Bool: {
616+ // Cast to string
617+ // TODO: Use value_doubleToStringPtr() and value_boolToStringPtr()
618+ llvm::Value *ptr = m_builder.CreateCall (m_functions.resolve_value_toStringPtr (), reg->value );
619+ freeStringLater (ptr);
620+ return ptr;
621+ }
622+
623+ case Compiler::StaticType::String: {
624+ // Read string pointer directly
625+ llvm::Value *ptr = m_builder.CreateStructGEP (m_valueDataType, reg->value , 0 );
626+ return m_builder.CreateLoad (m_stringPtrType->getPointerTo (), ptr);
627+ }
628+
629+ default :
630+ assert (false );
631+ return nullptr ;
478632 }
633+ } else {
634+ // Handle multiple type cases with runtime switch
635+ llvm::Value *typePtr = m_builder.CreateStructGEP (m_valueDataType, reg->value , 1 );
636+ llvm::Value *loadedType = m_builder.CreateLoad (m_builder.getInt32Ty (), typePtr);
479637
480- case Compiler::StaticType::String: {
481- // Read string pointer directly
638+ llvm::BasicBlock *mergeBlock = llvm::BasicBlock::Create (m_llvmCtx, " merge" , m_function);
639+ llvm::BasicBlock *defaultBlock = llvm::BasicBlock::Create (m_llvmCtx, " default" , m_function);
640+
641+ llvm::SwitchInst *sw = m_builder.CreateSwitch (loadedType, defaultBlock, 4 );
642+
643+ std::vector<std::pair<llvm::BasicBlock *, llvm::Value *>> results;
644+
645+ // Number case
646+ if ((type & Compiler::StaticType::Number) == Compiler::StaticType::Number) {
647+ llvm::BasicBlock *numberBlock = llvm::BasicBlock::Create (m_llvmCtx, " number" , m_function);
648+ sw->addCase (m_builder.getInt32 (static_cast <uint32_t >(ValueType::Number)), numberBlock);
649+
650+ m_builder.SetInsertPoint (numberBlock);
651+ // TODO: Use value_doubleToStringPtr()
652+ llvm::Value *numberResult = m_builder.CreateCall (m_functions.resolve_value_toStringPtr (), reg->value );
653+ m_builder.CreateBr (mergeBlock);
654+ results.push_back ({ numberBlock, numberResult });
655+ }
656+
657+ // Bool case
658+ if ((type & Compiler::StaticType::Bool) == Compiler::StaticType::Bool) {
659+ llvm::BasicBlock *boolBlock = llvm::BasicBlock::Create (m_llvmCtx, " bool" , m_function);
660+ sw->addCase (m_builder.getInt32 (static_cast <uint32_t >(ValueType::Bool)), boolBlock);
661+
662+ m_builder.SetInsertPoint (boolBlock);
663+ // TODO: Use value_boolToStringPtr()
664+ llvm::Value *boolResult = m_builder.CreateCall (m_functions.resolve_value_toStringPtr (), reg->value );
665+ m_builder.CreateBr (mergeBlock);
666+ results.push_back ({ boolBlock, boolResult });
667+ }
668+
669+ // String case
670+ if ((type & Compiler::StaticType::String) == Compiler::StaticType::String) {
671+ llvm::BasicBlock *stringBlock = llvm::BasicBlock::Create (m_llvmCtx, " string" , m_function);
672+ sw->addCase (m_builder.getInt32 (static_cast <uint32_t >(ValueType::String)), stringBlock);
673+
674+ m_builder.SetInsertPoint (stringBlock);
482675 llvm::Value *ptr = m_builder.CreateStructGEP (m_valueDataType, reg->value , 0 );
483- return m_builder.CreateLoad (m_stringPtrType->getPointerTo (), ptr);
676+ llvm::Value *stringPtr = m_builder.CreateLoad (m_stringPtrType->getPointerTo (), ptr);
677+ llvm::Value *stringResult = m_builder.CreateCall (m_functions.resolve_string_pool_new (), m_builder.getInt1 (true ));
678+ m_builder.CreateCall (m_functions.resolve_string_assign (), { stringResult, stringPtr });
679+ m_builder.CreateBr (mergeBlock);
680+ results.push_back ({ stringBlock, stringResult });
484681 }
485682
486- default :
487- assert (false );
488- return nullptr ;
489- }
683+ // Default case
684+ m_builder.SetInsertPoint (defaultBlock);
490685
491- case Compiler::StaticType::Unknown:
492- return createValue (reg);
686+ // All possible types are covered, mark as unreachable
687+ m_builder.CreateUnreachable ();
688+
689+ // Create phi node to merge results
690+ m_builder.SetInsertPoint (mergeBlock);
691+ llvm::PHINode *result = m_builder.CreatePHI (m_stringPtrType->getPointerTo (), results.size ());
692+
693+ for (auto &pair : results)
694+ result->addIncoming (pair.second , pair.first );
695+
696+ freeStringLater (result);
697+ return result;
698+ }
699+ }
493700
494701 default :
495- assert ( false );
496- return nullptr ;
702+ // Multiple types
703+ return createValue (reg) ;
497704 }
498705}
499706
0 commit comments