summaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGExprAgg.cpp
blob: 67050269356df49bea565f9a721be13be0c99d69 (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
//===--- CGExprAgg.cpp - Emit LLVM Code from Aggregate 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 Aggregate Expr nodes as LLVM code.
//
//===----------------------------------------------------------------------===//

#include "CodeGenFunction.h"
#include "CodeGenModule.h"
#include "flang/AST/ASTContext.h"
#include "flang/AST/ExprVisitor.h"

namespace flang {
namespace CodeGen {

class AggregateExprEmitter
  : public ConstExprVisitor<AggregateExprEmitter, RValueTy> {
  CodeGenFunction &CGF;
  CGBuilderTy &Builder;
public:

  AggregateExprEmitter(CodeGenFunction &cgf);

  RValueTy EmitExpr(const Expr *E);
  RValueTy VisitVarExpr(const VarExpr *E);
  RValueTy VisitArrayElementExpr(const ArrayElementExpr *E);
  RValueTy VisitMemberExpr(const MemberExpr *E);
  RValueTy VisitCallExpr(const CallExpr *E);
  RValueTy VisitTypeConstructorExpr(const TypeConstructorExpr *E);
};

AggregateExprEmitter::AggregateExprEmitter(CodeGenFunction &cgf)
  : CGF(cgf), Builder(cgf.getBuilder()) {}

RValueTy AggregateExprEmitter::EmitExpr(const Expr *E) {
  return Visit(E);
}

RValueTy AggregateExprEmitter::VisitVarExpr(const VarExpr *E) {
  auto VD = E->getVarDecl();
  if(CGF.IsInlinedArgument(VD))
    return CGF.GetInlinedArgumentValue(VD);
  else if(VD->isParameter())
    return EmitExpr(VD->getInit());
  else if(VD->isFunctionResult())
    return RValueTy::getAggregate(CGF.GetRetVarPtr());
  return RValueTy::getAggregate(CGF.GetVarPtr(VD));
}

RValueTy AggregateExprEmitter::VisitArrayElementExpr(const ArrayElementExpr *E) {
  return RValueTy::getAggregate(CGF.EmitArrayElementPtr(E));
}

RValueTy AggregateExprEmitter::VisitMemberExpr(const MemberExpr *E) {
  auto Val = EmitExpr(E->getTarget());
  return RValueTy::getAggregate(CGF.EmitAggregateMember(Val.getAggregateAddr(), E->getField()),
                                Val.isVolatileQualifier());
}

RValueTy AggregateExprEmitter::VisitCallExpr(const CallExpr *E) {
  return CGF.EmitCall(E);
}

RValueTy AggregateExprEmitter::VisitTypeConstructorExpr(const TypeConstructorExpr *E) {
  // create a temporary object.
  auto TempStruct = CGF.CreateTempAlloca(CGF.ConvertTypeForMem(E->getType()), "type-constructor");
  auto Values = E->getArguments();
  auto Fields = E->getType().getSelfOrArrayElementType()->asRecordType()->getElements();
  for(unsigned I = 0; I < Values.size(); ++I) {
    CGF.EmitStore(CGF.EmitRValue(Values[I]),
                  LValueTy(Builder.CreateStructGEP(CGF.ConvertTypeForMem(E->getType()),
                                                   TempStruct,I)),
                  Fields[I]->getType());
  }
  return RValueTy::getAggregate(TempStruct);
}

RValueTy CodeGenFunction::EmitAggregateExpr(const Expr *E) {
  AggregateExprEmitter EV(*this);
  return EV.EmitExpr(E);
}

void CodeGenFunction::EmitAggregateAssignment(const Expr *LHS, const Expr *RHS) {
  auto Val = EmitAggregateExpr(RHS);
  auto Dest = EmitLValue(LHS);
  Builder.CreateStore(Builder.CreateLoad(Val.getAggregateAddr(), Val.isVolatileQualifier()),
                      Dest.getPointer(), Dest.isVolatileQualifier());
}

llvm::Value *CodeGenFunction::EmitAggregateMember(llvm::Value *Agg, const FieldDecl *Field) {
  return Builder.CreateStructGEP(nullptr, Agg, Field->getIndex());
}

void CodeGenFunction::EmitAggregateReturn(const CGFunctionInfo::RetInfo &Info, llvm::Value *Ptr) {
  if(Info.Type->isComplexType()) {
    if(Info.ABIInfo.hasAggregateReturnType()) {
      Builder.CreateRet(Builder.CreateLoad(
        Builder.CreateBitCast(Ptr, llvm::PointerType::get(Info.ABIInfo.getAggregateReturnType(), 0))));
      return;
    }
    Builder.CreateRet(CreateComplexAggregate(
                        EmitComplexLoad(Ptr)));
  } else {
    Builder.CreateRet(Builder.CreateLoad(Ptr));
  }
}

}
}