#include "IR.h"
#include <algorithm>
#include <cassert>
#include <functional>
#include <memory>
#include <queue>
#include <set>
#include <sstream>
#include <iomanip>
#include <vector>
#include "IRBuilder.h"

using namespace std;

inline std::string getMachineCode(float fval) {
  // 如果是0，直接返回
  if (fval == 0.0f) {
    return "0x0000000000000000";
  }
  
  // 正确的float到double扩展：先转换值，再获取double的位表示
  double dval = static_cast<double>(fval);
  uint64_t bits = *reinterpret_cast<uint64_t*>(&dval);
  
  std::stringstream ss;
  ss << "0x" << std::hex << std::uppercase << std::setfill('0') << std::setw(16) << bits;
  return ss.str();
}

/**
 * @file IR.cpp
 *
 * @brief 定义IR相关类型与操作的源文件
 */
namespace sysy {

// Global cleanup function implementation
void cleanupIRPools() {
  // Clean up the main memory pools that cause leaks
  ConstantValue::cleanup();
  UndefinedValue::cleanup();
  
  // Note: Type pools (PointerType, FunctionType, ArrayType) use unique_ptr
  // and will be automatically cleaned up when the program exits.
  // For more thorough cleanup during program execution, consider refactoring
  // to use singleton pattern with explicit cleanup methods.
}

/*相关打印函数*/

template <typename T>
ostream &interleave(std::ostream &os, const T &container, const std::string sep = ", ") {
  auto b = container.begin(), e = container.end();
  if (b == e)
    return os;
  os << *b;
  for (b = std::next(b); b != e; b = std::next(b))
    os << sep << *b;
  return os;
}

template <typename T>
ostream &interleave_call(std::ostream &os, const T &container, const std::string sep = ", ") {
  auto b = container.begin(), e = container.end();
  b = std::next(b); // Skip the first element
  if (b == e)
    return os;
  os << *b;
  for (b = std::next(b); b != e; b = std::next(b))
    os << sep << *b;
  return os;
}

static inline ostream &printVarName(ostream &os, const Value *var)
{
  if (dynamic_cast<const GlobalValue*>(var) != nullptr || 
      dynamic_cast<const ConstantVariable*>(var) != nullptr) {
    return os << "@" << var->getName();
  } else {
    return os << "%" << var->getName();
  }
}
static inline ostream &printBlockName(ostream &os, const BasicBlock *block) {
  return os <<  block->getName();
}
static inline ostream &printFunctionName(ostream &os, const Function *fn) {
  return os << '@' << fn->getName();
}
static inline ostream &printOperand(ostream &os, const Value *value) {
  auto constValue = dynamic_cast<const ConstantValue*>(value);
  if (constValue != nullptr) {
    if (auto constInt = dynamic_cast<const ConstantInteger*>(constValue)) {
      os << constInt->getInt();
    } else if (auto constFloat = dynamic_cast<const ConstantFloating*>(constValue)) {
      float f = constFloat->getFloat();
      char buffer[64];
      snprintf(buffer, sizeof(buffer), "%.17g", f);
      std::string str(buffer);
      if (str.find('.') == std::string::npos && str.find('e') == std::string::npos) {
          str += ".0";
      }
      os << str;
  
    } else if (auto undefVal = dynamic_cast<const UndefinedValue*>(constValue)) {
      os << "undef";
    }
    return os;
  }
  return printVarName(os, value);
}

inline std::ostream& operator<<(std::ostream& os, const Type& type) {
  type.print(os);
  return os;
}

inline std::ostream& operator<<(std::ostream& os, const Value& value) {
  value.print(os);
  return os;
}
//===----------------------------------------------------------------------===//
// Types
//===----------------------------------------------------------------------===//

auto Type::getIntType() -> Type * {
  static Type intType(kInt);
  return &intType;
}

auto Type::getFloatType() -> Type * {
  static Type floatType(kFloat);
  return &floatType;
}

auto Type::getVoidType() -> Type * {
  static Type voidType(kVoid);
  return &voidType;
}

auto Type::getLabelType() -> Type * {
  static Type labelType(kLabel);
  return &labelType;
}

auto Type::getPointerType(Type *baseType) -> Type * {
  // forward to PointerType
  return PointerType::get(baseType);
}

auto Type::getFunctionType(Type *returnType, const std::vector<Type *> &paramTypes) -> Type * {
  // forward to FunctionType
  return FunctionType::get(returnType, paramTypes);
}

auto Type::getArrayType(Type *elementType, unsigned numElements) -> Type * {
  // forward to ArrayType
  return ArrayType::get(elementType, numElements);
}

auto Type::getSize() const -> unsigned {
  switch (kind) {
    case kInt:
    case kFloat:
      return 4;
    case kLabel:
    case kPointer:
    case kFunction:
      return 8;
    case Kind::kArray: {
      const ArrayType* arrType = static_cast<const ArrayType*>(this);
      return arrType->getElementType()->getSize() * arrType->getNumElements();
    }
    case kVoid:
      return 0;
  }
  return 0;
}


void Type::print(ostream &os) const {
  auto kind = getKind();
  switch (kind){
    case kInt:   os << "i32"; break;
    case kFloat: os << "float"; break;
    case kVoid:  os << "void"; break;
    case kPointer:
      static_cast<const PointerType *>(this)->getBaseType()->print(os);
      os << "*";
      break;
    case kFunction:
      static_cast<const FunctionType *>(this)->getReturnType()->print(os);
      os << "(";
      interleave(os, static_cast<const FunctionType *>(this)->getParamTypes());
      os << ")";
      break;
    case kArray:
      os << "[";
      os << static_cast<const ArrayType *>(this)->getNumElements();
      os << " x ";
      static_cast<const ArrayType *>(this)->getElementType()->print(os);
      os << "]";
      break;
    case kLabel:
    default:
      cerr << "error type\n";
      break;
  }
}

void Use::print(std::ostream& os) const {
  os << "Use[" << index << "]: ";
  if (value) {
    printVarName(os, value);
  } else {
    os << "null";
  }
  os << " used by ";
  if (user) {
    os << "User@" << user;
  } else {
    os << "null";
  }
}

PointerType* PointerType::get(Type *baseType) {
  static std::map<Type *, std::unique_ptr<PointerType>> pointerTypes;
  auto iter = pointerTypes.find(baseType);
  if (iter != pointerTypes.end()) {
    return iter->second.get();
  }
  auto type = new PointerType(baseType);
  assert(type);
  auto result = pointerTypes.emplace(baseType, type);
  return result.first->second.get();
}

void PointerType::cleanup() {
  // Note: Due to static variable scoping, we can't directly access
  // the static map here. The cleanup will happen when the program exits.
  // For more thorough cleanup, consider using a singleton pattern.
}

FunctionType*FunctionType::get(Type *returnType, const std::vector<Type *> &paramTypes) {
  static std::set<std::unique_ptr<FunctionType>> functionTypes;
  auto iter =
      std::find_if(functionTypes.begin(), functionTypes.end(), [&](const std::unique_ptr<FunctionType> &type) -> bool {
        if (returnType != type->getReturnType() ||
            paramTypes.size() != static_cast<size_t>(type->getParamTypes().size())) {
          return false;
        }
        return std::equal(paramTypes.begin(), paramTypes.end(), type->getParamTypes().begin());
      });
  if (iter != functionTypes.end()) {
    return iter->get();
  }
  auto type = new FunctionType(returnType, paramTypes);
  assert(type);
  auto result = functionTypes.emplace(type);
  return result.first->get();
}

void FunctionType::cleanup() {
  // Note: Due to static variable scoping, we can't directly access
  // the static set here. The cleanup will happen when the program exits.
  // For more thorough cleanup, consider using a singleton pattern.
}

ArrayType *ArrayType::get(Type *elementType, unsigned numElements) {
  static std::set<std::unique_ptr<ArrayType>> arrayTypes;
  auto iter = std::find_if(arrayTypes.begin(), arrayTypes.end(), [&](const std::unique_ptr<ArrayType> &type) -> bool {
    return elementType == type->getElementType() && numElements == type->getNumElements();
  });
  if (iter != arrayTypes.end()) {
    return iter->get();
  }
  auto type = new ArrayType(elementType, numElements);
  assert(type);
  auto result = arrayTypes.emplace(type);
  return result.first->get();
}

void ArrayType::cleanup() {
  // Note: Due to static variable scoping, we can't directly access
  // the static set here. The cleanup will happen when the program exits.
  // For more thorough cleanup, consider using a singleton pattern.
}

void Argument::print(std::ostream& os) const {
  os << *getType() << " %" << getName();
}

// 辅助函数：递归生成多维数组的初始化格式
static void printArrayInitializer(std::ostream& os, Type* arrayType, const ValueCounter& initValues, size_t& valueIndex) {
  if (auto arrType = arrayType->as<ArrayType>()) {
    auto elementType = arrType->getElementType();
    auto numElements = arrType->getNumElements();
    
    os << "[";
    for (unsigned i = 0; i < numElements; ++i) {
      if (i > 0) os << ", ";
      
      if (elementType->isArray()) {
        // 嵌套数组，递归处理
        os << *elementType << " ";
        printArrayInitializer(os, elementType, initValues, valueIndex);
      } else {
        // 基础类型元素
        os << *elementType << " ";
        if (valueIndex < initValues.size()) {
          const auto& values = initValues.getValues();
          const auto& numbers = initValues.getNumbers();
          
          // 找到当前应该使用的值
          size_t currentValueIdx = 0;
          size_t currentCount = 0;
          for (size_t j = 0; j < values.size(); ++j) {
            if (currentCount + numbers[j] > valueIndex) {
              currentValueIdx = j;
              break;
            }
            currentCount += numbers[j];
          }
          
          printOperand(os, values[currentValueIdx]);
          valueIndex++;
        } else {
          // 没有更多初始化值，使用默认值
          if (elementType->isInt()) {
            os << "0";
          } else if (elementType->isFloat()) {
            os << "0.0";
          }
          valueIndex++;
        }
      }
    }
    os << "]";
  }
}

void GlobalValue::print(std::ostream& os) const {
  // 输出全局变量的LLVM IR格式
  os << "@" << getName() << " = global ";
  
  auto baseType = getType()->as<PointerType>()->getBaseType();
  os << *baseType << " ";
  
  // 输出初始化值
  if (initValues.size() == 0) {
    // 没有初始化值，使用zeroinitializer
    os << "zeroinitializer";
  } else {
    // 检查是否所有值都是零值
    bool allZero = true;
    const auto& values = initValues.getValues();
    for (Value* val : values) {
      if (auto constVal = dynamic_cast<ConstantValue*>(val)) {
        if (!constVal->isZero()) {
          allZero = false;
          break;
        }
      } else {
        allZero = false;
        break;
      }
    }
    
    if (allZero) {
      // 所有值都是零，使用zeroinitializer
      os << "zeroinitializer";
    } else if (initValues.size() == 1) {
      // 单个初始值 - 如果是标量零值也考虑使用zeroinitializer
      auto singleVal = initValues.getValue(0);
      if (auto constVal = dynamic_cast<ConstantValue*>(singleVal)) {
        if (constVal->isZero() && (baseType->isInt() || baseType->isFloat())) {
          // 标量零值使用zeroinitializer
          os << "zeroinitializer";
        } else {
          // 非零值或非基本类型，打印实际值
          printOperand(os, singleVal);
        }
      } else {
        // 非常量值，打印实际值
        printOperand(os, singleVal);
      }
    } else {
      // 数组初始值 - 根据数组维度生成正确的初始化格式
      if (baseType->isArray()) {
        size_t valueIndex = 0;
        printArrayInitializer(os, baseType, initValues, valueIndex);
      } else {
        // 单个非零标量值
        auto singleVal = initValues.getValue(0);
        printOperand(os, singleVal);
      }
    }
  }
}

void ConstantVariable::print(std::ostream& os) const {
  // 输出常量的LLVM IR格式 
  os << "@" << getName() << " = constant ";
  
  auto baseType = getType()->as<PointerType>()->getBaseType();
  os << *baseType << " ";
  
  // 输出初始化值
  if (initValues.size() == 0) {
    // 没有初始化值，使用zeroinitializer
    os << "zeroinitializer";
  } else {
    // 检查是否所有值都是零值
    bool allZero = true;
    const auto& values = initValues.getValues();
    for (Value* val : values) {
      if (auto constVal = dynamic_cast<ConstantValue*>(val)) {
        if (!constVal->isZero()) {
          allZero = false;
          break;
        }
      } else {
        allZero = false;
        break;
      }
    }
    
    if (allZero) {
      // 所有值都是零，使用zeroinitializer
      os << "zeroinitializer";
    } else if (initValues.size() == 1) {
      // 单个初始值 - 如果是标量零值也考虑使用zeroinitializer
      auto singleVal = initValues.getValue(0);
      if (auto constVal = dynamic_cast<ConstantValue*>(singleVal)) {
        if (constVal->isZero() && (baseType->isInt() || baseType->isFloat())) {
          // 标量零值使用zeroinitializer
          os << "zeroinitializer";
        } else {
          // 非零值或非基本类型，打印实际值
          printOperand(os, singleVal);
        }
      } else {
        // 非常量值，打印实际值
        printOperand(os, singleVal);
      }
    } else {
      // 数组初始值 - 根据数组维度生成正确的初始化格式
      if (baseType->isArray()) {
        size_t valueIndex = 0;
        printArrayInitializer(os, baseType, initValues, valueIndex);
      } else {
        // 单个非零标量值
        auto singleVal = initValues.getValue(0);
        printOperand(os, singleVal);
      }
    }
  }
}

void ConstantVariable::print_init(std::ostream& os) const {
  // 只输出初始化值部分
  if (initValues.size() > 0) {
    if (initValues.size() == 1) {
      // 单个初始值
      initValues.getValue(0)->print(os);
    } else {
      // 数组初始值 - 根据数组维度生成正确的初始化格式
      auto baseType = getType()->as<PointerType>()->getBaseType();
      if (baseType->isArray()) {
        size_t valueIndex = 0;
        printArrayInitializer(os, baseType, initValues, valueIndex);
      } else {
        // 单个非零标量值
        auto singleVal = initValues.getValue(0);
        singleVal->print(os);
      }
    }
  } else {
    os << "zeroinitializer";
  }
}

// void Value::replaceAllUsesWith(Value *value) {
//   for (auto &use : uses) {
//     auto user = use->getUser();
//     assert(user && "Use's user cannot be null");
//     user->setOperand(use->getIndex(), value);
//   }
//   uses.clear();
// }
void Value::replaceAllUsesWith(Value *value) {
  // 1. 创建 uses 列表的副本进行迭代。
  //    这样做是为了避免在迭代过程中，由于 setOperand 间接调用 removeUse 或 addUse
  //    导致原列表被修改，从而引发迭代器失效问题。
  std::list<std::shared_ptr<Use>> uses_copy = uses; 

  for (auto &use_ptr : uses_copy) { // 遍历副本
    // 2. 检查 shared_ptr<Use> 本身是否为空。这是最常见的崩溃原因之一。
    if (use_ptr == nullptr) {
      std::cerr << "Warning: Encountered a null std::shared_ptr<Use> in Value::uses list. Skipping this entry." << std::endl;
      // 在一个健康的 IR 中，这种情况不应该发生。如果经常出现，说明你的 Use 创建或管理有问题。
      continue; // 跳过空的智能指针
    }
    
    // 3. 检查 Use 对象内部的 User* 是否为空。
    User* user_val = use_ptr->getUser(); 
    if (user_val == nullptr) {
      std::cerr << "Warning: Use object (" << use_ptr.get() << ") has a null User* in replaceAllUsesWith. Skipping this entry. This indicates IR corruption." << std::endl;
      // 同样，在一个健康的 IR 中，Use 对象的 User* 不应该为空。
      continue; // 跳过用户指针为空的 Use 对象
    }
    
    // 如果走到这里，use_ptr 和 user_val 都是有效的，可以安全调用 setOperand
    user_val->setOperand(use_ptr->getIndex(), value);
  }

  // 4. 处理完所有 use 之后，清空原始的 uses 列表。
  //    replaceAllUsesWith 的目的就是将所有使用关系从当前 Value 转移走，
  //    所以最后清空列表是正确的。
  uses.clear(); 
}

// Implementations for static members

std::unordered_map<ConstantValueKey, ConstantValue*, ConstantValueHash, ConstantValueEqual> ConstantValue::mConstantPool;
std::unordered_map<Type*, UndefinedValue*> UndefinedValue::UndefValues;

ConstantValue* ConstantValue::get(Type* type, ConstantValVariant val) {
  ConstantValueKey key = {type, val};
  auto it = mConstantPool.find(key);
  if (it != mConstantPool.end()) {
    return it->second;
  }

  ConstantValue* newConstant = nullptr;
  if (std::holds_alternative<int>(val)) {
    newConstant = new ConstantInteger(type, std::get<int>(val));
  } else if (std::holds_alternative<float>(val)) {
    newConstant = new ConstantFloating(type, std::get<float>(val));
  } else {
    assert(false && "Unsupported ConstantValVariant type");
  }

  mConstantPool[key] = newConstant;
  return newConstant;
}

void ConstantValue::cleanup() {
  for (auto& pair : mConstantPool) {
    delete pair.second;
  }
  mConstantPool.clear();
}

ConstantInteger* ConstantInteger::get(Type* type, int val) {
  return dynamic_cast<ConstantInteger*>(ConstantValue::get(type, val));
}

ConstantFloating* ConstantFloating::get(Type* type, float val) {
  return dynamic_cast<ConstantFloating*>(ConstantValue::get(type, val));
}

UndefinedValue* UndefinedValue::get(Type* type) {
  assert(!type->isVoid() && "Cannot get UndefinedValue of void type!");

  auto it = UndefValues.find(type);
  if (it != UndefValues.end()) {
    return it->second;
  }

  UndefinedValue* newUndef = new UndefinedValue(type);
  UndefValues[type] = newUndef;
  return newUndef;
}

void UndefinedValue::cleanup() {
  for (auto& pair : UndefValues) {
    delete pair.second;
  }
  UndefValues.clear();
}

void ConstantValue::print(std::ostream &os) const {
  if(dynamic_cast<const ConstantInteger*>(this)) {
    dynamic_cast<const ConstantInteger*>(this)->print(os);
  } else if(dynamic_cast<const ConstantFloating*>(this)) {
    dynamic_cast<const ConstantFloating*>(this)->print(os);
  } else if(dynamic_cast<const UndefinedValue*>(this)) {
    dynamic_cast<const UndefinedValue*>(this)->print(os);
  } else {
    os << "unknown constant type";
  }
}

void ConstantInteger::print(std::ostream &os) const {
  os << this->getInt();
}
void ConstantFloating::print(std::ostream &os) const {
  float f = this->getFloat();
  
  char buffer[64];
  snprintf(buffer, sizeof(buffer), "%.17g", f);
  std::string str(buffer);
  if (str.find('.') == std::string::npos && str.find('e') == std::string::npos) {
       str += ".0";
  }
  os  << str;
}
void UndefinedValue::print(std::ostream &os) const {
  os << this->getType() << " undef";
}

void BasicBlock::print(std::ostream &os) const {
  assert(this->getName() != "" && "BasicBlock name cannot be empty");
  os << "  ";
  printBlockName(os, this);
  os << ":\n";
  
  bool reachedTerminator = false;
  for (auto &inst : instructions) {
    // 跳过终结指令后的死代码
    if (reachedTerminator) {
      continue;
    }
    
    os << "    ";
    
    // 特殊处理逻辑非指令
    if (auto* unaryInst = dynamic_cast<UnaryInst*>(inst.get())) {
      if (unaryInst->getKind() == Instruction::kNot && unaryInst->getType()->isInt()) {
        // 生成两行：先比较，再扩展
        os << "%tmp_not_" << unaryInst->getName() << " = icmp eq " 
           << *unaryInst->getOperand()->getType() << " ";
        printOperand(os, unaryInst->getOperand());
        os << ", 0\n    %";
        os << unaryInst->getName() << " = zext i1 %tmp_not_" << unaryInst->getName() << " to i32";
        os << '\n';
        
        // 检查当前指令是否是终结指令
        if (inst->isTerminator()) {
          reachedTerminator = true;
        }
        continue;
      }
    }
    
    os << *inst << '\n';
    
    // 检查当前指令是否是终结指令
    if (inst->isTerminator()) {
      reachedTerminator = true;
    }
  }
}

void PhiInst::print(std::ostream &os) const {
  printVarName(os, this);
  os << " = " << getKindString() << " " << *getType() << " ";
  for (unsigned i = 0; i < vsize; ++i) {
    if (i > 0) {
      os << ", ";
    }
    os << " [";
    printOperand(os, getIncomingValue(i));
    os << ", %";
    printBlockName(os, getIncomingBlock(i));
    os << "]";
  }
}

CallInst::CallInst(Function *callee, const std::vector<Value *> &args, BasicBlock *parent, const std::string &name)
    : Instruction(kCall, callee->getReturnType(), parent, name) {
  addOperand(callee);
  for (auto arg : args) {
    addOperand(arg);
  }
}

Function *CallInst::getCallee() const {
  return dynamic_cast<Function *>(getOperand(0));
}

void CallInst::print(std::ostream &os) const {
  if(!getType()->isVoid()) {
    printVarName(os, this) << " = ";
  }
  os << getKindString() << " " << *getType() << " " ;
  printFunctionName(os, getCallee());
  os << "(";
  
  // 打印参数，跳过第一个操作数（函数本身）
  for (unsigned i = 1; i < getNumOperands(); ++i) {
    if (i > 1) os << ", ";
    auto arg = getOperand(i);
    os << *arg->getType() << " ";
    printOperand(os, arg);
  }
  os << ")";
}

// 情况比较复杂就不用getkindstring了
void UnaryInst::print(std::ostream &os) const {
  printVarName(os, this) << " = ";
  switch (getKind()) {
  case kNeg:
    os << "sub i32 0, ";
    printOperand(os, getOperand());
    break;
  case kFNeg:
    os << "fsub float 0.0, ";
    printOperand(os, getOperand());
    break;
  case kNot:
    // 在BasicBlock::print中特殊处理整数逻辑非，这里不应该执行到
    os << "xor " << *getOperand()->getType() << " ";
    printOperand(os, getOperand());
    os << ", -1";
    break;
  case kFNot:
    os << "fcmp une " << *getOperand()->getType() << " ";
    printOperand(os, getOperand());
    os << ", 0.0";
    return;
  case kFtoI:
    os << "fptosi " << *getOperand()->getType() << " ";
    printOperand(os, getOperand());
    os << " to " << *getType();
    return;
  case kItoF:
    os << "sitofp " << *getOperand()->getType() << " ";
    printOperand(os, getOperand());
    os << " to " << *getType();
    return;
  default:
    os << "error unary inst";
    return;
  }
}



void AllocaInst::print(std::ostream &os) const {
  PointerType *ptrType = dynamic_cast<PointerType *>(getType());
  Type *baseType = ptrType->getBaseType();
  printVarName(os, this);
  os <<  " = " << getKindString() << " " << *baseType;
}

void BinaryInst::print(std::ostream &os) const {
  auto kind = getKind();
  
  // 检查是否为比较指令
  if (kind == kICmpEQ || kind == kICmpNE || kind == kICmpLT || 
      kind == kICmpGT || kind == kICmpLE || kind == kICmpGE) {
    // 整数比较指令 - 生成临时i1结果然后转换为i32
    // 使用指令地址和操作数地址的组合哈希来确保唯一性
    auto inst_hash = std::hash<const void*>{}(static_cast<const void*>(this));
    auto lhs_hash = std::hash<const void*>{}(static_cast<const void*>(getLhs()));
    auto rhs_hash = std::hash<const void*>{}(static_cast<const void*>(getRhs()));
    size_t combined_hash = inst_hash ^ (lhs_hash << 1) ^ (rhs_hash << 2);
    std::string tmpName = "tmp_icmp_" + std::to_string(combined_hash % 1000000007);
    os << "%" << tmpName << " = " << getKindString() << " " << *getLhs()->getType() << " ";
    printOperand(os, getLhs());
    os << ", ";
    printOperand(os, getRhs());
    os << "\n    ";
    printVarName(os, this) << " = zext i1 %" << tmpName << " to i32";
  } else if (kind == kFCmpEQ || kind == kFCmpNE || kind == kFCmpLT || 
             kind == kFCmpGT || kind == kFCmpLE || kind == kFCmpGE) {
    // 浮点比较指令 - 生成临时i1结果然后转换为i32
    // 使用指令地址和操作数地址的组合哈希来确保唯一性
    auto inst_hash = std::hash<const void*>{}(static_cast<const void*>(this));
    auto lhs_hash = std::hash<const void*>{}(static_cast<const void*>(getLhs()));
    auto rhs_hash = std::hash<const void*>{}(static_cast<const void*>(getRhs()));
    size_t combined_hash = inst_hash ^ (lhs_hash << 1) ^ (rhs_hash << 2);
    std::string tmpName = "tmp_fcmp_" + std::to_string(combined_hash % 1000000007);
    os << "%" << tmpName << " = " << getKindString() << " " << *getLhs()->getType() << " ";
    printOperand(os, getLhs());
    os << ", ";
    printOperand(os, getRhs());
    os << "\n    ";
    printVarName(os, this) << " = zext i1 %" << tmpName << " to i32";
  } else if(kind == kMulh){
    // 模拟高位乘法：先扩展为i64，乘法，右移32位，截断为i32
    static int mulhCount = 0;
    mulhCount++;
    std::string lhsName = getLhs()->getName();
    std::string rhsName = getRhs()->getName();
    std::string tmpLhs = "tmp_mulh_lhs_" + std::to_string(mulhCount) + "_" + lhsName;
    std::string tmpRhs = "tmp_mulh_rhs_" + std::to_string(mulhCount) +  rhsName;
    std::string tmpMul = "tmp_mulh_mul_" + std::to_string(mulhCount) + getName();
    std::string tmpHigh = "tmp_mulh_high_" + std::to_string(mulhCount) + getName();
    // printVarName(os, this) << " = "; // 输出最终变量名

    // os << "; mulh emulation\n    ";
    os << "%" << tmpLhs << " = sext i32 ";
    printOperand(os, getLhs());
    os << " to i64\n    ";
    os << "%" << tmpRhs << " = sext i32 ";
    printOperand(os, getRhs());
    os << " to i64\n    ";
    os << "%" << tmpMul << " = mul i64 %" << tmpLhs << ", %" << tmpRhs << "\n    ";
    os << "%" << tmpHigh << " = ashr i64 %" << tmpMul << ", 32\n    ";
    printVarName(os, this) << " = trunc i64 %" << tmpHigh << " to i32";
  }else {
    // 算术和逻辑指令
    printVarName(os, this) << " = ";
    os << getKindString() << " " << *getType() << " ";
    printOperand(os, getLhs());
    os << ", ";
    printOperand(os, getRhs());
  }
}

void ReturnInst::print(std::ostream &os) const {
  os << "ret ";
  if (hasReturnValue()) {
    os << *getReturnValue()->getType() << " ";
    printOperand(os, getReturnValue());
  } else {
    os << "void";
  }
}

void UncondBrInst::print(std::ostream &os) const {
  os << "br label %";
  printBlockName(os, getBlock());
}

void CondBrInst::print(std::ostream &os) const {
  Value* condition = getCondition();
  
  // 使用多个因素的组合哈希来确保唯一性
  std::string condName = condition->getName();
  if (condName.empty()) {
    // 使用条件值地址的哈希值作为唯一标识
    auto ptr_hash = std::hash<const void*>{}(static_cast<const void*>(condition));
    condName = "const_" + std::to_string(ptr_hash % 1000000007);
  }
  
  // 组合指令地址、条件地址和目标块地址的哈希来确保唯一性
  auto inst_hash = std::hash<const void*>{}(static_cast<const void*>(this));
  auto cond_hash = std::hash<const void*>{}(static_cast<const void*>(condition));
  auto then_hash = std::hash<const void*>{}(static_cast<const void*>(getThenBlock()));
  auto else_hash = std::hash<const void*>{}(static_cast<const void*>(getElseBlock()));
  size_t combined_hash = inst_hash ^ (cond_hash << 1) ^ (then_hash << 2) ^ (else_hash << 3);
  std::string uniqueSuffix = std::to_string(combined_hash % 1000000007);
  
  os << "%tmp_cond_" << condName << "_" << uniqueSuffix << " = icmp ne i32 ";
  printOperand(os, condition);
  os << ", 0\n    br i1 %tmp_cond_" << condName << "_" << uniqueSuffix;
  
  os << ", label %";
  printBlockName(os, getThenBlock());
  os << ", label %";
  printBlockName(os, getElseBlock());
}

void GetElementPtrInst::print(std::ostream &os) const {
  printVarName(os, this) << " = getelementptr ";
  
  // 获取基指针的基类型
  auto basePtr = getBasePointer();
  auto basePtrType = basePtr->getType()->as<PointerType>();
  auto baseType = basePtrType->getBaseType();
  
  os << *baseType << ", " << *basePtr->getType() << " ";
  printOperand(os, basePtr);
  
  // 打印索引 - 使用getIndex方法而不是getIndices
  for (unsigned i = 0; i < getNumIndices(); ++i) {
    auto index = getIndex(i);
    os << ", " << *index->getType() << " ";
    printOperand(os, index);
  }
}

void LoadInst::print(std::ostream &os) const {
  printVarName(os, this) << " = load " << *getType() << ", " << *getPointer()->getType() << " ";
  printOperand(os, getPointer());
}

void MemsetInst::print(std::ostream &os) const {
  Value* ptr = getPointer();
  
  // Generate a temporary bitcast instruction before the memset call
  // This is done at print time to avoid modifying the IR structure
  os << "%tmp_bitcast_" << ptr->getName() << " = bitcast " << *ptr->getType() << " ";
  printOperand(os, ptr);
  os << " to i8*\n    ";
  
  // Now call memset with the bitcast result
  os << "call void @llvm.memset.p0i8.i32(i8* %tmp_bitcast_" << ptr->getName() << ", i8 ";
  printOperand(os, getValue());
  os << ", i32 ";
  printOperand(os, getSize());
  os << ", i1 false)";
}

void StoreInst::print(std::ostream &os) const {
  os << "store " << *getValue()->getType() << " ";
  printOperand(os, getValue());
  os << ", " << *getPointer()->getType() << " ";
  printOperand(os, getPointer());
}




auto Function::getCalleesWithNoExternalAndSelf() -> std::set<Function *> {
  std::set<Function *> result;
  for (auto callee : callees) {
    if (parent->getExternalFunctions().count(callee->getName()) == 0U && callee != this) {
      result.insert(callee);
    }
  }
  return result;
}

void Value::removeAllUses() {
  while (!uses.empty()) {
    auto use = uses.back();
    uses.pop_back();
    if (use && use->getUser()) {
      auto user = use->getUser();
      int index = use->getIndex();
      user->removeOperand(index); ///< 从User中移除该操作数
    } else {
      // 如果use或user为null，输出警告信息
      assert(use != nullptr && "Use cannot be null");
      assert(use->getUser() != nullptr && "Use's user cannot be null");
    }
  }
  uses.clear();
}

/**
 * 设置操作数
 */
void User::setOperand(unsigned index, Value *newvalue) {
  if (index >= operands.size()) {
    std::cerr << "index=" << index << ", but mOperands max size=" << operands.size() << std::endl;
    assert(index < operands.size());
  }
  std::shared_ptr<Use> olduse = operands[index];
  Value *oldValue = olduse->getValue();
  if (oldValue != newvalue) {
    // 如果新值和旧值不同，先移除旧值的使用关系
    oldValue->removeUse(olduse);
    // 设置新的操作数
    operands[index] = std::make_shared<Use>(index, this, newvalue);
    newvalue->addUse(operands[index]);
  }
  else {
    // 如果新值和旧值相同，直接更新use的索引
    operands[index]->setValue(newvalue);
  }
}
/**
 * 替换操作数
 */
void User::replaceOperand(unsigned index, Value *value) {
  assert(index < getNumOperands());
  auto &use = operands[index];
  use->getValue()->removeUse(use);
  use->setValue(value);
  value->addUse(use);
}

/**
 * 移除操作数
 */
void User::removeOperand(unsigned index) {
  assert(index < getNumOperands() && "Index out of range in removeOperand");
  std::shared_ptr<Use> useToRemove = operands.at(index);
  Value *valueToRemove = useToRemove->getValue();
  if(valueToRemove) {
    if(valueToRemove == this) {
      std::cerr << "Cannot remove operand that is the same as the User itself." << std::endl;
    }
    valueToRemove->removeUse(useToRemove);
  }
  operands.erase(operands.begin() + index);
  unsigned newIndex = 0;
  for(auto it = operands.begin(); it != operands.end(); ++it, ++newIndex) {
    (*it)->setIndex(newIndex);  // 更新剩余操作数的索引
  }
}


/**
 * phi相关函数
 */

Value* PhiInst::getValfromBlk(BasicBlock* blk) {
  refreshMap();
  if( blk2val.find(blk) != blk2val.end()) {
    return blk2val.at(blk);
  }
  return nullptr;
}

BasicBlock* PhiInst::getBlkfromVal(Value* val) {
  // 返回第一个值对应的基本块
  for(unsigned i = 0; i < vsize; i++) {
    if(getIncomingValue(i) == val) {
      return getIncomingBlock(i);
    }
  }
  return nullptr;
}

void PhiInst::removeIncomingValue(Value* val){
  //根据value删除对应的基本块和值
  unsigned i = 0;
  BasicBlock* blk = getBlkfromVal(val);
  if(blk == nullptr) {
    return; // 如果val没有对应的基本块，直接返回
  }
  for(i = 0; i < vsize; i++) {
    if(getIncomingValue(i) == val) {
      break;
    }
  }
  removeIncoming(i);
}

void PhiInst::removeIncomingBlock(BasicBlock* blk){
  //根据Blk删除对应的基本块和值
  unsigned i = 0;
  Value* val = getValfromBlk(blk);
  if(val == nullptr) {
    return; // 如果blk没有对应的值，直接返回
  }
  for(i = 0; i < vsize; i++) {
    if(getIncomingBlock(i) == blk) {
      break;
    }
  }
  removeIncoming(i);
}

void PhiInst::setIncomingValue(unsigned k, Value* val) {
  assert(k < vsize && "PhiInst: index out of range");
  assert(val != nullptr && "PhiInst: value cannot be null");
  refreshMap();
  blk2val.erase(getIncomingBlock(k));
  setOperand(2 * k, val);
  blk2val[getIncomingBlock(k)] = val;
}

void PhiInst::setIncomingBlock(unsigned k, BasicBlock* blk) {
  assert(k < vsize && "PhiInst: index out of range");
  assert(blk != nullptr && "PhiInst: block cannot be null");
  refreshMap();
  auto oldVal = getIncomingValue(k);
  blk2val.erase(getIncomingBlock(k));
  setOperand(2 * k + 1, blk);
  blk2val[blk] = oldVal;
}

void PhiInst::replaceIncomingValue(Value* newVal, Value* oldVal) {
  refreshMap();
  assert(blk2val.find(getBlkfromVal(oldVal)) != blk2val.end() && "PhiInst: oldVal not found in blk2val");
  auto blk = getBlkfromVal(oldVal);
  removeIncomingValue(oldVal);
  addIncoming(newVal, blk);
}

void PhiInst::replaceIncomingBlock(BasicBlock* newBlk, BasicBlock* oldBlk) {
  refreshMap();
  assert(blk2val.find(oldBlk) != blk2val.end() && "PhiInst: oldBlk not found in blk2val");
  auto val = blk2val[oldBlk];
  removeIncomingBlock(oldBlk);
  addIncoming(val, newBlk);
}

void PhiInst::replaceIncomingValue(Value *oldValue, Value *newValue, BasicBlock *newBlock) {
  refreshMap();
  assert(blk2val.find(getBlkfromVal(oldValue)) != blk2val.end() && "PhiInst: oldValue not found in blk2val");
  auto oldBlock = getBlkfromVal(oldValue);
  removeIncomingValue(oldValue);
  addIncoming(newValue, newBlock);
}

void PhiInst::replaceIncomingBlock(BasicBlock *oldBlock, BasicBlock *newBlock, Value *newValue) {
  refreshMap();
  assert(blk2val.find(oldBlock) != blk2val.end() && "PhiInst: oldBlock not found in blk2val");
  auto oldValue = blk2val[oldBlock];
  removeIncomingBlock(oldBlock);
  addIncoming(newValue, newBlock);
}


/**
 * 获取变量指针
 * 如果在当前作用域或父作用域中找到变量，则返回该变量的指针，否则返回nullptr
 */
auto SymbolTable::getVariable(const std::string &name) const -> Value * {
  auto node = curNode;
  while (node != nullptr) {
    auto iter = node->varList.find(name);
    if (iter != node->varList.end()) {
      return iter->second;
    }
    node = node->pNode;
  }

  return nullptr;
}
/**
 * 添加变量到符号表
 */
auto SymbolTable::addVariable(const std::string &name, Value *variable) -> Value * {
  Value *result = nullptr;
  if (curNode != nullptr) {
    std::stringstream ss;
    auto iter = variableIndex.find(name);
    
    // 处理超长变量名（超过100字符）
    std::string displayName = name;
    if (name.length() > 100) {
      // 计算简单哈希
      std::hash<std::string> hasher;
      size_t hash = hasher(name);
      // 截断到前100个字符 + 哈希后缀
      displayName = name.substr(0, 100) + "_hash_" + std::to_string(hash);
    }
    
    // 区分全局变量和局部变量的命名
    bool isGlobalVariable = (dynamic_cast<GlobalValue *>(variable) != nullptr) || 
                           (dynamic_cast<ConstantVariable *>(variable) != nullptr);
    
    int index = 0;
    if (iter != variableIndex.end()) {
      index = iter->second;
      iter->second += 1;
    } else {
      variableIndex.emplace(name, 1);
    }
    
    if (isGlobalVariable) {
      // 全局变量不使用 local_ 前缀
      ss << displayName << index;
    } else {
      // 局部变量使用 "local_" 前缀确保不会和函数参数名冲突
      ss << "local_" << displayName << index;
    }
    
    variable->setName(ss.str());
    curNode->varList.emplace(name, variable);
    auto global = dynamic_cast<GlobalValue *>(variable);
    auto constvar = dynamic_cast<ConstantVariable *>(variable);
    if (global != nullptr) {
      globals.emplace_back(global);
    } else if (constvar != nullptr) {
      globalconsts.emplace_back(constvar);
    }

    result = variable;
  }

  return result;
}

/**
 * 注册函数参数名字到符号表，确保后续的alloca变量不会使用相同的名字
 */
void SymbolTable::registerParameterName(const std::string &name) {
  // 由于局部变量现在使用 "local_" 前缀，不需要复杂的冲突避免逻辑
  // 这个方法现在主要用于参数相关的记录，可以简化
}

/**
 * 直接添加变量到当前作用域，不进行重命名
 */
void SymbolTable::addVariableDirectly(const std::string &name, Value *variable) {
  if (curNode != nullptr) {
    curNode->varList.emplace(name, variable);
    auto global = dynamic_cast<GlobalValue *>(variable);
    auto constvar = dynamic_cast<ConstantVariable *>(variable);
    if (global != nullptr) {
      globals.emplace_back(global);
    } else if (constvar != nullptr) {
      globalconsts.emplace_back(constvar);
    }
  }
}

/**
 * 获取全局变量
 */
auto SymbolTable::getGlobals() -> std::vector<std::unique_ptr<GlobalValue>> & { return globals; }
/**
 *  获取常量
 */
auto SymbolTable::getConsts() const -> const std::vector<std::unique_ptr<ConstantVariable>> & { return globalconsts; }
/**
 * 进入新的作用域
 */
void SymbolTable::enterNewScope() {
  auto newNode = new SymbolTableNode;
  nodeList.emplace_back(newNode);
  if (curNode != nullptr) {
    curNode->children.emplace_back(newNode);
  }
  newNode->pNode = curNode;
  curNode = newNode;
}
/**
 * 进入全局作用域
 */
void SymbolTable::enterGlobalScope() { curNode = nodeList.front().get(); }
/**
 * 离开作用域
 */
void SymbolTable::leaveScope() { curNode = curNode->pNode; }
/**
 * 是否位于全局作用域
 */
auto SymbolTable::isInGlobalScope() const -> bool { return curNode->pNode == nullptr; }

/**
 *移动指令
 */
auto BasicBlock::moveInst(iterator sourcePos, iterator targetPos, BasicBlock *block) -> iterator {
  auto inst = sourcePos->release();
  inst->setParent(block);
  block->instructions.emplace(targetPos, inst);
  return instructions.erase(sourcePos);
}

/**
 * 为Value重命名以符合LLVM IR格式
 */
void renameValues(Function* function) {
  std::unordered_map<Value*, std::string> valueNames;
  unsigned tempCounter = 0;
  unsigned labelCounter = 0;
  
  // 检查名字是否需要重命名（只有纯数字或空名字才需要重命名）
  auto needsRename = [](const std::string& name) {
    if (name.empty()) return true;
    
    // 检查是否为纯数字
    for (char c : name) {
      if (!std::isdigit(c)) {
        return false; // 包含非数字字符，不需要重命名
      }
    }
    return true; // 纯数字或空字符串，需要重命名
  };
  
  // 重命名函数参数
  for (auto arg : function->getArguments()) {
    if (needsRename(arg->getName())) {
      valueNames[arg] = "%" + std::to_string(tempCounter++);
      arg->setName(valueNames[arg].substr(1)); // 去掉%前缀，因为printVarName会加上
    }
  }
  
  // 重命名基本块
  for (auto& block : function->getBasicBlocks()) {
    if (needsRename(block->getName())) {
      valueNames[block.get()] = "label" + std::to_string(labelCounter++);
      block->setName(valueNames[block.get()]);
    }
  }
  
  // 重命名指令
  for (auto& block : function->getBasicBlocks()) {
    bool reachedTerminator = false;
    for (auto& inst : block->getInstructions()) {
      // 跳过终结指令后的死代码
      if (reachedTerminator) {
        continue;
      }
      
      // 检查当前指令是否是终结指令
      if (inst->isTerminator()) {
        reachedTerminator = true;
      }
      
      // 只有产生值的指令需要重命名
      if (!inst->getType()->isVoid() && needsRename(inst->getName())) {
        valueNames[inst.get()] = "%" + std::to_string(tempCounter++);
        inst->setName(valueNames[inst.get()].substr(1)); // 去掉%前缀
      }
    }
  }
}

void Function::print(std::ostream& os) const {
  // 重命名所有值
  auto* mutableThis = const_cast<Function*>(this);
  renameValues(mutableThis);
  
  // 打印函数签名
  os << "define " << *getReturnType() << " ";
  printFunctionName(os, this);
  os << "(";
  
  // 打印参数列表
  const auto& args = const_cast<Function*>(this)->getArguments();
  for (size_t i = 0; i < args.size(); ++i) {
    if (i > 0) os << ", ";
    os << *args[i]->getType() << " ";
    printVarName(os, args[i]);
  }
  os << ") {\n";
  
  // 打印基本块
  for (auto& block : const_cast<Function*>(this)->getBasicBlocks()) {
    block->print(os);
  } 
  
  os << "}\n";
}

void Module::print(std::ostream& os) const {
  // 打印全局变量声明
  for (auto& globalVar : const_cast<Module*>(this)->getGlobals()) {
    globalVar->print(os);
    os << "\n";
  }
  
  // 打印常量声明
  for (auto& constVar : getConsts()) {
    constVar->print(os);
    os << "\n";
  }
  
  // 打印外部函数声明
  for (auto& extFunc : getExternalFunctions()) {
    os << "declare " << *extFunc.second->getReturnType() << " ";
    printFunctionName(os, extFunc.second.get());
    os << "(";
    
    const auto& paramTypes = extFunc.second->getParamTypes();
    bool first = true;
    for (auto paramType : paramTypes) {
      if (!first) os << ", ";
      os << *paramType;
      first = false;
    }
    os << ")\n";
  }
  
  // Always declare memset intrinsic when needed
  os << "declare void @llvm.memset.p0i8.i32(i8*, i8, i32, i1)\n";
  
  if (!getExternalFunctions().empty()) {
    os << "\n"; // 外部函数和普通函数之间加空行
  }
  
  // 打印函数定义
  for (auto& func : const_cast<Module*>(this)->getFunctions()) {
    func.second->print(os);
    os << "\n"; // 函数之间加空行
  }
}

void Module::cleanup() {
  // 清理所有函数中的使用关系
  for (auto& func : functions) {
    if (func.second) {
      func.second->cleanup();
    }
  }
  
  for (auto& extFunc : externalFunctions) {
    if (extFunc.second) {
      extFunc.second->cleanup();
    }
  }
  
  // 清理符号表
  variableTable.cleanup();
  
  // 清理函数表
  functions.clear();
  externalFunctions.clear();
}

void Function::cleanup() {
  // 首先清理所有基本块中的使用关系
  for (auto& block : blocks) {
    if (block) {
      block->cleanup();
    }
  }
  
  // 然后安全地清理参数列表中的使用关系
  for (auto arg : arguments) {
    if (arg) {
      // 清理参数的所有使用关系
      arg->cleanup();
      // 现在安全地删除参数对象
      delete arg;
    }
  }
  
  // 清理基本块列表
  blocks.clear();
  arguments.clear();
  callees.clear();
}

void BasicBlock::cleanup() {
  // 直接清理指令列表，让析构函数自然处理
  instructions.clear();
  
  // 清理前驱后继关系
  predecessors.clear();
  successors.clear();
}

void User::cleanup() {
  // 简单清理：让shared_ptr的析构函数自动处理Use关系
  // 这样避免了手动管理可能已经被释放的Value对象
  operands.clear();
}

void SymbolTable::cleanup() {
  // 清理全局变量和常量
  globals.clear();
  globalconsts.clear();
  
  // 清理符号表节点
  nodeList.clear();
  
  // 重置当前节点
  curNode = nullptr;
  
  // 清理变量索引
  variableIndex.clear();
}

void Argument::cleanup() {
  // Argument继承自Value，清理其使用列表
  uses.clear();
}

}  // namespace sysy
