#define NULL ((void *)0)
typedef unsigned long size_t; // Customize by platform.
typedef long intptr_t;
typedef unsigned long uintptr_t;
typedef long scalar_t__; // Either arithmetic or pointer type.
/* By default, we understand bool (as a convenience). */
typedef int bool;
#define false 0
#define true 1

/* Forward declarations */

/* Type definitions */

/* Variables and functions */
int /*<<< orphan*/ printf(char *, char *);
void generate_macro_add_matrix() {
  char *macro =
      "void** add_matrix(char const* param_type, void** mat_1, void**  mat_2, "
      "int rows, int columns) { \n 	int i, j; \n 	if(strcmp(\"int\", "
      "param_type) == 0) { \n 		int** mat; \n 		int** mat1 = "
      "(int**) mat_1; \n 		int** mat2 = (int**) mat_2; \n  "
      "		mat = calloc(rows, sizeof(void*)); \n 		for(i=0; "
      "i<rows; i++) {  \n 			mat[i] = calloc(columns, "
      "sizeof(int)); \n 			for(j=0; j<columns; j++) { \n "
      "				mat[i][j] = mat1[i][j] + mat2[i][j]; \n "
      "			} \n 		} \n 		return mat; \n 	} \n "
      "	else { \n 		double** mat; \n 		double** mat1 "
      "= (double**)mat_1; \n 		double** mat2 = (double**)mat_2; \n "
      "		mat = calloc(rows, sizeof(void*)); \n 		for(i=0; "
      "i<rows; i++) { \n 			mat[i] = calloc(columns, "
      "sizeof(double)); \n 			for(j=0; j<columns; j++) { \n "
      "				mat[i][j] = mat1[i][j] + mat2[i][j]; \n "
      "			} \n 		} \n 		return mat; \n 	} \n "
      "	void** mat = 0; \n 	return mat; \n }\n";
  printf("%s", macro);
}


x86 assembly (clang, -O0):
<generate_macro_add_matrix>:
push   %rbp
mov    %rsp,%rbp
sub    $0x10,%rsp
lea    0xee1(%rip),%rax
mov    %rax,-0x8(%rbp)
mov    -0x8(%rbp),%rsi
lea    0x1200(%rip),%rdi
call   1030 <printf@plt>
add    $0x10,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<generate_macro_add_matrix>:
lea    0x1217(%rip),%rdi
lea    0xee2(%rip),%rsi
jmp    1030 <printf@plt>

LLVM IR (-O0):
@.str = [814 x i8] c"void** add_matrix(char const* param_type, void** mat_1, void** mat_2, int rows, int columns) { \0A \09int i, j; \0A \09if(strcmp(\22int\22, param_type) == 0) { \0A \09\09int** mat; \0A \09\09int** mat1 = (int**) mat_1; \0A \09\09int** mat2 = (int**) mat_2; \0A \09\09mat = calloc(rows, sizeof(void*)); \0A \09\09for(i=0; i<rows; i++) { \0A \09\09\09mat[i] = calloc(columns, sizeof(int)); \0A \09\09\09for(j=0; j<columns; j++) { \0A \09\09\09\09mat[i][j] = mat1[i][j] + mat2[i][j]; \0A \09\09\09} \0A \09\09} \0A \09\09return mat; \0A \09} \0A \09else { \0A \09\09double** mat; \0A \09\09double** mat1 = (double**)mat_1; \0A \09\09double** mat2 = (double**)mat_2; \0A \09\09mat = calloc(rows, sizeof(void*)); \0A \09\09for(i=0; i<rows; i++) { \0A \09\09\09mat[i] = calloc(columns, sizeof(double)); \0A \09\09\09for(j=0; j<columns; j++) { \0A \09\09\09\09mat[i][j] = mat1[i][j] + mat2[i][j]; \0A \09\09\09} \0A \09\09} \0A \09\09return mat; \0A \09} \0A \09void** mat = 0; \0A \09return mat; \0A }\0A\00"
@.str.1 = [3 x i8] c"%s\00"
define void @generate_macro_add_matrix() {
%1 = alloca i8*
store i8* getelementptr inbounds ([814 x i8], [814 x i8]* @.str, i64 0, i64 0), i8** %1
%2 = load i8*, i8** %1
%3 = call i32 @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.1, i64 0, i64 0), i8* %2)
ret void
}

LLVM IR (-O2):
@.str = [814 x i8] c"void** add_matrix(char const* param_type, void** mat_1, void** mat_2, int rows, int columns) { \0A \09int i, j; \0A \09if(strcmp(\22int\22, param_type) == 0) { \0A \09\09int** mat; \0A \09\09int** mat1 = (int**) mat_1; \0A \09\09int** mat2 = (int**) mat_2; \0A \09\09mat = calloc(rows, sizeof(void*)); \0A \09\09for(i=0; i<rows; i++) { \0A \09\09\09mat[i] = calloc(columns, sizeof(int)); \0A \09\09\09for(j=0; j<columns; j++) { \0A \09\09\09\09mat[i][j] = mat1[i][j] + mat2[i][j]; \0A \09\09\09} \0A \09\09} \0A \09\09return mat; \0A \09} \0A \09else { \0A \09\09double** mat; \0A \09\09double** mat1 = (double**)mat_1; \0A \09\09double** mat2 = (double**)mat_2; \0A \09\09mat = calloc(rows, sizeof(void*)); \0A \09\09for(i=0; i<rows; i++) { \0A \09\09\09mat[i] = calloc(columns, sizeof(double)); \0A \09\09\09for(j=0; j<columns; j++) { \0A \09\09\09\09mat[i][j] = mat1[i][j] + mat2[i][j]; \0A \09\09\09} \0A \09\09} \0A \09\09return mat; \0A \09} \0A \09void** mat = 0; \0A \09return mat; \0A }\0A\00"
@.str.1 = [3 x i8] c"%s\00"
define void @generate_macro_add_matrix() {
%1 = tail call i32 @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.1, i64 0, i64 0), i8* getelementptr inbounds ([814 x i8], [814 x i8]* @.str, i64 0, i64 0))
ret void
}