Skip to content

Instantly share code, notes, and snippets.

@SeijiEmery
Last active May 19, 2019 00:24
Show Gist options
  • Save SeijiEmery/8088773068ef73462de2b104f9ba1fe8 to your computer and use it in GitHub Desktop.
Save SeijiEmery/8088773068ef73462de2b104f9ba1fe8 to your computer and use it in GitHub Desktop.
Compile-time Arith
g++ -std=c++11 Arith.cpp -S && cat Arith.S
g++ -std=c++11 Arith.cpp && ./a.out
Const<12> => 12
Add<Const<2>, Const<3>> => 5
Add<Const<3>, Const<2>> => 5
Mul<Add<Const<2>, Const<3>>, Const<11>> => 55
Mul<Const<11>, Add<Const<2>, Const<3>>> => 55
Add<Const<12>, Mul<Add<Const<2>, Const<3>>, Const<11>>> => 67
Add<Mul<Add<Const<2>, Const<3>>, Const<11>>, Const<12>> => 67
#include <iostream>
#include <cstdio>
enum { TYPE_CONST = 0, TYPE_ADD, TYPE_MUL };
template <int x>
struct Const {
enum {
type = TYPE_CONST,
result = x
};
static std::ostream& repr (std::ostream& os) {
return os << "Const<" << x << ">";
}
static void printf () {
::printf("Const<%d>", x);
}
};
template <typename L, typename R>
struct Add {
typedef L Left;
typedef R Right;
enum {
type = TYPE_ADD,
result = Left::result + Right::result
};
static std::ostream& repr (std::ostream& os) {
return os << "Add<",
Left::repr(os) << ", ",
Right::repr(os) << ">";
}
static void printf () {
::printf("Add<"); Left::printf(); ::printf(", "); Right::printf(); ::printf(">");
}
};
template <typename L, typename R>
struct Mul {
typedef L Left;
typedef R Right;
enum {
type = TYPE_MUL,
result = Left::result * Right::result
};
static std::ostream& repr (std::ostream& os) {
return os << "Mul<",
Left::repr(os) << ", ",
Right::repr(os) << ">";
}
static void printf () {
::printf("Mul<"); Left::printf(); ::printf(", "); Right::printf(); ::printf(">");
}
};
#define eval(Expr) (Expr::result)
#define repr(Expr) (Expr::repr(std::cout))
#define print(Expr) (Expr::printf())
// #define printEval(Expr) (repr(Expr) << " => " << eval(Expr) << '\n')
// #define printEval(Expr) (std::cout << " => " << eval(Expr) << '\n')
#define printEval(Expr) (print(Expr), printf(" => %d\n", eval(Expr)))
// #define printEval(Expr)
// #define printEval(Expr) (printf(" => %d\n", eval(Expr)))
#define assertEvaluatesTo(Expr, result) \
static_assert(eval(Expr) == result, #Expr " !=> " #result)
int main () {
using A = Const<12>;
assertEvaluatesTo(A, 12);
printEval(A);
using B = Add<Const<2>, Const<3>>;
using B_ = Add<Const<3>, Const<2>>;
assertEvaluatesTo(B, 5);
assertEvaluatesTo(B_, 5);
printEval(B);
printEval(B_);
using C = Mul<B, Const<11>>;
using C_ = Mul<Const<11>, B>;
assertEvaluatesTo(C, 55);
assertEvaluatesTo(C_, 55);
printEval(C);
printEval(C_);
using D = Add<A, C>;
using D_ = Add<C, A>;
assertEvaluatesTo(D, 67);
assertEvaluatesTo(D_, 67);
// assertEvaluatesTo(D_, 62);
printEval(D);
printEval(D_);
}
.section __TEXT,__text,regular,pure_instructions
.build_version macos, 10, 14
.globl _main ## -- Begin function main
.p2align 4, 0x90
_main: ## @main
.cfi_startproc
## %bb.0:
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset %rbp, -16
movq %rsp, %rbp
.cfi_def_cfa_register %rbp
xorl %eax, %eax
popq %rbp
retq
.cfi_endproc
## -- End function
.subsections_via_symbols
.section __TEXT,__text,regular,pure_instructions
.build_version macos, 10, 14
.globl _main ## -- Begin function main
.p2align 4, 0x90
_main: ## @main
.cfi_startproc
## %bb.0:
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset %rbp, -16
movq %rsp, %rbp
.cfi_def_cfa_register %rbp
subq $32, %rsp
callq __ZN5ConstILi12EE6printfEv
leaq L_.str(%rip), %rdi
movl $12, %esi
movb $0, %al
callq _printf
movl %eax, -4(%rbp) ## 4-byte Spill
callq __ZN3AddI5ConstILi2EES0_ILi3EEE6printfEv
leaq L_.str(%rip), %rdi
movl $5, %esi
movb $0, %al
callq _printf
movl %eax, -8(%rbp) ## 4-byte Spill
callq __ZN3AddI5ConstILi3EES0_ILi2EEE6printfEv
leaq L_.str(%rip), %rdi
movl $5, %esi
movb $0, %al
callq _printf
movl %eax, -12(%rbp) ## 4-byte Spill
callq __ZN3MulI3AddI5ConstILi2EES1_ILi3EEES1_ILi11EEE6printfEv
leaq L_.str(%rip), %rdi
movl $55, %esi
movb $0, %al
callq _printf
movl %eax, -16(%rbp) ## 4-byte Spill
callq __ZN3MulI5ConstILi11EE3AddIS0_ILi2EES0_ILi3EEEE6printfEv
leaq L_.str(%rip), %rdi
movl $55, %esi
movb $0, %al
callq _printf
movl %eax, -20(%rbp) ## 4-byte Spill
callq __ZN3AddI5ConstILi12EE3MulIS_IS0_ILi2EES0_ILi3EEES0_ILi11EEEE6printfEv
leaq L_.str(%rip), %rdi
movl $67, %esi
movb $0, %al
callq _printf
movl %eax, -24(%rbp) ## 4-byte Spill
callq __ZN3AddI3MulIS_I5ConstILi2EES1_ILi3EEES1_ILi11EEES1_ILi12EEE6printfEv
leaq L_.str(%rip), %rdi
movl $67, %esi
movb $0, %al
callq _printf
xorl %esi, %esi
movl %eax, -28(%rbp) ## 4-byte Spill
movl %esi, %eax
addq $32, %rsp
popq %rbp
retq
.cfi_endproc
## -- End function
.globl __ZN5ConstILi12EE6printfEv ## -- Begin function _ZN5ConstILi12EE6printfEv
.weak_definition __ZN5ConstILi12EE6printfEv
.p2align 4, 0x90
__ZN5ConstILi12EE6printfEv: ## @_ZN5ConstILi12EE6printfEv
.cfi_startproc
## %bb.0:
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset %rbp, -16
movq %rsp, %rbp
.cfi_def_cfa_register %rbp
subq $16, %rsp
leaq L_.str.1(%rip), %rdi
movl $12, %esi
movb $0, %al
callq _printf
movl %eax, -4(%rbp) ## 4-byte Spill
addq $16, %rsp
popq %rbp
retq
.cfi_endproc
## -- End function
.globl __ZN3AddI5ConstILi2EES0_ILi3EEE6printfEv ## -- Begin function _ZN3AddI5ConstILi2EES0_ILi3EEE6printfEv
.weak_definition __ZN3AddI5ConstILi2EES0_ILi3EEE6printfEv
.p2align 4, 0x90
__ZN3AddI5ConstILi2EES0_ILi3EEE6printfEv: ## @_ZN3AddI5ConstILi2EES0_ILi3EEE6printfEv
.cfi_startproc
## %bb.0:
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset %rbp, -16
movq %rsp, %rbp
.cfi_def_cfa_register %rbp
subq $16, %rsp
leaq L_.str.2(%rip), %rdi
movb $0, %al
callq _printf
movl %eax, -4(%rbp) ## 4-byte Spill
callq __ZN5ConstILi2EE6printfEv
leaq L_.str.3(%rip), %rdi
movb $0, %al
callq _printf
movl %eax, -8(%rbp) ## 4-byte Spill
callq __ZN5ConstILi3EE6printfEv
leaq L_.str.4(%rip), %rdi
movb $0, %al
callq _printf
movl %eax, -12(%rbp) ## 4-byte Spill
addq $16, %rsp
popq %rbp
retq
.cfi_endproc
## -- End function
.globl __ZN3AddI5ConstILi3EES0_ILi2EEE6printfEv ## -- Begin function _ZN3AddI5ConstILi3EES0_ILi2EEE6printfEv
.weak_definition __ZN3AddI5ConstILi3EES0_ILi2EEE6printfEv
.p2align 4, 0x90
__ZN3AddI5ConstILi3EES0_ILi2EEE6printfEv: ## @_ZN3AddI5ConstILi3EES0_ILi2EEE6printfEv
.cfi_startproc
## %bb.0:
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset %rbp, -16
movq %rsp, %rbp
.cfi_def_cfa_register %rbp
subq $16, %rsp
leaq L_.str.2(%rip), %rdi
movb $0, %al
callq _printf
movl %eax, -4(%rbp) ## 4-byte Spill
callq __ZN5ConstILi3EE6printfEv
leaq L_.str.3(%rip), %rdi
movb $0, %al
callq _printf
movl %eax, -8(%rbp) ## 4-byte Spill
callq __ZN5ConstILi2EE6printfEv
leaq L_.str.4(%rip), %rdi
movb $0, %al
callq _printf
movl %eax, -12(%rbp) ## 4-byte Spill
addq $16, %rsp
popq %rbp
retq
.cfi_endproc
## -- End function
.globl __ZN3MulI3AddI5ConstILi2EES1_ILi3EEES1_ILi11EEE6printfEv ## -- Begin function _ZN3MulI3AddI5ConstILi2EES1_ILi3EEES1_ILi11EEE6printfEv
.weak_definition __ZN3MulI3AddI5ConstILi2EES1_ILi3EEES1_ILi11EEE6printfEv
.p2align 4, 0x90
__ZN3MulI3AddI5ConstILi2EES1_ILi3EEES1_ILi11EEE6printfEv: ## @_ZN3MulI3AddI5ConstILi2EES1_ILi3EEES1_ILi11EEE6printfEv
.cfi_startproc
## %bb.0:
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset %rbp, -16
movq %rsp, %rbp
.cfi_def_cfa_register %rbp
subq $16, %rsp
leaq L_.str.5(%rip), %rdi
movb $0, %al
callq _printf
movl %eax, -4(%rbp) ## 4-byte Spill
callq __ZN3AddI5ConstILi2EES0_ILi3EEE6printfEv
leaq L_.str.3(%rip), %rdi
movb $0, %al
callq _printf
movl %eax, -8(%rbp) ## 4-byte Spill
callq __ZN5ConstILi11EE6printfEv
leaq L_.str.4(%rip), %rdi
movb $0, %al
callq _printf
movl %eax, -12(%rbp) ## 4-byte Spill
addq $16, %rsp
popq %rbp
retq
.cfi_endproc
## -- End function
.globl __ZN3MulI5ConstILi11EE3AddIS0_ILi2EES0_ILi3EEEE6printfEv ## -- Begin function _ZN3MulI5ConstILi11EE3AddIS0_ILi2EES0_ILi3EEEE6printfEv
.weak_definition __ZN3MulI5ConstILi11EE3AddIS0_ILi2EES0_ILi3EEEE6printfEv
.p2align 4, 0x90
__ZN3MulI5ConstILi11EE3AddIS0_ILi2EES0_ILi3EEEE6printfEv: ## @_ZN3MulI5ConstILi11EE3AddIS0_ILi2EES0_ILi3EEEE6printfEv
.cfi_startproc
## %bb.0:
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset %rbp, -16
movq %rsp, %rbp
.cfi_def_cfa_register %rbp
subq $16, %rsp
leaq L_.str.5(%rip), %rdi
movb $0, %al
callq _printf
movl %eax, -4(%rbp) ## 4-byte Spill
callq __ZN5ConstILi11EE6printfEv
leaq L_.str.3(%rip), %rdi
movb $0, %al
callq _printf
movl %eax, -8(%rbp) ## 4-byte Spill
callq __ZN3AddI5ConstILi2EES0_ILi3EEE6printfEv
leaq L_.str.4(%rip), %rdi
movb $0, %al
callq _printf
movl %eax, -12(%rbp) ## 4-byte Spill
addq $16, %rsp
popq %rbp
retq
.cfi_endproc
## -- End function
.globl __ZN3AddI5ConstILi12EE3MulIS_IS0_ILi2EES0_ILi3EEES0_ILi11EEEE6printfEv ## -- Begin function _ZN3AddI5ConstILi12EE3MulIS_IS0_ILi2EES0_ILi3EEES0_ILi11EEEE6printfEv
.weak_definition __ZN3AddI5ConstILi12EE3MulIS_IS0_ILi2EES0_ILi3EEES0_ILi11EEEE6printfEv
.p2align 4, 0x90
__ZN3AddI5ConstILi12EE3MulIS_IS0_ILi2EES0_ILi3EEES0_ILi11EEEE6printfEv: ## @_ZN3AddI5ConstILi12EE3MulIS_IS0_ILi2EES0_ILi3EEES0_ILi11EEEE6printfEv
.cfi_startproc
## %bb.0:
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset %rbp, -16
movq %rsp, %rbp
.cfi_def_cfa_register %rbp
subq $16, %rsp
leaq L_.str.2(%rip), %rdi
movb $0, %al
callq _printf
movl %eax, -4(%rbp) ## 4-byte Spill
callq __ZN5ConstILi12EE6printfEv
leaq L_.str.3(%rip), %rdi
movb $0, %al
callq _printf
movl %eax, -8(%rbp) ## 4-byte Spill
callq __ZN3MulI3AddI5ConstILi2EES1_ILi3EEES1_ILi11EEE6printfEv
leaq L_.str.4(%rip), %rdi
movb $0, %al
callq _printf
movl %eax, -12(%rbp) ## 4-byte Spill
addq $16, %rsp
popq %rbp
retq
.cfi_endproc
## -- End function
.globl __ZN3AddI3MulIS_I5ConstILi2EES1_ILi3EEES1_ILi11EEES1_ILi12EEE6printfEv ## -- Begin function _ZN3AddI3MulIS_I5ConstILi2EES1_ILi3EEES1_ILi11EEES1_ILi12EEE6printfEv
.weak_definition __ZN3AddI3MulIS_I5ConstILi2EES1_ILi3EEES1_ILi11EEES1_ILi12EEE6printfEv
.p2align 4, 0x90
__ZN3AddI3MulIS_I5ConstILi2EES1_ILi3EEES1_ILi11EEES1_ILi12EEE6printfEv: ## @_ZN3AddI3MulIS_I5ConstILi2EES1_ILi3EEES1_ILi11EEES1_ILi12EEE6printfEv
.cfi_startproc
## %bb.0:
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset %rbp, -16
movq %rsp, %rbp
.cfi_def_cfa_register %rbp
subq $16, %rsp
leaq L_.str.2(%rip), %rdi
movb $0, %al
callq _printf
movl %eax, -4(%rbp) ## 4-byte Spill
callq __ZN3MulI3AddI5ConstILi2EES1_ILi3EEES1_ILi11EEE6printfEv
leaq L_.str.3(%rip), %rdi
movb $0, %al
callq _printf
movl %eax, -8(%rbp) ## 4-byte Spill
callq __ZN5ConstILi12EE6printfEv
leaq L_.str.4(%rip), %rdi
movb $0, %al
callq _printf
movl %eax, -12(%rbp) ## 4-byte Spill
addq $16, %rsp
popq %rbp
retq
.cfi_endproc
## -- End function
.globl __ZN5ConstILi2EE6printfEv ## -- Begin function _ZN5ConstILi2EE6printfEv
.weak_definition __ZN5ConstILi2EE6printfEv
.p2align 4, 0x90
__ZN5ConstILi2EE6printfEv: ## @_ZN5ConstILi2EE6printfEv
.cfi_startproc
## %bb.0:
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset %rbp, -16
movq %rsp, %rbp
.cfi_def_cfa_register %rbp
subq $16, %rsp
leaq L_.str.1(%rip), %rdi
movl $2, %esi
movb $0, %al
callq _printf
movl %eax, -4(%rbp) ## 4-byte Spill
addq $16, %rsp
popq %rbp
retq
.cfi_endproc
## -- End function
.globl __ZN5ConstILi3EE6printfEv ## -- Begin function _ZN5ConstILi3EE6printfEv
.weak_definition __ZN5ConstILi3EE6printfEv
.p2align 4, 0x90
__ZN5ConstILi3EE6printfEv: ## @_ZN5ConstILi3EE6printfEv
.cfi_startproc
## %bb.0:
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset %rbp, -16
movq %rsp, %rbp
.cfi_def_cfa_register %rbp
subq $16, %rsp
leaq L_.str.1(%rip), %rdi
movl $3, %esi
movb $0, %al
callq _printf
movl %eax, -4(%rbp) ## 4-byte Spill
addq $16, %rsp
popq %rbp
retq
.cfi_endproc
## -- End function
.globl __ZN5ConstILi11EE6printfEv ## -- Begin function _ZN5ConstILi11EE6printfEv
.weak_definition __ZN5ConstILi11EE6printfEv
.p2align 4, 0x90
__ZN5ConstILi11EE6printfEv: ## @_ZN5ConstILi11EE6printfEv
.cfi_startproc
## %bb.0:
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset %rbp, -16
movq %rsp, %rbp
.cfi_def_cfa_register %rbp
subq $16, %rsp
leaq L_.str.1(%rip), %rdi
movl $11, %esi
movb $0, %al
callq _printf
movl %eax, -4(%rbp) ## 4-byte Spill
addq $16, %rsp
popq %rbp
retq
.cfi_endproc
## -- End function
.section __TEXT,__cstring,cstring_literals
L_.str: ## @.str
.asciz " => %d\n"
L_.str.1: ## @.str.1
.asciz "Const<%d>"
L_.str.2: ## @.str.2
.asciz "Add<"
L_.str.3: ## @.str.3
.asciz ", "
L_.str.4: ## @.str.4
.asciz ">"
L_.str.5: ## @.str.5
.asciz "Mul<"
.subsections_via_symbols
@SeijiEmery
Copy link
Author

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