Beispiel #1
0
LLVMValueRef gen_right(struct node *ast)
{
	return LLVMBuildLShr(builder,
			codegen(ast->one),
			codegen(ast->two),
			"");
}
Beispiel #2
0
LLVMValueRef gen_switch(struct node *ast)
{
	LLVMValueRef func, switch_;
	LLVMBasicBlockRef this_block, switch_first_block, switch_last_block, end_block;
	int i;

	this_block = LLVMGetInsertBlock(builder);
	func = LLVMGetBasicBlockParent(this_block);
	switch_first_block = LLVMAppendBasicBlock(func, "");
	LLVMPositionBuilderAtEnd(builder, switch_first_block);

	case_count = 0;
	codegen(ast->two);

	switch_last_block = LLVMGetLastBasicBlock(func);
	end_block = LLVMAppendBasicBlock(func, "");

	LLVMPositionBuilderAtEnd(builder, switch_last_block);
	LLVMBuildBr(builder, end_block);

	LLVMPositionBuilderAtEnd(builder, this_block);
	switch_ = LLVMBuildSwitch(builder, codegen(ast->one), end_block, case_count);

	for (i = 0; i < case_count; i++)
		LLVMAddCase(switch_, case_vals[i], case_blocks[i]);

	LLVMPositionBuilderAtEnd(builder, end_block);

	return NULL;
}
Beispiel #3
0
LLVMValueRef gen_div(struct node *ast)
{
	return LLVMBuildSDiv(builder,
			codegen(ast->one),
			codegen(ast->two),
			"");
}
Beispiel #4
0
LLVMValueRef gen_mod(struct node *ast)
{
	return LLVMBuildSRem(builder,
			codegen(ast->one),
			codegen(ast->two),
			"");
}
Beispiel #5
0
LLVMValueRef gen_if(struct node *ast)
{
	LLVMValueRef condition, func;
	LLVMBasicBlockRef then_block, else_block, end;

	condition = codegen(ast->one);
	condition = LLVMBuildICmp(builder, LLVMIntNE, condition, CONST(0), "");
	func = LLVMGetBasicBlockParent(LLVMGetInsertBlock(builder));

	then_block = LLVMAppendBasicBlock(func, "");
	else_block = LLVMAppendBasicBlock(func, "");
	end = LLVMAppendBasicBlock(func, "");
	LLVMBuildCondBr(builder, condition, then_block, else_block);

	LLVMPositionBuilderAtEnd(builder, then_block);
	codegen(ast->two);
	LLVMBuildBr(builder, end);

	LLVMPositionBuilderAtEnd(builder, else_block);
	if (ast->three)
		codegen(ast->three);
	LLVMBuildBr(builder, end);

	LLVMPositionBuilderAtEnd(builder, end);

	return NULL;
}
Beispiel #6
0
LLVMValueRef gen_auto(struct node *ast)
{
	codegen(ast->one);
	codegen(ast->two);

	return NULL;
}
Beispiel #7
0
LLVMValueRef gen_case(struct node *ast)
{
	LLVMValueRef func;
	LLVMBasicBlockRef this_block, next_block;

	this_block = LLVMGetInsertBlock(builder);
	func = LLVMGetBasicBlockParent(this_block);
	next_block = LLVMAppendBasicBlock(func, "");
	LLVMMoveBasicBlockAfter(next_block, this_block);

	case_blocks[case_count] = next_block;
	case_vals[case_count] = codegen(ast->one);

	LLVMBuildBr(builder, next_block);
	LLVMPositionBuilderAtEnd(builder, next_block);

	case_count++;

	if (case_count >= MAX_CASES)
		generror(">c");

	codegen(ast->two);

	return NULL;
}
Beispiel #8
0
Value *ClastExpCodeGen::codegen(const clast_reduction *r, Type *Ty) {
  assert((r->type == clast_red_min || r->type == clast_red_max ||
          r->type == clast_red_sum) && "Clast reduction type not supported");
  Value *old = codegen(r->elts[0], Ty);

  for (int i = 1; i < r->n; ++i) {
    Value *exprValue = codegen(r->elts[i], Ty);

    switch (r->type) {
    case clast_red_min: {
      Value *cmp = Builder.CreateICmpSLT(old, exprValue);
      old = Builder.CreateSelect(cmp, old, exprValue);
      break;
    }
    case clast_red_max: {
      Value *cmp = Builder.CreateICmpSGT(old, exprValue);
      old = Builder.CreateSelect(cmp, old, exprValue);
      break;
    }
    case clast_red_sum:
      old = Builder.CreateAdd(old, exprValue);
      break;
    }
  }

  return old;
}
Beispiel #9
0
llvm::Value* Executor::codegenArrayAt(const Analyzer::BinOper* array_at, const CompilationOptions& co) {
  const auto arr_expr = array_at->get_left_operand();
  const auto idx_expr = array_at->get_right_operand();
  const auto& idx_ti = idx_expr->get_type_info();
  CHECK(idx_ti.is_integer());
  auto idx_lvs = codegen(idx_expr, true, co);
  CHECK_EQ(size_t(1), idx_lvs.size());
  auto idx_lv = idx_lvs.front();
  if (idx_ti.get_logical_size() < 8) {
    idx_lv = cgen_state_->ir_builder_.CreateCast(
        llvm::Instruction::CastOps::SExt, idx_lv, get_int_type(64, cgen_state_->context_));
  }
  const auto& array_ti = arr_expr->get_type_info();
  CHECK(array_ti.is_array());
  const auto& elem_ti = array_ti.get_elem_type();
  const std::string array_at_fname{
      elem_ti.is_fp() ? "array_at_" + std::string(elem_ti.get_type() == kDOUBLE ? "double_checked" : "float_checked")
                      : "array_at_int" + std::to_string(elem_ti.get_logical_size() * 8) + "_t_checked"};
  const auto ret_ty = elem_ti.is_fp() ? (elem_ti.get_type() == kDOUBLE ? llvm::Type::getDoubleTy(cgen_state_->context_)
                                                                       : llvm::Type::getFloatTy(cgen_state_->context_))
                                      : get_int_type(elem_ti.get_logical_size() * 8, cgen_state_->context_);
  const auto arr_lvs = codegen(arr_expr, true, co);
  CHECK_EQ(size_t(1), arr_lvs.size());
  return cgen_state_->emitExternalCall(array_at_fname,
                                       ret_ty,
                                       {arr_lvs.front(),
                                        posArg(arr_expr),
                                        idx_lv,
                                        elem_ti.is_fp() ? static_cast<llvm::Value*>(inlineFpNull(elem_ti))
                                                        : static_cast<llvm::Value*>(inlineIntNull(elem_ti))});
}
Beispiel #10
0
void IRGenerator::accept(MatchStmt& stmt)
{
    FNTRACE();

    Value* cond = codegen(stmt.condition());
    BasicBlock* contBlock = createBlock("match.cont");
    MatchInstr* matchInstr = createMatch(stmt.op(), cond);

    for (const MatchCase& one: stmt.cases()) {
        BasicBlock* bb = createBlock("match.case");
        setInsertPoint(bb);
        codegen(one.second.get());
        createBr(contBlock);

        for (auto& labelNode: one.first) {
            Constant* label = getConstant(labelNode.get());
            matchInstr->addCase(label, bb);
        }
    }

    if (stmt.elseStmt()) {
        BasicBlock* elseBlock = createBlock("match.else");
        setInsertPoint(elseBlock);
        codegen(stmt.elseStmt());
        createBr(contBlock);

        matchInstr->setElseBlock(elseBlock);
    }

    setInsertPoint(contBlock);
}
Beispiel #11
0
void CodeGen_X86::visit(const EQ *op) {
    Type t = op->a.type();
    int bits = t.lanes() * t.bits();
    if (t.lanes() == 1 || bits % 128 == 0) {
        // LLVM is fine for native vector widths or scalars
        CodeGen_Posix::visit(op);
    } else {
        // Non-native vector widths get legalized poorly by llvm. We
        // split it up ourselves.
        Value *a = codegen(op->a), *b = codegen(op->b);

        int slice_size = 128 / t.bits();
        if (target.has_feature(Target::AVX) && bits > 128) {
            slice_size = 256 / t.bits();
        }

        vector<Value *> result;
        for (int i = 0; i < op->type.lanes(); i += slice_size) {
            Value *sa = slice_vector(a, i, slice_size);
            Value *sb = slice_vector(b, i, slice_size);
            Value *slice_value;
            if (t.is_float()) {
                slice_value = builder->CreateFCmpOEQ(sa, sb);
            } else {
                slice_value = builder->CreateICmpEQ(sa, sb);
            }
            result.push_back(slice_value);
        }

        value = concat_vectors(result);
        value = slice_vector(value, 0, t.lanes());
    }
}
Beispiel #12
0
void IRGenerator::accept(CallExpr& call)
{
    FNTRACE();

    std::vector<Value*> args;
    for (Expr* arg: call.args().values()) {
        if (Value* v = codegen(arg)) {
            args.push_back(v);
        } else {
            return;
        }
    }

    if (call.callee()->isFunction()) {
        Value* callee = codegen(call.callee());
        // builtin function
        result_ = createCallFunction(static_cast<IRBuiltinFunction*>(callee), args);
    } else if (call.callee()->isBuiltin()) {
        Value* callee = codegen(call.callee());
        // builtin handler
        result_ = createInvokeHandler(static_cast<IRBuiltinHandler*>(callee), args);
    } else {
        // source handler
        codegenInline(*static_cast<Handler*>(call.callee()));
        result_ = nullptr;
    }
}
Beispiel #13
0
void CodeGen_X86::visit(const Select *op) {
    if (op->condition.type().is_vector()) {
        // LLVM handles selects on vector conditions much better at native width
        Value *cond = codegen(op->condition);
        Value *true_val = codegen(op->true_value);
        Value *false_val = codegen(op->false_value);
        Type t = op->true_value.type();
        int slice_size = 128 / t.bits();
        if (slice_size < t.lanes()) {
            slice_size = target.natural_vector_size(t);
        }

        vector<Value *> result;
        for (int i = 0; i < t.lanes(); i += slice_size) {
            Value *st = slice_vector(true_val, i, slice_size);
            Value *sf = slice_vector(false_val, i, slice_size);
            Value *sc = slice_vector(cond, i, slice_size);
            Value *slice_value = builder->CreateSelect(sc, st, sf);
            result.push_back(slice_value);
        }

        value = concat_vectors(result);
        value = slice_vector(value, 0, t.lanes());
    } else {
        CodeGen_Posix::visit(op);
    }
}
Beispiel #14
0
int genlst(Error_printer *err, char **argv, Pseudo ** initv, char *quote, Node * n)
{
	switch (n->what) {
		case nEMPTY: {
			return 0;
		} case nADDR: {
			quote[0] = 1;
			return genlst(err, argv, initv, quote, n->r);
		} case nPAREN: {
			return genlst(err, argv, initv, quote, n->r);
		} case nSEMI: case nCOMMA: case nCALL: {
			int x = genlst(err, argv, initv, quote, n->l);
			return x + genlst(err, argv + x, initv + x, quote + x, n->r);
/*		} case nCALL: {
			if (n->l->what == nNAM && n->r->what == nEMPTY)
				return argv[0] = strdup(n->l->s), initv[0] = 0, 1;
			break;
*/
		} case nNAM: {
			return argv[0] = strdup(n->s), initv[0] = 0, 1;
		} case nSET: {
			if (n->l->what == nNAM)
				return argv[0] = strdup(n->l->s), initv[0] = codegen(err, n->r), 1;
			else if (n->l->what == nADDR && n->l->r->what == nNAM) {
				quote[0] = 1;
				return argv[0] = strdup(n->l->r->s), initv[0] = codegen(err, n->r), 1;
			}
			break;
		}
	}
	error_3(err, "\"%s\" %d: incorrect argument list %s", n->loc->name, n->loc->line, what_tab[n->what].name);
	return 0;
}
Beispiel #15
0
LLVMValueRef gen_left(struct node *ast)
{
	return LLVMBuildShl(builder,
			codegen(ast->one),
			codegen(ast->two),
			"");
}
Beispiel #16
0
void CodeGen_X86::visit(const GT *op) {
    if (op->type.is_vector()) {
        // Non-native vector widths get legalized poorly by llvm. We
        // split it up ourselves.

        Type t = op->a.type();
        int slice_size = 128 / t.bits();
        if (slice_size < t.lanes()) {
            slice_size = target.natural_vector_size(t);
        }

        Value *a = codegen(op->a), *b = codegen(op->b);
        vector<Value *> result;
        for (int i = 0; i < op->type.lanes(); i += slice_size) {
            Value *sa = slice_vector(a, i, slice_size);
            Value *sb = slice_vector(b, i, slice_size);
            Value *slice_value;
            if (t.is_float()) {
                slice_value = builder->CreateFCmpOGT(sa, sb);
            } else if (t.is_int()) {
                slice_value = builder->CreateICmpSGT(sa, sb);
            } else {
                slice_value = builder->CreateICmpUGT(sa, sb);
            }
            result.push_back(slice_value);
        }

        value = concat_vectors(result);
        value = slice_vector(value, 0, t.lanes());
    } else {
        CodeGen_Posix::visit(op);
    }

}
Beispiel #17
0
static LLVMValueRef lvalue_index(struct node *ast)
{
	LLVMValueRef ptr;

	ptr = LLVMBuildAdd(builder, codegen(ast->one), codegen(ast->two), "");

	return rvalue_to_lvalue(ptr);
}
Beispiel #18
0
static ValueType genMod(Func *, Cons *cons, CodeBuilder *cb, int sp) {
	codegen(cons, cb, sp);
	cons = cons->cdr;
	for(; cons != NULL; cons = cons->cdr) {
		codegen(cons, cb, sp + 1);
		cb->createIMod(sp, sp + 1);
	}
	return VT_INT;
}
Beispiel #19
0
LLVMValueRef gen_inits(struct node *ast)
{
	codegen(ast->one);

	if (ast->two)
		codegen(ast->two);

	return NULL;
}
Beispiel #20
0
void IRGenerator::accept(BinaryExpr& expr)
{
    FNTRACE();

    static const std::unordered_map<
        int /*FlowVM::Opcode*/,
        Value* (IRGenerator::*)(Value*, Value*, const std::string&)
    > ops = {
        // numerical
        { FlowVM::Opcode::NADD, &IRGenerator::createAdd },
        { FlowVM::Opcode::NSUB, &IRGenerator::createSub },
        { FlowVM::Opcode::NMUL, &IRGenerator::createMul },
        { FlowVM::Opcode::NDIV, &IRGenerator::createDiv },
        { FlowVM::Opcode::NREM, &IRGenerator::createRem },
        { FlowVM::Opcode::NSHL, &IRGenerator::createShl },
        { FlowVM::Opcode::NSHR, &IRGenerator::createShr },
        { FlowVM::Opcode::NPOW, &IRGenerator::createPow },
        { FlowVM::Opcode::NAND, &IRGenerator::createAnd },
        { FlowVM::Opcode::NOR,  &IRGenerator::createOr },
        { FlowVM::Opcode::NXOR, &IRGenerator::createXor },
        { FlowVM::Opcode::NCMPEQ, &IRGenerator::createNCmpEQ },
        { FlowVM::Opcode::NCMPNE, &IRGenerator::createNCmpNE },
        { FlowVM::Opcode::NCMPLE, &IRGenerator::createNCmpLE },
        { FlowVM::Opcode::NCMPGE, &IRGenerator::createNCmpGE },
        { FlowVM::Opcode::NCMPLT, &IRGenerator::createNCmpLT },
        { FlowVM::Opcode::NCMPGT, &IRGenerator::createNCmpGT },

        // string
        { FlowVM::Opcode::SADD, &IRGenerator::createSAdd },
        { FlowVM::Opcode::SCMPEQ, &IRGenerator::createSCmpEQ },
        { FlowVM::Opcode::SCMPNE, &IRGenerator::createSCmpNE },
        { FlowVM::Opcode::SCMPLE, &IRGenerator::createSCmpLE },
        { FlowVM::Opcode::SCMPGE, &IRGenerator::createSCmpGE },
        { FlowVM::Opcode::SCMPLT, &IRGenerator::createSCmpLT },
        { FlowVM::Opcode::SCMPGT, &IRGenerator::createSCmpGT },
        { FlowVM::Opcode::SCMPBEG, &IRGenerator::createSCmpEB },
        { FlowVM::Opcode::SCMPEND, &IRGenerator::createSCmpEE },
        //{ FlowVM::Opcode::SCONTAINS, &IRGenerator::createSContains },

        // regex
        { FlowVM::Opcode::SREGMATCH, &IRGenerator::createSCmpRE },
    };

    Value* lhs = codegen(expr.leftExpr());
    Value* rhs = codegen(expr.rightExpr());

    auto i = ops.find(expr.op());
    if (i != ops.end()) {
        result_ = (this->*i->second)(lhs, rhs, "");
    } else {
        // fall back to generic VmInstr
        result_ = insert(new VmInstr(expr.op(), {lhs, rhs}));
    }
}
Beispiel #21
0
LLVMValueRef gen_ge(struct node *ast)
{
	LLVMValueRef truth;

	truth = LLVMBuildICmp(builder,
			LLVMIntSGE,
			codegen(ast->one),
			codegen(ast->two),
			"");

	return LLVMBuildZExt(builder, truth, TYPE_INT, "");
}
Beispiel #22
0
Value *ClastExpCodeGen::codegen(const clast_expr *e, Type *Ty) {
  switch (e->type) {
  case clast_expr_name:
    return codegen((const clast_name *)e, Ty);
  case clast_expr_term:
    return codegen((const clast_term *)e, Ty);
  case clast_expr_bin:
    return codegen((const clast_binary *)e, Ty);
  case clast_expr_red:
    return codegen((const clast_reduction *)e, Ty);
  }

  llvm_unreachable("Unknown clast expression!");
}
Beispiel #23
0
void IRGenerator::accept(UnaryExpr& expr)
{
    FNTRACE();

    static const std::unordered_map<
        int /*FlowVM::Opcode*/,
        Value* (IRGenerator::*)(Value*, const std::string&)
    > ops = {
        { FlowVM::Opcode::I2S, &IRGenerator::createI2S },
        { FlowVM::Opcode::P2S, &IRGenerator::createP2S },
        { FlowVM::Opcode::C2S, &IRGenerator::createC2S },
        { FlowVM::Opcode::R2S, &IRGenerator::createR2S },
        { FlowVM::Opcode::S2I, &IRGenerator::createS2I },
        { FlowVM::Opcode::NNEG, &IRGenerator::createNeg },
    };

    Value* rhs = codegen(expr.subExpr());

    auto i = ops.find(expr.op());
    if (i != ops.end()) {
        result_ = (this->*i->second)(rhs, "");
    } else {
        assert(!"Unsupported unary expression in IRGenerator.");
        result_ = nullptr;
    }
}
Beispiel #24
0
static void
gen_u8_cvt(const casemap &cm, const char *ftmpl)
{
	static const struct {
		unsigned	first, last;
	} u8r[] = {
		{0, 0x7f},
		{0x80, 0x7ff},
		{0x800, 0xffff},
		{0x10000, 0x1fffff}
	};
	for (unsigned i = 0; i < sizeof(u8r) / sizeof(*u8r); i++) {
		casemap::const_iterator b, e;
		char fname[1024];
		snprintf(fname, sizeof(fname), "%s_%04X_%04X.h", ftmpl, u8r[i].first, u8r[i].last);
		FILE *out = fopen(fname, "w");
		if (!out) {
			perror("fopen");
			exit(EXIT_FAILURE);
		}
		fprintf(out, "do {\n");
		b = cm.lower_bound(u8r[i].first);
		if (b != cm.end()) {
			e = cm.upper_bound(u8r[i].last);
			codegen(b, e, out, "ic", gen_var_cb, spanu8);
		}
		fprintf(out, "} while (0);\n");
		fclose(out);
	}
}
Beispiel #25
0
/* TCC isn't threadsafe and even seems not to like having more than
 * one TCCState created or used at any one time in a single threaded
 * environment.  So, this code is all for investigation only and can't
 * currently be used in Mesa proper.
 *
 * I've taken some liberties with globals myself, now.
 */
GLboolean
_swrast_execute_codegen_program( GLcontext *ctx,
			 const struct fragment_program *program, GLuint maxInst,
			 struct fp_machine *machine, const struct sw_span *span,
			 GLuint column )
{
   if (program != current_program) {
      
      _swrast_translate_program( ctx );

      fprintf(stderr, "%s: compiling:\n%s\n", __FUNCTION__, program->c_str);

      current_program = program;
      current_func = codegen( current_tcc_state, program->c_str, 
			      "run_program" );
   }

   assert(current_func);

   return current_func( ctx,
			program->Base.LocalParams,
 			(const GLfloat (*)[4])ctx->FragmentProgram.Parameters, 
			program->Parameters->Parameters,
			(const GLfloat (*)[4])machine->Inputs,
			machine->Outputs );
}
Beispiel #26
0
Datei: pass.c Projekt: ozra/ponyc
bool generate_passes(ast_t* program, pass_opt_t* options)
{
  if(options->limit < PASS_LLVM_IR)
    return true;

  return codegen(program, options);
}
Beispiel #27
0
LLVMValueRef gen_compound(struct node *ast)
{
	if (ast->one)
		return codegen(ast->one);

	return NULL;
}
Beispiel #28
0
LLVMValueRef gen_cond(struct node *ast)
{
	LLVMValueRef truth;

	truth = LLVMBuildICmp(builder,
			LLVMIntNE,
			codegen(ast->one),
			CONST(0),
			"");

	return LLVMBuildSelect(builder,
			truth,
			codegen(ast->two),
			codegen(ast->three),
			"");
}
Beispiel #29
0
void defun(Context *ctx, Cons *cons) {
	const char *name = cons->str;
	cons = cons->cdr;
	Cons *args = cons->car;
	cons = cons->cdr;
	Func *func = newFunc(name, args, genCall);
	func->rtype = VT_INT;

	ctx->putFunc(func);

	CodeBuilder cb(ctx, func, false, true);
	if(cons == NULL) {
		cb.createIConst(0, 0);
		func->rtype = VT_BOOLEAN;
	} else {
		while(cons != NULL) {
			func->rtype = codegen(cons, &cb, func->argc);
			cons = cons->cdr;
		}
	}
	cb.createRet(func->argc);
	cb.createEnd();
	func->code = cb.getCode();
	func->codeLength = cb.getCodeLength();
	codeopt(ctx, func);
}
Beispiel #30
0
void IRGenerator::accept(Handler& handler)
{
    FNTRACE();

    setHandler(getHandler(handler.name()));
    setInsertPoint(createBlock("EntryPoint"));
    this->handler()->setEntryPoint(getInsertPoint());

    for (Symbol* symbol: *handler.scope()) {
        codegen(symbol);
    }

    codegen(handler.body());

    createRet(get(false));
}