12bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg/*===-- calc.c - tool for testing libLLVM and llvm-c API ------------------===*\ 22bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg|* *| 32bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg|* The LLVM Compiler Infrastructure *| 42bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg|* *| 52bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg|* This file is distributed under the University of Illinois Open Source *| 62bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg|* License. See LICENSE.TXT for details. *| 72bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg|* *| 82bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg|*===----------------------------------------------------------------------===*| 92bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg|* *| 102bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg|* This file implements the --calc command in llvm-c-test. --calc reads lines *| 112bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg|* from stdin, parses them as a name and an expression in reverse polish *| 122bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg|* notation and prints a module with a function with the expression. *| 132bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg|* *| 142bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg\*===----------------------------------------------------------------------===*/ 152bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg 162bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg#include "llvm-c-test.h" 172bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg#include "llvm-c/Core.h" 182bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg#include <stdio.h> 192bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg#include <stdlib.h> 202bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg#include <string.h> 212bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg#include <assert.h> 222bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg 232bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborgtypedef LLVMValueRef (*binop_func_t)(LLVMBuilderRef, LLVMValueRef LHS, 242bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg LLVMValueRef RHS, const char *Name); 252bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg 262bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborgstatic LLVMOpcode op_to_opcode(char op) { 272bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg switch (op) { 282bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg case '+': return LLVMAdd; 292bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg case '-': return LLVMSub; 302bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg case '*': return LLVMMul; 312bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg case '/': return LLVMSDiv; 322bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg case '&': return LLVMAnd; 332bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg case '|': return LLVMOr; 342bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg case '^': return LLVMXor; 352bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg } 362bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg assert(0 && "unknown operation"); 372bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg return 0; 382bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg} 392bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg 402bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg#define MAX_DEPTH 32 412bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg 422bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborgstatic LLVMValueRef build_from_tokens(char **tokens, int ntokens, 432bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg LLVMBuilderRef builder, 442bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg LLVMValueRef param) { 452bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg LLVMValueRef stack[MAX_DEPTH]; 462bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg int depth = 0; 4790fd79a222652126ee7d85f3afb2cd85aa51b2f9NAKAMURA Takumi int i; 482bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg 4990fd79a222652126ee7d85f3afb2cd85aa51b2f9NAKAMURA Takumi for (i = 0; i < ntokens; i++) { 502bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg char tok = tokens[i][0]; 512bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg switch (tok) { 522bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg case '+': 532bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg case '-': 542bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg case '*': 552bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg case '/': 562bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg case '&': 572bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg case '|': 582bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg case '^': 592bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg if (depth < 2) { 602bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg printf("stack underflow\n"); 612bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg return NULL; 622bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg } 632bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg 642bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg stack[depth - 2] = LLVMBuildBinOp(builder, op_to_opcode(tok), 652bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg stack[depth - 1], stack[depth - 2], ""); 662bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg depth--; 672bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg 682bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg break; 692bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg 7090fd79a222652126ee7d85f3afb2cd85aa51b2f9NAKAMURA Takumi case '@': { 7190fd79a222652126ee7d85f3afb2cd85aa51b2f9NAKAMURA Takumi LLVMValueRef off; 7290fd79a222652126ee7d85f3afb2cd85aa51b2f9NAKAMURA Takumi 732bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg if (depth < 1) { 742bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg printf("stack underflow\n"); 752bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg return NULL; 762bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg } 772bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg 7890fd79a222652126ee7d85f3afb2cd85aa51b2f9NAKAMURA Takumi off = LLVMBuildGEP(builder, param, &stack[depth - 1], 1, ""); 792bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg stack[depth - 1] = LLVMBuildLoad(builder, off, ""); 802bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg 812bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg break; 8290fd79a222652126ee7d85f3afb2cd85aa51b2f9NAKAMURA Takumi } 832bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg 842bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg default: { 852bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg char *end; 862bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg long val = strtol(tokens[i], &end, 0); 872bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg if (end[0] != '\0') { 882bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg printf("error parsing number\n"); 892bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg return NULL; 902bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg } 912bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg 922bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg if (depth >= MAX_DEPTH) { 932bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg printf("stack overflow\n"); 942bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg return NULL; 952bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg } 962bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg 972bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg stack[depth++] = LLVMConstInt(LLVMInt64Type(), val, 1); 982bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg break; 992bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg } 1002bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg } 1012bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg } 1022bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg 1032bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg if (depth < 1) { 1042bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg printf("stack underflow at return\n"); 1052bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg return NULL; 1062bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg } 1072bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg 1082bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg LLVMBuildRet(builder, stack[depth - 1]); 1092bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg 1102bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg return stack[depth - 1]; 1112bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg} 1122bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg 1132bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborgstatic void handle_line(char **tokens, int ntokens) { 1142bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg char *name = tokens[0]; 11590fd79a222652126ee7d85f3afb2cd85aa51b2f9NAKAMURA Takumi LLVMValueRef param; 11690fd79a222652126ee7d85f3afb2cd85aa51b2f9NAKAMURA Takumi LLVMValueRef res; 1172bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg 1182bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg LLVMModuleRef M = LLVMModuleCreateWithName(name); 1192bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg 1202bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg LLVMTypeRef I64ty = LLVMInt64Type(); 1212bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg LLVMTypeRef I64Ptrty = LLVMPointerType(I64ty, 0); 1222bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg LLVMTypeRef Fty = LLVMFunctionType(I64ty, &I64Ptrty, 1, 0); 1232bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg 1242bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg LLVMValueRef F = LLVMAddFunction(M, name, Fty); 1252bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg LLVMBuilderRef builder = LLVMCreateBuilder(); 1262bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg LLVMPositionBuilderAtEnd(builder, LLVMAppendBasicBlock(F, "entry")); 1272bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg 1282bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg LLVMGetParams(F, ¶m); 1292bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg LLVMSetValueName(param, "in"); 1302bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg 13190fd79a222652126ee7d85f3afb2cd85aa51b2f9NAKAMURA Takumi res = build_from_tokens(tokens + 1, ntokens - 1, builder, param); 1322bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg if (res) { 1332bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg char *irstr = LLVMPrintModuleToString(M); 1342bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg puts(irstr); 1352bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg LLVMDisposeMessage(irstr); 1362bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg } 1372bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg 1382bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg LLVMDisposeBuilder(builder); 1392bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg 1402bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg LLVMDisposeModule(M); 1412bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg} 1422bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg 1432bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborgint calc(void) { 1442bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg 1452bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg tokenize_stdin(handle_line); 1462bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg 1472bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg return 0; 1482bef1a6b25d938210547cd0f5ba4a08abdad2583Anders Waldenborg} 149