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 <stdio.h> 18 #include <stdlib.h> 19 #include <string.h> 20 #include <assert.h> 21 22 typedef LLVMValueRef (*binop_func_t)(LLVMBuilderRef, LLVMValueRef LHS, 23 LLVMValueRef RHS, const char *Name); 24 25 static LLVMOpcode op_to_opcode(char op) { 26 switch (op) { 27 case '+': return LLVMAdd; 28 case '-': return LLVMSub; 29 case '*': return LLVMMul; 30 case '/': return LLVMSDiv; 31 case '&': return LLVMAnd; 32 case '|': return LLVMOr; 33 case '^': return LLVMXor; 34 } 35 assert(0 && "unknown operation"); 36 return 0; 37 } 38 39 #define MAX_DEPTH 32 40 41 static LLVMValueRef build_from_tokens(char **tokens, int ntokens, 42 LLVMBuilderRef builder, 43 LLVMValueRef param) { 44 LLVMValueRef stack[MAX_DEPTH]; 45 int depth = 0; 46 int i; 47 48 for (i = 0; i < ntokens; i++) { 49 char tok = tokens[i][0]; 50 switch (tok) { 51 case '+': 52 case '-': 53 case '*': 54 case '/': 55 case '&': 56 case '|': 57 case '^': 58 if (depth < 2) { 59 printf("stack underflow\n"); 60 return NULL; 61 } 62 63 stack[depth - 2] = LLVMBuildBinOp(builder, op_to_opcode(tok), 64 stack[depth - 1], stack[depth - 2], ""); 65 depth--; 66 67 break; 68 69 case '@': { 70 LLVMValueRef off; 71 72 if (depth < 1) { 73 printf("stack underflow\n"); 74 return NULL; 75 } 76 77 off = LLVMBuildGEP(builder, param, &stack[depth - 1], 1, ""); 78 stack[depth - 1] = LLVMBuildLoad(builder, off, ""); 79 80 break; 81 } 82 83 default: { 84 char *end; 85 long val = strtol(tokens[i], &end, 0); 86 if (end[0] != '\0') { 87 printf("error parsing number\n"); 88 return NULL; 89 } 90 91 if (depth >= MAX_DEPTH) { 92 printf("stack overflow\n"); 93 return NULL; 94 } 95 96 stack[depth++] = LLVMConstInt(LLVMInt64Type(), val, 1); 97 break; 98 } 99 } 100 } 101 102 if (depth < 1) { 103 printf("stack underflow at return\n"); 104 return NULL; 105 } 106 107 LLVMBuildRet(builder, stack[depth - 1]); 108 109 return stack[depth - 1]; 110 } 111 112 static void handle_line(char **tokens, int ntokens) { 113 char *name = tokens[0]; 114 LLVMValueRef param; 115 LLVMValueRef res; 116 117 LLVMModuleRef M = LLVMModuleCreateWithName(name); 118 119 LLVMTypeRef I64ty = LLVMInt64Type(); 120 LLVMTypeRef I64Ptrty = LLVMPointerType(I64ty, 0); 121 LLVMTypeRef Fty = LLVMFunctionType(I64ty, &I64Ptrty, 1, 0); 122 123 LLVMValueRef F = LLVMAddFunction(M, name, Fty); 124 LLVMBuilderRef builder = LLVMCreateBuilder(); 125 LLVMPositionBuilderAtEnd(builder, LLVMAppendBasicBlock(F, "entry")); 126 127 LLVMGetParams(F, ¶m); 128 LLVMSetValueName(param, "in"); 129 130 res = build_from_tokens(tokens + 1, ntokens - 1, builder, param); 131 if (res) { 132 char *irstr = LLVMPrintModuleToString(M); 133 puts(irstr); 134 LLVMDisposeMessage(irstr); 135 } 136 137 LLVMDisposeBuilder(builder); 138 139 LLVMDisposeModule(M); 140 } 141 142 int llvm_calc(void) { 143 144 llvm_tokenize_stdin(handle_line); 145 146 return 0; 147 } 148