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, &param);
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