Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(514)

Side by Side Diff: src/IceTargetLoweringX8664.cpp

Issue 1266673003: Subzero. Implements x86-64 lowerCall. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: git pull & painful merge. Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 //===- subzero/src/IceTargetLoweringX8664.cpp - x86-64 lowering -----------===// 1 //===- subzero/src/IceTargetLoweringX8664.cpp - x86-64 lowering -----------===//
2 // 2 //
3 // The Subzero Code Generator 3 // The Subzero Code Generator
4 // 4 //
5 // This file is distributed under the University of Illinois Open Source 5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details. 6 // License. See LICENSE.TXT for details.
7 // 7 //
8 //===----------------------------------------------------------------------===// 8 //===----------------------------------------------------------------------===//
9 /// 9 ///
10 /// \file 10 /// \file
11 /// This file implements the TargetLoweringX8664 class, which 11 /// This file implements the TargetLoweringX8664 class, which
12 /// consists almost entirely of the lowering sequence for each 12 /// consists almost entirely of the lowering sequence for each
13 /// high-level instruction. 13 /// high-level instruction.
14 /// 14 ///
15 //===----------------------------------------------------------------------===// 15 //===----------------------------------------------------------------------===//
16 16
17 #include "IceTargetLoweringX8664.h" 17 #include "IceTargetLoweringX8664.h"
18 18
19 #include "IceTargetLoweringX8664Traits.h" 19 #include "IceTargetLoweringX8664Traits.h"
20 #include "IceTargetLoweringX86Base.h" 20 #include "IceTargetLoweringX86Base.h"
21 21
22 namespace Ice { 22 namespace Ice {
23 23
24 //------------------------------------------------------------------------------
25 // ______ ______ ______ __ ______ ______
26 // /\__ _\ /\ == \ /\ __ \ /\ \ /\__ _\ /\ ___\
27 // \/_/\ \/ \ \ __< \ \ __ \ \ \ \ \/_/\ \/ \ \___ \
28 // \ \_\ \ \_\ \_\ \ \_\ \_\ \ \_\ \ \_\ \/\_____\
29 // \/_/ \/_/ /_/ \/_/\/_/ \/_/ \/_/ \/_____/
30 //
31 //------------------------------------------------------------------------------
24 namespace X86Internal { 32 namespace X86Internal {
25 const MachineTraits<TargetX8664>::TableFcmpType 33 const MachineTraits<TargetX8664>::TableFcmpType
26 MachineTraits<TargetX8664>::TableFcmp[] = { 34 MachineTraits<TargetX8664>::TableFcmp[] = {
27 #define X(val, dflt, swapS, C1, C2, swapV, pred) \ 35 #define X(val, dflt, swapS, C1, C2, swapV, pred) \
28 { \ 36 { \
29 dflt, swapS, X8664::Traits::Cond::C1, X8664::Traits::Cond::C2, swapV, \ 37 dflt, swapS, X8664::Traits::Cond::C1, X8664::Traits::Cond::C2, swapV, \
30 X8664::Traits::Cond::pred \ 38 X8664::Traits::Cond::pred \
31 } \ 39 } \
32 , 40 ,
33 FCMPX8664_TABLE 41 FCMPX8664_TABLE
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
74 }; 82 };
75 83
76 const size_t MachineTraits<TargetX8664>::TableTypeX8664AttributesSize = 84 const size_t MachineTraits<TargetX8664>::TableTypeX8664AttributesSize =
77 llvm::array_lengthof(TableTypeX8664Attributes); 85 llvm::array_lengthof(TableTypeX8664Attributes);
78 86
79 const uint32_t MachineTraits<TargetX8664>::X86_STACK_ALIGNMENT_BYTES = 16; 87 const uint32_t MachineTraits<TargetX8664>::X86_STACK_ALIGNMENT_BYTES = 16;
80 const char *MachineTraits<TargetX8664>::TargetName = "X8664"; 88 const char *MachineTraits<TargetX8664>::TargetName = "X8664";
81 89
82 } // end of namespace X86Internal 90 } // end of namespace X86Internal
83 91
92 //------------------------------------------------------------------------------
93 // __ ______ __ __ ______ ______ __ __ __ ______
94 // /\ \ /\ __ \/\ \ _ \ \/\ ___\/\ == \/\ \/\ "-.\ \/\ ___\
95 // \ \ \___\ \ \/\ \ \ \/ ".\ \ \ __\\ \ __<\ \ \ \ \-. \ \ \__ \
96 // \ \_____\ \_____\ \__/".~\_\ \_____\ \_\ \_\ \_\ \_\\"\_\ \_____\
97 // \/_____/\/_____/\/_/ \/_/\/_____/\/_/ /_/\/_/\/_/ \/_/\/_____/
98 //
99 //------------------------------------------------------------------------------
100 namespace {
101 static inline TargetX8664::Traits::RegisterSet::AllRegisters
102 getRegisterForXmmArgNum(uint32_t ArgNum) {
103 assert(ArgNum < TargetX8664::Traits::X86_MAX_XMM_ARGS);
104 return static_cast<TargetX8664::Traits::RegisterSet::AllRegisters>(
105 TargetX8664::Traits::RegisterSet::Reg_xmm0 + ArgNum);
106 }
107
108 static inline TargetX8664::Traits::RegisterSet::AllRegisters
109 getRegisterForGprArgNum(uint32_t ArgNum) {
110 assert(ArgNum < TargetX8664::Traits::X86_MAX_GPR_ARGS);
111 static const TargetX8664::Traits::RegisterSet::AllRegisters GprForArgNum[] = {
112 TargetX8664::Traits::RegisterSet::Reg_edi,
113 TargetX8664::Traits::RegisterSet::Reg_esi,
114 TargetX8664::Traits::RegisterSet::Reg_edx,
115 TargetX8664::Traits::RegisterSet::Reg_ecx,
116 TargetX8664::Traits::RegisterSet::Reg_r8d,
117 TargetX8664::Traits::RegisterSet::Reg_r9d,
118 };
119 static_assert(llvm::array_lengthof(GprForArgNum) ==
120 TargetX8664::TargetX8664::Traits::X86_MAX_GPR_ARGS,
121 "Mismtach between MAX_GPR_ARGS and GprForArgNum.");
jvoung (off chromium) 2015/07/31 23:53:49 "Mismatch"
John 2015/08/01 15:49:55 "Doen." :)
122 return GprForArgNum[ArgNum];
123 }
124 }
125
126 void TargetX8664::lowerCall(const InstCall *Instr) {
127 // x86-64 calling convention:
128 //
129 // * At the point before the call, the stack must be aligned to 16
130 // bytes.
131 //
132 // * The first eight arguments of vector/fp type, regardless of their
133 // position relative to the other arguments in the argument list, are
134 // placed in registers %xmm0 - %xmm7.
135 //
136 // * The first six arguments of integer types, regardless of their
137 // position relative to the other arguments in the argument list, are
138 // placed in registers %rdi, %rsi, %rdx, %rcx, %r8, and %r9.
139 //
140 // * Other arguments are pushed onto the stack in right-to-left order,
141 // such that the left-most argument ends up on the top of the stack at
142 // the lowest memory address.
143 //
144 // * Stack arguments of vector type are aligned to start at the next
145 // highest multiple of 16 bytes. Other stack arguments are aligned to
146 // 8 bytes.
147 //
148 // This intends to match the section "Function Calling Sequence" of the
149 // document "System V Application Binary Interface."
150 NeedsStackAlignment = true;
151
152 using OperandList = std::vector<Operand *>;
jvoung (off chromium) 2015/08/03 17:04:55 Might be able to use "llvm::SmallVector<Operand *,
John 2015/08/05 16:53:03 Done.
153 OperandList XmmArgs;
154 OperandList GprArgs;
155 OperandList StackArgs, StackArgLocations;
156 uint32_t ParameterAreaSizeBytes = 0;
157
158 // Classify each argument operand according to the location where the
159 // argument is passed.
160 for (SizeT i = 0, NumArgs = Instr->getNumArgs(); i < NumArgs; ++i) {
161 Operand *Arg = Instr->getArg(i);
162 Type Ty = Arg->getType();
163 // The PNaCl ABI requires the width of arguments to be at least 32 bits.
164 assert(typeWidthInBytes(Ty) >= 4);
165 if (isVectorType(Ty) && XmmArgs.size() < Traits::X86_MAX_XMM_ARGS) {
166 XmmArgs.push_back(Arg);
167 } else if (isScalarFloatingType(Ty) &&
168 XmmArgs.size() < Traits::X86_MAX_XMM_ARGS) {
169 XmmArgs.push_back(Arg);
170 } else if (isScalarIntegerType(Ty) &&
171 GprArgs.size() < Traits::X86_MAX_GPR_ARGS) {
172 GprArgs.push_back(Arg);
173 } else {
174 StackArgs.push_back(Arg);
175 if (isVectorType(Arg->getType())) {
176 ParameterAreaSizeBytes =
177 Traits::applyStackAlignment(ParameterAreaSizeBytes);
178 }
179 Variable *esp = getPhysicalRegister(Traits::RegisterSet::Reg_esp);
180 Constant *Loc = Ctx->getConstantInt32(ParameterAreaSizeBytes);
181 StackArgLocations.push_back(
182 Traits::X86OperandMem::create(Func, Ty, esp, Loc));
183 ParameterAreaSizeBytes += typeWidthInBytesOnStack(Arg->getType());
jvoung (off chromium) 2015/07/31 23:53:49 Is typeWidthInBytesOnStack defined differently for
John 2015/08/01 15:49:55 We could avoid the overhead, but if we want to be
jvoung (off chromium) 2015/08/03 17:04:55 Yes, my understanding is that the calling conventi
John 2015/08/05 16:53:03 Oh, now I see what you mean. :) I added a TODO in
184 }
185 }
186
187 // Adjust the parameter area so that the stack is aligned. It is
188 // assumed that the stack is already aligned at the start of the
189 // calling sequence.
190 ParameterAreaSizeBytes = Traits::applyStackAlignment(ParameterAreaSizeBytes);
191
192 // Subtract the appropriate amount for the argument area. This also
193 // takes care of setting the stack adjustment during emission.
194 //
195 // TODO: If for some reason the call instruction gets dead-code
196 // eliminated after lowering, we would need to ensure that the
197 // pre-call and the post-call esp adjustment get eliminated as well.
198 if (ParameterAreaSizeBytes) {
199 _adjust_stack(ParameterAreaSizeBytes);
200 }
201
202 // Copy arguments that are passed on the stack to the appropriate
203 // stack locations.
204 for (SizeT i = 0, e = StackArgs.size(); i < e; ++i) {
205 lowerStore(InstStore::create(Func, StackArgs[i], StackArgLocations[i]));
206 }
207
208 // Copy arguments to be passed in registers to the appropriate
209 // registers.
210 // TODO: Investigate the impact of lowering arguments passed in
211 // registers after lowering stack arguments as opposed to the other
212 // way around. Lowering register arguments after stack arguments may
213 // reduce register pressure. On the other hand, lowering register
214 // arguments first (before stack arguments) may result in more compact
215 // code, as the memory operand displacements may end up being smaller
216 // before any stack adjustment is done.
217 for (SizeT i = 0, NumXmmArgs = XmmArgs.size(); i < NumXmmArgs; ++i) {
218 Variable *Reg = legalizeToReg(XmmArgs[i], getRegisterForXmmArgNum(i));
219 // Generate a FakeUse of register arguments so that they do not get
220 // dead code eliminated as a result of the FakeKill of scratch
221 // registers after the call.
222 Context.insert(InstFakeUse::create(Func, Reg));
223 }
224
225 for (SizeT i = 0, NumGprArgs = GprArgs.size(); i < NumGprArgs; ++i) {
226 Variable *Reg = legalizeToReg(GprArgs[i], getRegisterForGprArgNum(i));
227 Context.insert(InstFakeUse::create(Func, Reg));
228 }
229
230 // Generate the call instruction. Assign its result to a temporary
231 // with high register allocation weight.
232 Variable *Dest = Instr->getDest();
233 // ReturnReg doubles as ReturnRegLo as necessary.
234 Variable *ReturnReg = nullptr;
235 Variable *ReturnRegHi = nullptr;
236 if (Dest) {
237 switch (Dest->getType()) {
238 case IceType_NUM:
239 llvm_unreachable("Invalid Call dest type");
240 break;
241 case IceType_void:
jvoung (off chromium) 2015/07/31 23:53:49 This is the same in the other targets, but it seem
Jim Stichnoth 2015/08/05 04:43:51 Yeah, I don't remember why it ended up this way, b
242 break;
243 case IceType_i1:
244 case IceType_i8:
245 case IceType_i16:
246 case IceType_i32:
247 ReturnReg = makeReg(Dest->getType(), Traits::RegisterSet::Reg_eax);
248 break;
249 case IceType_i64:
250 // TODO(jpp): return i64 in a GPR.
251 ReturnReg = makeReg(IceType_i32, Traits::RegisterSet::Reg_eax);
252 ReturnRegHi = makeReg(IceType_i32, Traits::RegisterSet::Reg_edx);
253 break;
254 case IceType_f32:
255 case IceType_f64:
256 case IceType_v4i1:
257 case IceType_v8i1:
258 case IceType_v16i1:
259 case IceType_v16i8:
260 case IceType_v8i16:
261 case IceType_v4i32:
262 case IceType_v4f32:
263 ReturnReg = makeReg(Dest->getType(), Traits::RegisterSet::Reg_xmm0);
264 break;
265 }
266 }
267
268 Operand *CallTarget = legalize(Instr->getCallTarget());
269 const bool NeedSandboxing = Ctx->getFlags().getUseSandboxing();
270 if (NeedSandboxing) {
271 if (llvm::isa<Constant>(CallTarget)) {
272 _bundle_lock(InstBundleLock::Opt_AlignToEnd);
273 } else {
274 Variable *CallTargetVar = nullptr;
275 _mov(CallTargetVar, CallTarget);
276 _bundle_lock(InstBundleLock::Opt_AlignToEnd);
277 const SizeT BundleSize =
278 1 << Func->getAssembler<>()->getBundleAlignLog2Bytes();
279 _and(CallTargetVar, Ctx->getConstantInt32(~(BundleSize - 1)));
280 CallTarget = CallTargetVar;
281 }
282 }
283 Inst *NewCall = Traits::Insts::Call::create(Func, ReturnReg, CallTarget);
284 Context.insert(NewCall);
285 if (NeedSandboxing)
286 _bundle_unlock();
287 if (ReturnRegHi)
288 Context.insert(InstFakeDef::create(Func, ReturnRegHi));
289
290 // Add the appropriate offset to esp. The call instruction takes care
291 // of resetting the stack offset during emission.
292 if (ParameterAreaSizeBytes) {
293 Variable *Esp =
294 Func->getTarget()->getPhysicalRegister(Traits::RegisterSet::Reg_esp);
295 _add(Esp, Ctx->getConstantInt32(ParameterAreaSizeBytes));
296 }
297
298 // Insert a register-kill pseudo instruction.
299 Context.insert(InstFakeKill::create(Func, NewCall));
300
301 // Generate a FakeUse to keep the call live if necessary.
302 if (Instr->hasSideEffects() && ReturnReg) {
303 Inst *FakeUse = InstFakeUse::create(Func, ReturnReg);
304 Context.insert(FakeUse);
305 }
306
307 if (!Dest)
308 return;
309
310 if (!ReturnReg)
jvoung (off chromium) 2015/07/31 23:53:49 Seems a bit odd to have a Dest, but no ReturnReg.
John 2015/08/01 15:49:55 Yes, indeed. This became an assert(ReturnReg);
jvoung (off chromium) 2015/08/03 17:04:55 New patch upload?
John 2015/08/05 16:53:03 Done.
311 return;
312
313 // Assign the result of the call to Dest.
314 if (ReturnRegHi) {
315 assert(Dest->getType() == IceType_i64);
316 split64(Dest);
317 Variable *DestLo = Dest->getLo();
318 Variable *DestHi = Dest->getHi();
319 _mov(DestLo, ReturnReg);
320 _mov(DestHi, ReturnRegHi);
321 return;
322 }
323
324 assert(Dest->getType() == IceType_f32 || Dest->getType() == IceType_f64 ||
325 Dest->getType() == IceType_i32 || Dest->getType() == IceType_i16 ||
326 Dest->getType() == IceType_i8 || Dest->getType() == IceType_i1 ||
327 isVectorType(Dest->getType()));
328
329 if (isScalarFloatingType(Dest->getType()) || isVectorType(Dest->getType())) {
330 _movp(Dest, ReturnReg);
331 } else {
332 _mov(Dest, ReturnReg);
333 }
334 }
335
336 void TargetX8664::emitJumpTable(const Cfg *Func,
337 const InstJumpTable *JumpTable) const {
338 if (!BuildDefs::dump())
339 return;
340 Ostream &Str = Ctx->getStrEmit();
341 IceString MangledName = Ctx->mangleName(Func->getFunctionName());
342 Str << "\t.section\t.rodata." << MangledName
343 << "$jumptable,\"a\",@progbits\n";
344 Str << "\t.align\t" << typeWidthInBytes(getPointerType()) << "\n";
345 Str << InstJumpTable::makeName(MangledName, JumpTable->getId()) << ":";
346
347 // On X8664 ILP32 pointers are 32-bit hence the use of .long
348 for (SizeT I = 0; I < JumpTable->getNumTargets(); ++I)
349 Str << "\n\t.long\t" << JumpTable->getTarget(I)->getAsmName();
350 Str << "\n";
351 }
352
353 void TargetDataX8664::lowerJumpTables() {
354 switch (Ctx->getFlags().getOutFileType()) {
355 case FT_Elf: {
356 ELFObjectWriter *Writer = Ctx->getObjectWriter();
357 for (const JumpTableData &JumpTable : *Ctx->getJumpTables())
358 // TODO(jpp): not 386.
359 Writer->writeJumpTable(JumpTable, llvm::ELF::R_386_32);
360 } break;
361 case FT_Asm:
362 // Already emitted from Cfg
363 break;
364 case FT_Iasm: {
365 if (!BuildDefs::dump())
366 return;
367 Ostream &Str = Ctx->getStrEmit();
368 for (const JumpTableData &JT : *Ctx->getJumpTables()) {
369 Str << "\t.section\t.rodata." << JT.getFunctionName()
370 << "$jumptable,\"a\",@progbits\n";
371 Str << "\t.align\t" << typeWidthInBytes(getPointerType()) << "\n";
372 Str << InstJumpTable::makeName(JT.getFunctionName(), JT.getId()) << ":";
373
374 // On X8664 ILP32 pointers are 32-bit hence the use of .long
375 for (intptr_t TargetOffset : JT.getTargetOffsets())
376 Str << "\n\t.long\t" << JT.getFunctionName() << "+" << TargetOffset;
377 Str << "\n";
378 }
379 } break;
380 }
381 }
382
84 namespace { 383 namespace {
85 template <typename T> struct PoolTypeConverter {}; 384 template <typename T> struct PoolTypeConverter {};
86 385
87 template <> struct PoolTypeConverter<float> { 386 template <> struct PoolTypeConverter<float> {
88 typedef uint32_t PrimitiveIntType; 387 typedef uint32_t PrimitiveIntType;
89 typedef ConstantFloat IceType; 388 typedef ConstantFloat IceType;
90 static const Type Ty = IceType_f32; 389 static const Type Ty = IceType_f32;
91 static const char *TypeName; 390 static const char *TypeName;
92 static const char *AsmTag; 391 static const char *AsmTag;
93 static const char *PrintfString; 392 static const char *PrintfString;
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
212 emitConstantPool<PoolTypeConverter<uint8_t>>(Ctx); 511 emitConstantPool<PoolTypeConverter<uint8_t>>(Ctx);
213 emitConstantPool<PoolTypeConverter<uint16_t>>(Ctx); 512 emitConstantPool<PoolTypeConverter<uint16_t>>(Ctx);
214 emitConstantPool<PoolTypeConverter<uint32_t>>(Ctx); 513 emitConstantPool<PoolTypeConverter<uint32_t>>(Ctx);
215 514
216 emitConstantPool<PoolTypeConverter<float>>(Ctx); 515 emitConstantPool<PoolTypeConverter<float>>(Ctx);
217 emitConstantPool<PoolTypeConverter<double>>(Ctx); 516 emitConstantPool<PoolTypeConverter<double>>(Ctx);
218 } break; 517 } break;
219 } 518 }
220 } 519 }
221 520
222 void TargetX8664::emitJumpTable(const Cfg *Func,
223 const InstJumpTable *JumpTable) const {
224 if (!BuildDefs::dump())
225 return;
226 Ostream &Str = Ctx->getStrEmit();
227 IceString MangledName = Ctx->mangleName(Func->getFunctionName());
228 Str << "\t.section\t.rodata." << MangledName
229 << "$jumptable,\"a\",@progbits\n";
230 Str << "\t.align\t" << typeWidthInBytes(getPointerType()) << "\n";
231 Str << InstJumpTable::makeName(MangledName, JumpTable->getId()) << ":";
232
233 // On X8664 ILP32 pointers are 32-bit hence the use of .long
234 for (SizeT I = 0; I < JumpTable->getNumTargets(); ++I)
235 Str << "\n\t.long\t" << JumpTable->getTarget(I)->getAsmName();
236 Str << "\n";
237 }
238
239 void TargetDataX8664::lowerJumpTables() {
240 switch (Ctx->getFlags().getOutFileType()) {
241 case FT_Elf: {
242 ELFObjectWriter *Writer = Ctx->getObjectWriter();
243 for (const JumpTableData &JumpTable : *Ctx->getJumpTables())
244 // TODO(jpp): not 386.
245 Writer->writeJumpTable(JumpTable, llvm::ELF::R_386_32);
246 } break;
247 case FT_Asm:
248 // Already emitted from Cfg
249 break;
250 case FT_Iasm: {
251 if (!BuildDefs::dump())
252 return;
253 Ostream &Str = Ctx->getStrEmit();
254 for (const JumpTableData &JT : *Ctx->getJumpTables()) {
255 Str << "\t.section\t.rodata." << JT.getFunctionName()
256 << "$jumptable,\"a\",@progbits\n";
257 Str << "\t.align\t" << typeWidthInBytes(getPointerType()) << "\n";
258 Str << InstJumpTable::makeName(JT.getFunctionName(), JT.getId()) << ":";
259
260 // On X8664 ILP32 pointers are 32-bit hence the use of .long
261 for (intptr_t TargetOffset : JT.getTargetOffsets())
262 Str << "\n\t.long\t" << JT.getFunctionName() << "+" << TargetOffset;
263 Str << "\n";
264 }
265 } break;
266 }
267 }
268
269 void TargetDataX8664::lowerGlobals(const VariableDeclarationList &Vars, 521 void TargetDataX8664::lowerGlobals(const VariableDeclarationList &Vars,
270 const IceString &SectionSuffix) { 522 const IceString &SectionSuffix) {
271 switch (Ctx->getFlags().getOutFileType()) { 523 switch (Ctx->getFlags().getOutFileType()) {
272 case FT_Elf: { 524 case FT_Elf: {
273 ELFObjectWriter *Writer = Ctx->getObjectWriter(); 525 ELFObjectWriter *Writer = Ctx->getObjectWriter();
274 // TODO(jpp): not 386. 526 // TODO(jpp): not 386.
275 Writer->writeDataSection(Vars, llvm::ELF::R_386_32, SectionSuffix); 527 Writer->writeDataSection(Vars, llvm::ELF::R_386_32, SectionSuffix);
276 } break; 528 } break;
277 case FT_Asm: 529 case FT_Asm:
278 case FT_Iasm: { 530 case FT_Iasm: {
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
389 // entries in case the high-level table has extra entries. 641 // entries in case the high-level table has extra entries.
390 #define X(tag, sizeLog2, align, elts, elty, str) \ 642 #define X(tag, sizeLog2, align, elts, elty, str) \
391 static_assert(_table1_##tag == _table2_##tag, \ 643 static_assert(_table1_##tag == _table2_##tag, \
392 "Inconsistency between ICETYPEX8664_TABLE and ICETYPE_TABLE"); 644 "Inconsistency between ICETYPEX8664_TABLE and ICETYPE_TABLE");
393 ICETYPE_TABLE 645 ICETYPE_TABLE
394 #undef X 646 #undef X
395 } // end of namespace dummy3 647 } // end of namespace dummy3
396 } // end of anonymous namespace 648 } // end of anonymous namespace
397 649
398 } // end of namespace Ice 650 } // end of namespace Ice
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698