Skip to content

Instantly share code, notes, and snippets.

@kant2002
Created March 7, 2024 08:33
Show Gist options
  • Save kant2002/0c5371ebceb7261ae761c21630a04927 to your computer and use it in GitHub Desktop.
Save kant2002/0c5371ebceb7261ae761c21630a04927 to your computer and use it in GitHub Desktop.
Урок из Цезиума

Урок из Цезиума

Цезиум дает мне кучу анти-уроков по архитектуре компиляторов. Это явно не самый эффективный способ построения компилятора, так как вечный рефакторинг деморализует даже оптимистов вроде меня. Потому попробую рассказать как выглядит лень и не желание учить теорию.

Есть такая маленькая особенность в С, это то что в main последний return не обязателен и компилятор может его сам вставить за программиста. Мы как большие прагматики, сперва сделали какой-то костыль, чтобы тестовые програмки которые мы писали проходили. Просто смотрели на наличие return в теле функции и если его не было, компилятор возмущался. у нас тогда не было даже нормальных циклов в свитчей, потому это была победа. Но пришли циклы и с ними новые вызовы, добрый человек взял и начал строить граф зависимости между стейтментами, и пытался найти все ли пути ведут к выходу. Зашибись, прогресс идет. Но кто же знал что бывают бесконечные циклы, в которых есть return. Новый алгоритм с графами сломался :(. Сломался он потому что дерево кода у нас в этом моменте все еще достаточно высокоуровнево, у нас есть блоки {} со своей областью видимости(CompoundStatement), все переменные живут каждая в своей области видимости, это все делает нашу структуру кода древовидной и где-то что-то мы делаем не так.

Наверное можно починить алгоритм построения графа прохождения по коду, но это все выглядит слишком сложно, для такой простой вещи как компилятор С. Я решил что пора нам в компилятор засунуть создаение базовых блоков (basic blocks), но оказалось (как я выше упоминал) что у нас слишком высокооуровневое дерево. Потом я подумал что может быть нам стоит линеаризировать все что находится внутри тела функции чтобы у нас не было никаких CompoundStatement. В целом это было легко сделать, но оказалось что у нас привязаны к области видимости внутренних блоков, и если мы убираем их, то переменные надо переносить в область видимости функции. Тоесть нужен еще один этап когда мы переназываем переменные.

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

  1. переименование переменных и перенос их под уникальными именами в область видимости функции
  2. линеаризация кода
  3. построение базовых блоков из линеаризованного кода

Я больше чем уверен что это не конец, и наше ковбойское отношение будет нам и дальше аукаться. Так что учите матчасть.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment