llvm::Function* WasmImportFunction::GetFunction(WasmModule* module) {
  if (function_ == nullptr) {
    // This probably should be done better but will work like this for now.
    std::string full_name = module_name_ + "_" + function_name_;

    // Now what we really want is the parameters of this method.
    std::vector<llvm::Type*> params;
    Populate(params);

    // Add to the name the type of the arguments for the import.
    //  Again, probably not what we want finally but this will work.
    //  My problem right now is how to handle the variadic functions well.
    for (auto elem : params) {
      full_name += "_";
      full_name += GetTypeName(elem);
    }

    BISON_PRINT("Import Function not created yet: Internal name: %s Module: %s Function: %s -> Full %s\n", internal_name_.c_str(), module_name_.c_str(), function_name_.c_str(), full_name.c_str());

    // Now get the result type.
    llvm::Type* result_type = ConvertType(result_);

    // Finally, create the function type.
    llvm::FunctionType* fct_type = llvm::FunctionType::get(result_type, params, false);

    // Now create the function.
    function_ = llvm::Function::Create(fct_type, llvm::Function::ExternalLinkage, full_name, module->GetModule());
  }

  // Paranoid.
  assert(function_ != nullptr);

  // Finally we can return the function_.
  return function_;
}
void Unop::Dump(int tabs) const {
  BISON_TABBED_PRINT(tabs, "(");

  if (operation_) {
    operation_->Dump();
  } else {
    BISON_PRINT("Operation is nullptr");
  }

  BISON_PRINT(" ");

  if (only_) {
    only_->Dump();
  } else {
    BISON_PRINT("nullptr");
  }
  BISON_PRINT(")");
}
llvm::Value* HandleTypeCasts(llvm::Value* value, llvm::Type* src_type, llvm::Type* dest_type, bool sign, llvm::IRBuilder<>& builder) {
  if (dest_type != src_type) {
    llvm::Type::TypeID src_type_id = src_type->getTypeID();

    switch (src_type_id) {
      case llvm::Type::IntegerTyID: {
        int src_type_bw = src_type->getIntegerBitWidth();
        return HandleTypeCastsFromIntegers(value, src_type_bw, dest_type, sign, builder);
      }
      case llvm::Type::FloatTyID:
        return HandleTypeCastsFromFloats(value, dest_type, sign, builder);
      case llvm::Type::DoubleTyID:
        return HandleTypeCastsFromDoubles(value, dest_type, sign, builder);
      case llvm::Type::PointerTyID:
        // Probably not good to do this.
        return value;
      default: {
        llvm::Type::TypeID dest_type_id = dest_type->getTypeID();

        BISON_PRINT("HandleTypeCast failure: destination is %d and src is %d\n", dest_type_id, src_type_id);

        (void) dest_type_id;
        assert(0);
        break;
      }
    }
  } else {
    // A bit more code to handle integer case
    llvm::Type::TypeID dest_type_id = dest_type->getTypeID();
    if (dest_type_id == llvm::Type::IntegerTyID) {
      // Now check sizes.
      int dest_type_bw = dest_type->getIntegerBitWidth();
      int src_type_bw = src_type->getIntegerBitWidth();

      // We have a problem here.
      if (dest_type_bw != src_type_bw) {
        // Handle difference of sizes.
        value = HandleIntegerTypeCast(value, dest_type, src_type_bw, dest_type_bw, sign, builder);
      }
    }

    return value;
  }
}
WasmFunction* CallExpression::GetCallee(WasmFunction* fct) const {
  WasmModule* module = fct->GetModule();
  WasmFunction* wfct = nullptr;

  if (call_id_->IsString()) {
    const char* name = call_id_->GetString();
    wfct = module->GetWasmFunction(name);
  } else {
    size_t idx = call_id_->GetIdx();
    wfct  = module->GetWasmFunction(idx);
  }

  if (wfct == nullptr) {
    BISON_PRINT("Problem with finding %s\n", call_id_->GetString());
  }
  assert(wfct != nullptr);

  return wfct;
}