[Code generation] Added skeleton for expressions generation
This commit is contained in:
@@ -13,9 +13,7 @@ extern translation_unit *ast_root;
|
||||
const char src[] =
|
||||
"\
|
||||
void test(fp32 *A, fp32 *B, fp32 *C){\
|
||||
fp32 c[16, 16] = {0};\
|
||||
int32 i = 0;\
|
||||
i += 1;\
|
||||
}\
|
||||
";
|
||||
|
||||
|
142
include/ast.h
142
include/ast.h
@@ -2,8 +2,9 @@
|
||||
#define TDL_INCLUDE_AST_H
|
||||
|
||||
#include "parser.hpp"
|
||||
#include "llvm/IR/IRBuilder.h"
|
||||
#include <cassert>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace llvm{
|
||||
@@ -58,7 +59,7 @@ enum TYPE_T{
|
||||
// AST
|
||||
class node {
|
||||
public:
|
||||
virtual void codegen(module*) const { }
|
||||
virtual llvm::Value* codegen(module*) const { return nullptr; }
|
||||
};
|
||||
|
||||
template<class T>
|
||||
@@ -71,100 +72,146 @@ public:
|
||||
return this;
|
||||
}
|
||||
|
||||
void codegen(module* mod) const
|
||||
{ for(T x: values_){ x->codegen(mod); } }
|
||||
llvm::Value* codegen(module* mod) const{
|
||||
for(T x: values_){
|
||||
x->codegen(mod);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const std::list<T> &values() const
|
||||
const std::vector<T> &values() const
|
||||
{ return values_; }
|
||||
|
||||
private:
|
||||
std::list<T> values_;
|
||||
std::vector<T> values_;
|
||||
};
|
||||
|
||||
class binary_operator: public node{
|
||||
class expression: public node{
|
||||
public:
|
||||
virtual llvm::Value* codegen(module *) const = 0;
|
||||
};
|
||||
|
||||
class binary_operator: public expression{
|
||||
private:
|
||||
llvm::Value* llvm_op(llvm::IRBuilder<> &bld, llvm::Value *lhs, llvm::Value *rhs, const std::string &name) const;
|
||||
|
||||
public:
|
||||
binary_operator(BIN_OP_T op, node *lhs, node *rhs)
|
||||
: op_(op), lhs_(lhs), rhs_(rhs) { }
|
||||
: op_(op), lhs_((expression*)lhs), rhs_((expression*)rhs) { }
|
||||
llvm::Value* codegen(module *) const;
|
||||
|
||||
private:
|
||||
const BIN_OP_T op_;
|
||||
const node *lhs_;
|
||||
const node *rhs_;
|
||||
const expression *lhs_;
|
||||
const expression *rhs_;
|
||||
};
|
||||
|
||||
|
||||
class constant: public node{
|
||||
class constant: public expression{
|
||||
public:
|
||||
constant(int value): value_(value) { }
|
||||
llvm::Value* codegen(module *mod) const;
|
||||
|
||||
private:
|
||||
const int value_;
|
||||
};
|
||||
|
||||
|
||||
class string_literal: public node{
|
||||
class string_literal: public expression{
|
||||
public:
|
||||
string_literal(char *&value): value_(value) { }
|
||||
llvm::Value* codegen(module *mod) const;
|
||||
|
||||
public:
|
||||
std::string value_;
|
||||
};
|
||||
|
||||
class unary_operator: public node{
|
||||
class unary_operator: public expression{
|
||||
private:
|
||||
llvm::Value *llvm_op(llvm::IRBuilder<> &builder, llvm::Value *arg, const std::string &name) const;
|
||||
|
||||
public:
|
||||
unary_operator(UNARY_OP_T op, node *arg)
|
||||
: op_(op), arg_(arg) { }
|
||||
: op_(op),
|
||||
arg_((expression*)arg) { }
|
||||
|
||||
llvm::Value* codegen(module *mod) const;
|
||||
|
||||
private:
|
||||
const UNARY_OP_T op_;
|
||||
const node *arg_;
|
||||
const expression *arg_;
|
||||
};
|
||||
|
||||
class cast_operator: public node{
|
||||
public:
|
||||
cast_operator(node *type, node *arg): type_(type), arg_(arg) { }
|
||||
class type_name;
|
||||
class cast_operator: public expression{
|
||||
private:
|
||||
llvm::Value *llvm_op(llvm::IRBuilder<> &builder, llvm::Type *T, llvm::Value *arg, const std::string &name) const;
|
||||
|
||||
public:
|
||||
const node *type_;
|
||||
const node *arg_;
|
||||
cast_operator(node *T, node *arg):
|
||||
T_((type_name*)T),
|
||||
arg_((expression*)arg) { }
|
||||
|
||||
llvm::Value* codegen(module *mod) const;
|
||||
|
||||
public:
|
||||
const type_name *T_;
|
||||
const expression *arg_;
|
||||
};
|
||||
|
||||
class conditional_expression: public node{
|
||||
class conditional_expression: public expression{
|
||||
private:
|
||||
llvm::Value *llvm_op(llvm::IRBuilder<> &builder,
|
||||
llvm::Value *cond, llvm::Value *true_value, llvm::Value *false_value,
|
||||
const std::string &name) const;
|
||||
|
||||
public:
|
||||
conditional_expression(node *cond, node *true_value, node *false_value)
|
||||
: cond_(cond), true_value_(true_value), false_value_(false_value) { }
|
||||
: cond_((expression*)cond),
|
||||
true_value_((expression*)true_value),
|
||||
false_value_((expression*)false_value) { }
|
||||
|
||||
llvm::Value* codegen(module *mod) const;
|
||||
|
||||
public:
|
||||
const node *cond_;
|
||||
const node *true_value_;
|
||||
const node *false_value_;
|
||||
const expression *cond_;
|
||||
const expression *true_value_;
|
||||
const expression *false_value_;
|
||||
};
|
||||
|
||||
class assignment_expression: public node{
|
||||
class assignment_expression: public expression{
|
||||
private:
|
||||
llvm::Value *llvm_op(llvm::IRBuilder<> &builder,
|
||||
llvm::Value *lvalue, llvm::Value *rvalue,
|
||||
const std::string &name) const;
|
||||
|
||||
public:
|
||||
assignment_expression(node *lvalue, ASSIGN_OP_T op, node *rvalue)
|
||||
: lvalue_(lvalue), op_(op), rvalue_(rvalue) { }
|
||||
: lvalue_((expression*)lvalue), op_(op), rvalue_((expression*)rvalue) { }
|
||||
|
||||
llvm::Value* codegen(module *mod) const;
|
||||
|
||||
public:
|
||||
ASSIGN_OP_T op_;
|
||||
const node *lvalue_;
|
||||
const node *rvalue_;
|
||||
const expression *lvalue_;
|
||||
const expression *rvalue_;
|
||||
};
|
||||
|
||||
class statement: public node{
|
||||
|
||||
};
|
||||
|
||||
class initializer;
|
||||
class declaration_specifier;
|
||||
|
||||
class declaration: public node{
|
||||
public:
|
||||
declaration(node *spec, node *init)
|
||||
: spec_(spec), init_((list<initializer*>*)init) { }
|
||||
: spec_((declaration_specifier*)spec), init_((list<initializer*>*)init) { }
|
||||
|
||||
void codegen(module* mod) const;
|
||||
llvm::Value* codegen(module* mod) const;
|
||||
|
||||
public:
|
||||
const node *spec_;
|
||||
const declaration_specifier *spec_;
|
||||
const list<initializer*> *init_;
|
||||
};
|
||||
|
||||
@@ -177,7 +224,7 @@ public:
|
||||
compound_statement(node* decls, node* statements)
|
||||
: decls_((declarations_t)decls), statements_((statements_t)statements) {}
|
||||
|
||||
virtual void codegen(module* mod) const;
|
||||
llvm::Value* codegen(module* mod) const;
|
||||
|
||||
private:
|
||||
declarations_t decls_;
|
||||
@@ -230,6 +277,7 @@ public:
|
||||
decl_((declarator*)decl) { }
|
||||
|
||||
llvm::Type* type(module *mod) const;
|
||||
std::string name() const;
|
||||
|
||||
public:
|
||||
const declaration_specifier *spec_;
|
||||
@@ -267,7 +315,7 @@ class identifier: public declarator{
|
||||
llvm::Type* type_impl(module*mod, llvm::Type *type) const;
|
||||
|
||||
public:
|
||||
identifier(char *&name): declarator(nullptr), name_(name) { }
|
||||
identifier(char *&name): declarator(this), name_(name) { }
|
||||
const std::string &name() const;
|
||||
|
||||
private:
|
||||
@@ -302,6 +350,8 @@ public:
|
||||
function(node *id, node *args)
|
||||
: declarator(id), args_((list<parameter*>*)args) { }
|
||||
|
||||
void bind_parameters(module *mod, llvm::Function *fn) const;
|
||||
|
||||
public:
|
||||
const list<parameter*>* args_;
|
||||
};
|
||||
@@ -314,23 +364,27 @@ private:
|
||||
public:
|
||||
initializer(node *decl, node *init)
|
||||
: declarator((node*)((declarator*)decl)->id()),
|
||||
decl_((declarator*)decl), init_(init){ }
|
||||
decl_((declarator*)decl), init_((expression*)init){ }
|
||||
|
||||
void codegen(module *) const;
|
||||
void specifier(const declaration_specifier *spec);
|
||||
llvm::Value* codegen(module *) const;
|
||||
|
||||
public:
|
||||
const declaration_specifier *spec_;
|
||||
const declarator *decl_;
|
||||
const node *init_;
|
||||
const expression *init_;
|
||||
};
|
||||
|
||||
|
||||
class type: public node{
|
||||
class type_name: public node{
|
||||
public:
|
||||
type(TYPE_T spec, node * decl)
|
||||
: spec_(spec), decl_((declarator*)decl) { }
|
||||
type_name(node *spec, node * decl)
|
||||
: spec_((declaration_specifier*)spec), decl_((declarator*)decl) { }
|
||||
|
||||
llvm::Type *type(module *mod) const;
|
||||
|
||||
public:
|
||||
const TYPE_T spec_;
|
||||
const declaration_specifier *spec_;
|
||||
const declarator *decl_;
|
||||
};
|
||||
|
||||
@@ -340,7 +394,7 @@ public:
|
||||
function_definition(node *spec, node *header, node *body)
|
||||
: spec_((declaration_specifier*)spec), header_((function *)header), body_((compound_statement*)body) { }
|
||||
|
||||
void codegen(module* mod) const;
|
||||
llvm::Value* codegen(module* mod) const;
|
||||
|
||||
public:
|
||||
const declaration_specifier *spec_;
|
||||
@@ -359,7 +413,7 @@ public:
|
||||
return this;
|
||||
}
|
||||
|
||||
void codegen(module* mod) const;
|
||||
llvm::Value* codegen(module* mod) const;
|
||||
|
||||
private:
|
||||
list<node*>* decls_;
|
||||
|
@@ -1,3 +1,4 @@
|
||||
#include <unordered_map>
|
||||
#include "ast.h"
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
#include "llvm/IR/IRBuilder.h"
|
||||
@@ -19,10 +20,13 @@ public:
|
||||
module(const std::string &name, context *ctx);
|
||||
llvm::Module* handle();
|
||||
llvm::IRBuilder<>& builder();
|
||||
void value(ast::node* node, llvm::Value* value);
|
||||
llvm::Value *value(ast::node* node);
|
||||
|
||||
private:
|
||||
llvm::Module handle_;
|
||||
llvm::IRBuilder<> builder_;
|
||||
std::unordered_map<ast::node*, llvm::Value*> values_;
|
||||
};
|
||||
|
||||
|
||||
|
@@ -96,8 +96,8 @@ constant_list
|
||||
;
|
||||
|
||||
type_name
|
||||
: type_specifier { $$ = new type(get_type_spec($1), nullptr); }
|
||||
| type_specifier abstract_declarator { $$ = new type(get_type_spec($1), $2); }
|
||||
: declaration_specifiers { $$ = new type_name($1, nullptr); }
|
||||
| declaration_specifiers abstract_declarator { $$ = new type_name($1, $2); }
|
||||
;
|
||||
|
||||
/* -------------------------- */
|
||||
@@ -228,6 +228,13 @@ expression
|
||||
: assignment_expression { $$ = $1; }
|
||||
;
|
||||
|
||||
/* Initialization */
|
||||
initialization_expression
|
||||
: assignment_expression { $$ = $1; }
|
||||
| '{' constant '}' { $$ = $2; }
|
||||
;
|
||||
|
||||
|
||||
/* -------------------------- */
|
||||
/* Statements */
|
||||
/* -------------------------- */
|
||||
@@ -315,14 +322,10 @@ declarator
|
||||
| direct_declarator { $$ = $1; }
|
||||
;
|
||||
|
||||
initializer
|
||||
: assignment_expression { $$ = $1; }
|
||||
| '{' constant '}' { $$ = $2; }
|
||||
;
|
||||
|
||||
|
||||
init_declarator
|
||||
: declarator { $$ = new initializer($1, nullptr); }
|
||||
| declarator '=' initializer { $$ = new initializer($1, $3); }
|
||||
| declarator '=' initialization_expression { $$ = new initializer($1, $3); }
|
||||
;
|
||||
|
||||
/* -------------------------- */
|
||||
|
270
lib/codegen.cpp
270
lib/codegen.cpp
@@ -1,3 +1,4 @@
|
||||
#include <functional>
|
||||
#include "ast.h"
|
||||
#include "codegen.h"
|
||||
#include "llvm/IR/DerivedTypes.h"
|
||||
@@ -27,12 +28,21 @@ llvm::IRBuilder<>& module::builder() {
|
||||
return builder_;
|
||||
}
|
||||
|
||||
void module::value(ast::node* node, llvm::Value* value){
|
||||
values_[node] = value;
|
||||
}
|
||||
|
||||
llvm::Value *module::value(ast::node* node){
|
||||
return values_[node];
|
||||
}
|
||||
|
||||
|
||||
namespace ast{
|
||||
|
||||
/* Translation unit */
|
||||
void translation_unit::codegen(module *mod) const{
|
||||
Value* translation_unit::codegen(module *mod) const{
|
||||
decls_->codegen(mod);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* Declaration specifier */
|
||||
@@ -55,6 +65,12 @@ Type* parameter::type(module *mod) const {
|
||||
return decl_->type(mod, spec_->type(mod));
|
||||
}
|
||||
|
||||
std::string parameter::name() const {
|
||||
if(auto id = decl_->id())
|
||||
return id->name();
|
||||
return "";
|
||||
}
|
||||
|
||||
/* Declarators */
|
||||
Type* declarator::type(module *mod, Type *type) const{
|
||||
if(ptr_)
|
||||
@@ -88,6 +104,17 @@ Type* pointer::type_impl(module*, Type *type) const{
|
||||
}
|
||||
|
||||
// Function
|
||||
void function::bind_parameters(module *mod, Function *fn) const{
|
||||
std::vector<llvm::Value*> args;
|
||||
std::transform(fn->arg_begin(), fn->arg_end(), std::back_inserter(args), [&](llvm::Argument& x){ return &x;});
|
||||
assert(args.size() == args_->values().size());
|
||||
for(size_t i = 0; i < args.size(); i++){
|
||||
parameter *param_i = args_->values().at(i);
|
||||
args[i]->setName(param_i->name());
|
||||
mod->value(param_i, args[i]);
|
||||
}
|
||||
}
|
||||
|
||||
Type* function::type_impl(module*mod, Type *type) const{
|
||||
SmallVector<Type*, 8> types;
|
||||
for(parameter* param: args_->values()){
|
||||
@@ -97,31 +124,256 @@ Type* function::type_impl(module*mod, Type *type) const{
|
||||
}
|
||||
|
||||
/* Function definition */
|
||||
void function_definition::codegen(module *mod) const{
|
||||
Value* function_definition::codegen(module *mod) const{
|
||||
FunctionType *prototype = (FunctionType *)header_->type(mod, spec_->type(mod));
|
||||
const std::string &name = header_->id()->name();
|
||||
Function *fn = Function::Create(prototype, Function::ExternalLinkage, name, mod->handle());
|
||||
header_->bind_parameters(mod, fn);
|
||||
BasicBlock *entry = BasicBlock::Create(mod->handle()->getContext(), "entry", fn);
|
||||
mod->builder().SetInsertPoint(entry);
|
||||
body_->codegen(mod);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* Statements */
|
||||
void compound_statement::codegen(module* mod) const{
|
||||
Value* compound_statement::codegen(module* mod) const{
|
||||
decls_->codegen(mod);
|
||||
statements_->codegen(mod);
|
||||
// statements_->codegen(mod);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* Declaration */
|
||||
void declaration::codegen(module* mod) const{
|
||||
|
||||
Value* declaration::codegen(module* mod) const{
|
||||
for(initializer *init: init_->values())
|
||||
init->specifier(spec_);
|
||||
init_->codegen(mod);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* Initializat */
|
||||
void initializer::codegen(module *) const{
|
||||
|
||||
/* Initializer */
|
||||
void initializer::specifier(const declaration_specifier *spec) {
|
||||
spec_ = spec;
|
||||
}
|
||||
|
||||
Value* initializer::codegen(module * mod) const{
|
||||
Type *ty = decl_->type(mod, spec_->type(mod));
|
||||
std::string name = decl_->id()->name();
|
||||
Value *value = llvm::UndefValue::get(ty);
|
||||
value->setName(name);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/*------------------*/
|
||||
/* Expression */
|
||||
/*------------------*/
|
||||
|
||||
/* Binary operator */
|
||||
Value *binary_operator::llvm_op(llvm::IRBuilder<> &builder, Value *lhs, Value *rhs, const std::string &name) const
|
||||
{
|
||||
Type *ltype = lhs->getType();
|
||||
Type *rtype = rhs->getType();
|
||||
bool is_float = ltype->isFloatingPointTy() || rtype->isFloatingPointTy();
|
||||
bool is_ptr = ltype->isPointerTy() || rtype->isPointerTy();
|
||||
bool is_int = ltype->isIntegerTy() || rtype->isIntegerTy();
|
||||
bool is_signed = false;
|
||||
// Mul
|
||||
if(op_==MUL && is_float)
|
||||
return builder.CreateFMul(lhs, rhs, name);
|
||||
if(op_==MUL && is_int)
|
||||
return builder.CreateMul(lhs, rhs, name);
|
||||
// Div
|
||||
if(op_==DIV && is_float)
|
||||
return builder.CreateFDiv(lhs, rhs, name);
|
||||
if(op_==DIV && is_int && is_signed)
|
||||
return builder.CreateSDiv(lhs, rhs, name);
|
||||
if(op_==DIV && is_int && !is_signed)
|
||||
return builder.CreateUDiv(lhs, rhs, name);
|
||||
// Mod
|
||||
if(op_==MOD && is_float)
|
||||
return builder.CreateFRem(lhs, rhs, name);
|
||||
if(op_==MOD && is_int && is_signed)
|
||||
return builder.CreateSRem(lhs, rhs, name);
|
||||
if(op_==MOD && is_int && !is_signed)
|
||||
return builder.CreateURem(lhs, rhs, name);
|
||||
// Add
|
||||
if(op_==ADD && is_float)
|
||||
return builder.CreateFAdd(lhs, rhs, name);
|
||||
if(op_==ADD && is_int)
|
||||
return builder.CreateAdd(lhs, rhs);
|
||||
if(op_==ADD && is_ptr)
|
||||
return builder.CreateGEP(lhs, {rhs});
|
||||
// Sub
|
||||
if(op_==SUB && is_float)
|
||||
return builder.CreateFSub(lhs, rhs, name);
|
||||
if(op_==SUB && is_int)
|
||||
return builder.CreateSub(lhs, rhs, name);
|
||||
if(op_==SUB && is_ptr)
|
||||
return builder.CreateGEP(lhs, {builder.CreateNeg(rhs)});
|
||||
// Left shift
|
||||
if(op_==LEFT_SHIFT){
|
||||
assert(is_int);
|
||||
return builder.CreateLShr(lhs, rhs, name);
|
||||
}
|
||||
// Right shift
|
||||
if(op_==RIGHT_SHIFT){
|
||||
assert(is_int);
|
||||
return builder.CreateAShr(lhs, rhs, name);
|
||||
}
|
||||
// LT
|
||||
if(op_ == LT && is_float)
|
||||
return builder.CreateFCmpOLT(lhs, rhs, name);
|
||||
if(op_ == LT && is_int && is_signed)
|
||||
return builder.CreateICmpSLT(lhs, rhs, name);
|
||||
if(op_ == LT && is_int && !is_signed)
|
||||
return builder.CreateICmpULT(lhs, rhs, name);
|
||||
// GT
|
||||
if(op_ == GT && is_float)
|
||||
return builder.CreateFCmpOGT(lhs, rhs, name);
|
||||
if(op_ == GT && is_int && is_signed)
|
||||
return builder.CreateICmpSGT(lhs, rhs, name);
|
||||
if(op_ == GT && is_int && !is_signed)
|
||||
return builder.CreateICmpUGT(lhs, rhs, name);
|
||||
// LE
|
||||
if(op_ == LE && is_float)
|
||||
return builder.CreateFCmpOLE(lhs, rhs, name);
|
||||
if(op_ == LE && is_int && is_signed)
|
||||
return builder.CreateICmpSLE(lhs, rhs, name);
|
||||
if(op_ == LE && is_int && !is_signed)
|
||||
return builder.CreateICmpULE(lhs, rhs, name);
|
||||
// GE
|
||||
if(op_ == GE && is_float)
|
||||
return builder.CreateFCmpOGE(lhs, rhs, name);
|
||||
if(op_ == GE && is_int && is_signed)
|
||||
return builder.CreateICmpSGE(lhs, rhs, name);
|
||||
if(op_ == GE && is_int && !is_signed)
|
||||
return builder.CreateICmpUGE(lhs, rhs, name);
|
||||
// EQ
|
||||
if(op_ == EQ && is_float)
|
||||
return builder.CreateFCmpOEQ(lhs, rhs, name);
|
||||
if(op_ == EQ && is_int)
|
||||
return builder.CreateICmpEQ(lhs, rhs, name);
|
||||
// NE
|
||||
if(op_ == NE && is_float)
|
||||
return builder.CreateFCmpONE(lhs, rhs, name);
|
||||
if(op_ == NE && is_int)
|
||||
return builder.CreateICmpNE(lhs, rhs, name);
|
||||
// AND
|
||||
if(op_ == AND){
|
||||
assert(is_int);
|
||||
return builder.CreateAnd(lhs, rhs, name);
|
||||
}
|
||||
if(op_ == XOR){
|
||||
assert(is_int);
|
||||
return builder.CreateXor(lhs, rhs, name);
|
||||
}
|
||||
if(op_ == OR){
|
||||
assert(is_int);
|
||||
return builder.CreateOr(lhs, rhs, name);
|
||||
}
|
||||
if(op_ == LAND){
|
||||
assert(is_int);
|
||||
return builder.CreateAnd(lhs, rhs, name);
|
||||
}
|
||||
if(op_ == LOR){
|
||||
assert(is_int);
|
||||
return builder.CreateOr(lhs, rhs, name);
|
||||
}
|
||||
assert(false && "unreachable");
|
||||
throw;
|
||||
}
|
||||
|
||||
Value* binary_operator::codegen(module *mod) const{
|
||||
Value *lhs = lhs_->codegen(mod);
|
||||
Value *rhs = rhs_->codegen(mod);
|
||||
Value *result = llvm_op(mod->builder(), lhs, rhs, "");
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Unary operator */
|
||||
Value *unary_operator::llvm_op(llvm::IRBuilder<> &builder, Value *arg, const std::string &name) const{
|
||||
Type *atype = arg->getType();
|
||||
bool is_float = atype->isFloatingPointTy();
|
||||
bool is_int = atype->isIntegerTy();
|
||||
if(op_ == INC){
|
||||
assert(is_int);
|
||||
return builder.CreateAdd(arg, builder.getInt32(1), name);
|
||||
}
|
||||
if(op_ == DEC){
|
||||
assert(is_int);
|
||||
return builder.CreateSub(arg, builder.getInt32(1), name);
|
||||
}
|
||||
if(op_ == PLUS)
|
||||
return arg;
|
||||
if(op_ == MINUS && is_float)
|
||||
return builder.CreateFNeg(arg, name);
|
||||
if(op_ == MINUS && is_int)
|
||||
return builder.CreateNeg(arg, name);
|
||||
if(op_ == ADDR)
|
||||
throw std::runtime_error("not supported");
|
||||
if(op_ == DEREF)
|
||||
return builder.CreateLoad(arg, name);
|
||||
if(op_ == COMPL)
|
||||
throw std::runtime_error("not supported");
|
||||
if(op_ == NOT)
|
||||
return builder.CreateNot(arg, name);
|
||||
assert(false && "unrechable");
|
||||
throw;
|
||||
}
|
||||
|
||||
Value* unary_operator::codegen(module *mod) const{
|
||||
Value *arg = arg_->codegen(mod);
|
||||
Value *result = llvm_op(mod->builder(), arg, "");
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Cast operator */
|
||||
Value *cast_operator::llvm_op(IRBuilder<> &builder, Type *T, Value *arg, const std::string &name) const{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Value* cast_operator::codegen(module *mod) const{
|
||||
Value *arg = arg_->codegen(mod);
|
||||
Type *T = T_->type(mod);
|
||||
return llvm_op(mod->builder(), T, arg, "");
|
||||
}
|
||||
|
||||
/* Conditional expression */
|
||||
Value *conditional_expression::llvm_op(IRBuilder<> &builder, Value *cond, Value *true_value, Value *false_value, const std::string &name) const{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Value *conditional_expression::codegen(module *mod) const{
|
||||
Value *cond = cond_->codegen(mod);
|
||||
Value *true_value = true_value_->codegen(mod);
|
||||
Value *false_value = false_value_->codegen(mod);
|
||||
return llvm_op(mod->builder(), cond, true_value, false_value, "");
|
||||
}
|
||||
|
||||
/* Assignment expression */
|
||||
Value *assignment_expression::llvm_op(llvm::IRBuilder<> &builder, Value *lvalue, Value *rvalue, const std::string &name) const{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Value *assignment_expression::codegen(module *mod) const{
|
||||
Value *lvalue = lvalue_->codegen(mod);
|
||||
Value *rvalue = rvalue_->codegen(mod);
|
||||
return llvm_op(mod->builder(), lvalue, rvalue, "");
|
||||
}
|
||||
|
||||
/* Type name */
|
||||
llvm::Type *type_name::type(module *mod) const{
|
||||
return decl_->type(mod, spec_->type(mod));
|
||||
}
|
||||
|
||||
/* String literal */
|
||||
llvm::Value* string_literal::codegen(module *mod) const{
|
||||
return ConstantDataArray::getString(mod->handle()->getContext(), value_);
|
||||
}
|
||||
|
||||
/* Constant */
|
||||
llvm::Value* constant::codegen(module *mod) const{
|
||||
return mod->builder().getInt32(value_);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user