Как Ada реализует типы 'mod' и 'range'? Каковы последствия производительности?

В Ada вы можете определить так называемые типы ' mod' и ' range':

type Unsigned_n is mod 2**n;
type Range_Type is range -5 .. 10;

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

1 ответ

Решение

Непонятно, что вы подразумеваете под "на уровне языка". На уровне Ады они просто есть! и на уровне машины они реализованы так, как вы ожидаете.

Для модульных типов, если вы используете степень 2 для модуля, скомпилированный код использует маски; в противном случае будут тесты.

type Modular is mod 42;
...
procedure T (M : in out Modular) is
begin
   M := M + 1;
end T;

переводит (x86_64, -O2) в

_foo__t:
LFB2:
        leal    1(%rdi), %eax
        cmpb    $40, %dil
        leal    -41(%rdi), %edx
        cmovg   %edx, %eax
        ret

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

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

Но на самом деле, для большинства случаев вы не пишете эти операции приращения самостоятельно; если вам нужно перебрать все значения типа, который вы можете сказать

for J in Modular loop

или, если вы объявили Arr : array (Range_Type) of Foo;,

for J in Arr'Range loop

и нет необходимости проверять действительность Jи, следовательно, нет потери производительности.

Всегда возможно подавить проверки ограничений (в GNAT, -gnatp подавляет все проверки); но это немного похоже на снятие ремня безопасности, как только вы покинете дорогу!

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