brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.0 KiB · 267397a Raw
149 lines · c
1/*===-- calc.c - tool for testing libLLVM and llvm-c API ------------------===*\2|*                                                                            *|3|* Part of the LLVM Project, under the Apache License v2.0 with LLVM          *|4|* Exceptions.                                                                *|5|* See https://llvm.org/LICENSE.txt for license information.                  *|6|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception                    *|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 22typedef LLVMValueRef (*binop_func_t)(LLVMBuilderRef, LLVMValueRef LHS,23                                     LLVMValueRef RHS, const char *Name);24 25static 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 3240 41static 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      LLVMTypeRef ty = LLVMInt64Type();78      off = LLVMBuildGEP2(builder, ty, param, &stack[depth - 1], 1, "");79      stack[depth - 1] = LLVMBuildLoad2(builder, ty, 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 113static 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 143int llvm_calc(void) {144 145  llvm_tokenize_stdin(handle_line);146 147  return 0;148}149