コード例 #1
0
ファイル: genexpr.c プロジェクト: awaidmann/ponyc
LLVMValueRef gen_expr(compile_t* c, ast_t* ast)
{
  LLVMValueRef ret;
  bool has_scope = ast_has_scope(ast);

  if(has_scope)
    codegen_pushscope(c, ast);

  switch(ast_id(ast))
  {
    case TK_SEQ:
      ret = gen_seq(c, ast);
      break;

    case TK_FVARREF:
    case TK_FLETREF:
      ret = gen_fieldload(c, ast);
      break;

    case TK_EMBEDREF:
      ret = gen_fieldptr(c, ast);
      break;

    case TK_PARAMREF:
      ret = gen_param(c, ast);
      break;

    case TK_VAR:
    case TK_LET:
    case TK_MATCH_CAPTURE:
      ret = gen_localdecl(c, ast);
      break;

    case TK_VARREF:
    case TK_LETREF:
      ret = gen_localload(c, ast);
      break;

    case TK_IF:
      ret = gen_if(c, ast);
      break;

    case TK_WHILE:
      ret = gen_while(c, ast);
      break;

    case TK_REPEAT:
      ret = gen_repeat(c, ast);
      break;

    case TK_TRY:
    case TK_TRY_NO_CHECK:
      ret = gen_try(c, ast);
      break;

    case TK_MATCH:
      ret = gen_match(c, ast);
      break;

    case TK_CALL:
      ret = gen_call(c, ast);
      break;

    case TK_CONSUME:
      ret = gen_expr(c, ast_childidx(ast, 1));
      break;

    case TK_RECOVER:
      ret = gen_expr(c, ast_childidx(ast, 1));
      break;

    case TK_BREAK:
      ret = gen_break(c, ast);
      break;

    case TK_CONTINUE:
      ret = gen_continue(c, ast);
      break;

    case TK_RETURN:
      ret = gen_return(c, ast);
      break;

    case TK_ERROR:
      ret = gen_error(c, ast);
      break;

    case TK_IS:
      ret = gen_is(c, ast);
      break;

    case TK_ISNT:
      ret = gen_isnt(c, ast);
      break;

    case TK_ASSIGN:
      ret = gen_assign(c, ast);
      break;

    case TK_THIS:
      ret = gen_this(c, ast);
      break;

    case TK_TRUE:
      ret = LLVMConstInt(c->i1, 1, false);
      break;

    case TK_FALSE:
      ret = LLVMConstInt(c->i1, 0, false);
      break;

    case TK_INT:
      ret = gen_int(c, ast);
      break;

    case TK_FLOAT:
      ret = gen_float(c, ast);
      break;

    case TK_STRING:
      ret = gen_string(c, ast);
      break;

    case TK_TUPLE:
      ret = gen_tuple(c, ast);
      break;

    case TK_FFICALL:
      ret = gen_ffi(c, ast);
      break;

    case TK_ADDRESS:
      ret = gen_addressof(c, ast);
      break;

    case TK_DIGESTOF:
      ret = gen_digestof(c, ast);
      break;

    case TK_DONTCARE:
      ret = GEN_NOVALUE;
      break;

    case TK_COMPILE_INTRINSIC:
      ast_error(c->opt->check.errors, ast, "unimplemented compile intrinsic");
      return NULL;

    case TK_COMPILE_ERROR:
    {
      ast_t* reason_seq = ast_child(ast);
      ast_t* reason = ast_child(reason_seq);
      ast_error(c->opt->check.errors, ast, "compile error: %s",
        ast_name(reason));
      return NULL;
    }

    default:
      ast_error(c->opt->check.errors, ast, "not implemented (codegen unknown)");
      return NULL;
  }

  if(has_scope)
    codegen_popscope(c);

  return ret;
}
コード例 #2
0
ファイル: genexpr.c プロジェクト: ozra/ponyc
LLVMValueRef gen_expr(compile_t* c, ast_t* ast)
{
  LLVMValueRef ret;
  bool has_scope = ast_has_scope(ast);
  bool has_source = codegen_hassource(c);

  if(has_scope)
  {
    codegen_pushscope(c);

    // Dwarf a new lexical scope, if necessary.
    if(has_source)
      dwarf_lexicalscope(&c->dwarf, ast);
  }

  switch(ast_id(ast))
  {
    case TK_SEQ:
      ret = gen_seq(c, ast);
      break;

    case TK_FVARREF:
    case TK_FLETREF:
      ret = gen_fieldload(c, ast);
      break;

    case TK_PARAMREF:
      ret = gen_param(c, ast);
      break;

    case TK_VAR:
    case TK_LET:
      ret = gen_localdecl(c, ast);
      break;

    case TK_VARREF:
    case TK_LETREF:
      ret = gen_localload(c, ast);
      break;

    case TK_IF:
      ret = gen_if(c, ast);
      break;

    case TK_WHILE:
      ret = gen_while(c, ast);
      break;

    case TK_REPEAT:
      ret = gen_repeat(c, ast);
      break;

    case TK_TRY:
    case TK_TRY_NO_CHECK:
      ret = gen_try(c, ast);
      break;

    case TK_MATCH:
      ret = gen_match(c, ast);
      break;

    case TK_CALL:
      ret = gen_call(c, ast);
      break;

    case TK_CONSUME:
      ret = gen_expr(c, ast_childidx(ast, 1));
      break;

    case TK_RECOVER:
      ret = gen_expr(c, ast_childidx(ast, 1));
      break;

    case TK_BREAK:
      ret = gen_break(c, ast);
      break;

    case TK_CONTINUE:
      ret = gen_continue(c, ast);
      break;

    case TK_RETURN:
      ret = gen_return(c, ast);
      break;

    case TK_ERROR:
      ret = gen_error(c, ast);
      break;

    case TK_IS:
      ret = gen_is(c, ast);
      break;

    case TK_ISNT:
      ret = gen_isnt(c, ast);
      break;

    case TK_ASSIGN:
      ret = gen_assign(c, ast);
      break;

    case TK_THIS:
      ret = gen_this(c, ast);
      break;

    case TK_TRUE:
      ret = LLVMConstInt(c->i1, 1, false);
      break;

    case TK_FALSE:
      ret = LLVMConstInt(c->i1, 0, false);
      break;

    case TK_INT:
      ret = gen_int(c, ast);
      break;

    case TK_FLOAT:
      ret = gen_float(c, ast);
      break;

    case TK_STRING:
      ret = gen_string(c, ast);
      break;

    case TK_TUPLE:
      ret = gen_tuple(c, ast);
      break;

    case TK_FFICALL:
      ret = gen_ffi(c, ast);
      break;

    case TK_AMP:
      ret = gen_addressof(c, ast);
      break;

    case TK_IDENTITY:
      ret = gen_identity(c, ast);
      break;

    case TK_DONTCARE:
      ret = GEN_NOVALUE;
      break;

    case TK_COMPILER_INTRINSIC:
      ast_error(ast, "unimplemented compiler intrinsic");
      LLVMBuildUnreachable(c->builder);
      ret = GEN_NOVALUE;
      break;

    default:
      ast_error(ast, "not implemented (codegen unknown)");
      return NULL;
  }

  if(has_scope)
  {
    codegen_popscope(c);

    if(has_source)
      dwarf_finish(&c->dwarf);
  }

  return ret;
}
コード例 #3
0
ファイル: genmatch.c プロジェクト: danielaRiesgo/ponyc
LLVMValueRef gen_match(compile_t* c, ast_t* ast)
{
  bool needed = is_result_needed(ast);
  ast_t* type = ast_type(ast);
  AST_GET_CHILDREN(ast, match_expr, cases, else_expr);

  // We will have no type if all case have control types.
  LLVMTypeRef phi_type = NULL;

  if(needed && !is_control_type(type))
  {
    reach_type_t* t_phi = reach_type(c->reach, type);
    phi_type = t_phi->use_type;
  }

  ast_t* match_type = alias(ast_type(match_expr));
  LLVMValueRef match_value = gen_expr(c, match_expr);

  LLVMBasicBlockRef pattern_block = codegen_block(c, "case_pattern");
  LLVMBasicBlockRef else_block = codegen_block(c, "match_else");
  LLVMBasicBlockRef post_block = NULL;
  LLVMBasicBlockRef next_block = NULL;

  // Jump to the first case.
  LLVMBuildBr(c->builder, pattern_block);

  LLVMValueRef phi = GEN_NOVALUE;

  if(!is_control_type(type))
  {
    // Start the post block so that a case can modify the phi node.
    post_block = codegen_block(c, "match_post");
    LLVMPositionBuilderAtEnd(c->builder, post_block);

    if(needed)
      phi = LLVMBuildPhi(c->builder, phi_type, "");
    else
      phi = GEN_NOTNEEDED;
  }

  // Iterate over the cases.
  ast_t* the_case = ast_child(cases);

  while(the_case != NULL)
  {
    ast_t* next_case = ast_sibling(the_case);

    if(next_case != NULL)
      next_block = codegen_block(c, "case_pattern");
    else
      next_block = else_block;

    AST_GET_CHILDREN(the_case, pattern, guard, body);
    LLVMPositionBuilderAtEnd(c->builder, pattern_block);
    codegen_pushscope(c, the_case);

    ast_t* pattern_type = ast_type(pattern);
    bool ok = true;

    if(is_matchtype(match_type, pattern_type, c->opt) != MATCHTYPE_ACCEPT)
    {
      // If there's no possible match, jump directly to the next block.
      LLVMBuildBr(c->builder, next_block);
    } else {
      // Check the pattern.
      ok = static_match(c, match_value, match_type, pattern, next_block);

      // Check the guard.
      ok = ok && guard_match(c, guard, next_block);

      // Case body.
      ok = ok && case_body(c, body, post_block, phi, phi_type);
    }

    codegen_popscope(c);

    if(!ok)
    {
      ast_free_unattached(match_type);
      return NULL;
    }

    the_case = next_case;
    pattern_block = next_block;
  }

  ast_free_unattached(match_type);

  // Else body.
  LLVMPositionBuilderAtEnd(c->builder, else_block);
  codegen_pushscope(c, else_expr);
  bool ok = case_body(c, else_expr, post_block, phi, phi_type);
  codegen_popscope(c);

  if(!ok)
    return NULL;

  if(post_block != NULL)
    LLVMPositionBuilderAtEnd(c->builder, post_block);

  return phi;
}