#include "AliasAnalysis.h"
#include "SysYIRPrinter.h"
#include <iostream>

extern int DEBUG;

namespace sysy {

// 静态成员初始化
void *SysYAliasAnalysisPass::ID = (void *)&SysYAliasAnalysisPass::ID;

// ========== AliasAnalysisResult 实现 ==========

void AliasAnalysisResult::print() const {
    std::cout << "---- Alias Analysis Results for Function: " << AssociatedFunction->getName() << " ----\n";
    
    // 打印内存位置信息
    std::cout << "  Memory Locations (" << LocationMap.size() << "):\n";
    for (const auto& pair : LocationMap) {
        const auto& loc = pair.second;
        std::cout << "    - Base: " << loc->basePointer->getName();
        std::cout << " (Type: ";
        if (loc->isLocalArray) std::cout << "Local";
        else if (loc->isFunctionParameter) std::cout << "Parameter";
        else if (loc->isGlobalArray) std::cout << "Global";
        else std::cout << "Unknown";
        std::cout << ")\n";
    }
    
    // 打印别名关系
    std::cout << "  Alias Relations (" << AliasMap.size() << "):\n";
    for (const auto& pair : AliasMap) {
        std::cout << "    - (" << pair.first.first->getName() << ", " << pair.first.second->getName() << "): ";
        switch (pair.second) {
            case AliasType::NO_ALIAS: std::cout << "No Alias"; break;
            case AliasType::SELF_ALIAS: std::cout << "Self Alias"; break;
            case AliasType::POSSIBLE_ALIAS: std::cout << "Possible Alias"; break;
            case AliasType::UNKNOWN_ALIAS: std::cout << "Unknown Alias"; break;
        }
        std::cout << "\n";
    }
    std::cout << "-----------------------------------------------------------\n";
}

AliasType AliasAnalysisResult::queryAlias(Value* ptr1, Value* ptr2) const {
  auto key = std::make_pair(ptr1, ptr2);
  auto it = AliasMap.find(key);
  if (it != AliasMap.end()) {
    return it->second;
  }
  
  // 尝试反向查找
  key = std::make_pair(ptr2, ptr1);
  it = AliasMap.find(key);
  if (it != AliasMap.end()) {
    return it->second;
  }
  
  return AliasType::UNKNOWN_ALIAS; // 保守估计
}

const MemoryLocation* AliasAnalysisResult::getMemoryLocation(Value* ptr) const {
  auto it = LocationMap.find(ptr);
  return (it != LocationMap.end()) ? it->second.get() : nullptr;
}

bool AliasAnalysisResult::isLocalArray(Value* ptr) const {
  const MemoryLocation* loc = getMemoryLocation(ptr);
  return loc && loc->isLocalArray;
}

bool AliasAnalysisResult::isFunctionParameter(Value* ptr) const {
  const MemoryLocation* loc = getMemoryLocation(ptr);
  return loc && loc->isFunctionParameter;
}

bool AliasAnalysisResult::isGlobalArray(Value* ptr) const {
  const MemoryLocation* loc = getMemoryLocation(ptr);
  return loc && loc->isGlobalArray;
}

bool AliasAnalysisResult::hasConstantAccess(Value* ptr) const {
  const MemoryLocation* loc = getMemoryLocation(ptr);
  return loc && loc->hasConstantIndices;
}

AliasAnalysisResult::Statistics AliasAnalysisResult::getStatistics() const {
  Statistics stats = {0};
  
  stats.totalQueries = AliasMap.size();
  
  for (auto& pair : AliasMap) {
    switch (pair.second) {
      case AliasType::NO_ALIAS: stats.noAlias++; break;
      case AliasType::SELF_ALIAS: stats.selfAlias++; break;
      case AliasType::POSSIBLE_ALIAS: stats.possibleAlias++; break;
      case AliasType::UNKNOWN_ALIAS: stats.unknownAlias++; break;
    }
  }
  
  for (auto& loc : LocationMap) {
    if (loc.second->isLocalArray) stats.localArrays++;
    if (loc.second->isFunctionParameter) stats.functionParameters++;
    if (loc.second->isGlobalArray) stats.globalArrays++;
    if (loc.second->hasConstantIndices) stats.constantAccesses++;
  }
  
  return stats;
}

void AliasAnalysisResult::printStatics() const {
  std::cout << "=== Alias Analysis Results ===" << std::endl;
  
  auto stats = getStatistics();
  std::cout << "Total queries: " << stats.totalQueries << std::endl;
  std::cout << "No alias: " << stats.noAlias << std::endl;
  std::cout << "Self alias: " << stats.selfAlias << std::endl;
  std::cout << "Possible alias: " << stats.possibleAlias << std::endl;
  std::cout << "Unknown alias: " << stats.unknownAlias << std::endl;
  std::cout << "Local arrays: " << stats.localArrays << std::endl;
  std::cout << "Function parameters: " << stats.functionParameters << std::endl;
  std::cout << "Global arrays: " << stats.globalArrays << std::endl;
  std::cout << "Constant accesses: " << stats.constantAccesses << std::endl;
}

void AliasAnalysisResult::addMemoryLocation(std::unique_ptr<MemoryLocation> location) {
  Value* ptr = location->accessPointer;
  LocationMap[ptr] = std::move(location);
}

void AliasAnalysisResult::addAliasRelation(Value* ptr1, Value* ptr2, AliasType type) {
  auto key = std::make_pair(ptr1, ptr2);
  AliasMap[key] = type;
}

// ========== SysYAliasAnalysisPass 实现 ==========

bool SysYAliasAnalysisPass::runOnFunction(Function *F, AnalysisManager &AM) {
  if (DEBUG) {
    std::cout << "Running SysY Alias Analysis on function: " << F->getName() << std::endl;
  }
  
  // 创建分析结果
  CurrentResult = std::make_unique<AliasAnalysisResult>(F);
  
  // 执行主要分析步骤
  collectMemoryAccesses(F);
  buildAliasRelations(F);
  optimizeForSysY(F);
  
  if (DEBUG) {
    CurrentResult->print();
    CurrentResult->printStatics();
  }

  return false; // 分析遍不修改IR
}

void SysYAliasAnalysisPass::collectMemoryAccesses(Function* F) {
  // 收集函数中所有内存访问指令
  for (auto& bb : F->getBasicBlocks()) {
    for (auto& inst : bb->getInstructions()) {
      Value* ptr = nullptr;
      
      if (auto* loadInst = dynamic_cast<LoadInst*>(inst.get())) {
        ptr = loadInst->getPointer();
      } else if (auto* storeInst = dynamic_cast<StoreInst*>(inst.get())) {
        ptr = storeInst->getPointer();
      }
      
      if (ptr) {
        // 创建内存位置信息
        auto location = createMemoryLocation(ptr);
        location->accessInsts.push_back(inst.get());
        
        // 更新读写标记
        if (dynamic_cast<LoadInst*>(inst.get())) {
          location->hasReads = true;
        } else {
          location->hasWrites = true;
        }
        
        CurrentResult->addMemoryLocation(std::move(location));
      }
    }
  }
}

void SysYAliasAnalysisPass::buildAliasRelations(Function *F) {
  // 构建所有内存访问之间的别名关系
  auto& locationMap = CurrentResult->LocationMap;
  
  std::vector<Value*> allPointers;
  for (auto& pair : locationMap) {
    allPointers.push_back(pair.first);
  }
  
  // 两两比较所有指针
  for (size_t i = 0; i < allPointers.size(); ++i) {
    for (size_t j = i + 1; j < allPointers.size(); ++j) {
      Value* ptr1 = allPointers[i];
      Value* ptr2 = allPointers[j];
      
      MemoryLocation* loc1 = locationMap[ptr1].get();
      MemoryLocation* loc2 = locationMap[ptr2].get();
      
      AliasType aliasType = analyzeAliasBetween(loc1, loc2);
      CurrentResult->addAliasRelation(ptr1, ptr2, aliasType);
    }
  }
}

void SysYAliasAnalysisPass::optimizeForSysY(Function* F) {
  // SysY特化优化
  applySysYConstraints(F);
  optimizeParameterAnalysis(F);
  optimizeArrayAccessAnalysis(F);
}

std::unique_ptr<MemoryLocation> SysYAliasAnalysisPass::createMemoryLocation(Value* ptr) {
  Value* basePtr = getBasePointer(ptr);
  auto location = std::make_unique<MemoryLocation>(basePtr, ptr);
  
  // 分析内存类型和索引模式
  analyzeMemoryType(location.get());
  analyzeIndexPattern(location.get());
  
  return location;
}

Value* SysYAliasAnalysisPass::getBasePointer(Value* ptr) {
  // 递归剥离GEP指令，找到真正的基指针
  if (auto* gepInst = dynamic_cast<GetElementPtrInst*>(ptr)) {
    return getBasePointer(gepInst->getBasePointer());
  }
  return ptr;
}

void SysYAliasAnalysisPass::analyzeMemoryType(MemoryLocation* location) {
  Value* base = location->basePointer;
  
  // 检查内存类型
  if (dynamic_cast<AllocaInst*>(base)) {
    location->isLocalArray = true;
  } else if (dynamic_cast<Argument*>(base)) {
    location->isFunctionParameter = true;
  } else if (dynamic_cast<GlobalValue*>(base)) {
    location->isGlobalArray = true;
  }
}

void SysYAliasAnalysisPass::analyzeIndexPattern(MemoryLocation* location) {
  // 分析GEP指令的索引模式
  if (auto* gepInst = dynamic_cast<GetElementPtrInst*>(location->accessPointer)) {
    // 初始化为true，如果发现非常量索引则设为false
    location->hasConstantIndices = true;
    
    // 收集所有索引
    for (unsigned i = 0; i < gepInst->getNumIndices(); ++i) {
      Value* index = gepInst->getIndex(i);
      location->indices.push_back(index);
      
      // 检查是否为常量索引
      if (!isConstantValue(index)) {
        location->hasConstantIndices = false;
      }
    }
    
    // 检查是否包含循环变量
    Function* containingFunc = nullptr;
    if (auto* inst = dynamic_cast<Instruction*>(location->basePointer)) {
      containingFunc = inst->getParent()->getParent();
    } else if (auto* arg = dynamic_cast<Argument*>(location->basePointer)) {
      containingFunc = arg->getParent();
    }
    
    if (containingFunc) {
      location->hasLoopVariableIndex = hasLoopVariableInIndices(location->indices, containingFunc);
    }
    
    // 计算常量偏移
    if (location->hasConstantIndices) {
      location->constantOffset = calculateConstantOffset(location->indices);
    }
  }
}

AliasType SysYAliasAnalysisPass::analyzeAliasBetween(MemoryLocation* loc1, MemoryLocation* loc2) {
  // 分析两个内存位置之间的别名关系
  
  // 1. 相同基指针的情况需要进一步分析索引
  if (loc1->basePointer == loc2->basePointer) {
    // 如果是同一个访问指针，那就是完全相同的内存位置
    if (loc1->accessPointer == loc2->accessPointer) {
      return AliasType::SELF_ALIAS;
    }
    
    // 相同基指针但不同访问指针，需要比较索引
    return compareIndices(loc1, loc2);
  }
  
  // 2. 不同类型的内存位置
  if ((loc1->isLocalArray && loc2->isLocalArray)) {
    return compareLocalArrays(loc1, loc2);
  }
  
  if ((loc1->isFunctionParameter && loc2->isFunctionParameter)) {
    return compareParameters(loc1, loc2);
  }
  
  if ((loc1->isGlobalArray || loc2->isGlobalArray)) {
    return compareWithGlobal(loc1, loc2);
  }
  
  return compareMixedTypes(loc1, loc2);
}

AliasType SysYAliasAnalysisPass::compareIndices(MemoryLocation* loc1, MemoryLocation* loc2) {
  // 比较相同基指针下的不同索引访问
  
  // 如果都有常量索引，可以精确比较
  if (loc1->hasConstantIndices && loc2->hasConstantIndices) {
    // 比较索引数量
    if (loc1->indices.size() != loc2->indices.size()) {
      return AliasType::NO_ALIAS;
    }
    
    // 逐个比较索引值
    for (size_t i = 0; i < loc1->indices.size(); ++i) {
      Value* idx1 = loc1->indices[i];
      Value* idx2 = loc2->indices[i];
      
      // 都是常量，比较值
      auto* const1 = dynamic_cast<ConstantInteger*>(idx1);
      auto* const2 = dynamic_cast<ConstantInteger*>(idx2);
      
      if (const1 && const2) {
        int val1 = std::get<int>(const1->getVal());
        int val2 = std::get<int>(const2->getVal());
        
        if (val1 != val2) {
          return AliasType::NO_ALIAS;  // 不同常量索引，确定无别名
        }
      } else {
        // 不是常量，无法确定
        return AliasType::POSSIBLE_ALIAS;
      }
    }
    
    // 所有索引都相同
    return AliasType::SELF_ALIAS;
  }
  
  // 如果有非常量索引，保守估计
  return AliasType::POSSIBLE_ALIAS;
}

AliasType SysYAliasAnalysisPass::compareLocalArrays(MemoryLocation* loc1, MemoryLocation* loc2) {
  // 不同局部数组不别名
  return AliasType::NO_ALIAS;
}

AliasType SysYAliasAnalysisPass::compareParameters(MemoryLocation* loc1, MemoryLocation* loc2) {
  // SysY特化：可配置的数组参数别名策略
  // 
  // SysY中数组参数的语法形式：
  //   void func(int a[], int b[])     - 一维数组参数
  //   void func(int a[][10], int b[]) - 多维数组参数
  //
  // 默认保守策略：不同数组参数可能别名（因为可能传入相同数组）
  //   func(arr, arr);  // 传入同一个数组给两个参数
  //
  // 激进策略：假设不同数组参数不会传入相同数组（适用于评测环境）
  //   在SysY评测中，这种情况很少出现
  
  if (useAggressiveParameterAnalysis()) {
    // 激进策略：不同数组参数假设不别名
    return AliasType::NO_ALIAS;
  } else {
    // 保守策略：不同数组参数可能别名
    return AliasType::POSSIBLE_ALIAS;
  }
}

AliasType SysYAliasAnalysisPass::compareWithGlobal(MemoryLocation* loc1, MemoryLocation* loc2) {
  // 涉及全局数组的访问分析
  // 这里处理所有涉及全局数组的情况
  
  // SysY特化：局部数组与全局数组不别名
  if ((loc1->isLocalArray && loc2->isGlobalArray) || 
      (loc1->isGlobalArray && loc2->isLocalArray)) {
    // 局部数组在栈上，全局数组在全局区，确定不别名
    return AliasType::NO_ALIAS;
  }
  
  // SysY特化：数组参数与全局数组可能别名（保守处理）
  if ((loc1->isFunctionParameter && loc2->isGlobalArray) || 
      (loc1->isGlobalArray && loc2->isFunctionParameter)) {
    // 数组参数可能指向全局数组，需要保守处理
    return AliasType::POSSIBLE_ALIAS;
  }
  
  // 其他涉及全局数组的情况，采用保守策略
  return AliasType::POSSIBLE_ALIAS;
}

AliasType SysYAliasAnalysisPass::compareMixedTypes(MemoryLocation* loc1, MemoryLocation* loc2) {
  // 混合类型访问的别名分析
  // 处理不同内存类型之间的别名关系
  
  // SysY特化：局部数组与数组参数通常不别名
  // 典型场景：
  //   void func(int p[]) {       // p 是数组参数
  //       int local[10];         // local 是局部数组
  //       p[0] = local[0];       // 混合类型访问
  //   }
  // 或多维数组：
  //   void func(int p[][10]) {   // p 是多维数组参数
  //       int local[10];         // local 是局部数组
  //       p[i][0] = local[0];    // 混合类型访问
  //   } 
  // 局部数组与数组参数：在SysY中通常不别名
  if ((loc1->isLocalArray && loc2->isFunctionParameter) || 
      (loc1->isFunctionParameter && loc2->isLocalArray)) {
    // 因为局部数组是栈上分配，而数组参数是传入的外部数组
    return AliasType::NO_ALIAS;
  }

  // 对于其他混合情况，保守估计
  return AliasType::UNKNOWN_ALIAS;
}

void SysYAliasAnalysisPass::applySysYConstraints(Function* F) {
  // SysY语言特定的约束和优化
  // 1. SysY没有指针运算，简化了别名分析
  // 2. 数组传参时保持数组语义
  // 3. 没有动态内存分配，所有数组要么是局部的要么是参数/全局
}

void SysYAliasAnalysisPass::optimizeParameterAnalysis(Function* F) {
  // 数组参数别名分析优化
  // 为SysY评测环境提供可配置的优化策略
  
  if (!enableParameterOptimization()) {
    return; // 保持默认的保守策略
  }
  
  // 可选的参数优化：假设不同数组参数不会传入相同数组
  // 典型的SysY函数调用：
  //   int arr1[10], arr2[20];
  //   func(arr1, arr2);  // 传入不同数组
  // 而不是：
  //   func(arr1, arr1);  // 传入相同数组给两个参数
  // 这在SysY评测中通常是安全的假设
  auto& locationMap = CurrentResult->LocationMap;
  
  for (auto it1 = locationMap.begin(); it1 != locationMap.end(); ++it1) {
    for (auto it2 = std::next(it1); it2 != locationMap.end(); ++it2) {
      MemoryLocation* loc1 = it1->second.get();
      MemoryLocation* loc2 = it2->second.get();
      
      // 如果两个都是数组参数且基指针不同，设为NO_ALIAS
      if (loc1->isFunctionParameter && loc2->isFunctionParameter && 
          loc1->basePointer != loc2->basePointer) {
        CurrentResult->addAliasRelation(it1->first, it2->first, AliasType::NO_ALIAS);
      }
    }
  }
}

void SysYAliasAnalysisPass::optimizeArrayAccessAnalysis(Function* F) {
  // 数组访问别名分析优化
  // 基于SysY语言的特点进行简单优化
  
  // 优化1：同一数组的不同常量索引访问确定无别名
  optimizeConstantIndexAccesses();
  
  // 优化2：识别简单的顺序访问模式
  optimizeSequentialAccesses();
}

bool SysYAliasAnalysisPass::isConstantValue(Value* val) {
  return dynamic_cast<ConstantInteger*>(val) != nullptr; // 简化，只检查整数常量
}

bool SysYAliasAnalysisPass::hasLoopVariableInIndices(const std::vector<Value*>& indices, Function* F) {
  // 保守策略：所有非常量索引都视为可能的循环变量
  // 这样可以避免复杂的循环分析依赖，保持分析的独立性
  for (Value* index : indices) {
    if (!isConstantValue(index)) {
      return true; // 保守估计，确保正确性
    }
  }
  return false;
}

int SysYAliasAnalysisPass::calculateConstantOffset(const std::vector<Value*>& indices) {
  int offset = 0;
  for (Value* index : indices) {
    if (auto* constInt = dynamic_cast<ConstantInteger*>(index)) {
      // ConstantInteger的getVal()返回variant，需要提取int值
      auto val = constInt->getVal();
      if (std::holds_alternative<int>(val)) {
        offset += std::get<int>(val);
      }
    }
  }
  return offset;
}

void SysYAliasAnalysisPass::printStatistics() const {
  if (CurrentResult) {
    CurrentResult->print();
  }
}

void SysYAliasAnalysisPass::optimizeConstantIndexAccesses() {
  // 优化常量索引访问的别名关系
  // 对于相同基指针的访问，如果索引都是常量且不同，则确定无别名
  
  auto& locationMap = CurrentResult->LocationMap;
  std::vector<Value*> allPointers;
  for (auto& pair : locationMap) {
    allPointers.push_back(pair.first);
  }
  
  for (size_t i = 0; i < allPointers.size(); ++i) {
    for (size_t j = i + 1; j < allPointers.size(); ++j) {
      Value* ptr1 = allPointers[i];
      Value* ptr2 = allPointers[j];
      MemoryLocation* loc1 = locationMap[ptr1].get();
      MemoryLocation* loc2 = locationMap[ptr2].get();
      
      // 相同基指针且都有常量索引
      if (loc1->basePointer == loc2->basePointer && 
          loc1->hasConstantIndices && loc2->hasConstantIndices) {
        
        // 比较常量偏移
        if (loc1->constantOffset != loc2->constantOffset) {
          // 不同的常量偏移，确定无别名
          CurrentResult->addAliasRelation(ptr1, ptr2, AliasType::NO_ALIAS);
        }
      }
    }
  }
}

void SysYAliasAnalysisPass::optimizeSequentialAccesses() {
  // 识别和优化顺序访问模式
  // 这是一个简化的实现，主要用于识别数组的顺序遍历
  
  // 在SysY中，大多数数组访问都是通过循环进行的
  // 对于非常量索引的访问，我们采用保守策略，不进行过多优化
  // 这样可以保持分析的简单性和正确性
  
  // 未来如果需要更精确的分析，可以在这里添加更复杂的逻辑
}

} // namespace sysy
