Skip to content

Commit

Permalink
Add Compile-Time Term-Rewriting Template Optimizations, optional when…
Browse files Browse the repository at this point in the history
… defined(release) and defined(danger)
  • Loading branch information
juancarlospaco committed Aug 28, 2019
1 parent bfbb4ca commit 16f0bd4
Showing 1 changed file with 104 additions and 1 deletion.
105 changes: 104 additions & 1 deletion src/contra.nim
Expand Up @@ -39,8 +39,58 @@ template hardenedBuild*() =
const hf = "-fstack-protector-all -Wstack-protector --param ssp-buffer-size=4 -pie -fPIE -Wformat -Wformat-security -D_FORTIFY_SOURCE=2 -Wall -Wextra -Wconversion -Wsign-conversion -mindirect-branch=thunk -mfunction-return=thunk -fstack-clash-protection -Wl,-z,relro,-z,now -Wl,-z,noexecstack -fsanitize=signed-integer-overflow -fsanitize-undefined-trap-on-error -fno-common"
{.passC: hf, passL: hf, assertions: on, checks: on.}

when defined(danger) and defined(gcc) and not defined(hardened):
when defined(danger) and defined(release) and defined(gcc) and not defined(hardened):
{.passC: "-flto -ffast-math -march=native -mtune=native -fsingle-precision-constant".}
when defined(linux) or defined(windows) or defined(macos) and not defined(js):
{.hint: "Compile-Time Term-Rewriting Template Optimizations is enabled.".}
func fwrite(formatstr: cstring, size = 1.cuint, nmemb: cuint, stream = stdout) {.importc, header: "<stdio.h>".}
template echo*(s: any{lit, noalias}) = # SomeOrdinal? SomeNumber?
fwrite($s & "\n", nmemb = len($s) + 1) # Whats better?
template echo*(s0, s1: any{lit, noalias}) = # fwrite() > puts() > printf()
fwrite($s0 & $s1 & "\n", nmemb = len($s0) + len($s1) + 1)
template echo*(s0, s1, s2: any{lit, noalias}) =
fwrite($s0 & $s1 & $s2 & "\n", nmemb = len($s0) + len($s1) + len($s2) + 1)
template echo*(s0, s1, s2, s3: any{lit, noalias}) =
fwrite($s0 & $s1 & $s2 & $s3 & "\n", nmemb = len($s0) + len($s1) + len($s2) + len($s3) + 1)
template echo*(s0, s1, s2, s3, s4: any{lit, noalias}) =
fwrite($s0 & $s1 & $s2 & $s3 & $s4 & "\n", nmemb = len($s0) + len($s1) + len($s2) + len($s3) + len($s4) + 1)
template echo*(s0, s1, s2, s3, s4, s5: any{lit, noalias}) =
fwrite($s0 & $s1 & $s2 & $s3 & $s4 & $s5 & "\n",
nmemb = len($s0) + len($s1) + len($s2) + len($s3) + len($s4) + len($s5) + 1)
template echo*(s0, s1, s2, s3, s4, s5, s6: any{lit, noalias}) =
fwrite($s0 & $s1 & $s2 & $s3 & $s4 & $s5 & $s6 & "\n",
nmemb = len($s0) + len($s1) + len($s2) + len($s3) + len($s4) + len($s5) + len($s6) + 1)
template echo*(s0, s1, s2, s3, s4, s5, s6, s7: any{lit, noalias}) =
fwrite($s0 & $s1 & $s2 & $s3 & $s4 & $s5 & $s6 & $s7 & "\n",
nmemb = len($s0) + len($s1) + len($s2) + len($s3) + len($s4) + len($s5) + len($s6) + len($s7) + 1)
template echo*(s0, s1, s2, s3, s4, s5, s6, s7, s8: any{lit, noalias}) =
fwrite($s0 & $s1 & $s2 & $s3 & $s4 & $s5 & $s6 & $s7 & $s8 & "\n",
nmemb = len($s0) + len($s1) + len($s2) + len($s3) + len($s4) + len($s5) + len($s6) + len($s7) + len($s8) + 1)
template debugEcho*(s: any{lit, noalias}) =
fwrite($s & "\n", nmemb = len($s) + 1)
template debugEcho*(s0, s1: any{lit, noalias}) =
fwrite($s0 & $s1 & "\n", nmemb = len($s0) + len($s1) + 1)
template debugEcho*(s0, s1, s2: any{lit, noalias}) =
fwrite($s0 & $s1 & $s2 & "\n", nmemb = len($s0) + len($s1) + len($s2) + 1)
template debugEcho*(s0, s1, s2, s3: any{lit, noalias}) =
fwrite($s0 & $s1 & $s2 & $s3 & "\n", nmemb = len($s0) + len($s1) + len($s2) + len($s3) + 1)
template debugEcho*(s0, s1, s2, s3, s4: any{lit, noalias}) =
fwrite($s0 & $s1 & $s2 & $s3 & $s4 & "\n", nmemb = len($s0) + len($s1) + len($s2) + len($s3) + len($s4) + 1)
template debugEcho*(s0, s1, s2, s3, s4, s5: any{lit, noalias}) =
fwrite($s0 & $s1 & $s2 & $s3 & $s4 & $s5 & "\n",
nmemb = len($s0) + len($s1) + len($s2) + len($s3) + len($s4) + len($s5) + 1)
template debugEcho*(s0, s1, s2, s3, s4, s5, s6: any{lit, noalias}) =
fwrite($s0 & $s1 & $s2 & $s3 & $s4 & $s5 & $s6 & "\n",
nmemb = len($s0) + len($s1) + len($s2) + len($s3) + len($s4) + len($s5) + len($s6) + 1)
template debugEcho*(s0, s1, s2, s3, s4, s5, s6, s7: any{lit, noalias}) =
fwrite($s0 & $s1 & $s2 & $s3 & $s4 & $s5 & $s6 & $s7 & "\n",
nmemb = len($s0) + len($s1) + len($s2) + len($s3) + len($s4) + len($s5) + len($s6) + len($s7) + 1)
template debugEcho*(s0, s1, s2, s3, s4, s5, s6, s7, s8: any{lit, noalias}) =
fwrite($s0 & $s1 & $s2 & $s3 & $s4 & $s5 & $s6 & $s7 & $s8 & "\n",
nmemb = len($s0) + len($s1) + len($s2) + len($s3) + len($s4) + len($s5) + len($s6) + len($s7) + len($s8) + 1)
template optimizedFloatDivision*{f0 / f1}(f0: SomeFloat, f1: SomeFloat{lit, noalias}): untyped =
## Float Division 2x slow than multiplication. Eg x/3.0 --> x*(1.0/3.0)
f0 * static(1.0 / f1) # Rewrite division by constant to multiplication with the inverse.

when defined(release) and defined(gcc):
{.passL: "-s", passC: "-fno-ident".}
Expand All @@ -59,6 +109,10 @@ template deepCopy*(immutableVariable, changes: untyped): untyped =
runnableExamples:
hardenedBuild() ## Security Hardened mode enabled, compile with: -d:hardened


# ^ Hardened Build Templates ########## v Preconditions/Postconditions (DbC)


func funcWithContract(mustBePositive: int): int {.compiletime.} =
preconditions mustBePositive > 0, mustBePositive > -1 ## Require (Preconditions)
postconditions result > 0, result < int32.high ## Ensure (Postconditions)
Expand All @@ -69,6 +123,10 @@ runnableExamples:
result = mustBePositive - 1 ## Same func but without Contract templates.
echo funcWithoutContract(1) > 0, " <-- This must be 'true', if not is a Bug!"


# ^ Preconditions/Postconditions (DbC) ################# v deepCopy Templates


type Person = object # Changing Immutable Variables,into Immutable Variables.
name: string
age: Natural
Expand All @@ -81,3 +139,48 @@ runnableExamples:
echo bob # (name: "Bob", age: 42) Original Immutable
echo olderBob # (name: "Bo", age: 45) Changed Immutable
echo otherBob # (name: "Bob", age: 42) Just to control is not confused


# ^ deepCopy Templates ######################## v echo(literal) Optimizations


echo "a"
echo "a", "b"
echo "a", "b", "c"
echo "a", "b", "c", "d"
echo "a", "b", "c", "d", "e"
echo "a", "b", "c", "d", "e", "f"
echo "a", "b", "c", "d", "e", "f", "g"
echo "a", "b", "c", "d", "e", "f", "g", "h"
echo 1
echo 1, 2
echo 1, 2, 3
echo 1, 2, 3, 4
echo 1, 2, 3, 4, 5
echo 1, 2, 3, 4, 5, 6
echo 1, 2, 3, 4, 5, 6, 7
echo 1, 2, 3, 4, 5, 6, 7, 8
debugEcho "a"
debugEcho "a", "b"
debugEcho "a", "b", "c"
debugEcho "a", "b", "c", "d"
debugEcho "a", "b", "c", "d", "e"
debugEcho "a", "b", "c", "d", "e", "f"
debugEcho "a", "b", "c", "d", "e", "f", "g"
debugEcho "a", "b", "c", "d", "e", "f", "g", "h"
debugEcho 1
debugEcho 1, 2
debugEcho 1, 2, 3
debugEcho 1, 2, 3, 4
debugEcho 1, 2, 3, 4, 5
debugEcho 1, 2, 3, 4, 5, 6
debugEcho 1, 2, 3, 4, 5, 6, 7
debugEcho 1, 2, 3, 4, 5, 6, 7, 8


# ^ echo(literal) Optimizations ############## v Float Division Optimizations


var x, y = 2.0
echo x / 2.0
echo y / x

1 comment on commit 16f0bd4

@juancarlospaco
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Float Division Optimization C output:

NF x_9b3J8iZeIHRoRKYxMY9a9bzzQ;
x_9b3J8iZeIHRoRKYxMY9a9bzzQ = 2.0000000000000000e+00;
( (NF)(x_9b3J8iZeIHRoRKYxMY9a9bzzQ) * (NF)(5.0000000000000000e-01) )

Echo Literal Optimization C output:

fwrite("2.0\012", ((unsigned int) 1), ((unsigned int) 4), stdout);
fwrite("2.0\012", ((unsigned int) 1), ((unsigned int) 4), stdout);
fwrite("a\012", ((unsigned int) 1), ((unsigned int) 2), stdout);
fwrite("ab\012", ((unsigned int) 1), ((unsigned int) 3), stdout);
fwrite("abc\012", ((unsigned int) 1), ((unsigned int) 4), stdout);
fwrite("abcd\012", ((unsigned int) 1), ((unsigned int) 5), stdout);
fwrite("abcde\012", ((unsigned int) 1), ((unsigned int) 6), stdout);
fwrite("abcdef\012", ((unsigned int) 1), ((unsigned int) 7), stdout);
fwrite("abcdefg\012", ((unsigned int) 1), ((unsigned int) 8), stdout);
fwrite("abcdefgh\012", ((unsigned int) 1), ((unsigned int) 9), stdout);
fwrite("1\012", ((unsigned int) 1), ((unsigned int) 2), stdout);
fwrite("12\012", ((unsigned int) 1), ((unsigned int) 3), stdout);
fwrite("123\012", ((unsigned int) 1), ((unsigned int) 4), stdout);
fwrite("1234\012", ((unsigned int) 1), ((unsigned int) 5), stdout);
fwrite("12345\012", ((unsigned int) 1), ((unsigned int) 6), stdout);
fwrite("123456\012", ((unsigned int) 1), ((unsigned int) 7), stdout);
fwrite("1234567\012", ((unsigned int) 1), ((unsigned int) 8), stdout);
fwrite("12345678\012", ((unsigned int) 1), ((unsigned int) 9), stdout);
fwrite("a\012", ((unsigned int) 1), ((unsigned int) 2), stdout);
fwrite("ab\012", ((unsigned int) 1), ((unsigned int) 3), stdout);
fwrite("abc\012", ((unsigned int) 1), ((unsigned int) 4), stdout);
fwrite("abcd\012", ((unsigned int) 1), ((unsigned int) 5), stdout);
fwrite("abcde\012", ((unsigned int) 1), ((unsigned int) 6), stdout);
fwrite("abcdef\012", ((unsigned int) 1), ((unsigned int) 7), stdout);
fwrite("abcdefg\012", ((unsigned int) 1), ((unsigned int) 8), stdout);
fwrite("abcdefgh\012", ((unsigned int) 1), ((unsigned int) 9), stdout);
fwrite("1\012", ((unsigned int) 1), ((unsigned int) 2), stdout);
fwrite("12\012", ((unsigned int) 1), ((unsigned int) 3), stdout);
fwrite("123\012", ((unsigned int) 1), ((unsigned int) 4), stdout);
fwrite("1234\012", ((unsigned int) 1), ((unsigned int) 5), stdout);
fwrite("12345\012", ((unsigned int) 1), ((unsigned int) 6), stdout);
fwrite("123456\012", ((unsigned int) 1), ((unsigned int) 7), stdout);
fwrite("1234567\012", ((unsigned int) 1), ((unsigned int) 8), stdout);
fwrite("12345678\012", ((unsigned int) 1), ((unsigned int) 9), stdout);

Please sign in to comment.