calc.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  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. #include "llvm-c-test.h"
  16. #include "llvm-c/Core.h"
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <assert.h>
  21. typedef LLVMValueRef (*binop_func_t)(LLVMBuilderRef, LLVMValueRef LHS,
  22. LLVMValueRef RHS, const char *Name);
  23. static LLVMOpcode op_to_opcode(char op) {
  24. switch (op) {
  25. case '+': return LLVMAdd;
  26. case '-': return LLVMSub;
  27. case '*': return LLVMMul;
  28. case '/': return LLVMSDiv;
  29. case '&': return LLVMAnd;
  30. case '|': return LLVMOr;
  31. case '^': return LLVMXor;
  32. }
  33. assert(0 && "unknown operation");
  34. return 0;
  35. }
  36. #define MAX_DEPTH 32
  37. static LLVMValueRef build_from_tokens(char **tokens, int ntokens,
  38. LLVMBuilderRef builder,
  39. LLVMValueRef param) {
  40. LLVMValueRef stack[MAX_DEPTH];
  41. int depth = 0;
  42. int i;
  43. for (i = 0; i < ntokens; i++) {
  44. char tok = tokens[i][0];
  45. switch (tok) {
  46. case '+':
  47. case '-':
  48. case '*':
  49. case '/':
  50. case '&':
  51. case '|':
  52. case '^':
  53. if (depth < 2) {
  54. printf("stack underflow\n");
  55. return NULL;
  56. }
  57. stack[depth - 2] = LLVMBuildBinOp(builder, op_to_opcode(tok),
  58. stack[depth - 1], stack[depth - 2], "");
  59. depth--;
  60. break;
  61. case '@': {
  62. LLVMValueRef off;
  63. if (depth < 1) {
  64. printf("stack underflow\n");
  65. return NULL;
  66. }
  67. off = LLVMBuildGEP(builder, param, &stack[depth - 1], 1, "");
  68. stack[depth - 1] = LLVMBuildLoad(builder, off, "");
  69. break;
  70. }
  71. default: {
  72. char *end;
  73. long val = strtol(tokens[i], &end, 0);
  74. if (end[0] != '\0') {
  75. printf("error parsing number\n");
  76. return NULL;
  77. }
  78. if (depth >= MAX_DEPTH) {
  79. printf("stack overflow\n");
  80. return NULL;
  81. }
  82. stack[depth++] = LLVMConstInt(LLVMInt64Type(), val, 1);
  83. break;
  84. }
  85. }
  86. }
  87. if (depth < 1) {
  88. printf("stack underflow at return\n");
  89. return NULL;
  90. }
  91. LLVMBuildRet(builder, stack[depth - 1]);
  92. return stack[depth - 1];
  93. }
  94. static void handle_line(char **tokens, int ntokens) {
  95. char *name = tokens[0];
  96. LLVMValueRef param;
  97. LLVMValueRef res;
  98. LLVMModuleRef M = LLVMModuleCreateWithName(name);
  99. LLVMTypeRef I64ty = LLVMInt64Type();
  100. LLVMTypeRef I64Ptrty = LLVMPointerType(I64ty, 0);
  101. LLVMTypeRef Fty = LLVMFunctionType(I64ty, &I64Ptrty, 1, 0);
  102. LLVMValueRef F = LLVMAddFunction(M, name, Fty);
  103. LLVMBuilderRef builder = LLVMCreateBuilder();
  104. LLVMPositionBuilderAtEnd(builder, LLVMAppendBasicBlock(F, "entry"));
  105. LLVMGetParams(F, &param);
  106. LLVMSetValueName(param, "in");
  107. res = build_from_tokens(tokens + 1, ntokens - 1, builder, param);
  108. if (res) {
  109. char *irstr = LLVMPrintModuleToString(M);
  110. puts(irstr);
  111. LLVMDisposeMessage(irstr);
  112. }
  113. LLVMDisposeBuilder(builder);
  114. LLVMDisposeModule(M);
  115. }
  116. int calc(void) {
  117. tokenize_stdin(handle_line);
  118. return 0;
  119. }