struct vm_value * vm_value_build_math_op(struct vm_state *vm, int operation, struct vm_value *lhs, struct vm_value *rhs) { struct vm_value *res; LLVMOpcode opcode; res = vm_value_new(lhs->type_specifier, ""); switch (operation) { case AST_ADD: opcode = (res->type_specifier == TYPE_INT) ? LLVMAdd : LLVMFAdd; break; case AST_SUB: opcode = (res->type_specifier == TYPE_INT) ? LLVMSub : LLVMFSub; break; case AST_MUL: opcode = (res->type_specifier == TYPE_INT) ? LLVMMul: LLVMFMul; break; case AST_DIV: opcode = (res->type_specifier == TYPE_INT) ? LLVMSDiv: LLVMFDiv; break; default: fprintf(stderr, "Unknown math operation: %d\n", operation); exit(EXIT_FAILURE); } res->llvm_value = LLVMBuildBinOp(vm->builder, opcode, lhs->llvm_value, rhs->llvm_value, ""); return res; }
static LLVMValueRef build_from_tokens(char **tokens, int ntokens, LLVMBuilderRef builder, LLVMValueRef param) { LLVMValueRef stack[MAX_DEPTH]; int depth = 0; int i; for (i = 0; i < ntokens; i++) { char tok = tokens[i][0]; switch (tok) { case '+': case '-': case '*': case '/': case '&': case '|': case '^': if (depth < 2) { printf("stack underflow\n"); return NULL; } stack[depth - 2] = LLVMBuildBinOp(builder, op_to_opcode(tok), stack[depth - 1], stack[depth - 2], ""); depth--; break; case '@': { LLVMValueRef off; if (depth < 1) { printf("stack underflow\n"); return NULL; } off = LLVMBuildGEP(builder, param, &stack[depth - 1], 1, ""); stack[depth - 1] = LLVMBuildLoad(builder, off, ""); break; } default: { char *end; long val = strtol(tokens[i], &end, 0); if (end[0] != '\0') { printf("error parsing number\n"); return NULL; } if (depth >= MAX_DEPTH) { printf("stack overflow\n"); return NULL; } stack[depth++] = LLVMConstInt(LLVMInt64Type(), val, 1); break; } } } if (depth < 1) { printf("stack underflow at return\n"); return NULL; } LLVMBuildRet(builder, stack[depth - 1]); return stack[depth - 1]; }