Add LDC compiler to list of external OS projects using LLVM 3.8
[oota-llvm.git] / tools / llvm-c-test / calc.c
1 /*===-- calc.c - tool for testing libLLVM and llvm-c API ------------------===*\
2 |*                                                                            *|
3 |*                     The LLVM Compiler Infrastructure                       *|
4 |*                                                                            *|
5 |* This file is distributed under the University of Illinois Open Source      *|
6 |* License. See LICENSE.TXT for details.                                      *|
7 |*                                                                            *|
8 |*===----------------------------------------------------------------------===*|
9 |*                                                                            *|
10 |* This file implements the --calc command in llvm-c-test. --calc reads lines *|
11 |* from stdin, parses them as a name and an expression in reverse polish      *|
12 |* notation and prints a module with a function with the expression.          *|
13 |*                                                                            *|
14 \*===----------------------------------------------------------------------===*/
15
16 #include "llvm-c-test.h"
17 #include "llvm-c/Core.h"
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <assert.h>
22
23 typedef LLVMValueRef (*binop_func_t)(LLVMBuilderRef, LLVMValueRef LHS,
24                                      LLVMValueRef RHS, const char *Name);
25
26 static LLVMOpcode op_to_opcode(char op) {
27   switch (op) {
28   case '+': return LLVMAdd;
29   case '-': return LLVMSub;
30   case '*': return LLVMMul;
31   case '/': return LLVMSDiv;
32   case '&': return LLVMAnd;
33   case '|': return LLVMOr;
34   case '^': return LLVMXor;
35   }
36   assert(0 && "unknown operation");
37   return 0;
38 }
39
40 #define MAX_DEPTH 32
41
42 static LLVMValueRef build_from_tokens(char **tokens, int ntokens,
43                                       LLVMBuilderRef builder,
44                                       LLVMValueRef param) {
45   LLVMValueRef stack[MAX_DEPTH];
46   int depth = 0;
47   int i;
48
49   for (i = 0; i < ntokens; i++) {
50     char tok = tokens[i][0];
51     switch (tok) {
52     case '+':
53     case '-':
54     case '*':
55     case '/':
56     case '&':
57     case '|':
58     case '^':
59       if (depth < 2) {
60         printf("stack underflow\n");
61         return NULL;
62       }
63
64       stack[depth - 2] = LLVMBuildBinOp(builder, op_to_opcode(tok),
65                                         stack[depth - 1], stack[depth - 2], "");
66       depth--;
67
68       break;
69
70     case '@': {
71       LLVMValueRef off;
72
73       if (depth < 1) {
74         printf("stack underflow\n");
75         return NULL;
76       }
77
78       off = LLVMBuildGEP(builder, param, &stack[depth - 1], 1, "");
79       stack[depth - 1] = LLVMBuildLoad(builder, off, "");
80
81       break;
82     }
83
84     default: {
85       char *end;
86       long val = strtol(tokens[i], &end, 0);
87       if (end[0] != '\0') {
88         printf("error parsing number\n");
89         return NULL;
90       }
91
92       if (depth >= MAX_DEPTH) {
93         printf("stack overflow\n");
94         return NULL;
95       }
96
97       stack[depth++] = LLVMConstInt(LLVMInt64Type(), val, 1);
98       break;
99     }
100     }
101   }
102
103   if (depth < 1) {
104     printf("stack underflow at return\n");
105     return NULL;
106   }
107
108   LLVMBuildRet(builder, stack[depth - 1]);
109
110   return stack[depth - 1];
111 }
112
113 static void handle_line(char **tokens, int ntokens) {
114   char *name = tokens[0];
115   LLVMValueRef param;
116   LLVMValueRef res;
117
118   LLVMModuleRef M = LLVMModuleCreateWithName(name);
119
120   LLVMTypeRef I64ty = LLVMInt64Type();
121   LLVMTypeRef I64Ptrty = LLVMPointerType(I64ty, 0);
122   LLVMTypeRef Fty = LLVMFunctionType(I64ty, &I64Ptrty, 1, 0);
123
124   LLVMValueRef F = LLVMAddFunction(M, name, Fty);
125   LLVMBuilderRef builder = LLVMCreateBuilder();
126   LLVMPositionBuilderAtEnd(builder, LLVMAppendBasicBlock(F, "entry"));
127
128   LLVMGetParams(F, &param);
129   LLVMSetValueName(param, "in");
130
131   res = build_from_tokens(tokens + 1, ntokens - 1, builder, param);
132   if (res) {
133     char *irstr = LLVMPrintModuleToString(M);
134     puts(irstr);
135     LLVMDisposeMessage(irstr);
136   }
137
138   LLVMDisposeBuilder(builder);
139
140   LLVMDisposeModule(M);
141 }
142
143 int calc(void) {
144
145   tokenize_stdin(handle_line);
146
147   return 0;
148 }