Компиляция операторов switch для простой виртуальной машины

Итак, я собираю подмножество C в простую стековую виртуальную машину для целей обучения и хотел бы узнать, как лучше всего скомпилировать оператор switch, например

switch (e) {
  case 0: { ... }
  case 1: { ... }
  ...
  case k: { ... }
}

Книга, которую я изучаю, предлагает простой способ компиляции с помощью индексированных переходов, но простая схема, описанная в книге, работает только для непрерывных, возрастающих диапазонов значений регистра.

Прямо сейчас я использую символические метки для первого прохода, а во время второго прохода я собираюсь разрешить метки для реальных целей перехода, потому что наличие меток значительно упрощает первоначальную компиляцию, чтобы складывать инструкции. Моя идея сейчас состоит в том, чтобы обобщить то, что в книге, для любой последовательности значений падежей в любом порядке по следующей схеме. Назовите значения дела c1, c2, ..., cn и соответствующие ярлыки j1, j2, ..., jn затем сгенерируйте следующую последовательность команд, принимая значение e находится на вершине стека:

dup, loadc c1, eq, jumpnz j1,
dup, loadc c2, eq, jumpnz j2,
...
dup, loadc cn, eq, jumpnz jn,
pop, jump :default
j1: ...
j2: ...
...
jn: ...
default: ...

Надеемся, что запись понятна, но если нет: dup = дублирующее значение на вершине стека, loadc c = толкать константу c на вершине стека, eq = сравнить два верхних значения в стеке и нажать 0 или 1 на основе сравнения, jumpnz j = перейти к метке j если значение верхнего стека не равно 0, label: = то, что будет преобразовано в фактический адрес во время второго этапа компиляции.

Итак, мой вопрос: каковы другие способы составления операторов switch? Мой способ сделать это намного менее компактен, чем индексированная таблица переходов для смежных диапазонов значений регистра, но работает довольно хорошо, когда есть большие промежутки.

1 ответ

Решение

Сначала рассортируйте все дела. Затем идентифицируйте все (достаточно большие, чтобы иметь смысл) случайные или почти смежные последовательности и рассматривайте их как единое целое, которое обрабатывается таблицей переходов. Затем вместо линейной последовательности сравнений и переходов используйте сбалансированное двоичное дерево ветвей, чтобы минимизировать среднее количество переходов. Вы делаете это путем рекурсивного сравнения со средним числом дел или блоков дел.

Другие вопросы по тегам