public function gen() { $ir = ""; $leftname = "\\Codegen\\Generator\\" . \Misc::baseClass($this->obj->left); $left = new $leftname($this->obj->left); $ir .= $left->gen(); $rightname = "\\Codegen\\Generator\\" . \Misc::baseClass($this->obj->right); $right = new $rightname($this->obj->right); $ir .= $right->gen(); $leftreg = \Tables::$register_alloc - 1; $rightreg = $leftreg + 1; if ($this->obj->left instanceof \Parser\Parsers\Integer) { $reg1 = \Tables::alloc(); /* holds the left value */ $ir .= "\t%{$reg1} = load i32* %{$leftreg}" . PHP_EOL; } else { $reg1 = $leftreg; } if ($this->obj->right instanceof \Parser\Parsers\Integer) { $reg2 = \Tables::alloc(); /* holds the right value */ $ir .= "\t%{$reg2} = load i32* %{$rightreg}" . PHP_EOL; } else { $reg2 = $rightreg; } $reg3 = \Tables::alloc(); /* holds the result */ $ir .= "\t%{$reg3} = sub nsw i32 %{$reg1}, %{$reg2}" . PHP_EOL; $this->resultreg = $reg3; return $ir; }
public function gen() { $ir = ""; foreach ($this->ast as $item) { $name = "\\Codegen\\Generator\\" . \Misc::baseClass($item); $gen = new $name($item); $ir .= $gen->gen(); } return $ir; }
public function gen() { if (is_object($this->obj->content[0])) { /* it is a arithmetic expression */ $ir = ""; $name = "\\Codegen\\Generator\\" . \Misc::baseClass($this->obj->content[0]); $obj = new $name($this->obj->content[0]); $var =& \Tables::updateLocalVariable($this->obj->function, $this->obj->name); $ir .= $obj->gen(); for ($i = 0; $i <= $this->obj->line; $i++) { if (isset($var->type[$i])) { $type = $var->type[$i]; } } $var->type[$this->obj->line] = $type | \Tables::POINTER; $var->type[$this->obj->line] &= ~\Tables::POINTER; $var->name = \Tables::$register_alloc; } elseif (!is_null(\Tables::localVariable($this->obj->function, $this->obj->name))) { /* allocate and get everything ready */ $reg1 = \Tables::alloc(); /* the reg number */ $reg2 = \Tables::alloc(); /* the reg number */ $var =& \Tables::updateLocalVariable($this->obj->function, $this->obj->name); /* our reference to the variable */ /* get the correct type */ for ($i = 0; $i <= $this->obj->line; $i++) { if (isset($var->type[$i])) { $type = $var->type[$i]; } } $type = \Misc::getType($type); /* its type */ $name = "\\Codegen\\Generator\\" . \Misc::baseClass($this->obj->content[0]); $obj = new $name($this->obj->content[0]); /* the code that is to be moved into the reg */ $code = $obj->arg(); /* change the name of the variable to the new register */ $var->name = $reg2; /* generate the code */ $ir = "\t%{$reg1} = alloca {$type}" . PHP_EOL; /* allocate the register */ $ir .= "\tstore " . $code . ", {$type}* %{$reg1}" . PHP_EOL; /* store our value in it */ $ir .= "\t%{$reg2} = load {$type}* %{$reg1}" . PHP_EOL; /* move it into a register we don't have to reference it as a pointer */ } return $ir; }
public function gen() { $ir = ""; if (\Tables::declaration($this->obj->name) || \Tables::func($this->obj->name)) { $gen = array(); $ir .= "\t; prepare the arguments" . PHP_EOL; for ($i = 0; $i < count($this->obj->content); $i++) { $arg = $this->obj->content[$i]; if (\Misc::baseClass($arg) == "Addition" || \Misc::baseClass($arg) == "Subtraction" || \Misc::baseClass($arg) == "Multiplication" || \Misc::baseClass($arg) == "Division" || \Misc::baseClass($arg) == "Call") { $name = "\\Codegen\\Generator\\" . \Misc::baseClass($arg); $obj = new $name($arg); $ir .= $obj->gen(); $gen[$i] = $obj; } } if (\Tables::declaration($this->obj->name)) { $dec = \Tables::getDeclaration($this->obj->name); } elseif (\Tables::func($this->obj->name)) { $dec = \Tables::getFunc($this->obj->name); } $reg = \Tables::alloc(); $this->result = $reg; $ir .= "\t; call {$dec->name}" . PHP_EOL; if (empty($dec->args)) { $ir .= "\t%{$reg} = call {$dec->return} @{$dec->name}"; } else { $ir .= "\t%{$reg} = call {$dec->return} {$dec->args}* @{$dec->name}"; } if (count($this->obj->content) > 0) { for ($i = 0; $i < count($this->obj->content); $i++) { $arg = $this->obj->content[$i]; if (isset($gen[$i]) && !empty($gen[$i])) { $obj = $gen[$i]; } else { $name = "\\Codegen\\Generator\\" . \Misc::baseClass($arg); $obj = new $name($arg); } $ir .= $obj->arg() . ", "; } $ir = substr($ir, 0, -2); } $ir .= ")" . PHP_EOL; $ir .= "\t; end of call to {$dec->name}" . PHP_EOL . PHP_EOL; } else { error("unknown function in line {$this->obj->line}"); } return $ir; }
public function gen() { $ir = ""; $item = $this->obj->content[0]; if ($item instanceof \Parser\Parsers\Integer) { $ir .= "\tret i32 {$item->value}" . PHP_EOL; } elseif ($item instanceof \Parser\Parsers\Variable) { $val = new \Codegen\Generator\Variable($item); $ir .= "\tret " . $val->arg() . PHP_EOL; /* TODO: maybe have a function that checks for arithmetic parsers/codegenerators? */ } elseif ($item instanceof \Parser\Parsers\Addition || $item instanceof \Parser\Parsers\Subtraction || $item instanceof \Parser\Parsers\Multiplication || $item instanceof \Parser\Parsers\Division) { $name = "\\Codegen\\Generator\\" . \Misc::baseClass($item); $val = new $name($item); $ir .= $val->gen(); $ir .= "\tret i32 %" . \Tables::$register_alloc . PHP_EOL; } else { error("invalid return type '" . \Misc::baseClass($item) . "' in line {$this->obj->line}"); } return $ir; }
public function analyze($ast, $parent = NULL) { /* holds the name of the currently compiled function */ $function = ""; foreach ($ast as $i => $node) { /* set the function name in the objects */ if ($node instanceof \Parser\Parsers\FunctionDefinition) { $function = $node->name; $node->function = $node->name; } elseif (!empty($node->function)) { $function = $node->function; } else { if (isset($node->name) && $node->name == "extern") { continue; } elseif (!empty($function)) { $node->function = $function; } else { if (!empty($parent->function)) { $node->function = $parent->function; } elseif (!empty($function)) { $node->function = $function; } } } /* set the arguments as local variables */ if ($node instanceof \Parser\Parsers\FunctionDefinition && count($node->arguments) > 0) { foreach ($node->arguments as $arg) { \Tables::addLocalVariable($function, $arg->name); } } if ($node instanceof \Parser\Parsers\Assignment) { /* deal with assignments */ if (is_object($node->content)) { if (\Tables::localVariable($node->function, $node->name)) { $var =& \Tables::updateLocalVariable($node->function, $node->name); } else { $var =& \Tables::addLocalVariable($node->function, $node->name); } $var->type[$node->line] = \Tables::I32; continue; } switch (\Misc::baseClass($node->content[0])) { case "String": $type = \Tables::STRING; break; case "Integer": $type = \Tables::I32; break; case "Addition": case "Subtraction": case "Multiplication": case "Division": $type = \Tables::I32; break; default: error("unknown assignment type '" . \Misc::baseClass($node->content[0]) . "' in line {$node->line}"); } if (\Tables::localVariable($node->function, $node->name)) { $var =& \Tables::updateLocalVariable($node->function, $node->name); } else { $var =& \Tables::addLocalVariable($node->function, $node->name); } $var->type[$node->line] = $type; } elseif (!$node instanceof \Parser\Parsers\Variable && count($node->content) > 0) { /* analyze recursively if needed */ if ($node instanceof \Parser\Parsers\FunctionDefinition && !empty($node->arguments)) { foreach ($node->arguments as $arg) { $arg->function = $function; } } $this->analyze($node->content, $node); } elseif ($node instanceof \Parser\Parsers\Variable) { /* do type inference based on printf */ if ($parent instanceof \Parser\Parsers\Call) { if ($parent->name == "printf") { $matches = array(); preg_match_all("/%[scdiu]/", $ast[0]->string, $matches); $format = substr($matches[0][$i - 1], -1); $type = 0; switch ($format) { case 'd': case 'i': case 'c': $type |= \Tables::I32; break; case 's': $type |= \Tables::STRING; } $var =& \Tables::updateLocalVariable($node->function, $node->name); if ($var == NULL) { continue; } $node->type[$node->line] = $type; } } } } }