Files
hakorune/docs/development/issues/llvm_binop_string_mismatch.md
nyash-codex 000335c32e feat(hako_check): Phase 154 MIR CFG integration & HC020 dead block detection
Implements block-level unreachable code detection using MIR CFG information.
Complements Phase 153's method-level HC019 with fine-grained analysis.

Core Infrastructure (Complete):
- CFG Extractor: Extract block reachability from MirModule
- DeadBlockAnalyzerBox: HC020 rule for unreachable blocks
- CLI Integration: --dead-blocks flag and rule execution
- Test Cases: 4 comprehensive patterns (early return, constant false, infinite loop, break)
- Smoke Test: Validation script for all test cases

Implementation Details:
- src/mir/cfg_extractor.rs: New module for CFG→JSON extraction
- tools/hako_check/rules/rule_dead_blocks.hako: HC020 analyzer box
- tools/hako_check/cli.hako: Added --dead-blocks flag and HC020 integration
- apps/tests/hako_check/test_dead_blocks_*.hako: 4 test cases

Architecture:
- Follows Phase 153 boxed modular pattern (DeadCodeAnalyzerBox)
- Optional CFG field in Analysis IR (backward compatible)
- Uses MIR's built-in reachability computation
- Gracefully skips if CFG unavailable

Known Limitation:
- CFG data bridge pending (Phase 155): analysis_consumer.hako needs MIR access
- Current: DeadBlockAnalyzerBox implemented, but CFG not yet in Analysis IR
- Estimated 2-3 hours to complete bridge in Phase 155

Test Coverage:
- Unit tests: cfg_extractor (simple CFG, unreachable blocks)
- Integration tests: 4 test cases ready (will activate with bridge)
- Smoke test: tools/hako_check_deadblocks_smoke.sh

Documentation:
- phase154_mir_cfg_inventory.md: CFG structure investigation
- phase154_implementation_summary.md: Complete implementation guide
- hako_check_design.md: HC020 rule documentation

Next Phase 155:
- Implement CFG data bridge (extract_mir_cfg builtin)
- Update analysis_consumer.hako to call bridge
- Activate HC020 end-to-end testing

🤖 Generated with Claude Code (https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 15:00:45 +09:00

1.5 KiB

LLVM lowering: string + int causes binop type mismatch

Status: open (issue memo; see roadmap/CURRENT_TASK for up-to-date status)

Summary

  • When compiling code that concatenates a string literal with a non-string (e.g., integer), LLVM object emission fails with a type mismatch in binop.
  • Example from apps/ny-map-llvm-smoke/main.hako: print("Map: v=" + v) and print("size=" + s).

Environment

  • LLVM 18 / inkwell 0.5.0
  • Phase 11.2 lowering

Repro

  1. Run: NYASH_LLVM_ARRAY_SMOKE=1 ./tools/llvm_smoke.sh release (or build/link the map smoke similarly)
  2. Observe: ❌ LLVM object emit error: binop type mismatch

Expected

  • String concatenation should be lowered to a safe runtime shim (e.g., NyRT string builder or nyash_string_concat) that accepts (i8* string, i64/int) and returns i8*.

Observed

  • + binop is currently generated as integer addition for non-float operands, leading to a type mismatch when one side is a pointer (string) and the other is integer.

Plan

  1. Introduce string-like detection in lowering: if either operand is String (or pointer from nyash_string_new), route to a NyRT concat shim.
  2. Provide NyRT APIs:
    • nyash.string.concat_ss(i8*, i8*) -> i8*
    • nyash.string.concat_si(i8*, i64) -> i8*
    • Optional: concat_sf, concat_sb (format helpers)
  3. As an interim simplification for smoke, emit print("..." ) in two steps to avoid mixed-type + until the concat shim is ready.

CI

  • Keep apps/ny-llvm-smoke OFF by default. Re-enable once concat shim lands and binop lowering is updated.