typedef struct Type {
enum {
FORM_BOOL, FORM_INT, FORM_REAL, FORM_ARRAY, FORM_STRING,
- FORM_RECORD, FORM_PROC,
+ FORM_RECORD, FORM_PROC, FORM_VOID,
FORM_COUNT
} form;
struct Field* fields;
char* s;
} Operand;
+struct AstNode;
+
typedef struct Symbol {
enum{
SYM_SCOPE, SYM_CONST, SYM_VAR, SYM_TYPE, SYM_PROC, SYM_FIELD
char* name;
Type* type;
struct Symbol* desc;
+ struct AstNode* value;
long nargs;
- Operand imm;
int export : 1;
int global : 1;
} Symbol;
/* Backend Code Generation
*****************************************************************************/
-extern Type BoolType, IntType, RealType, StringType;
+extern Type VoidType, BoolType, IntType, RealType, StringType;
void codegen_startmod(Parser* p);
void codegen_endmod(Parser* p);
/* Abstract Syntax Tree Definition
*****************************************************************************/
-struct AstNode;
+//enum AstMode {
+// AST_CONST = 0,
+// AST_EXPR,
+// AST_CTRL,
+//};
typedef struct {
int code : 28;
} val;
} AstValue;
-AstNode* ast_new(int type, AstNode* l0, AstNode* l1, AstNode* l2);
-AstNode* ast_ident(long long index);
+AstNode* ast_ident(Parser* p, long long index);
AstNode* ast_bool(bool val);
AstNode* ast_int(long long val);
AstNode* ast_real(double val);
/* Optimizations to Perform:
-* Constant folding - (Constant expression evaluation)
-* Dead code elimination
-* Block coalescing
-*
+ * Constant folding - (Constant expression evaluation)
+ * Dead code elimination - (when building conditional and loop nodes)
+ * Block coalescing (see above)
+
+ * https://en.wikipedia.org/wiki/Bounds-checking_elimination
+ * https://en.wikipedia.org/wiki/Compile-time_function_execution
+ * https://en.wikipedia.org/wiki/Common_subexpression_elimination
+ * https://en.wikipedia.org/wiki/Copy_propagation
+ * https://en.wikipedia.org/wiki/Dead_code_elimination
+ * https://en.wikipedia.org/wiki/Dead_store
+ * https://en.wikipedia.org/wiki/Induction_variable
+ * https://en.wikipedia.org/wiki/Inline_expansion
+ * https://en.wikipedia.org/wiki/Interprocedural_optimization
+ * https://en.wikipedia.org/wiki/Jump_threading
+ * https://en.wikipedia.org/wiki/Loop_inversion
+ * https://en.wikipedia.org/wiki/Loop-invariant_code_motion
+ * https://en.wikipedia.org/wiki/Redundant_code
+ * https://en.wikipedia.org/wiki/Value_numbering
*/
+static bool is_const(AstNode* node)
+{
+ bool ret;
+ switch (node->hdr.code)
+ {
+ case BOOL:
+ case INT:
+ case REAL:
+ case IDENT:
+ ret = true;
+ break;
+
+ default:
+ ret = false;
+ break;
+ }
+ return ret;
+}
+
+static bool both_const(AstNode* left, AstNode* right)
+{
+ return is_const(left) && is_const(right);
+}
-AstNode* ast_new(int type, AstNode* l0, AstNode* l1, AstNode* l2)
+static AstNode* ast_new(int code, Type* type, AstNode* l0, AstNode* l1, AstNode* l2)
{
AstNode* node = calloc(1, sizeof(AstNode));
- node->hdr.code = type;
+ node->hdr.code = code;
+ node->hdr.type = type;
node->links[0] = l0;
node->links[1] = l1;
node->links[2] = l2;
return node;
}
-AstNode* ast_ident(long long index)
+static AstNode* ast_clone(AstNode* parent)
{
- AstValue* node = (AstValue*)ast_new(IDENT, NULL, NULL, NULL);
- node->val.i = index;
+ AstNode* node = calloc(1, sizeof(AstNode));
+ *node = *parent;
+ return node;
+}
+
+AstNode* ast_ident(Parser* p, long long index)
+{
+ Symbol* sym = symbol_getbyid(p, (size_t)index);
+ AstNode* node;
+ if (sym && sym->class == SYM_CONST)
+ {
+ assert(sym->value != NULL);
+ node = ast_clone(sym->value);
+ }
+ else
+ {
+ node = ast_new(IDENT, sym->type, NULL, NULL, NULL);
+ ((AstValue*)node)->val.i = index;
+ }
return (AstNode*)node;
}
AstNode* ast_bool(bool val)
{
- AstValue* node = (AstValue*)ast_new(BOOL, NULL, NULL, NULL);
+ AstValue* node = (AstValue*)ast_new(BOOL, &BoolType, NULL, NULL, NULL);
node->val.i = val;
return (AstNode*)node;
}
AstNode* ast_int(long long val)
{
- AstValue* node = (AstValue*)ast_new(INT, NULL, NULL, NULL);
+ AstValue* node = (AstValue*)ast_new(INT, &IntType, NULL, NULL, NULL);
node->val.i = val;
return (AstNode*)node;
}
AstNode* ast_real(double val)
{
- AstValue* node = (AstValue*)ast_new(REAL, NULL, NULL, NULL);
+ AstValue* node = (AstValue*)ast_new(REAL, &RealType, NULL, NULL, NULL);
node->val.f = val;
return (AstNode*)node;
}
{
assert(left);
assert(right);
- return ast_new(op, left, right, NULL);
+ return ast_new(op, left->hdr.type, left, right, NULL);
}
AstNode* ast_unop(int op, AstNode* operand)
{
assert(operand);
- return ast_new(op, operand, NULL, NULL);
+ AstNode* ret = NULL;
+ if (is_const(operand))
+ {
+ AstValue* a = (AstValue*)operand;
+ if (a->hdr.type->form == FORM_INT)
+ {
+ switch (op)
+ {
+ case '+': a->val.i = +a->val.i; break;
+ case '-': a->val.i = -a->val.i; break;
+ default: assert(!"not a valid op"); break;
+ }
+ }
+ else if (a->hdr.type->form == FORM_REAL)
+ {
+ switch (op)
+ {
+ case '+': a->val.f = +a->val.f; break;
+ case '-': a->val.f = -a->val.f; break;
+ default: assert(!"not a valid op"); break;
+ }
+ }
+ else if (a->hdr.type->form == FORM_BOOL)
+ {
+ switch (op)
+ {
+ case NOT: a->val.i = !a->val.i; break;
+ default: assert(!"not a valid op"); break;
+ }
+ }
+ else
+ {
+ assert(!"not a valid form");
+ }
+ ret = (AstNode*)a;
+ }
+ else
+ {
+ ret = ast_new(op, operand->hdr.type, operand, NULL, NULL);
+ }
+ return ret;
}
AstNode* ast_block(void)
{
- return ast_new(BEGIN, NULL, NULL, NULL);
+ return ast_new(BEGIN, &VoidType, NULL, NULL, NULL);
}
void ast_block_add(AstNode* func)
AstNode* ast_call(AstNode* func)
{
- return ast_new(CALL, func, NULL, NULL);
+ return ast_new(CALL, func->hdr.type, func, NULL, NULL);
}
void ast_call_add(AstNode* func)
AstNode* ast_if(AstNode* cond, AstNode* br1, AstNode* br2)
{
- return ast_new(IF, cond, br1, br2);
+ return ast_new(IF, &VoidType, cond, br1, br2);
}
AstNode* ast_return(AstNode* expr)
{
- return ast_new(RETURN, expr, NULL, NULL);
+ return ast_new(RETURN, &VoidType, expr, NULL, NULL);
}
void ast_print(AstNode* node)
printf("R:%f", ((AstValue*)node)->val.f);
break;
+ case IDENT:
+ printf("S:%lld", ((AstValue*)node)->val.i);
+ break;
+
default:
if (node->links[1])
{