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