summaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGExpr.cpp
blob: a16e63e17fa388b3a513e60673a15d14d99610b6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
//===--- CGExpr.cpp - Emit LLVM Code from Expressions ---------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This contains code to emit Expr nodes as LLVM code.
//
//===----------------------------------------------------------------------===//

#include "CodeGenFunction.h"
#include "CodeGenModule.h"
#include "flang/AST/ASTContext.h"
#include "flang/AST/ExprVisitor.h"
#include "flang/Frontend/CodeGenOptions.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/MDBuilder.h"

namespace flang {
namespace CodeGen {

/// CreateTempAlloca - This creates a alloca and inserts it into the entry
/// block.
llvm::AllocaInst *CodeGenFunction::CreateTempAlloca(llvm::Type *Ty,
                                                    const llvm::Twine &Name) {
  return new llvm::AllocaInst(Ty, 0, Name, AllocaInsertPt);
}

RValueTy CodeGenFunction::EmitRValue(const Expr *E) {
  auto EType = E->getType();
  if(EType->isComplexType())
    return EmitComplexExpr(E);
  else if(EType->isCharacterType())
    return EmitCharacterExpr(E);
  else if(EType->isLogicalType())
    return EmitLogicalValueExpr(E);
  else if(EType->isRecordType())
    return EmitAggregateExpr(E);
  else
    return EmitScalarExpr(E);
}

RValueTy CodeGenFunction::EmitLoad(llvm::Value *Ptr, QualType T, bool IsVolatile) {
  if(T->isComplexType())
    return EmitComplexLoad(Ptr, IsVolatile);
  else
    return Builder.CreateLoad(Ptr, IsVolatile);
}

void CodeGenFunction::EmitStore(RValueTy Val, LValueTy Dest, QualType T) {
  auto Ptr = Dest.getPointer();
  auto IsVolatile = Dest.isVolatileQualifier();
  if(Val.isScalar()) {
    if(Val.asScalar()->getType() == CGM.Int1Ty)
      Val = ConvertLogicalValueToLogicalMemoryValue(Val.asScalar(),
                                                    T->isArrayType()? T->asArrayType()->getElementType() : T);
    Builder.CreateStore(Val.asScalar(), Ptr, IsVolatile);
  } else if(Val.isComplex())
    EmitComplexStore(Val.asComplex(), Ptr, IsVolatile);
  else if(Val.isAggregate()) {
    Builder.CreateStore(Builder.CreateLoad(Val.getAggregateAddr(), Val.isVolatileQualifier()),
                        Ptr, IsVolatile);
  }
}

void CodeGenFunction::EmitStoreCharSameLength(RValueTy Val, LValueTy Dest, QualType T) {
  if(!Val.isCharacter())
    return EmitStore(Val, Dest, T);
  auto CharVal = Val.asCharacter();
  Builder.CreateMemCpy(Dest.getPointer(), CharVal.Ptr, CharVal.Len, 1, Dest.isVolatileQualifier());
}

RValueTy CodeGenFunction::EmitBinaryExpr(BinaryExpr::Operator Op, RValueTy LHS, RValueTy RHS) {
  if(LHS.isScalar())
    return EmitScalarBinaryExpr(Op, LHS.asScalar(), RHS.asScalar());
  else if(LHS.isComplex()) {
    if(Op == BinaryExpr::Plus || Op == BinaryExpr::Minus || Op == BinaryExpr::Multiply ||
       Op == BinaryExpr::Divide || Op == BinaryExpr::Power)
     return EmitComplexBinaryExpr(Op, LHS.asComplex(), RHS.asComplex());
    return EmitComplexRelationalExpr(Op, LHS.asComplex(), RHS.asComplex());
  } else // FIXME: character concat
    return EmitCharacterRelationalExpr(Op, LHS.asCharacter(), RHS.asCharacter());
}

RValueTy CodeGenFunction::EmitUnaryExpr(UnaryExpr::Operator Op, RValueTy Val) {
  switch(Op) {
  case UnaryExpr::Plus:
    return Val;
  case UnaryExpr::Minus:
    if(Val.isScalar())
      return EmitScalarUnaryMinus(Val.asScalar());
    return EmitComplexUnaryMinus(Val.asComplex());
  case UnaryExpr::Not:
    return EmitScalarUnaryNot(Val.asScalar());
  }
  return RValueTy();
}

RValueTy CodeGenFunction::EmitImplicitConversion(RValueTy Val, QualType T) {
  if(Val.isScalar()) {
    if(T->isComplexType())
      return EmitScalarToComplexConversion(Val.asScalar(), T);
    return EmitScalarToScalarConversion(Val.asScalar(), T);
  }
  assert(Val.isComplex());
  if(T->isComplexType())
    return EmitComplexToComplexConversion(Val.asComplex(), T);
  return EmitComplexToScalarConversion(Val.asComplex(), T);
}

llvm::Constant *CodeGenFunction::EmitConstantExpr(const Expr *E) {
  auto T = E->getType();
  if(T->isComplexType())
    return CreateComplexConstant(EmitComplexExpr(E));
  else if(T->isCharacterType()) //FIXME
    ;//;return CreateCharacterConstant(EmitCharacterExpr(E));
  else if(T->isLogicalType())
    return cast<llvm::Constant>(EmitLogicalValueExpr(E));
  else if(T->isArrayType())
    return EmitConstantArrayExpr(dyn_cast<ArrayConstructorExpr>(E));
  else
    return cast<llvm::Constant>(EmitScalarExpr(E));
}

class LValueExprEmitter
  : public ConstExprVisitor<LValueExprEmitter, LValueTy> {
  CodeGenFunction &CGF;
  CGBuilderTy &Builder;
  llvm::LLVMContext &VMContext;
public:

  LValueExprEmitter(CodeGenFunction &cgf);

  LValueTy VisitVarExpr(const VarExpr *E);
  LValueTy VisitArrayElementExpr(const ArrayElementExpr *E);
  LValueTy VisitMemberExpr(const MemberExpr *E);
};

LValueExprEmitter::LValueExprEmitter(CodeGenFunction &cgf)
  : CGF(cgf), Builder(cgf.getBuilder()),
    VMContext(cgf.getLLVMContext()) {
}

LValueTy LValueExprEmitter::VisitVarExpr(const VarExpr *E) {
  return LValueTy(CGF.GetVarPtr(E->getVarDecl()));
}

LValueTy LValueExprEmitter::VisitArrayElementExpr(const ArrayElementExpr *E) {
  return CGF.EmitArrayElementPtr(E->getTarget(), E->getSubscripts());
}

LValueTy LValueExprEmitter::VisitMemberExpr(const MemberExpr *E) {
  return CGF.EmitAggregateMember(Visit(E->getTarget()).getPointer(),
                                 E->getField());
}

LValueTy CodeGenFunction::EmitLValue(const Expr *E) {
  LValueExprEmitter EV(*this);
  return EV.Visit(E);
}

}
} // end namespace flang