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, ¶m); 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 } 149