首页 > 解决方案 > 具有智能数组分配(堆或堆栈)的语言

问题描述

我正在为(有趣和)科学应用程序编写一个小型玩具语言/编译器。核心设计原则是简单和高效(如果你愿意,可以使用某种“现代”Fortran)。该语言将具有内置数组,看起来像这样:

let x: Real[5] = {1.0, 2.0, 3.0, 4.0, 5.0}

let n = get_runtime_value()
let y: Integer[100,n] = ...

在上面的语句中,用户没有明确说明数组应该分配在栈上还是堆上。如果可能的话,我宁愿不把它暴露给用户(我的理由是大多数工程师不知道区别,也不应该关心。他们还有其他问题要担心。)。

从技术上讲,我可以写如下内容:

if (some input parameter cannot be known at compile time)
  allocate on the heap
else  # candidate for the stack
  if (the array is not returned by the function && the allocated size is smaller than some threshold)
     allocate on the stack
  else
     allocate on the heap

然而,这个设计让我害怕有几个原因:

  1. 增加了复杂性,更长的编译时间?
  2. 在 C++ 中,编译器可以执行 RVO 并直接在堆栈上返回一个值。我想我可以使算法更复杂以检测这种情况,但这会使整个事情变得更复杂/错误/编译缓慢。
  3. 数组大小的微小变化可能会导致从堆栈切换到堆。这可能会让用户感到困惑。定义这个阈值也需要一些小心。
  4. 我需要检查是否没有返回对该数组的某些引用(以及引用的引用等)。我想追踪它可能会很昂贵。

请注意,我不想以我的语言公开指针或引用。数组将始终在引擎盖下通过引用传递。

文献中有没有解决这个问题的巧妙方法?以前用现有的语言做过吗?我知道的所有语言都要求用户指定他们想要数据的位置:Fortran 有::allocatable、C++ 有std::vectorstd::array等。我也可以做一些类似 llvm 的事情SmallVector,并且总是在移动到堆之前在堆栈上分配一些元素。我的方法有任何意义吗?我正在使用这个项目来了解更多关于编译器和语言设计的信息。有什么我应该注意的吗?

标签: c++compiler-constructionllvmlanguage-design

解决方案


该选项实际上取决于您,但如果我是您,我会让用户选择是在堆上分配还是在堆栈上分配。如果没有,它很可能会让您和用户感到非常困惑。如果您仍想实现该功能,我有一些提示。

  • 与其检查是否在编译时无法知道,不如检查在编译时可以知道的内容——它将简化事情。
  • 默认情况下在堆或堆栈上定义所有内容——这将使您更容易处理需要从堆栈切换到堆(反之亦然)的情况(这更容易,因为假设何时append调用您可以切换到堆)。

总之,我建议您让用户明确声明堆栈或堆上的数组。


推荐阅读