Home | History | Annotate | Download | only in llvm-c-test
      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 }
    149