blob: b2fe140da9cacc06e5ae8ec0c7ed4a4882636efe [file] [log] [blame]
David Neto85082642018-03-24 06:55:20 -07001// Copyright 2018 The Clspv Authors. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include "ConstantEmitter.h"
16
17#include <cassert>
18
David Neto85082642018-03-24 06:55:20 -070019#include "llvm/ADT/APFloat.h"
Diego Novillo3cc8d7a2019-04-10 13:30:34 -040020#include "llvm/ADT/APInt.h"
David Neto85082642018-03-24 06:55:20 -070021#include "llvm/IR/Constants.h"
22#include "llvm/IR/Value.h"
23#include "llvm/Support/ErrorHandling.h"
24
25using namespace llvm;
26
27namespace clspv {
28
29void ConstantEmitter::Emit(Constant *c) {
30 AlignTo(Layout.getABITypeAlignment(c->getType()));
31 if (auto i = dyn_cast<ConstantInt>(c)) {
32 EmitInt(i);
33 } else if (auto f = dyn_cast<ConstantFP>(c)) {
34 EmitFP(f);
35 } else if (auto st = dyn_cast<ConstantStruct>(c)) {
36 EmitStruct(st);
37 } else if (auto ag = dyn_cast<ConstantArray>(c)) {
38 EmitAggregate(ag);
39 } else if (auto ag = dyn_cast<ConstantVector>(c)) {
40 EmitAggregate(ag);
41 } else if (auto cds = dyn_cast<ConstantDataSequential>(c)) {
42 EmitDataSequential(cds);
43 } else if (auto ag = dyn_cast<ConstantAggregate>(c)) {
44 EmitAggregate(ag);
45 } else if (auto ag = dyn_cast<ConstantAggregateZero>(c)) {
46 EmitAggregateZero(ag);
47 } else {
48 errs() << "Don't know how to emit " << *c << " with value id "
Diego Novillo3cc8d7a2019-04-10 13:30:34 -040049 << int(c->getValueID()) << " compared to "
50 << int(Value::ConstantVectorVal) << "\n";
David Neto85082642018-03-24 06:55:20 -070051 llvm_unreachable("Unhandled constant");
52 }
53}
54
55void ConstantEmitter::EmitZeroes(size_t n) {
56 for (size_t i = 0; i < n; ++i) {
57 Out << "00";
58 ++Offset;
59 }
60}
61
62void ConstantEmitter::AlignTo(size_t alignment) {
63 size_t overflow = Offset % alignment;
64 if (overflow) {
65 const size_t padding = alignment - overflow;
66 EmitZeroes(padding);
67 }
68 assert(0 == (Offset % alignment));
69}
70
71void ConstantEmitter::EmitStruct(ConstantStruct *c) {
72 const StructLayout *sl = Layout.getStructLayout(c->getType());
alan-baker214254f2019-09-25 11:42:01 -040073 AlignTo(sl->getAlignment().value()); // Might be redundant.
David Neto85082642018-03-24 06:55:20 -070074 const size_t BaseOffset = Offset;
75 for (unsigned i = 0; i < c->getNumOperands(); ++i) {
76 EmitZeroes(sl->getElementOffset(i) - (Offset - BaseOffset));
77 Emit(c->getOperand(i));
78 }
79 EmitZeroes(sl->getSizeInBytes() - (Offset - BaseOffset));
80}
81
82void ConstantEmitter::EmitDataSequential(ConstantDataSequential *c) {
83 for (unsigned i = 0; i < c->getNumElements(); ++i) {
84 // The elements will align themselves.
85 Constant *elem = c->getElementAsConstant(i);
86 Emit(elem);
87 }
88}
89
90void ConstantEmitter::EmitAggregate(ConstantAggregate *c) {
91 for (unsigned i = 0; i < c->getNumOperands(); ++i) {
92 // The elements will align themselves.
93 Emit(c->getOperand(i));
94 }
95}
96
97void ConstantEmitter::EmitAggregateZero(ConstantAggregateZero *c) {
98 if (StructType *sty = dyn_cast<StructType>(c->getType())) {
99
100 const StructLayout *sl = Layout.getStructLayout(sty);
alan-baker214254f2019-09-25 11:42:01 -0400101 AlignTo(sl->getAlignment().value()); // Might be redundant.
David Neto85082642018-03-24 06:55:20 -0700102 const size_t BaseOffset = Offset;
103 for (unsigned i = 0; i < c->getNumElements(); ++i) {
104 EmitZeroes(sl->getElementOffset(i) - (Offset - BaseOffset));
105 Emit(c->getElementValue(i));
106 }
107 EmitZeroes(sl->getSizeInBytes() - (Offset - BaseOffset));
108
109 } else {
110 for (unsigned i = 0; i < c->getNumElements(); ++i) {
111 // The elements will align themselves.
112 Emit(c->getElementValue(i));
113 }
114 }
115}
116
117void ConstantEmitter::EmitInt(ConstantInt *c) {
118 EmitRaw(c->getBitWidth(), c->getValue().getRawData());
119}
120
121void ConstantEmitter::EmitFP(ConstantFP *c) {
122 APInt asInt = c->getValueAPF().bitcastToAPInt();
123 EmitRaw(asInt.getBitWidth(), asInt.getRawData());
124}
125
126void ConstantEmitter::EmitRaw(unsigned num_bits, const uint64_t *data) {
127 unsigned num_bytes = (num_bits + 7) / 8;
128 while (num_bytes) {
129 uint64_t word = *data++;
130 for (int i = 0; i < 8 && num_bytes; --num_bytes, ++i) {
131 EmitByte(word & 0xff);
132 word = (word >> 8);
133 }
134 }
135}
136
137void ConstantEmitter::EmitByte(size_t byte) {
138 static const char hex[] = "0123456789abcdef";
139 Out << hex[(byte & 0xf0) >> 4] << hex[byte & 0xf];
140 ++Offset;
141}
142
143} // namespace clspv