# build.tcl --
#
#	Implementations of the quadcodes in LLVM IR. Most all of these
#	quadcode implementations are issued as calls to mandatory-inline
#	functions (defined in stdlib.tcl) so that they can inject extra basic
#	blocks without disturbing the analysis from the reasoning engine.
#
# Copyright (c) 2014-2016 by Donal K. Fellows
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
#------------------------------------------------------------------------------

oo::define Builder {
    # Builder:isInt32 --
    #
    #	Generate code to test if an INT holds an int32.
    #
    # Parameters:
    #	INT -	The INT LLVM value reference.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A boolean (int1) LLVM value reference.

    method isInt32 {INT {name ""}} {
	my eq [my extract $INT INT.kind] \
	    [Const ${::LLVM::INT.type.32bit} int1] $name
    }

    # Builder:isNumericInt --
    #
    #	Generate code to test if a NUMERIC holds an INT.
    #
    # Parameters:
    #	NUMERIC -
    #		The NUMERIC LLVM value reference.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A boolean (int1) LLVM value reference.

    method isNumericInt {NUMERIC {name ""}} {
	my eq [my extract $NUMERIC NUMERIC.kind] \
	    [Const ${::LLVM::NUMERIC.type.int} int1] $name
    }

    # Builder:packInt32 --
    #
    #	Generate code to convert an int32 to an INT.
    #
    # Parameters:
    #	value -	The 32-bit integer LLVM value reference.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	The INT LLVM value reference.

    method packInt32 {value {name ""}} {
	my insert [my insert [my undef INT] \
		[Const ${::LLVM::INT.type.32bit} int1] INT.kind] \
	    $value INT.i32 $name
    }

    # Builder:packInt64 --
    #
    #	Generate code to convert an int64 to an INT.
    #
    # Parameters:
    #	value -	The 64-bit integer LLVM value reference.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	The INT LLVM value reference.

    method packInt64 {value {name ""}} {
	my insert [my insert [my undef INT] \
		[Const ${::LLVM::INT.type.64bit} int1] INT.kind] \
	    $value INT.i64 $name
    }

    # Builder:packNumericInt --
    #
    #	Generate code to convert an INT to a NUMERIC.
    #
    # Parameters:
    #	value -	The INT LLVM value reference.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	The NUMERIC LLVM value reference.

    method packNumericInt {value {name ""}} {
	my insert [my insert [my undef NUMERIC] \
		[Const ${::LLVM::NUMERIC.type.int} int1] NUMERIC.kind] \
	    $value NUMERIC.int $name
    }

    # Builder:packNumericDouble --
    #
    #	Generate code to convert a DOUBLE to a NUMERIC.
    #
    # Parameters:
    #	value -	The DOUBLE LLVM value reference.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	The NUMERIC LLVM value reference.

    method packNumericDouble {value {name ""}} {
	my insert [my insert [my undef NUMERIC] \
		[Const ${::LLVM::NUMERIC.type.double} int1] NUMERIC.kind] \
	    $value NUMERIC.double $name
    }

    # Builder:int.32 --
    #
    #	Generate code to extract the int32 from an INT. Caller MUST guarantee
    #	that the size was tested for first.
    #
    # Parameters:
    #	INT -	The INT LLVM value reference.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An int32 LLVM value reference.

    method int.32 {INT {name ""}} {
	my extract $INT INT.i32 $name
    }

    # Builder:int.64 --
    #
    #	Generate code to extract the int64 from an INT. Caller MUST guarantee
    #	that the size was tested for first.
    #
    # Parameters:
    #	INT -	The INT LLVM value reference.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An int64 LLVM value reference.

    method int.64 {INT {name ""}} {
	my extract $INT INT.i64 $name
    }

    # Builder:numeric.int --
    #
    #	Generate code to extract the INT from a NUMERIC. Caller MUST guarantee
    #	that the kind was tested for first.
    #
    # Parameters:
    #	NUMERIC -
    #		The NUMERIC LLVM value reference.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An INT LLVM value reference.

    method numeric.int {NUMERIC {name ""}} {
	my extract $NUMERIC NUMERIC.int $name
    }

    # Builder:numeric.double --
    #
    #	Generate code to extract the DOUBLE from a NUMERIC. Caller MUST
    #	guarantee that the kind was tested for first.
    #
    # Parameters:
    #	NUMERIC -
    #		The NUMERIC LLVM value reference.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A DOUBLE LLVM value reference.

    method numeric.double {NUMERIC {name ""}} {
	my extract $NUMERIC NUMERIC.double $name
    }

    # Builder:NumToDbl --
    #
    #	Generate code to convert a NUMERIC to a DOUBLE. The value inside the
    #	NUMERIC might be INT or DOUBLE; this handles both cases.
    #
    # Parameters:
    #	value -	The NUMERIC LLVM value reference.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A DOUBLE LLVM value reference.

    method NumToDbl {value {name ""}} {
	my select [my isNumericInt $value] \
	    [my cast(DOUBLE) [my numeric.int $value]] \
	    [my numeric.double $value] $name
    }

    # Builder:in32range --
    #
    #	Generate code to test if an int64 value will fit exactly in an int32.
    #
    # Parameters:
    #	int -	The int64 LLVM value reference.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A boolean (int1) LLVM value reference.

    method in32range {int {name ""}} {
	my and [my ge $int [Const -0x80000000 int64]] \
	    [my le $int [Const 0x7fffffff int64]] $name
    }

    # Builder:fieldtostruct --
    #
    #	Given a pointer to a field in a structure and a specification of which
    #	type and field it is, return a pointer to the overall structure
    #	containing that field. Note that this does not require dereferencing
    #	the field pointer.
    #
    # Parameters:
    #	fieldPtr -
    #		The pointer LLVM value reference to the field.
    #	type -	The LLVM type of the structure.
    #	fieldname -
    #		The name of the field within the structure.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A pointer LLVM value reference to the structure.

    method fieldtostruct {fieldPtr type fieldname {name ""}} {
	set off [my neg [my offsetof $type $fieldname]]
	set ptr [my cast(ptr) $fieldPtr char]
	return [my cast(ptr) [my getelementptr $ptr $off] $type $name]
    }

    # Builder:frame.pack --
    #
    #	Combine a callframe with another value.
    #
    # Parameters:
    #	callframe -
    #		The CALLFRAME LLVM value reference.
    #	value -	The INT LLVM value reference for the non-callframe value.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A CALLFRAME-value tuple LLVM value reference.

    method frame.pack {callframe value {name ""}} {
	set type [Type struct{CALLFRAME,[TypeOf $value]}]
	my insert [my insert [my undef $type] $callframe 0] $value 1 $name
    }

    # Builder:frame.frame --
    #
    #	Extract the callframe from a tupled value.
    #
    # Parameters:
    #	callframetuple -
    #		The CALLFRAME-tuple LLVM value reference.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A CALLFRAME LLVM value reference.

    method frame.frame {callframetuple {name ""}} {
	my extract $callframetuple 0 $name
    }

    # Builder:frame.value --
    #
    #	Extract the non-callframe value from a tuple.
    #
    # Parameters:
    #	callframetuple -
    #		The CALLFRAME-tuple LLVM value reference.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An LLVM value reference.

    method frame.value {callframetuple {name ""}} {
	my extract $callframetuple 1 $name
    }

    # Builder:frame.create --
    #
    #	Create and initialise a callframe.
    #
    # Parameters:
    #	varlist -
    #		The Tcl list of information about the callframe's variables
    #		extracted from the bytecode.
    #	argc -	The int LLVM value reference for the number of arguments.
    #	argv -	The STRING* LLVM value reference (or equivalent type) for the
    #		array of arguments, allocated on the function stack.
    #	proc -	The LLVM value reference to the procedure's metadata.
    #	localcache -
    #		The LLVM value reference to the procedure's local variable
    #		metadata.
    #
    # Results:
    #	A Tcl list of the LLVM CALLFRAME value reference and the mapping
    #	dictionary from string variable names to the corresponding LLVM Var*
    #	value references.

    method frame.create {varlist argc argv proc localcache} {
	# Construct the call frame itself
	set callframe [my alloc CallFrame "callframe"]
	set length [Const [llength $varlist]]
	set locals [my arrayAlloc Var $length]
	my Call tcl.callframe.init $callframe $length \
	    $argc [my cast(ptr) $argv STRING] $proc $localcache $locals
	# Initialise the information about the local variables
	set idx -1
	set varmap {}
	foreach varinfo $varlist {
	    lassign $varinfo flags var
	    set flagbits 0
	    set FLAGS {
		scalar 0x0 array 0x1 link 0x2
		arg 0x100 temp 0x200 args 0x400
		resolved 0x8000
	    }
	    foreach bit $flags {
		incr flagbits [dict get $FLAGS $bit]
	    }
	    set v [my Call tcl.callframe.makevar $callframe \
		       [Const [incr idx] int] [Const $flagbits int]]
	    dict set varmap $var $v
	}
	return [list $callframe $varmap]
    }

    # Builder:frame.release --
    #
    #	Delete the contents of a call frame.
    #
    # Parameters:
    #	callframe -
    #		The CALLFRAME LLVM value reference.
    #	synthetics -
    #		A Tcl list of booleans saying which values in the callframe's
    #		argv array need to have their reference counts decremented
    #		because they are synthetic.
    #
    # Results:
    #	None.

    method frame.release {callframe synthetics} {
	set idx -1
	foreach drop $synthetics {
	    incr idx
	    if {$drop} {
		if {![info exist objv]} {
		    set objv [my dereference $callframe 0 CallFrame.objv]
		}
		set obj [my dereference $objv $idx]
		my dropReference(STRING) $obj
	    }
	}
	my Call tcl.callframe.clear $callframe
	return
    }

    # Builder:frame.store(STRING) --
    #
    #	Transfer a value into a call frame variable.
    #
    # Parameters:
    #	value -	The LLVM value reference to go into the call frame's var.
    #	callframe -
    #		The CALLFRAME LLVM value reference.
    #	var -	The Var* LLVM reference for the variable to write to.
    #	varName -
    #		The Tcl string of the name of the variable.
    #
    # Results:
    #	None.

    method frame.store(STRING) {value callframe var varName} {
	my frame.store(NEXIST\040STRING) [my just $value] \
	    $callframe $var $varName
    }

    # Builder:frame.store(NEXIST STRING) --
    #
    #	Transfer a value into a call frame variable. A non-existing value will
    #	convert into an unsetting of the variable.
    #
    # Parameters:
    #	value -	The LLVM value reference to go into the call frame's var.
    #	callframe -
    #		The CALLFRAME LLVM value reference.
    #	var -	The Var* LLVM reference for the variable to write to.
    #	varName -
    #		The Tcl string of the name of the variable.
    #
    # Results:
    #	None.

    method frame.store(NEXIST\040STRING) {value callframe var varName} {
	my Call tcl.callframe.store $var [Const $varName STRING] $value
	return
    }

    # Builder:frame.store(NEXIST) --
    #
    #	Unset a variable in a call frame.
    #
    # Parameters:
    #	value -	The non-existing value to put in the variable.
    #	callframe -
    #		The CALLFRAME LLVM value reference.
    #	var -	The Var* LLVM reference for the variable to unset.
    #	varName -
    #		The Tcl string of the name of the variable.
    #
    # Results:
    #	None.

    method frame.store(NEXIST) {value callframe var varName} {
	my frame.unset $callframe $var $varName
    }

    # Builder:frame.unset --
    #
    #	Unset a variable in a call frame.
    #
    # Parameters:
    #	callframe -
    #		The CALLFRAME LLVM value reference.
    #	var -	The Var* LLVM reference for the variable to unset.
    #	varName -
    #		The Tcl string of the name of the variable.
    #
    # Results:
    #	None.

    method frame.unset {callframe var varName} {
	my frame.store(NEXIST\040STRING) [my nothing STRING] \
	    $callframe $var $varName
    }

    # Builder:frame.load --
    #
    #	Read a value from a variable in a call frame. Only variables in the
    #	call frame may be read or writen with this method call.
    #
    # Parameters:
    #	callframe -
    #		The CALLFRAME LLVM value reference.
    #	var -	The Var* LLVM reference for the variable to read.
    #	varName -
    #		The Tcl string of the name of the variable.
    #	name (optional) -
    #		The LLVM name of the result value.
    #
    # Results:
    #	An LLVM STRING? value reference.

    method frame.load {callframe var varName {name ""}} {
	my call ${tcl.callframe.load} [list $var [Const $varName STRING]] \
	    $name
    }

    # Builder:frame.bind.nsvar(STRING,STRING,STRING) --
    #
    #	Link a variable in the local call frame to a variable looked up in a
    #	given named namespace.
    #
    # Parameters:
    #	localName -
    #		An LLVM STRING reference to the local variable name.
    #	nsName -
    #		An LLVM STRING reference to the namespace name.
    #	otherName -
    #		An LLVM STRING reference to the name of the variable in the
    #		namespace to link to.
    #	localVar -
    #		An LLVM Var* reference to the local variable.
    #	callframe -
    #		The CALLFRAME LLVM value reference.
    #	ec -	An int* LLVM reference for where to write error codes into.
    #	name (optional) -
    #		The LLVM name of the result value.
    #
    # Results:
    #	An LLVM bool? value reference.

    method frame.bind.nsvar(STRING,STRING,STRING) {
	    localName nsName otherName localVar callframe ec {name ""}} {
	set otherVar [my call ${tcl.callframe.lookup.varns} [list \
		$callframe $nsName $otherName] "otherVar"]
	set val [my Call tcl.callframe.bindvar $callframe \
		     $otherVar $localVar $localName $ec]
	return [my frame.pack $callframe $val $name]
    }

    # Builder:frame.bind.var(STRING,STRING) --
    #
    #	Link a variable in the local call frame to a variable looked up with
    #	general respect to the call frame's context.
    #
    # Parameters:
    #	localName -
    #		An LLVM STRING reference to the local variable name.
    #	otherName -
    #		An LLVM STRING reference to the name of the variable to link
    #		to.
    #	localVar -
    #		An LLVM Var* reference to the local variable.
    #	callframe -
    #		The CALLFRAME LLVM value reference.
    #	ec -	An int* LLVM reference for where to write error codes into.
    #	name (optional) -
    #		The LLVM name of the result value.
    #
    # Results:
    #	An LLVM bool? value reference.

    method frame.bind.var(STRING,STRING) {
	    localName otherName localVar callframe ec {name ""}} {
	set otherVar [my call ${tcl.callframe.lookup.var} [list \
		$callframe $otherName] "otherVar"]
	set val [my call ${tcl.callframe.bindvar} [list \
		$callframe $otherVar $localVar $localName $ec] $name]
	return [my frame.pack $callframe $val $name]
    }

    # Builder:frame.bind.nsvar(STRING,STRING,STRING) --
    #
    #	Link a variable in the local call frame to a variable looked up in an
    #	indicated call frame.
    #
    # Parameters:
    #	localName -
    #		An LLVM STRING reference to the local variable name.
    #	level -	An LLVM STRING reference to the level descriptor.
    #	otherName -
    #		An LLVM STRING reference to the name of the variable in the
    #		namespace to link to.
    #	localVar -
    #		An LLVM Var* reference to the local variable.
    #	callframe -
    #		The CALLFRAME LLVM value reference.
    #	ec -	An int* LLVM reference for where to write error codes into.
    #	name (optional) -
    #		The LLVM name of the result value.
    #
    # Results:
    #	An LLVM bool? value reference.

    method frame.bind.upvar(STRING,STRING,STRING) {
	    localName level otherName localVar callframe ec {name ""}} {
	set otherVar [my call ${tcl.callframe.lookup.upvar} [list \
		$callframe $level $otherName] "otherVar"]
	set val [my call ${tcl.callframe.bindvar} [list \
		$callframe $otherVar $localVar $localName $ec] $name]
	return [my frame.pack $callframe $val $name]
    }

    # Builder:add(INT,INT) --
    #
    #	Generate code to add two INTs. Quadcode implementation ('add').
    #
    # Parameters:
    #	left -	The INT LLVM value reference for the left operand.
    #	right -	The INT LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An INT LLVM value reference.

    method add(INT,INT) {left right {name ""}} {
	my call ${tcl.add} [list $left $right] $name
    }

    # Builder:add(DOUBLE,DOUBLE) --
    #
    #	Generate code to add two DOUBLEs. Quadcode implementation ('add').
    #
    # Parameters:
    #	left -	The DOUBLE LLVM value reference for the left operand.
    #	right -	The DOUBLE LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A DOUBLE LLVM value reference.

    method add(DOUBLE,DOUBLE) {left right {name ""}} {
	my add $left $right $name
    }

    # Builder:add(DOUBLE,NUMERIC) --
    #
    #	Generate code to add a DOUBLE and a NUMERIC. Quadcode implementation
    #	('add').
    #
    # Parameters:
    #	left -	The DOUBLE LLVM value reference for the left operand.
    #	right -	The NUMERIC LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A DOUBLE LLVM value reference.

    method add(DOUBLE,NUMERIC) {left right {name ""}} {
	my add(DOUBLE,DOUBLE) $left [my NumToDbl $right] $name
    }

    # Builder:add(NUMERIC,DOUBLE) --
    #
    #	Generate code to add a NUMERIC and a DOUBLE. Quadcode implementation
    #	('add').
    #
    # Parameters:
    #	left -	The NUMERIC LLVM value reference for the left operand.
    #	right -	The DOUBLE LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A DOUBLE LLVM value reference.

    method add(NUMERIC,DOUBLE) {left right {name ""}} {
	my add(DOUBLE,DOUBLE) [my NumToDbl $left] $right $name
    }

    # Builder:add(INT,NUMERIC) --
    #
    #	Generate code to add an INT and a NUMERIC. Quadcode implementation
    #	('add').
    #
    # Parameters:
    #	left -	The INT LLVM value reference for the left operand.
    #	right -	The NUMERIC LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A NUMERIC LLVM value reference.

    method add(INT,NUMERIC) {left right {name ""}} {
	my add(NUMERIC,NUMERIC) [my packNumericInt $left] $right $name
    }

    # Builder:add(NUMERIC,INT) --
    #
    #	Generate code to add a NUMERIC and an INT. Quadcode implementation
    #	('add').
    #
    # Parameters:
    #	left -	The NUMERIC LLVM value reference for the left operand.
    #	right -	The INT LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A NUMERIC LLVM value reference.

    method add(NUMERIC,INT) {left right {name ""}} {
	my add(NUMERIC,NUMERIC) $left [my packNumericInt $right] $name
    }

    # Builder:add(NUMERIC,NUMERIC) --
    #
    #	Generate code to add two NUMERICs. Quadcode implementation ('add').
    #
    # Parameters:
    #	left -	The NUMERIC LLVM value reference for the left operand.
    #	right -	The NUMERIC LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A NUMERIC LLVM value reference.

    method add(NUMERIC,NUMERIC) {left right {name ""}} {
	my call ${tcl.add.numeric} [list $left $right] $name
    }

    # Builder:addReference(STRING) --
    #
    #	Generate code to increment the reference count of a value.
    #
    # Parameters:
    #	value -	The STRING/etc. LLVM value reference for the operand.
    #
    # Results:
    #	None.

    method addReference(STRING) {value} {
	my Call tcl.addReference $value
	return
    }

    # Builder:addReference(EMPTY) --
    #
    #	Generate code to increment the reference count of a value.
    #
    # Parameters:
    #	value -	The STRING/etc. LLVM value reference for the operand.
    #
    # Results:
    #	None.

    method addReference(EMPTY) {value} {
	my Call tcl.addReference $value
	return
    }

    # Builder:addReference(NEXIST STRING) --
    #
    #	Generate code to increment the reference count of a value.
    #
    # Parameters:
    #	value -	The STRING/etc. LLVM value reference for the operand.
    #
    # Results:
    #	None.

    method addReference(NEXIST\040STRING) {value} {
	my Call tcl.addNExistReference $value
	return
    }

    # Builder:addReference(FAIL STRING) --
    #
    #	Generate code to increment the reference count of a value.
    #
    # Parameters:
    #	value -	The STRING/etc. LLVM value reference for the operand.
    #
    # Results:
    #	None.

    method addReference(FAIL\040STRING) {value} {
	my Call tcl.addFailReference $value
	return
    }

    # Builder:addReference(NEXIST EMPTY) --
    #
    #	Generate code to increment the reference count of a value.
    #
    # Parameters:
    #	value -	The STRING/etc. LLVM value reference for the operand.
    #
    # Results:
    #	None.

    method addReference(NEXIST\040EMPTY) {value} {
	my Call tcl.addNExistReference $value
	return
    }

    # Builder:addReference(FAIL EMPTY) --
    #
    #	Generate code to increment the reference count of a value.
    #
    # Parameters:
    #	value -	The STRING/etc. LLVM value reference for the operand.
    #
    # Results:
    #	None.

    method addReference(FAIL\040EMPTY) {value} {
	my Call tcl.addFailReference $value
	return
    }

    # Builder:addReference(DICTITER) --
    #
    #	Generate code to increment the reference count of a DICTITER value.
    #
    # Parameters:
    #	value -	The DICTITER LLVM value reference for the operand.
    #
    # Results:
    #	None.

    method addReference(DICTITER) {value} {
	my call ${tcl.dict.addIterReference} [list $value] ""
	return
    }

    # Builder:addReference(FAIL DICTITER) --
    #
    #	Generate code to increment the reference count of a FAIL DICTITER value.
    #
    # Parameters:
    #	value -	The DICTITER LLVM value reference for the operand.
    #
    # Results:
    #	None.

    method addReference(FAIL\040DICTITER) {value} {
	my Call tcl.dict.addIterFailReference $value
    }

    # Builder:appendString --
    #
    #	Append a string value to a working buffer. The working buffer is
    #	assumed to be an UNSHARED Tcl_Obj reference; caller must ensure this,
    #	and the quadcode stream does not provide this guarantee. See also the
    #	unshare(STRING) and unshareCopy(STRING) methods.
    #
    #	Part of the 'strcat' quadcode implementation.
    #
    # Parameters:
    #	value -	The string to append. Note that this comes first as it
    #		participates in the type system.
    #	buffer -
    #		The buffer (an unshared Tcl_Obj reference) to append to.
    #
    # Results:
    #	None.

    method appendString(STRING) {value buffer} {
	my Call tcl.append.string $buffer $value
	return
    }

    # Builder:assume --
    #
    #	Generate code to tell LLVM that a particular boolean expression is
    #	true. Used to optimize reference count management, among other things.
    #
    # Parameters:
    #	fact -	The int1 LLVM value reference for the fact that is being told
    #		to the LLVM engine.
    #
    # Results:
    #	None.

    method assume {fact} {
	catch {
	    if {![info exist ::env(NOASSERTS)]} {
		my Call [$m intrinsic assume] $fact
	    }
	}
	return
    }

    # Builder:bitand(INT,INT) --
    #
    #	Generate code to create the bitwise-and of two INTs. Quadcode
    #	implementation ('bitand').
    #
    # Parameters:
    #	left -	The INT LLVM value reference for the left operand.
    #	right -	The INT LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An INT LLVM value reference.

    method bitand(INT,INT) {left right {name ""}} {
	my call ${tcl.and} [list $left $right] $name
    }

    # Builder:bitnot(INT) --
    #
    #	Generate code to create the bitwise-not of an INT. Quadcode
    #	implementation ('bitnot').
    #
    # Parameters:
    #	value -	The INT LLVM value reference for the operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An INT LLVM value reference.

    method bitnot(INT) {value {name ""}} {
	my call ${tcl.not} [list $value] $name
    }

    # Builder:bitor(INT,INT) --
    #
    #	Generate code to create the bitwise-or of two INTs. Quadcode
    #	implementation ('bitor').
    #
    # Parameters:
    #	left -	The INT LLVM value reference for the left operand.
    #	right -	The INT LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An INT LLVM value reference.

    method bitor(INT,INT) {left right {name ""}} {
	my call ${tcl.or} [list $left $right] $name
    }

    # Builder:bitxor(INT,INT) --
    #
    #	Generate code to create the bitwise exclusive-or of two INTs.
    #	Quadcode implementation ('bitxor').
    #
    # Parameters:
    #	left -	The INT LLVM value reference for the left operand.
    #	right -	The INT LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An INT LLVM value reference.

    method bitxor(INT,INT) {left right {name ""}} {
	my call ${tcl.xor} [list $left $right] $name
    }

    # Builder:foreachStart --
    #
    #	Apply the runtime checks that what we are iterating over are lists,
    #	and compute the maximum number of iterations that we might use.
    #	Quadcode implementation ('foreachStart').
    #
    # Parameters:
    #	assignPattern -
    #		A Tcl list of lists of indices into the local variable table,
    #		extracted from the original foreach auxiliary data. Note that
    #		this code just uses the list structure; the actual values are
    #		ignored.
    #	lists -	The Tcl lists to iterate over, as LLVM package of STRING
    #		values (i.e., the same as with an [lset] index path or a [dict
    #		set] key path).
    #	ecvar -	Location to write the Tcl return code into, as an LLVM int*
    #		reference.
    #
    # Results:
    #	The runtime state value, as an LLVM FOREACH FAIL value. This will have
    #	the name "pair" associated with it.

    method foreachStart {assignPattern lists ecvar} {
	set stack [my Call [$m intrinsic stacksave]]
	set lengths [my arrayAlloc int [Const [llength $assignPattern]] "lengths"]
	set idx 0
	foreach sublist $assignPattern {
	    my store [Const [llength $sublist]] [my gep $lengths $idx]
	    incr idx
	}
	set len [my extract $lists 0]
	set ary [my cast(ptr) [my extract $lists 1] STRING]
	set result [my call ${tcl.list.foreach.start} \
		[list $len $lengths $ary $ecvar] "pair"]
	my Call [$m intrinsic stackrestore] $stack
	return $result
    }

    # Builder:unshareList --
    #
    #	Convert a list into an unshared pure-list form. The list must have
    #	already been checked for validity; this opcode does not bother to
    #	check. Quadcode implementation ('unshareList').
    #
    # Parameters:
    #	list -	A Tcl list to be unshared, as LLVM STRING value.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	The runtime state value, as an LLVM FOREACH FAIL value. This will have
    #	the name "pair" associated with it.

    method unshareList {list {name ""}} {
	my call ${tcl.list.unshare} [list $list] $name
    }

    # Builder:foreachIter --
    #
    #	Get the iteration number from a FOREACH state. Quadcode implementation
    #	('foreachIter').
    #
    # Parameters:
    #	pair -	An iteration state, as an LLVM FOREACH value.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	The iteration number, as an LLVM INT value.

    method foreachIter {pair {name ""}} {
	my call ${tcl.list.foreach.getStep} [list $pair] $name
    }

    # Builder:foreachAdvance --
    #
    #	Get the next a FOREACH state after the current one. Quadcode
    #	implementation ('foreachAdvance').
    #
    # Parameters:
    #	pair -	An iteration state, as an LLVM FOREACH value.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A new iteration state, as an LLVM FOREACH value.

    method foreachAdvance {pair {name ""}} {
	my call ${tcl.list.foreach.nextStep} [list $pair] $name
    }

    # Builder:foreachMayStep --
    #
    #	Get whether the maximum iteration number has been reached from a
    #	FOREACH state. Quadcode implementation ('foreachMayStep').
    #
    # Parameters:
    #	pair -	An iteration state, as an LLVM FOREACH value.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	The flag to use in a conditional jump, as an LLVM ZEROONE value.

    method foreachMayStep {pair {name ""}} {
	my call ${tcl.list.foreach.mayStep} [list $pair] $name
    }

    # Builder:IsVectorItemConstant --
    #
    #	Determine if an element of a vector is a constant STRING and so does
    #	not need to have its reference count managed during construction of
    #	the vector.
    #
    # Parameters:
    #   value -	The tclquadcode value being considered.
    #	type -	The tclquadcode type of the value.
    #
    # Results:
    #	Tcl boolean.

    method IsVectorItemConstant {value type} {
	expr {[lindex $value 0] eq "literal" && $type eq "STRING"}
    }

    # Builder:buildVector --
    #
    #	Create a vector value that can be used with variadic operations such
    #	as where a multi-element dictionary path is required. This value
    #	*MUST* be cleaned up after use with clearVector.
    #
    #	The vector "type" is special, as it is actually a family of related
    #	types. It *must* not be passed directly to a function, as it isn't a
    #	fixed type and causes confusion. It exists to efficiently assemble a
    #	group of (STRING-typed) arguments into an array and length.
    #
    # Parameters:
    #	types -	The types of the values used to build the vector, as a Tcl
    #		list of type descriptors.
    #	values -
    #		Tcl list of LLVM value references that are the individual
    #		elements of the vector.
    #
    # Results:
    #	LLVM vector value reference.

    method buildVector {types values} {
	# Implementation note: there must be no branches in the issued code.
	set arraytype [Type array{STRING,[llength $values]}]
	set vectortype [Type struct{int,$arraytype*,void*}]
	set stack [my call [$m intrinsic stacksave] {} "SP"]
	set ary [my alloc $arraytype]
	set idx -1
	foreach src $values t $types {
	    set s [my stringify($t) $src]
	    set cell [my gep $ary 0 [incr idx]]
	    my store $s $cell
	    if {![my IsVectorItemConstant $src $t]} {
		my addReference(STRING) $s
	    }
	}
	set vector [my undef $vectortype]
	set vector [my insert $vector [Const [llength $values]] 0]
	set vector [my insert $vector $ary 1]
	set vector [my insert $vector $stack 2]
	return $vector
    }

    # Builder:ExtractVector --
    #
    #	Extract the length and array of STRINGs from a vector.
    #
    # Parameters:
    #	vector -
    #		The LLVM vector value created by 'buildVector'.
    #	lenVar (optional) -
    #		The variable in the caller to store the length in. Defaults to
    #		'len'.
    #	aryVar (optional) -
    #		The variable in the caller to store the array pointer in.
    #		Defaults to 'ary'.
    #
    # Results:
    #	None.

    method ExtractVector {vector {lenVar len} {aryVar ary}} {
	upvar 1 $lenVar len $aryVar ary
	set len [my extract $vector 0]
	set ary [my cast(ptr) [my extract $vector 1] STRING]
	return
    }

    # Builder:Call --
    #
    #	Generate code to call a function. Note that the function might be an
    #	inlining candidate, and might be a candidate for being tail-called.
    #	This is a wrapper round the Builder:call method to make it easier to
    #	use in the common case where no name is given to the result.
    #
    # Parameters:
    #	function -
    #		The LLVM value reference to the function. Note that this is
    #		NOT the wrapped reference.
    #	args... -
    #		The LLVM value references to pass as arguments to the
    #		function. These *must* match the argument types of the
    #		function.
    #
    # Results:
    #	An LLVM value reference if the function returns anything. The type
    #	depends on what the function returns.

    method Call {function args} {
	if {![string match LLVMValueRef* $function]} {
	    upvar 1 $function var
	    set function $var
	}
	my call $function $args ""
    }

    # Builder:cast(BOOLEAN) --
    #
    #	Generate code to cast an int1 to an INT.
    #
    # Parameters:
    #	value -	The int1 LLVM value reference.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An INT LLVM value reference.

    method cast(BOOLEAN) {value {name ""}} {
	if {$::tcl_platform(wordSize) == 4} {
	    my packInt32 [my castUInt2Int $value int $name]
	} else {
	    my packInt64 [my castUInt2Int $value int64 $name]
	}
    }

    # Builder:cast(DOUBLE) --
    #
    #	Generate code to cast an INT or a NUMERIC to a DOUBLE.
    #
    # Parameters:
    #	value -	The INT or NUMERIC LLVM value reference.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A DOUBLE LLVM value reference.

    method cast(DOUBLE) {value {name ""}} {
	if {[TypeOf $value] eq [Type INT]} {
	    my castInt2Dbl [my getInt64 $value] $name
	} else {
	    my select [my isNumericInt $value] \
		[my castInt2Dbl [my getInt64 [my numeric.int $value]]] \
		[my numeric.double $value] $name
	}
    }

    # Builder:cast(INT) --
    #
    #	Generate code to cast a DOUBLE to an INT.
    #
    # Parameters:
    #	value -	The DOUBLE LLVM value reference.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An INT LLVM value reference.

    method cast(INT) {value {name ""}} {
	set val [my castDbl2Int $value int64 ""]
	if {$::tcl_platform(wordSize) == 4} {
	    my select [my in32range $val] \
		[my packInt32 [my cast(int) $val]] [my packInt64 $val] \
		$name
	} else {
	    my packInt64 $val $name
	}
    }

    # Builder:cast(INT?) --
    #
    #	Generate code to cast an int32 or int64 to an INT?.
    #
    # Parameters:
    #	value -	The int32 or int64 LLVM value reference.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An INT FAIL LLVM value reference (not a fail case).

    method cast(INT?) {value {name ""}} {
	if {[TypeOf $value] eq [Type int32]} {
	    set packer packInt32
	} else {
	    set packer packInt64
	}
	my ok [my $packer $value] $name
    }

    # Builder:cast(NUMERIC?) --
    #
    #	Generate code to cast an INT, DOUBLE, INT? or DOUBLE? to a NUMERIC?.
    #
    # Parameters:
    #	value -	The LLVM value reference. Must be of type INT, DOUBLE, INT? or
    #		DOUBLE? for this code to work.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A NUMERIC FAIL LLVM value reference.

    method cast(NUMERIC?) {value {name ""}} {
	set t [TypeOf $value]
	if {$t eq [Type DOUBLE]} {
	    return [my ok [my packNumericDouble $value]]
	} elseif {$t eq [Type INT]} {
	    return [my ok [my packNumericInt $value]]
	} elseif {$t eq [Type DOUBLE?]} {
	    set packer packNumericDouble
	} else {
	    set packer packNumericInt
	}
	my select [my maybe $value] [my fail NUMERIC] \
		[my ok [my $packer [my unmaybe $value]]] $name
    }

    # Builder:cast(bool) --
    #
    #	Generate code to cast an INT to an int1.
    #
    # Parameters:
    #	value -	The INT LLVM value reference.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An int1 LLVM value reference.

    method cast(bool) {value {name ""}} {
	my cmpInt [my getInt64 $value] NE [Const 0 int64] $name
    }

    # Builder:cast(int) --
    #
    #	Generate code to cast an arbitrary int[X] to an int32 by sign
    #	extension.
    #
    # Parameters:
    #	value -	The int[X] LLVM value reference. (X can be any integer width
    #		from 1 to 64.)
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An int32 LLVM value reference.

    method cast(int) {value {name ""}} {
	my castInt2Int $value int $name
    }

    # Builder:cast(int64) --
    #
    #	Generate code to cast an arbitrary int[X] to an int64 by sign
    #	extension.
    #
    # Parameters:
    #	value -	The int[X] LLVM value reference. (X can be any integer width
    #		from 1 to 64.)
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An int64 LLVM value reference.

    method cast(int64) {value {name ""}} {
	my castInt2Int $value int64 $name
    }

    # Builder:cast(ptr) --
    #
    #	Generate code to cast an arbitrary pointer to another pointer.
    #
    # Parameters:
    #	value -	The pointer LLVM value reference.
    #	type -	The type of value that the result pointer will point at.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A pointer LLVM value reference.

    method cast(ptr) {value type {name ""}} {
	my castPtr2Ptr $value $type* $name
    }

    # Builder:cast(ptr2int) --
    #
    #	Generate code to cast an arbitrary pointer to an integer.
    #
    # Parameters:
    #	value -	The pointer LLVM value reference.
    #	type -	The type of integer that the result will be.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An int[X] LLVM value reference.

    method cast(ptr2int) {value type {name ""}} {
	my castPtr2Int $value $type $name
    }

    # Builder:cast(ptr2ptr) --
    #
    #	Generate code to cast an arbitrary pointer to another pointer.
    #
    # Parameters:
    #	value -	The pointer LLVM value reference.
    #	llvmtype -
    #		The type of the result pointer.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A pointer LLVM value reference.

    method cast(ptr2ptr) {value llvmtype {name ""}} {
	my castPtr2Ptr $value $llvmtype $name
    }

    # Builder:cast(uint) --
    #
    #	Generate code to cast an arbitrary int[X] to an int32 by zero
    #	extension.
    #
    # Parameters:
    #	value -	The int[X] LLVM value reference. (X can be any integer width
    #		from 1 to 64.)
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An int32 LLVM value reference.

    method cast(uint) {value {name ""}} {
	my castUInt2Int $value int $name
    }

    # Builder:checkArithDomain.DOUBLE(STRING) --
    #
    #	Generate code to check if the given STRING contains something that can
    #	be parsed to get a DOUBLE, and set up an exception to throw if it is
    #	not. Quadcode implementation ('checkArithDomain').
    #
    # Parameters:
    #	value -	The STRING LLVM value reference to check.
    #	msg -	The exception message. Expected to be a Const STRING.
    #	exn -	The exception code. Expected to be a Const STRING.
    #	ec -	Memory location to write the Tcl error code if an exception is
    #		generated.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An int1 LLVM value reference.

    method checkArithDomain.DOUBLE(STRING) {value msg exn ec {name ""}} {
	my call ${tcl.checkDouble} [list $value $msg $exn $ec] $name
    }

    # Builder:checkArithDomain.INT(STRING) --
    #
    #	Generate code to check if the given STRING contains something that can
    #	be parsed to get an INT, and set up an exception to throw if it is
    #	not. Quadcode implementation ('checkArithDomain').
    #
    # Parameters:
    #	value -	The STRING LLVM value reference to check.
    #	msg -	The exception message. Expected to be a Const STRING.
    #	exn -	The exception code. Expected to be a Const STRING.
    #	ec -	Memory location to write the Tcl error code if an exception is
    #		generated.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An int1 LLVM value reference.

    method checkArithDomain.INT(STRING) {value msg exn ec {name ""}} {
	my call ${tcl.checkInteger} [list $value $msg $exn $ec] $name
    }
    method {checkArithDomain.IMPURE INT(STRING)} {value msg exn ec {name ""}} {
	my call ${tcl.checkInteger} [list $value $msg $exn $ec] $name
    }

    # Builder:checkArithDomain.NUMERIC(STRING) --
    #
    #	Generate code to check if the given STRING contains something that can
    #	be parsed to get a NUMERIC, and set up an exception to throw if it is
    #	not. Quadcode implementation ('checkArithDomain').
    #
    # Parameters:
    #	value -	The STRING LLVM value reference to check.
    #	msg -	The exception message. Expected to be a Const STRING.
    #	exn -	The exception code. Expected to be a Const STRING.
    #	ec -	Memory location to write the Tcl error code if an exception is
    #		generated.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An int1 LLVM value reference.

    method checkArithDomain.NUMERIC(STRING) {value msg exn ec {name ""}} {
	my call ${tcl.checkNumeric} [list $value $msg $exn $ec] $name
    }
    method {checkArithDomain.IMPURE NUMERIC(STRING)} {value msg exn ec 
						      {name ""}} {
	my call ${tcl.checkNumeric} [list $value $msg $exn $ec] $name
    }

    # Builder:clearVector --
    #
    #	Clean up a vector value created with buildVector.
    #
    # Parameters:
    #	srcs -	The quadcode values that the vector elements were built from.
    #		Used to detect direct literal STRINGs, which don't need
    #		free-ing.
    #	vector -
    #		The LLVM vector value reference.
    #	types -	The types of the values used to build the vector.
    #
    # Results:
    #	None.

    method clearVector {srcs vector types} {
	set idx -1
	set ary [my extract $vector 1]
	set stack [my extract $vector 2]
	foreach src $srcs t $types {
	    my dropReference [my load [my gep $ary 0 [incr idx]]]
	}
	my Call [$m intrinsic stackrestore] $stack
	return
    }

    # Builder:concat() --
    #
    #	Concatenate a collection of values using the classic Tcl algorithm.
    #	Quadcode implementation ('concat').
    #
    # Parameters:
    #	vector -
    #		The values to concatente as an LLVM vector value reference.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	The concatenated value as an LLVM value reference.

    method concat() {vector {name ""}} {
	my ExtractVector $vector
	my call ${tcl.concatenate} [list $len $ary] $name
    }

    # Builder:dictAppend(STRING,STRING,STRING) --
    #
    #	Append a value to a key in a dictionary. NOTE: this operation can fail
    #	(e.g., because it can be given an invalid dictionary) so it produces a
    #	STRING FAIL. Quadcode implementation ('dictAppend').
    #
    # Parameters:
    #	dict -	The dictionary as an LLVM value reference.
    #	key -	The key as an LLVM value reference.
    #	value -	The value to append as an LLVM value reference.
    #	ec -	Where to write the error code if an error happens.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	The resulting dictionary as an LLVM value reference, or a FAIL.

    method dictAppend(STRING,STRING,STRING) {dict key value ec {name ""}} {
	my call ${tcl.dict.append} [list $dict $key $value $ec] $name
    }

    # Builder:dictExists(STRING) --
    #
    #	Find whether a key exists in a dictionary. This version uses a vector
    #	of values for the key path. Quadcode implementation ('dictExists').
    #
    # Parameters:
    #	dict -	The dictionary as an LLVM value reference.
    #	vector -
    #		The key path as an LLVM vector value reference.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	Whether the value exists as an LLVM ZEROONE value reference.

    method dictExists(STRING) {dict vector {name ""}} {
	my ExtractVector $vector
	my call ${tcl.dict.exists} [list $dict $len $ary] $name
    }

    # Builder:dictExists(STRING,STRING) --
    #
    #	Find whether a key exists in a dictionary. This version uses a single
    #	simple key. Quadcode implementation ('dictExists').
    #
    # Parameters:
    #	dict -	The dictionary as an LLVM value reference.
    #	key -	The key as an LLVM value reference.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	Whether the value exists as an LLVM ZEROONE value reference.

    method dictExists(STRING,STRING) {dict key {name ""}} {
	my call ${tcl.dict.exists1} [list $dict $key] $name
    }

    # Builder:dictGet(STRING) --
    #
    #	Retrieve a value from a dictionary. This version uses a vector as a
    #	key path. NOTE: this operation can fail (e.g., because it can be given
    #	an invalid dictionary) so it produces a STRING FAIL. Quadcode
    #	implementation ('dictGet').
    #
    # Parameters:
    #	dict -	The dictionary as an LLVM value reference.
    #	vector -
    #		The key path as an LLVM vector value reference.
    #	ec -	Where to write the error code if an error happens.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	The retrieved value as an LLVM value reference, or a FAIL.

    method dictGet(STRING) {dict vector ec {name ""}} {
	my ExtractVector $vector
	my call ${tcl.dict.get} [list $dict $len $ary $ec] $name
    }

    # Builder:dictGet(STRING,STRING) --
    #
    #	Retrieve a value from a dictionary. This version uses a single simple
    #	key. NOTE: this operation can fail (e.g., because it can be given an
    #	invalid dictionary) so it produces a STRING FAIL. Quadcode
    #	implementation ('dictGet').
    #
    # Parameters:
    #	dict -	The dictionary as an LLVM value reference.
    #	key -	The key as an LLVM value reference.
    #	ec -	Where to write the error code if an error happens.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	The retrieved value as an LLVM value reference, or a FAIL.

    method dictGet(STRING,STRING) {dict key ec {name ""}} {
	my call ${tcl.dict.get1} [list $dict $key $ec] $name
    }

    # Builder:dictIncr(STRING,STRING,INT) --
    #
    #	Increment the value for a key in a dictionary. NOTE: this operation
    #	can fail (e.g., because it can be given an invalid dictionary) so it
    #	produces a STRING FAIL. Quadcode implementation ('dictIncr').
    #
    # Parameters:
    #	dict -	The dictionary as an LLVM value reference.
    #	key -	The key as an LLVM value reference.
    #	value -	The amount to increment by as an LLVM value reference.
    #	ec -	Where to write the error code if an error happens.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	The resulting dictionary as an LLVM value reference, or a FAIL.

    method dictIncr(STRING,STRING,INT) {dict key value ec {name ""}} {
	my call ${tcl.dict.incr} [list $dict $key $value $ec] $name
    }

    # Builder:dictIterStart(STRING) --
    #
    #	Start iterating over a dictionary; other opcodes are used to retrieve
    #	what the state of the iteration is. NOTE: this operation can fail
    #	(e.g., because it can be given an invalid dictionary) so it produces a
    #	DICTITER FAIL. Quadcode implementation ('dictIterStart').
    #
    # Parameters:
    #	dict -	The dictionary as an LLVM value reference.
    #	ec -	Where to write the error code if an error happens.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	The iteration state as an LLVM DICTITER value reference, or a FAIL.

    method dictIterStart(STRING) {dict ec {name ""}} {
	my call ${tcl.dict.iterStart} [list $dict $ec] $name
    }

    # Builder:dictIterNext --
    #
    #	Get the next step when iterating over a dictionary; other opcodes are
    #	used to retrieve what the state of the iteration is. Quadcode
    #	implementation ('dictIterNext').
    #
    # Parameters:
    #	iter -	The iteration state as an LLVM value reference.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	The new iteration state as an LLVM DICTITER value reference.

    method dictIterNext {iter {name ""}} {
	my call ${tcl.dict.iterNext} [list $iter] $name
    }

    # Builder:dictIterKey --
    #
    #	Get the current key for the iteration step, or the empty string if we
    #	have finished. Quadcode implementation ('dictIterKey').
    #
    # Parameters:
    #	iter -	The iteration state as an LLVM value reference.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	The iteration key as an LLVM STRING value reference.

    method dictIterKey {iter {name ""}} {
	my call ${tcl.dict.iterKey} [list $iter] $name
    }

    # Builder:dictIterValue --
    #
    #	Get the current value for the iteration step, or the empty string if
    #	we have finished. Quadcode implementation ('dictIterValue').
    #
    # Parameters:
    #	iter -	The iteration state as an LLVM value reference.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	The iteration value as an LLVM STRING value reference.

    method dictIterValue {iter {name ""}} {
	my call ${tcl.dict.iterValue} [list $iter] $name
    }

    # Builder:dictIterDone --
    #
    #	Get whether the iteration has finished. Quadcode implementation
    #	('dictIterDone').
    #
    # Parameters:
    #	iter -	The iteration state as an LLVM value reference.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	The termination flag as an LLVM ZEROONE value reference.

    method dictIterDone {iter {name ""}} {
	my call ${tcl.dict.iterDone} [list $iter] $name
    }

    # Builder:dictLappend(STRING,STRING,STRING) --
    #
    #	List-append a value to a key in a dictionary. NOTE: this operation can
    #	fail (e.g., because it can be given an invalid dictionary) so it
    #	produces a STRING FAIL. Quadcode implementation ('dictLappend').
    #
    # Parameters:
    #	dict -	The dictionary as an LLVM value reference.
    #	key -	The key as an LLVM value reference.
    #	value -	The value to append as an LLVM value reference.
    #	ec -	Where to write the error code if an error happens.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	The resulting dictionary as an LLVM value reference, or a FAIL.

    method dictLappend(STRING,STRING,STRING) {dict key value ec {name ""}} {
	my call ${tcl.dict.lappend} [list $dict $key $value $ec] $name
    }

    # Builder:dictSet(STRING,STRING) --
    #
    #	Set or create a value in a dictionary. This version uses a vector as a
    #	dictionary key path. NOTE: this operation can fail (e.g., because it
    #	can be given an invalid dictionary) so it produces a STRING FAIL.
    #	Quadcode implementation ('dictSet').
    #
    # Parameters:
    #	dict -	The dictionary as an LLVM value reference.
    #	value -	The value as an LLVM value reference.
    #	vector -
    #		The key path as an LLVM vector value reference.
    #	ec -	Where to write the error code if an error happens.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	The new dictionary value.

    method dictSet(STRING,STRING) {dict value vector ec {name ""}} {
	my ExtractVector $vector
	my call ${tcl.dict.set} [list $dict $len $ary $value $ec] $name
    }

    # Builder:dictSet(STRING,STRING,STRING) --
    #
    #	Set or create a value in a dictionary. This version uses a single
    #	simple key. NOTE: this operation can fail (e.g., because it can be
    #	given an invalid dictionary) so it produces a STRING FAIL. Quadcode
    #	implementation ('dictSet').
    #
    # Parameters:
    #	dict -	The dictionary as an LLVM value reference.
    #	key -	The key as an LLVM value reference.
    #	value -	The value as an LLVM value reference.
    #	ec -	Where to write the error code if an error happens.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	The new dictionary value.

    method dictSet(STRING,STRING,STRING) {dict key value ec {name ""}} {
	my call ${tcl.dict.set1} [list $dict $key $value $ec] $name
    }

    # Builder:dictSize(STRING) --
    #
    #	Get the size of a dictionary, i.e., the number of key-value pairs.
    #
    # Parameters:
    #	value -	The STRING LLVM value reference to a dict to get the size of.
    #	ecvar -	Location to write the Tcl return code into, as an LLVM int*
    #		reference.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An INT FAIL in an LLVM value reference.

    method dictSize(STRING) {value ecvar {name ""}} {
	my call ${tcl.dict.size} [list $value $ecvar] $name
    }

    # Builder:dictUnset(STRING) --
    #
    #	Remove a key from a dictionary. This version uses a vector as a
    #	dictionary key path. NOTE: this operation can fail (e.g., because it
    #	can be given an invalid dictionary) so it produces a STRING FAIL.
    #	Quadcode implementation ('dictUnset').
    #
    # Parameters:
    #	dict -	The dictionary as an LLVM value reference.
    #	vector -
    #		The key path as an LLVM vector value reference.
    #	ec -	Where to write the error code if an error happens.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	The new dictionary value.

    method dictUnset(STRING) {dict vector ec {name ""}} {
	my ExtractVector $vector
	my call ${tcl.dict.unset} [list $dict $len $ary $ec] $name
    }

    # Builder:dictUnset(STRING,STRING) --
    #
    #	Remove a key from a dictionary. This version uses a single simple
    #	key. NOTE: this operation can fail (e.g., because it can be given an
    #	invalid dictionary) so it produces a STRING FAIL. Quadcode
    #	implementation ('dictUnset').
    #
    # Parameters:
    #	dict -	The dictionary as an LLVM value reference.
    #	key -	The key as an LLVM value reference.
    #	ec -	Where to write the error code if an error happens.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	The new dictionary value.

    method dictUnset(STRING,STRING) {dict key ec {name ""}} {
	my call ${tcl.dict.unset1} [list $dict $key $ec] $name
    }

    # Builder:directAppend(STRING,STRING) --
    #
    #	Append a value to a variable, which should be referred to by a
    #	fully-qualified name. NOTE: this operation can fail because of traces
    #	so it produces a STRING FAIL. Quadcode implementation
    #	('directAppend').
    #
    # Parameters:
    #	varname -
    #		The variable name as an LLVM value reference.
    #	value -	The value to append as an LLVM value reference.
    #	ec -	Where to write the error code if an error happens.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	The new contents of the variable.

    method directAppend(STRING,STRING) {varname value ec {name ""}} {
	my call ${tcl.direct.append} [list $varname $value $ec] $name
    }

    # Builder:directExists(STRING) --
    #
    #	Test if a variable exists; the variable should be referred to by a
    #	fully-qualified name. Quadcode implementation ('directExists').
    #
    # Parameters:
    #	varname -
    #		The variable name as an LLVM value reference.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A ZEROONE that indicates whether the variable is set.

    method directExists(STRING) {varname {name ""}} {
	my call ${tcl.direct.exists} [list $varname] $name
    }

    # Builder:directGet(STRING) --
    #
    #	Read the value of a variable, which should be referred to by a
    #	fully-qualified name. NOTE: this operation can fail because of traces
    #	so it produces a STRING FAIL. Quadcode implementation ('directGet').
    #
    # Parameters:
    #	varname -
    #		The variable name as an LLVM value reference.
    #	ec -	Where to write the error code if an error happens.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	The contents of the variable.

    method directGet(STRING) {varname ec {name ""}} {
	my call ${tcl.direct.get} [list $varname $ec] $name
    }

    # Builder:directLappend(STRING,STRING) --
    #
    #	Append a value to a list in a variable, which should be referred to by
    #	a fully-qualified name. NOTE: this operation can fail because of
    #	traces so it produces a STRING FAIL. Quadcode implementation
    #	('directLappend').
    #
    # Parameters:
    #	varname -
    #		The variable name as an LLVM value reference.
    #	value -	The value to append as an LLVM value reference.
    #	ec -	Where to write the error code if an error happens.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	The new contents of the variable.

    method directLappend(STRING,STRING) {varname value ec {name ""}} {
	my call ${tcl.direct.lappend} [list $varname $value $ec] $name
    }

    # Builder:directSet(STRING,STRING) --
    #
    #	Set the value of a variable, which should be referred to by a
    #	fully-qualified name. NOTE: this operation can fail because of traces
    #	so it produces a STRING FAIL. Quadcode implementation ('directSet').
    #
    # Parameters:
    #	varname -
    #		The variable name as an LLVM value reference.
    #	value -	The value to append as an LLVM value reference.
    #	ec -	Where to write the error code if an error happens.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	The new contents of the variable.

    method directSet(STRING,STRING) {varname value ec {name ""}} {
	my call ${tcl.direct.set} [list $varname $value $ec] $name
    }

    # Builder:directUnset(STRING,INT) --
    #
    #	Unset a variable, which should be referred to by a fully-qualified
    #	name. NOTE: this operation can fail because of traces so it produces a
    #	ZEROONE FAIL (with meaningless value when not failing). Quadcode
    #	implementation ('directUnset').
    #
    # Parameters:
    #	varname -
    #		The variable name as an LLVM value reference.
    #	flag -	Whether failures are allowed, as an LLVM value reference.
    #	ec -	Where to write the error code if an error happens.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	Whether the unset was successful.

    method directUnset(STRING,INT) {varname flag ec {name ""}} {
	my call ${tcl.direct.unset} [list $varname $flag $ec] $name
    }

    # Builder:div(INT,INT) --
    #
    #	Generate code to divide two INTs. Quadcode implementation ('div').
    #
    # Parameters:
    #	left -	The INT LLVM value reference for the left operand.
    #	right -	The INT LLVM value reference for the right operand.
    #	ec -	Where to write the error code if an error happens.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An INT? LLVM value reference.

    method div(INT,INT) {left right ec {name ""}} {
	my call ${tcl.div} [list $left $right $ec] $name
    }

    # Builder:div(DOUBLE,DOUBLE) --
    #
    #	Generate code to divide two DOUBLEs. Quadcode implementation ('div').
    #
    # Parameters:
    #	left -	The DOUBLE LLVM value reference for the left operand.
    #	right -	The DOUBLE LLVM value reference for the right operand.
    #	ec -	Where to write the error code if an error happens.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A DOUBLE? LLVM value reference.

    method div(DOUBLE,DOUBLE) {left right ec {name ""}} {
	my call ${tcl.div.double} [list $left $right $ec] $name
    }

    # Builder:div(DOUBLE,NUMERIC) --
    #
    #	Generate code to divide a DOUBLE by a NUMERIC. Quadcode implementation
    #	('div').
    #
    # Parameters:
    #	left -	The DOUBLE LLVM value reference for the left operand.
    #	right -	The NUMERIC LLVM value reference for the right operand.
    #	ec -	Where to write the error code if an error happens.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A DOUBLE? LLVM value reference.

    method div(DOUBLE,NUMERIC) {left right ec {name ""}} {
	my div(DOUBLE,DOUBLE) $left [my NumToDbl $right] $ec $name
    }

    # Builder:div(NUMERIC,DOUBLE) --
    #
    #	Generate code to divide a NUMERIC by a DOUBLE. Quadcode implementation
    #	('div').
    #
    # Parameters:
    #	left -	The NUMERIC LLVM value reference for the left operand.
    #	right -	The DOUBLE LLVM value reference for the right operand.
    #	ec -	Where to write the error code if an error happens.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A DOUBLE? LLVM value reference.

    method div(NUMERIC,DOUBLE) {left right ec {name ""}} {
	my div(DOUBLE,DOUBLE) [my NumToDbl $left] $right $ec $name
    }

    # Builder:div(INT,NUMERIC) --
    #
    #	Generate code to divide an INT by a NUMERIC. Quadcode implementation
    #	('div').
    #
    # Parameters:
    #	left -	The INT LLVM value reference for the left operand.
    #	right -	The NUMERIC LLVM value reference for the right operand.
    #	ec -	Where to write the error code if an error happens.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A NUMERIC? LLVM value reference.

    method div(INT,NUMERIC) {left right ec {name ""}} {
	my div(NUMERIC,NUMERIC) [my packNumericInt $left] $right $ec $name
    }

    # Builder:div(NUMERIC,INT) --
    #
    #	Generate code to divide a NUMERIC by an INT. Quadcode implementation
    #	('div').
    #
    # Parameters:
    #	left -	The NUMERIC LLVM value reference for the left operand.
    #	right -	The INT LLVM value reference for the right operand.
    #	ec -	Where to write the error code if an error happens.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A NUMERIC? LLVM value reference.

    method div(NUMERIC,INT) {left right ec {name ""}} {
	my div(NUMERIC,NUMERIC) $left [my packNumericInt $right] $ec $name
    }

    # Builder:div(NUMERIC,NUMERIC) --
    #
    #	Generate code to divide two NUMERICs. Quadcode implementation ('div').
    #
    # Parameters:
    #	left -	The NUMERIC LLVM value reference for the left operand.
    #	right -	The NUMERIC LLVM value reference for the right operand.
    #	ec -	Where to write the error code if an error happens.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A NUMERIC? LLVM value reference.

    method div(NUMERIC,NUMERIC) {left right ec {name ""}} {
	my call ${tcl.div.numeric} [list $left $right $ec] $name
    }

    # Builder:dropReference --
    #
    #	Generate code to decrement the reference count of a value and delete
    #	the value if it has ceased to be used.
    #
    # Parameters:
    #	value -	The STRING/etc. LLVM value reference for the operand.
    #
    # Results:
    #	None.

    method dropReference {value} {
	my Call tcl.dropReference $value
	return
    }

    # Builder:dropReference(STRING) --
    #
    #	Generate code to decrement the reference count of a value and delete
    #	the value if it has ceased to be used.
    #
    # Parameters:
    #	value -	The STRING LLVM value reference for the operand.
    #
    # Results:
    #	None.

    method dropReference(STRING) {value} {
	my Call tcl.dropReference $value
	return
    }

    # Builder:dropReference(FAIL EMPTY) --
    #
    #	Generate code to decrement the reference count of a value and delete
    #	the value if it has ceased to be used.
    #
    # Parameters:
    #	value -	The STRING FAIL LLVM value reference for the operand.
    #
    # Results:
    #	None.

    method dropReference(FAIL\040EMPTY) {value} {
	my Call tcl.dropFailReference $value
	return
    }

    # Builder:dropReference(FAIL STRING) --
    #
    #	Generate code to decrement the reference count of a value and delete
    #	the value if it has ceased to be used.
    #
    # Parameters:
    #	value -	The STRING FAIL LLVM value reference for the operand.
    #
    # Results:
    #	None.

    method dropReference(FAIL\040STRING) {value} {
	my Call tcl.dropFailReference $value
	return
    }

    # Builder:dropReference(NEXIST STRING) --
    #
    #	Generate code to decrement the reference count of a value and delete
    #	the value if it has ceased to be used.
    #
    # Parameters:
    #	value -	The NEXIST STRING LLVM value reference for the operand.
    #
    # Results:
    #	None.

    method dropReference(NEXIST\040STRING) {value} {
	my Call tcl.dropNExistReference $value
	return
    }

    # Builder:dropReference(NEXIST EMPTY) --
    #
    #	Generate code to decrement the reference count of a value and delete
    #	the value if it has ceased to be used.
    #
    # Parameters:
    #	value -	The NEXIST EMPTY LLVM value reference for the operand.
    #
    # Results:
    #	None.

    method dropReference(NEXIST\040EMPTY) {value} {
	my Call tcl.dropNExistReference $value
	return
    }

    # Builder:dropReference(DICTITER) --
    #
    #	Generate code to decrement the reference count of a value and delete
    #	the value if it has ceased to be used.
    #
    # Parameters:
    #	value -	The DICTITER LLVM value reference for the operand.
    #
    # Results:
    #	None.

    method dropReference(DICTITER) {value} {
	my Call tcl.dict.dropIterReference $value
	return
    }

    # Builder:dropReference(DICTITER FAIL) --
    #
    #	Generate code to decrement the reference count of a value and delete
    #	the value if it has ceased to be used.
    #
    # Parameters:
    #	value -	The DICTITER FAIL LLVM value reference for the operand.
    #
    # Results:
    #	None.

    method dropReference(DICTITER\040FAIL) {value} {
	my Call tcl.dict.dropIterFailReference $value
	return
    }

    # Builder:dropReference(FAIL DICTITER) --
    #
    #	Generate code to decrement the reference count of a value and delete
    #	the value if it has ceased to be used.
    #
    # Parameters:
    #	value -	The DICTITER FAIL LLVM value reference for the operand.
    #
    # Results:
    #	None.

    method dropReference(FAIL\040DICTITER) {value} {
	my Call tcl.dict.dropIterFailReference $value
	return
    }

    # Builder:eq --
    #
    #	Generate code to compare two integers of the same bit width *or* two
    #	pointers for equality.
    #
    # Parameters:
    #	left -	The int[X] or pointer LLVM value reference for the left
    #		operand. (X is any width supported by LLVM.)
    #	right -	The int[X] or pointer LLVM value reference for the right
    #		operand. (X is the same as for the 'left' parameter.)
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An int1 LLVM value reference.

    method eq {left right {name ""}} {
	if {[GetTypeKind [TypeOf $left]] eq "LLVMIntegerTypeKind"} {
	    my cmpInt $left EQ $right $name
	} else {
	    my cmpPtr $left EQ $right $name
	}
    }

    # Builder:eq(INT,INT) --
    #
    #	Generate code to compare two INTs for equality. Quadcode
    #	implementation ('eq').
    #
    # Parameters:
    #	left -	The INT LLVM value reference for the left operand.
    #	right -	The INT LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A ZEROONE LLVM value reference.

    method eq(INT,INT) {left right {name ""}} {
	my call ${tcl.eq} [list $left $right] $name
    }

    # Builder:eq(DOUBLE,DOUBLE) --
    #
    #	Generate code to compare two DOUBLEs for equality. Quadcode
    #	implementation ('eq').
    #
    # Parameters:
    #	left -	The DOUBLE LLVM value reference for the left operand.
    #	right -	The DOUBLE LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A ZEROONE LLVM value reference.

    method eq(DOUBLE,DOUBLE) {left right {name ""}} {
	my cmpDbl $left EQ $right $name
    }

    # Builder:eq(NUMERIC,NUMERIC) --
    #
    #	Generate code to compare two NUMERICs for equality. Quadcode
    #	implementation ('eq').
    #
    # Parameters:
    #	left -	The NUMERIC LLVM value reference for the left operand.
    #	right -	The NUMERIC LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A ZEROONE LLVM value reference.

    method eq(NUMERIC,NUMERIC) {left right {name ""}} {
	my call ${tcl.eq.numeric} [list $left $right] $name
    }

    # Builder:eq(STRING,NUMERIC) --
    #
    #	Generate code to compare a STRING and NUMERICs for equality. Quadcode
    #	implementation ('eq').
    #
    # Parameters:
    #	left -	The STRING LLVM value reference for the left operand.
    #	right -	The NUMERIC LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A ZEROONE LLVM value reference.

    method eq(STRING,NUMERIC) {left right {name ""}} {
	my eq [my Call tcl.cmp.strnum $left $right] [Const 0] $name
    }
    method eq(NUMERIC,STRING) {left right {name ""}} {
	my eq [my Call tcl.cmp.strnum $right $left] [Const 0] $name
    }

    # Builder:eq(STRING,STRING) --
    #
    #	Generate code to compare two STRINGs for equality. Quadcode
    #	implementation ('eq').
    #
    # Parameters:
    #	left -	The STRING LLVM value reference for the left operand.
    #	right -	The STRING LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A ZEROONE LLVM value reference.

    method eq(STRING,STRING) {left right {name ""}} {
	my eq [my Call tcl.cmp.strstr $left $right] [Const 0] $name
    }

    # Builder:exists --
    #
    #	Test if a possibly-nonexisting value (something with NEXIST as part of
    #	its type) is actually an existing value. Quadcode implementation
    #	('exists').
    #
    # Parameters:
    #	value -	The *NEXISTS LLVM value reference for the operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A ZEROONE LLVM value reference.

    method exists {value {name ""}} {
	my not [my maybe $value] $name
    }

    # Builder:existsOrError --
    #
    #	Test if a possibly-nonexisting value (something with NEXIST as part of
    #	its type) is actually an existing value, and generate an error message
    #	if it does not. Quadcode implementation ('throwIfNotExists').
    #
    # Parameters:
    #	value -	The *NEXISTS LLVM value reference for the operand.
    #	message -
    #		The error message (LLVM STRING, literal) to use when the value
    #		does not exist.
    #	exception -
    #		The -errorcode (LLVM STRING, literal) to use when the value
    #		does not exist.
    #	ec -	Where to write the error code if an error happens.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An int1 LLVM value reference.

    method existsOrError {value message exception ec {name ""}} {
	my call ${tcl.existsOrError} \
	    [list [my maybe $value] $message $exception $ec] \
	    $name
    }

    # Builder:expect --
    #
    #	Issue the expectation that a condition will be true or false. This
    #	affects the weights in the LLVM metadata, and guides the low-level
    #	code issuing.
    #
    # Parameters:
    #	value - LLVM value of boolean type.
    #	expectedBoolean -
    #		The most likely ("expected") value of that boolean.
    #	name (optional) -
    #		The name of the result value, which will be the same as the
    #		input value except with the expectation attached.
    #
    # Results:
    #	LLVM boolean value.

    method expect {value expectedBoolean {name ""}} {
	my call [$m intrinsic expect bool] \
	    [list $value [Const $expectedBoolean bool]] $name
    }

    # Builder:expon(INT,INT) --
    #
    #	Generate code to compute one INT raised to the exponent another INT
    #	(i.e., left**right).  Quadcode implementation ('expon').
    #
    # Parameters:
    #	left -	The INT LLVM value reference for the left operand.
    #	right -	The INT LLVM value reference for the right operand.
    #	ec -	Where to write the error code if an error happens.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An INT? LLVM value reference.

    method expon(INT,INT) {left right ec {name ""}} {
	my call ${tcl.ipow} [list $left $right $ec] $name
    }

    # Builder:expon(DOUBLE,INT) --
    #
    #	Generate code to raise a DOUBLE to the power of an INT. Quadcode
    #	implementation ('expon').
    #
    # Parameters:
    #	left -	The DOUBLE LLVM value reference for the left operand.
    #	right -	The INT LLVM value reference for the right operand.
    #	ec -	Where to write the error code if an error happens.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A DOUBLE? LLVM value reference.

    method expon(DOUBLE,INT) {left right ec {name ""}} {
	my call ${tcl.powi} [list $left $right $ec] $name
    }

    # Builder:expon(DOUBLE,DOUBLE) --
    #
    #	Generate code to raise a DOUBLE to the power of a DOUBLE. Quadcode
    #	implementation ('expon').
    #
    # Parameters:
    #	left -	The DOUBLE LLVM value reference for the left operand.
    #	right -	The DOUBLE LLVM value reference for the right operand.
    #	ec -	Where to write the error code if an error happens.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A DOUBLE? LLVM value reference.

    method expon(DOUBLE,DOUBLE) {left right ec {name ""}} {
	my call ${tcl.fpow} [list $left $right $ec] $name
    }

    # Builder:expon(DOUBLE,NUMERIC) --
    #
    #	Generate code to raise a DOUBLE to the power of a NUMERIC. Quadcode
    #	implementation ('expon').
    #
    # Parameters:
    #	left -	The DOUBLE LLVM value reference for the left operand.
    #	right -	The NUMERIC LLVM value reference for the right operand.
    #	ec -	Where to write the error code if an error happens.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A DOUBLE? LLVM value reference.

    method expon(DOUBLE,NUMERIC) {left right ec {name ""}} {
	my expon(DOUBLE,DOUBLE) $left [my NumToDbl $right] $ec $name
    }

    # Builder:expon(NUMERIC,DOUBLE) --
    #
    #	Generate code to raise a NUMERIC to the power of a DOUBLE. Quadcode
    #	implementation ('expon').
    #
    # Parameters:
    #	left -	The NUMERIC LLVM value reference for the left operand.
    #	right -	The DOUBLE LLVM value reference for the right operand.
    #	ec -	Where to write the error code if an error happens.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A DOUBLE? LLVM value reference.

    method expon(NUMERIC,DOUBLE) {left right ec {name ""}} {
	my expon(DOUBLE,DOUBLE) [my NumToDbl $left] $right $ec $name
    }

    # Builder:expon(INT,NUMERIC) --
    #
    #	Generate code to raise an INT to the power of a NUMERIC. Quadcode
    #	implementation ('expon').
    #
    # Parameters:
    #	left -	The INT LLVM value reference for the left operand.
    #	right -	The NUMERIC LLVM value reference for the right operand.
    #	ec -	Where to write the error code if an error happens.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A NUMERIC? LLVM value reference.

    method expon(INT,NUMERIC) {left right ec {name ""}} {
	my expon(NUMERIC,NUMERIC) [my packNumericInt $left] $right $ec $name
    }

    # Builder:expon(NUMERIC,INT) --
    #
    #	Generate code to raise a NUMERIC to the power of an INT. Quadcode
    #	implementation ('expon').
    #
    # Parameters:
    #	left -	The NUMERIC LLVM value reference for the left operand.
    #	right -	The INT LLVM value reference for the right operand.
    #	ec -	Where to write the error code if an error happens.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A NUMERIC? LLVM value reference.

    method expon(NUMERIC,INT) {left right ec {name ""}} {
	my expon(NUMERIC,NUMERIC) $left [my packNumericInt $right] $ec $name
    }

    # Builder:expon(NUMERIC,NUMERIC) --
    #
    #	Generate code to raise a NUMERIC to the power of another NUMERIC.
    #	Quadcode implementation ('expon').
    #
    # Parameters:
    #	left -	The NUMERIC LLVM value reference for the left operand.
    #	right -	The NUMERIC LLVM value reference for the right operand.
    #	ec -	Where to write the error code if an error happens.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A NUMERIC? LLVM value reference.

    method expon(NUMERIC,NUMERIC) {left right ec {name ""}} {
	my call ${tcl.pow.numeric} [list $left $right $ec] $name
    }

    # Builder:fail --
    #
    #	Create a Nothing FAIL of the given type.
    #
    # Parameters:
    #	type -	The type of the FAIL.
    #	code (optional) -
    #		The error code in the failure (LLVM int32 reference), or the
    #		empty string to use the default.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An LLVM FAIL value reference containing nothing.

    method fail {type {code ""} {name ""}} {
	if {[string match "* FAIL" $type]} {
	    set type [string range $type 0 end-5]
	} elseif {[string match "FAIL *" $type]} {
	    set type [string range $type 5 end]
	}
	if {$code eq ""} {
	    set code [Const 1]
	}
	my insert [my undef $type?] $code 0 $name
    }

    # Builder:ge --
    #
    #	Generate code to compare two integers of the same bit width *or* two
    #	pointers to see if the first is greater or equal to the second.
    #
    # Parameters:
    #	left -	The int[X] or pointer LLVM value reference for the left
    #		operand. (X is any width supported by LLVM.)
    #	right -	The int[X] or pointer LLVM value reference for the right
    #		operand. (X is the same as for the 'left' parameter.)
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An int1 LLVM value reference.

    method ge {left right {name ""}} {
	if {[GetTypeKind [TypeOf $left]] eq "LLVMIntegerTypeKind"} {
	    my cmpInt $left SGE $right $name
	} else {
	    my cmpPtr $left SGE $right $name
	}
    }

    # Builder:ge(INT,INT) --
    #
    #	Generate code to see if one INT is greater than or equal to another
    #	INT.  Quadcode implementation ('ge').
    #
    # Parameters:
    #	left -	The INT LLVM value reference for the left operand.
    #	right -	The INT LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A ZEROONE LLVM value reference.

    method ge(INT,INT) {left right {name ""}} {
	my call ${tcl.ge} [list $left $right] $name
    }

    # Builder:ge(DOUBLE,DOUBLE) --
    #
    #	Generate code to compare two DOUBLEs for being greater than or equal.
    #	Quadcode implementation ('eq').
    #
    # Parameters:
    #	left -	The DOUBLE LLVM value reference for the left operand.
    #	right -	The DOUBLE LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A ZEROONE LLVM value reference.

    method ge(DOUBLE,DOUBLE) {left right {name ""}} {
	my cmpDbl $left GE $right $name
    }

    # Builder:ge(NUMERIC,NUMERIC) --
    #
    #	Generate code to compare two NUMERICs for being greater than or equal.
    #	Quadcode implementation ('ge').
    #
    # Parameters:
    #	left -	The NUMERIC LLVM value reference for the left operand.
    #	right -	The NUMERIC LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A ZEROONE LLVM value reference.

    method ge(NUMERIC,NUMERIC) {left right {name ""}} {
	my call ${tcl.ge.numeric} [list $left $right] $name
    }

    # Builder:ge(STRING,NUMERIC) --
    #
    #	Generate code to compare a STRING and a NUMERIC for being greater than
    #	or equal. Quadcode implementation ('eq').
    #
    # Parameters:
    #	left -	The STRING LLVM value reference for the left operand.
    #	right -	The NUMERIC LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A ZEROONE LLVM value reference.

    method ge(STRING,NUMERIC) {left right {name ""}} {
	my ge [my Call tcl.cmp.strnum $left $right] [Const 0] $name
    }
    method ge(NUMERIC,STRING) {left right {name ""}} {
	my le [my Call tcl.cmp.strnum $right $left] [Const 0] $name
    }

    # Builder:ge(STRING,STRING) --
    #
    #	Generate code to compare two STRINGs for being greater than or equal.
    #	Quadcode implementation ('ge').
    #
    # Parameters:
    #	left -	The STRING LLVM value reference for the left operand.
    #	right -	The STRING LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A ZEROONE LLVM value reference.

    method ge(STRING,STRING) {left right {name ""}} {
	my ge [my Call tcl.cmp.strstr $left $right] [Const 0] $name
    }

    # Builder:gep --
    #
    #	Wrapper round 'getelementptr' that adds convenient conversion of Tcl
    #	numbers into LLVM int32 constants for the indices, and processes a
    #	variable number of arguments.
    #
    # Parameters:
    #	ptr -	The pointer LLVM value reference.
    #	args -	The sequence of Tcl integer literals that indexes into the
    #		structure. The first element does whole-structure
    #		incrementing, and is useful for arrays and general address
    #		arithmetic. The final element may be a non-numeric name for
    #		the result value.
    #
    # Results:
    #	A pointer LLVM value reference.

    method gep {ptr args} {
	set name ""
	my getelementptr $ptr [lmap idx $args {
	    if {[regexp {^(\w+)\.(\w+)$} $idx -> type field]} {
		set idx [FieldIndex $type $field]
		set name $field
	    }
	    Const $idx
	}] $name
    }

    # Builder:dereference --
    #
    #	Wrapper round 'getelementptr' that adds convenient conversion of Tcl
    #	numbers into LLVM int32 constants for the indices, and processes a
    #	variable number of arguments. It then 'load's the result.
    #
    # Parameters:
    #	ptr -	The pointer LLVM value reference.
    #	args -	The sequence of Tcl integer literals that indexes into the
    #		structure. The first element does whole-structure
    #		incrementing, and is useful for arrays. The final element may
    #		be a non-numeric name for the result value.
    #
    # Results:
    #	A LLVM value reference that was read from the variable.

    method dereference {ptr args} {
	set nameout [set namein ""]
	set indices [lmap idx $args {
	    if {[regexp {^(\w+)\.(\w+)$} $idx -> type field]} {
		set idx [FieldIndex $type $field]
		set namein $field.ptr
		set nameout $field
	    }
	    Const $idx
	}]
	my load [my getelementptr $ptr $indices $namein] $nameout
    }

    # Builder:gt --
    #
    #	Generate code to compare two integers of the same bit width *or* two
    #	pointers to see if the first is greater than the second.
    #
    # Parameters:
    #	left -	The int[X] or pointer LLVM value reference for the left
    #		operand. (X is any width supported by LLVM.)
    #	right -	The int[X] or pointer LLVM value reference for the right
    #		operand. (X is the same as for the 'left' parameter.)
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An int1 LLVM value reference.

    method gt {left right {name ""}} {
	if {[GetTypeKind [TypeOf $left]] eq "LLVMIntegerTypeKind"} {
	    my cmpInt $left SGT $right $name
	} else {
	    my cmpPtr $left SGT $right $name
	}
    }

    # Builder:gt(INT,INT) --
    #
    #	Generate code to see if one INT is greater than another INT.  Quadcode
    #	implementation ('gt').
    #
    # Parameters:
    #	left -	The INT LLVM value reference for the left operand.
    #	right -	The INT LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A ZEROONE LLVM value reference.

    method gt(INT,INT) {left right {name ""}} {
	my call ${tcl.gt} [list $left $right] $name
    }

    # Builder:gt(DOUBLE,DOUBLE) --
    #
    #	Generate code to compare two DOUBLEs for the first being greater than
    #	the second. Quadcode implementation ('eq').
    #
    # Parameters:
    #	left -	The DOUBLE LLVM value reference for the left operand.
    #	right -	The DOUBLE LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A ZEROONE LLVM value reference.

    method gt(DOUBLE,DOUBLE) {left right {name ""}} {
	my cmpDbl $left GT $right $name
    }

    # Builder:gt(NUMERIC,NUMERIC) --
    #
    #	Generate code to compare two NUMERICs for the first being greater than
    #	the second. Quadcode implementation ('gt').
    #
    # Parameters:
    #	left -	The NUMERIC LLVM value reference for the left operand.
    #	right -	The NUMERIC LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A ZEROONE LLVM value reference.

    method gt(NUMERIC,NUMERIC) {left right {name ""}} {
	my call ${tcl.gt.numeric} [list $left $right] $name
    }

    # Builder:gt(STRING,NUMERIC) --
    #
    #	Generate code to compare a STRING and a NUMERIC for the first being
    #	greater than the second. Quadcode implementation ('gt').
    #
    # Parameters:
    #	left -	The STRING LLVM value reference for the left operand.
    #	right -	The STRING LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A ZEROONE LLVM value reference.

    method gt(STRING,NUMERIC) {left right {name ""}} {
	my gt [my Call tcl.cmp.strnum $left $right] [Const 0] $name
    }
    method gt(NUMERIC,STRING) {left right {name ""}} {
	my lt [my Call tcl.cmp.strnum $right $left] [Const 0] $name
    }

    # Builder:gt(STRING,STRING) --
    #
    #	Generate code to compare two STRINGs for the first being greater than
    #	the second. Quadcode implementation ('gt').
    #
    # Parameters:
    #	left -	The STRING LLVM value reference for the left operand.
    #	right -	The STRING LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A ZEROONE LLVM value reference.

    method gt(STRING,STRING) {left right {name ""}} {
	my gt [my Call tcl.cmp.strstr $left $right] [Const 0] $name
    }

    # Builder:impure --
    #
    #	Construct an impure value from its components. Note that this does not
    #	perform reference management.
    #
    # Parameters:
    #	basetype -
    #		The type to add impurity to.
    #	string -
    #		The string version of the resulting value, as a STRING LLVM
    #		reference.
    #	value -
    #		The non-string version of the resulting value, as an LLVM
    #		reference of the correct type.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A IMPURE $basetype LLVM value reference.

    method impure {basetype string value {name ""}} {
	set ival [my undef [Type "IMPURE $basetype"]]
	return [my insert [my insert $ival $string 0] $value 1 $name]
    }

    # Builder:impure.string --
    #
    #	Get the string part of an impure value. Note that this does not
    #	perform reference management.
    #
    # Parameters:
    #	value -	The IMPURE * LLVM value.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A STRING LLVM value reference.

    method impure.string {value {name ""}} {
	set result [my extract $value 0 [GetValueName $value].string]
	if {$name ne ""} {
	    SetValueName $result $name
	}
	return $result
    }

    # Builder:impure.value --
    #
    #	Get the non-string part of an impure value. Note that this does not
    #	perform reference management.
    #
    # Parameters:
    #	value -	The IMPURE * LLVM value.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An LLVM value reference. The type of the result will be the type of
    #	the value packed within the IMPURE holder.

    method impure.value {value {name ""}} {
	set result [my extract $value 1 [GetValueName $value].value]
	if {$name ne ""} {
	    SetValueName $result $name
	}
	return $result
    }

    # Builder:initException --
    #
    #	Generate/set up an exception.
    #
    # Parameters:
    #	errorcode -
    #		The -errorcode list. Caller must guarantee that it is a list
    #		in a STRING LLVM reference.
    #	message -
    #		The result, as a STRING LLVM reference.
    #	errVar -
    #		Where the result code (always TCL_ERROR) is to be written to.
    #
    # Results:
    #	none

    method initException {errorcode message errVar} {
	my Call tcl.initExceptionSimple $message $errorcode
	my store [Const 1] $errVar
	return
    }

    # Builder:initException(STRING) --
    #
    #	Generate/set up an exception, returning a FAIL derived from the
    #	'value' argument. Quadcode implementation ('initException').
    #
    # Parameters:
    #	dict -	The options dictionary, as a STRING.
    #	value -	The result, as a variable-type LLVM reference.
    #	type -	The quadcode type of the result.
    #	errVar -
    #		Where the actual result code is to be written to.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An LLVM value reference.

    method initException(STRING) {dict value type errVar {name ""}} {
	if {$type eq "STRING"} {
	    set code [my Call tcl.initExceptionOptions $value $dict]
	} else {
	    set stringed [my stringify($type) $value]
	    set code [my Call tcl.initExceptionOptions $stringed $dict]
	    # FIXME?
	    # my dropReference $stringed
	}
	my store $code $errVar
	my select [my eq $code [Const 0]] \
	    [my ok $value] [my fail $type $code] $name
    }

    # Builder:initException(STRING,INT,INT) --
    #
    #	Generate/set up an exception, returning a FAIL derived from the
    #	'value' argument. Quadcode implementation ('initException').
    #
    # Parameters:
    #	dict -	The options dictionary, as a STRING.
    #	code -	The Tcl return code, as an INT.
    #	level -	The Tcl return level, as an INT.
    #	value -	The result, as a variable-type LLVM reference.
    #	type -	The quadcode type of the result.
    #	errVar -
    #		Where the actual result code is to be written to.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An LLVM value reference.

    method initException(STRING,INT,INT) {dict code level value type errVar {name ""}} {
	if {$type in {STRING EMPTY}} {
	    set newcode [my Call tcl.processReturn \
		$value [my getInt32 $code] [my getInt32 $level] $dict]
	} else {
	    set stringed [my stringify($type) $value]
	    set newcode [my Call tcl.processReturn \
		$stringed [my getInt32 $code] [my getInt32 $level] $dict]
	    # FIXME?
	    my dropReference $stringed
	}
	SetValueName $newcode "code"
	my store $newcode $errVar
	my select [my eq $newcode [Const 0]] \
	    [my ok $value] [my fail $type $newcode] $name
    }

    # Builder:instanceOf.DOUBLE(STRING) --
    #
    #	Generate code to check if the given STRING contains something that can
    #	be parsed to get a DOUBLE. Quadcode implementation ('instanceOf').
    #
    # Parameters:
    #	value -	The STRING LLVM value reference to check.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A ZEROONE LLVM value reference.

    method instanceOf.DOUBLE(STRING) {value {name ""}} {
	my call ${tcl.isDouble} [list $value [Const false bool]] $name
    }
    method instanceOf.IMPURE_DOUBLE(STRING) {value {name ""}} {
	my call ${tcl.isDouble} [list $value [Const false bool]] $name
    }

    # Builder:instanceOf.EMPTY_DOUBLE(STRING) --
    #
    #	Generate code to check if the given STRING contains something that can
    #	be parsed to get a DOUBLE or that it is an empty string. Quadcode
    #	implementation ('instanceOf').
    #
    # Parameters:
    #	value -	The STRING LLVM value reference to check.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A ZEROONE LLVM value reference.

    method instanceOf.EMPTY_DOUBLE(STRING) {value {name ""}} {
	my call ${tcl.isDouble} [list $value [Const true bool]] $name
    }

    # Builder:instanceOf.EMPTY_INT(STRING) --
    #
    #	Generate code to check if the given STRING contains something that can
    #	be parsed to get an INT or that it is an empty string. Quadcode
    #	implementation ('instanceOf').
    #
    # Parameters:
    #	value -	The STRING LLVM value reference to check.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A ZEROONE LLVM value reference.

    method instanceOf.EMPTY_INT(STRING) {value {name ""}} {
	my call ${tcl.isInteger} [list $value [Const true bool]] $name
    }
    method instanceOf.IMPURE_EMPTY_INT(STRING) {value {name ""}} {
	my call ${tcl.isInteger} [list $value [Const true bool]] $name
    }

    # Builder:instanceOf.EMPTY_NUMERIC(STRING) --
    #
    #	Generate code to check if the given STRING contains something that can
    #	be parsed to get a NUMERIC or that it is an empty string. Quadcode
    #	implementation ('instanceOf').
    #
    # Parameters:
    #	value -	The STRING LLVM value reference to check.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A ZEROONE LLVM value reference.

    method instanceOf.EMPTY_NUMERIC(STRING) {value {name ""}} {
	my call ${tcl.isNumeric} [list $value [Const true bool]] $name
    }
    method instanceOf.IMPURE_EMPTY_NUMERIC(STRING) {value {name ""}} {
	my call ${tcl.isNumeric} [list $value [Const true bool]] $name
    }

    # Builder:instanceOf.INT(STRING) --
    #
    #	Generate code to check if the given STRING contains something that can
    #	be parsed to get an INT. Quadcode implementation ('instanceOf').
    #
    # Parameters:
    #	value -	The STRING LLVM value reference to check.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A ZEROONE LLVM value reference.

    method instanceOf.INT(STRING) {value {name ""}} {
	my call ${tcl.isInteger} [list $value [Const false bool]] $name
    }
    method instanceOf.IMPURE_INT(STRING) {value {name ""}} {
	my call ${tcl.isInteger} [list $value [Const false bool]] $name
    }

    # Builder:instanceOf.NUMERIC(STRING) --
    #
    #	Generate code to check if the given STRING contains something that can
    #	be parsed to get a NUMERIC. Quadcode implementation ('instanceOf').
    #
    # Parameters:
    #	value -	The STRING LLVM value reference to check.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A ZEROONE LLVM value reference.

    method instanceOf.NUMERIC(STRING) {value {name ""}} {
	my call ${tcl.isNumeric} [list $value [Const false bool]] $name
    }
    method instanceOf.IMPURE_NUMERIC(STRING) {value {name ""}} {
	my call ${tcl.isNumeric} [list $value [Const false bool]] $name
    }

    # Builder:int --
    #
    #	Generate code to create an integer "literal".
    #
    # Parameters:
    #	value -	The Tcl integer that we are converting to an LLVM INT.
    #	name (optional) -
    #		A name to give to the value.
    #
    # Results:
    #	An LLVM INT value reference.

    method int {value {name ""}} {
	if {$value ne wide($value)} {
	    # A somewhat strict rule
	    return -code error "not an integer"
	}
	if {$::tcl_platform(wordSize) < 8 &&
		$value >= -0x80000000 && $value <= 0x7fffffff} {
	    my packInt32 [Const $value int] $name
	} else {
	    my packInt64 [Const $value int64] $name
	}
    }

    # Builder:invoke --
    #
    #	Generate code to call a Tcl command.  Quadcode implementation
    #	('invoke').
    #
    # Parameters:
    #	arguments -
    #		The arguments as an LLVM vector value reference. Note that
    #		this includes the function name as the first argument.
    #	ec -	Location to write the Tcl return code into, as an LLVM int*
    #		reference. (TODO: Not yet used because we give the wrong type
    #		to command signatures.)
    #	resultName (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An LLVM value reference.

    method invoke {arguments ec {resultName ""}} {
	my ExtractVector $arguments
	my call ${tcl.invoke.command} [list $len $ary $ec] $resultName
    }

    # Builder:isBoolean(INT BOOLEAN) --
    #
    #	Test if a value is a boolean. Quadcode implementation ('isBoolean').
    #
    # Parameters:
    #	value -	The value to test, as an LLVM value reference.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An LLVM INT value reference containing a boolean value.

    method isBoolean(INT\040BOOLEAN) {value {name ""}} {
	# We know we've got one by the type logic; this is trivial
	my cast(BOOLEAN) [Const true bool] $name
    }

    # Builder:isBoolean(STRING) --
    #
    #	Test if a value is a boolean. Quadcode implementation ('isBoolean').
    #
    # Parameters:
    #	value -	The value to test, as an LLVM value reference.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An LLVM INT value reference containing a boolean value.

    method isBoolean(STRING) {value {name ""}} {
	my call ${tcl.booleanTest} [list $value] $name
    }

    # Builder:land(INT,INT) --
    #
    #	Generate code to compute the logical and of two INTs.  Quadcode
    #	implementation ('land').
    #
    # Parameters:
    #	left -	The INT LLVM value reference for the left operand.
    #	right -	The INT LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A ZEROONE LLVM value reference.

    method land(INT,INT) {left right {name ""}} {
	my call ${tcl.land} [list $left $right] $name
    }

    # Builder:land(INT,INT) --
    #
    #	Generate code to compute the logical and of two DOUBLEs.  Quadcode
    #	implementation ('land').
    #
    # Parameters:
    #	left -	The DOUBLE LLVM value reference for the left operand.
    #	right -	The DOUBLE LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A ZEROONE LLVM value reference.

    method land(DOUBLE,DOUBLE) {left right {name ""}} {
	my call ${tcl.land.double} [list $left $right] $name
    }

    # Builder:land(NUMERIC,NUMERIC) --
    #
    #	Generate code to compute the logical and of two NUMERICs. Quadcode
    #	implementation ('land').
    #
    # Parameters:
    #	left -	The NUMERIC LLVM value reference for the left operand.
    #	right -	The NUMERIC LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A NUMERIC LLVM value reference.

    method land(NUMERIC,NUMERIC) {left right {name ""}} {
	my call ${tcl.land.numeric} [list $left $right] $name
    }

    # Builder:le --
    #
    #	Generate code to compare two integers of the same bit width *or* two
    #	pointers to see if the first is less or equal to the second.
    #
    # Parameters:
    #	left -	The int[X] or pointer LLVM value reference for the left
    #		operand. (X is any width supported by LLVM.)
    #	right -	The int[X] or pointer LLVM value reference for the right
    #		operand. (X is the same as for the 'left' parameter.)
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An int1 LLVM value reference.

    method le {left right {name ""}} {
	if {[GetTypeKind [TypeOf $left]] eq "LLVMIntegerTypeKind"} {
	    my cmpInt $left SLE $right $name
	} else {
	    my cmpPtr $left SLE $right $name
	}
    }

    # Builder:le(INT,INT) --
    #
    #	Generate code to see of one INT is less than or equal to another INT.
    #	Quadcode implementation ('le').
    #
    # Parameters:
    #	left -	The INT LLVM value reference for the left operand.
    #	right -	The INT LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A ZEROONE LLVM value reference.

    method le(INT,INT) {left right {name ""}} {
	my call ${tcl.le} [list $left $right] $name
    }

    # Builder:le(DOUBLE,DOUBLE) --
    #
    #	Generate code to compare two DOUBLEs for the first being less than or
    #	equal to the second. Quadcode implementation ('eq').
    #
    # Parameters:
    #	left -	The DOUBLE LLVM value reference for the left operand.
    #	right -	The DOUBLE LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A ZEROONE LLVM value reference.

    method le(DOUBLE,DOUBLE) {left right {name ""}} {
	my cmpDbl $left LE $right $name
    }

    # Builder:le(NUMERIC,NUMERIC) --
    #
    #	Generate code to compare two NUMERICs for being less than or equal.
    #	Quadcode implementation ('le').
    #
    # Parameters:
    #	left -	The NUMERIC LLVM value reference for the left operand.
    #	right -	The NUMERIC LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A ZEROONE LLVM value reference.

    method le(NUMERIC,NUMERIC) {left right {name ""}} {
	my call ${tcl.le.numeric} [list $left $right] $name
    }

    # Builder:le(STRING,NUMERIC) --
    #
    #	Generate code to compare a STRING and a NUMERIC for the first being
    #	less than or equal to the second. Quadcode implementation ('le').
    #
    # Parameters:
    #	left -	The STRING LLVM value reference for the left operand.
    #	right -	The NUMERIC LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A ZEROONE LLVM value reference.

    method le(STRING,NUMERIC) {left right {name ""}} {
	my le [my Call tcl.cmp.strnum $left $right] [Const 0] $name
    }
    method le(NUMERIC,STRING) {left right {name ""}} {
	my ge [my Call tcl.cmp.strnum $right $left] [Const 0] $name
    }

    # Builder:le(STRING,STRING) --
    #
    #	Generate code to compare two STRINGs for the first being less than or
    #	equal to the second. Quadcode implementation ('le').
    #
    # Parameters:
    #	left -	The STRING LLVM value reference for the left operand.
    #	right -	The STRING LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A ZEROONE LLVM value reference.

    method le(STRING,STRING) {left right {name ""}} {
	my le [my Call tcl.cmp.strstr $left $right] [Const 0] $name
    }

    # Builder:list --
    #
    #	Construct a Tcl list out of the list of LLVM value references passed
    #	in. Note that this does most of the work of the 'list' instruction
    #	directly, as it is dealing with a variadic instruction; it doesn't
    #	delegate to the general code. It also knows more about how reference
    #	counts are managed to make it more efficient.
    #
    # Parameters:
    #	values -
    #		Tcl list of LLVM value references.
    #	types -	Tcl list of human-readable type descriptions (e.g., STRING).
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A STRING LLVM value reference.

    method list {values types {name ""}} {
	set stack [my Call [$m intrinsic stacksave]]
	try {
	    if {[llength $values]} {
		set len [Const [llength $values]]
		set vlist [my arrayAlloc STRING $len]
		set idx -1
		foreach value $values type $types {
		    if {[lindex $type 0] eq "IMPURE"} {
			set value [my stringify($type) $value]
		    } else {
			switch -exact -- $type {
			    "INT" - "INT BOOLEAN" - "ZEROONE" - "DOUBLE" -
			    "ENTIER" - "NUMERIC" {
				set value [my stringify($type) $value]
			    }
			}
		    }
		    my store $value [my gep $vlist [incr idx]]
		}
	    } else {
		set len [Const 0]
		set vlist [my null STRING*]
	    }
	    my call ${tcl.list.create} [list $len $vlist] $name
	} finally {
	    my Call [$m intrinsic stackrestore] $stack
	}
    }

    # Builder:listAppend(STRING,STRING) --
    #
    #	Append an element to a list. NOTE: this operation can fail (e.g.,
    #	because it can be given an invalid list) so it produces a STRING FAIL.
    #	Quadcode implementation ('listAppend').
    #
    # Parameters:
    #	list -	List value to get append to, in an LLVM STRING reference.
    #	value -	The value to append as an LLVM STRING value reference.
    #	ec -	Location to write the Tcl return code into, as an LLVM int*
    #		reference.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	The element of the list, as an LLVM STRING FAIL reference.

    method listAppend(STRING,STRING) {list value ec {name ""}} {
	my call ${tcl.list.append} [list $list $value $ec] $name
    }

    # Builder:listConcat(STRING,STRING) --
    #
    #	Append a list of elements to a list. NOTE: this operation can fail
    #	(e.g., because it can be given an invalid list) so it produces a
    #	STRING FAIL. Quadcode implementation ('listConcat').
    #
    # Parameters:
    #	list -	List value to get append to, in an LLVM STRING reference.
    #	value -	The list of values to append, as an LLVM STRING value
    #		reference.
    #	ec -	Location to write the Tcl return code into, as an LLVM int*
    #		reference.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	The element of the list, as an LLVM STRING FAIL reference.

    method listConcat(STRING,STRING) {list value ec {name ""}} {
	my call ${tcl.list.concat} [list $list $value $ec] $name
    }

    # Builder:listIn(STRING,STRING) --
    #
    #	Determine if an element is present in a list by simple linear search.
    #	NOTE: this operation can fail (e.g., because it can be given an
    #	invalid list) so it produces an INT FAIL. Quadcode implementation
    #	('listIn').
    #
    # Parameters:
    #	value -	The value to check for, as an LLVM STRING value reference.
    #	list -	List value to search, in an LLVM STRING reference.
    #	ec -	Location to write the Tcl return code into, as an LLVM int*
    #		reference.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	If the element is present, as an LLVM INT FAIL reference.

    method listIn(STRING,STRING) {value list ec {name ""}} {
	my call ${tcl.list.in} [list $value $list $ec] $name
    }

    # Builder:listIndex(STRING) --
    #
    #	Get an element of a list. NOTE: this operation can fail (e.g., because
    #	it can be given an invalid list) so it produces a STRING FAIL.
    #	Quadcode implementation ('listIndex').
    #
    # Parameters:
    #	value -	List value to get the length of, in an LLVM STRING reference.
    #	vector -
    #		The indices as an LLVM vector value reference.
    #	errVar -
    #		Location to write the Tcl return code into, as an LLVM int*
    #		reference.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	The element of the list, as an LLVM STRING FAIL reference.

    method listIndex(STRING) {value vector ec {name ""}} {
	my ExtractVector $vector
	my call ${tcl.list.index} [list $value $len $ary $ec] $name
    }

    # Builder:listIndex(STRING,INT) --
    #
    #	Get an element of a list. NOTE: this operation can fail (e.g., because
    #	it can be given an invalid list) so it produces a STRING FAIL.
    #	Quadcode implementation ('listIndex').
    #
    # Parameters:
    #	value -	List value to get the length of, in an LLVM STRING reference.
    #	index -	Index value to use, in an LLVM INT reference.
    #	errVar -
    #		Location to write the Tcl return code into, as an LLVM int*
    #		reference.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	The element of the list, as an LLVM STRING FAIL reference.

    method listIndex(STRING,INT) {value index ec {name ""}} {
	my call ${tcl.list.index1} [list $value $index $ec] $name
    }

    # Builder:listIndex(STRING,STRING) --
    #
    #	Get an element of a list. NOTE: this operation can fail (e.g., because
    #	it can be given an invalid list) so it produces a STRING FAIL.
    #	Quadcode implementation ('listIndex').
    #
    # Parameters:
    #	value -	List value to get the length of, in an LLVM STRING reference.
    #	index -	Index value to use, in an LLVM STRING reference.
    #	errVar -
    #		Location to write the Tcl return code into, as an LLVM int*
    #		reference.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	The element of the list, as an LLVM STRING FAIL reference.

    method listIndex(STRING,STRING) {value index ec {name ""}} {
	my call ${tcl.list.indexList} [list $value $index $ec] $name
    }

    # Builder:listLength(STRING) --
    #
    #	Get the length of a list. NOTE: this operation can fail (e.g., because
    #	it can be given an invalid list) so it produces an INT FAIL. Quadcode
    #	implementation ('listLength').
    #
    # Parameters:
    #	value -	List value to get the length of, in an LLVM STRING reference.
    #	errVar -
    #		Location to write the Tcl return code into, as an LLVM int*
    #		reference.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	The length of the list, as an LLVM INT FAIL reference.

    method listLength(STRING) {value ec {name ""}} {
	my call ${tcl.list.length} [list $value $ec] $name
    }

    # Builder:listRange(STRING,INT,INT) --
    #
    #	Get a sublist of a list. NOTE: this operation can fail (e.g., because
    #	it can be given an invalid list) so it produces a STRING FAIL.
    #	Quadcode implementation ('listRange').
    #
    # Parameters:
    #	value -	List value to get a substring of, in an LLVM STRING reference.
    #	from -	Index of first element to return, in an LLVM INT reference.
    #	to -	Index of last element to return, in an LLVM INT reference.
    #	errVar -
    #		Location to write the Tcl return code into, as an LLVM int*
    #		reference.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	The sublist, as an LLVM STRING FAIL reference.

    method listRange(STRING,INT,INT) {value from to ec {name ""}} {
	my call ${tcl.list.range1} [list $value $from $to $ec] $name
    }

    # Builder:listRange(STRING,STRING,STRING) --
    #
    #	Get a sublist of a list. NOTE: this operation can fail (e.g., because
    #	it can be given an invalid list) so it produces a STRING FAIL.
    #	Quadcode implementation ('listRange').
    #
    # Parameters:
    #	value -	List value to get a substring of, in an LLVM STRING reference.
    #	from -	Index of first element to return, in an LLVM STRING reference.
    #	to -	Index of last element to return, in an LLVM STRING reference.
    #	errVar -
    #		Location to write the Tcl return code into, as an LLVM int*
    #		reference.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	The sublist, as an LLVM STRING FAIL reference.

    method listRange(STRING,STRING,STRING) {value from to ec {name ""}} {
	my call ${tcl.list.range} [list $value $from $to $ec] $name
    }

    # Builder:listSet(STRING,STRING) --
    #
    #	Update an element in a sublist of a list. NOTE: this operation can
    #	fail (e.g., because it can be given an invalid list) so it produces a
    #	STRING FAIL. Quadcode implementation ('listSet').
    #
    # Parameters:
    #	list -	List value to get a substring of, in an LLVM STRING reference.
    #	elem -	The value to write into the list, in an LLVM STRING reference.
    #	vector -
    #		The indices as an LLVM vector value reference.
    #	ecvar -	Location to write the Tcl return code into, as an LLVM int*
    #		reference.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	The updated list, as an LLVM STRING FAIL reference.

    method listSet(STRING,STRING) {list elem vector ecvar {name ""}} {
	my ExtractVector $vector
	my call ${tcl.list.set} [list $list $len $ary $elem $ecvar] $name
    }

    # Builder:listSet(STRING,INT,STRING) --
    #
    #	Update an element of a list. NOTE: this operation can fail (e.g.,
    #	because it can be given an invalid list) so it produces a STRING FAIL.
    #	Quadcode implementation ('listSet').
    #
    # Parameters:
    #	list -	List value update, in an LLVM STRING reference.
    #	idx -	The index into the list to set, in an LLVM INT reference.
    #	elem -	The value to write into the list, in an LLVM STRING reference.
    #	ecvar -	Location to write the Tcl return code into, as an LLVM int*
    #		reference.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	The updated list, as an LLVM STRING FAIL reference.

    method listSet(STRING,INT,STRING) {list idx elem ecvar {name ""}} {
	my call ${tcl.list.set1} [list $list $idx $elem $ecvar] $name
    }

    # Builder:listSet(STRING,STRING,STRING) --
    #
    #	Update an element of a list or sublist. NOTE: this operation can fail
    #	(e.g., because it can be given an invalid list) so it produces a
    #	STRING FAIL. Quadcode implementation ('listSet').
    #
    # Parameters:
    #	list -	List value update, in an LLVM STRING reference.
    #	idx -	The index into the list to set, in an LLVM STRING reference.
    #	elem -	The value to write into the list, in an LLVM STRING reference.
    #	ecvar -	Location to write the Tcl return code into, as an LLVM int*
    #		reference.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	The updated list, as an LLVM STRING FAIL reference.

    method listSet(STRING,STRING,STRING) {list idx elem ecvar {name ""}} {
	my call ${tcl.list.setList} [list $list $idx $elem $ecvar] $name
    }

    # Builder:lor(INT,INT) --
    #
    #	Generate code to compute the logical or of two INTs.  Quadcode
    #	implementation ('lor').
    #
    # Parameters:
    #	left -	The INT LLVM value reference for the left operand.
    #	right -	The INT LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A ZEROONE LLVM value reference.

    method lor(INT,INT) {left right {name ""}} {
	my call ${tcl.lor} [list $left $right] $name
    }

    # Builder:lor(INT,INT) --
    #
    #	Generate code to compute the logical or of two DOUBLEs.  Quadcode
    #	implementation ('lor').
    #
    # Parameters:
    #	left -	The DOUBLE LLVM value reference for the left operand.
    #	right -	The DOUBLE LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A ZEROONE LLVM value reference.

    method lor(DOUBLE,DOUBLE) {left right {name ""}} {
	my call ${tcl.lor.double} [list $left $right] $name
    }

    # Builder:lor(NUMERIC,NUMERIC) --
    #
    #	Generate code to compute the logical or of two NUMERICs. Quadcode
    #	implementation ('lor').
    #
    # Parameters:
    #	left -	The NUMERIC LLVM value reference for the left operand.
    #	right -	The NUMERIC LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A NUMERIC LLVM value reference.

    method lor(NUMERIC,NUMERIC) {left right {name ""}} {
	my call ${tcl.lor.numeric} [list $left $right] $name
    }

    # Builder:lshift(INT,INT) --
    #
    #	Generate code to shift an INT left (multiply by powers of 2). Quadcode
    #	implementation ('lshift').
    #
    # Parameters:
    #	left -	The INT LLVM value reference for the left operand.
    #	right -	The INT LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An INT LLVM value reference.

    method lshift(INT,INT) {left right {name ""}} {
	my call ${tcl.shl} [list $left $right] $name
    }

    # Builder:lt --
    #
    #	Generate code to compare two integers of the same bit width *or* two
    #	pointers to see if the first is less than the second.
    #
    # Parameters:
    #	left -	The int[X] or pointer LLVM value reference for the left
    #		operand. (X is any width supported by LLVM.)
    #	right -	The int[X] or pointer LLVM value reference for the right
    #		operand. (X is the same as for the 'left' parameter.)
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An int1 LLVM value reference.

    method lt {left right {name ""}} {
	if {[GetTypeKind [TypeOf $left]] eq "LLVMIntegerTypeKind"} {
	    my cmpInt $left SLT $right $name
	} else {
	    my cmpPtr $left SLT $right $name
	}
    }

    # Builder:lt(INT,INT) --
    #
    #	Generate code to see if one INT is less than another INT. Quadcode
    #	implementation ('lt').
    #
    # Parameters:
    #	left -	The INT LLVM value reference for the left operand.
    #	right -	The INT LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A ZEROONE LLVM value reference.

    method lt(INT,INT) {left right {name ""}} {
	my call ${tcl.lt} [list $left $right] $name
    }

    # Builder:lt(DOUBLE,DOUBLE) --
    #
    #	Generate code to compare two DOUBLEs for the first being less than the
    #	second. Quadcode implementation ('eq').
    #
    # Parameters:
    #	left -	The DOUBLE LLVM value reference for the left operand.
    #	right -	The DOUBLE LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A ZEROONE LLVM value reference.

    method lt(DOUBLE,DOUBLE) {left right {name ""}} {
	my cmpDbl $left LT $right $name
    }

    # Builder:lt(NUMERIC,NUMERIC) --
    #
    #	Generate code to compare two NUMERICs for the first being less than
    #	the second. Quadcode implementation ('lt').
    #
    # Parameters:
    #	left -	The NUMERIC LLVM value reference for the left operand.
    #	right -	The NUMERIC LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A ZEROONE LLVM value reference.

    method lt(NUMERIC,NUMERIC) {left right {name ""}} {
	my call ${tcl.lt.numeric} [list $left $right] $name
    }

    # Builder:lt(STRING,NUMERIC) --
    #
    #	Generate code to compare a STRING and a NUMERIC for the first being
    #	less than the second. Quadcode implementation ('lt').
    #
    # Parameters:
    #	left -	The STRING LLVM value reference for the left operand.
    #	right -	The NUMERIC LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A ZEROONE LLVM value reference.

    method lt(STRING,NUMERIC) {left right {name ""}} {
	my lt [my Call tcl.cmp.strnum $left $right] [Const 0] $name
    }
    method lt(NUMERIC,STRING) {left right {name ""}} {
	my gt [my Call tcl.cmp.strnum $right $left] [Const 0] $name
    }

    # Builder:lt(STRING,STRING) --
    #
    #	Generate code to compare two STRINGs for the first being less than the
    #	second. Quadcode implementation ('lt').
    #
    # Parameters:
    #	left -	The STRING LLVM value reference for the left operand.
    #	right -	The STRING LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A ZEROONE LLVM value reference.

    method lt(STRING,STRING) {left right {name ""}} {
	my lt [my Call tcl.cmp.strstr $left $right] [Const 0] $name
    }

    # Builder:just --
    #
    #	Package a value as a Just NEXIST.
    #
    # Parameters:
    #	value -	The value to put inside the NEXIST.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An LLVM NEXIST value reference containing the other value.

    method just {value {name ""}} {
	my insert [my insert [my undef [TypeOf $value]!] \
		       [Const false bool] 0] $value 1 $name
    }

    # Builder:narrowToType.DOUBLE(STRING) --
    #
    #	Generate code to parse the given STRING and extract a DOUBLE. The
    #	STRING is already be known to contain a value of the right type (due
    #	to higher-level quadcode constraints). Quadcode implementation
    #	('narrowToType').
    #
    # Parameters:
    #	value -	The STRING LLVM value reference to parse.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A DOUBLE LLVM value reference.

    method narrowToType.DOUBLE(STRING) {value {name ""}} {
	my call ${tcl.extractDouble} [list $value] $name
    }

    # Builder:narrowToType.IMPURE_DOUBLE(STRING) --
    #
    #	Generate code to extract IMPURE DOUBLE from STRING.  This parses the
    #	number in the string and pairs it up with the string, as well as
    #	adding a reference to the string itself.
    #
    # Parameters:
    #	value -	The STRING LLVM value reference to parse.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An IMPURE DOUBLE LLVM value reference.

    method narrowToType.IMPURE_DOUBLE(STRING) {value {name ""}} {
	set nval [my Call tcl.extractDouble $value]
	my addReference(STRING) $value
	return [my impure DOUBLE $value $nval $name]
    }

    # Builder:narrowToType.IMPURE_BOOLEAN(IMPURE ZEROONE BOOLEAN) --
    #
    #	Generate code to extract IMPURE BOOLEAN from IMPURE ZEROONE BOOLEAN.
    #	The extraction does nothing except bump the reference count, the two
    #	types have the same internal representation
    #
    # Parameters:
    #	value -	The STRING LLVM value reference to parse.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An IMPURE BOOLEAN LLVM value reference.

    method narrowToType.IMPURE_BOOLEAN(IMPURE\040ZEROONE\040BOOLEAN) {value {name ""}} {
	my addReference(STRING) [my impure.string $value]
	if {$name ne "" && [string match {[0-9]*} [GetValueName $value]]} {
	    SetValueName $value $name
	}
	return $value
    }

    # Builder:narrowToType.IMPURE_ZEROONE(IMPURE ZEROONE BOOLEAN) --
    #
    #	Generate code to extract IMPURE ZEROONE from IMPURE ZEROONE BOOLEAN.
    #	The extracton does nothing except bump the reference count, the two
    #	types have the same internal representation
    #
    # Parameters:
    #	value -	The STRING LLVM value reference to parse.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An IMPURE ZEROONE LLVM value reference.

    method narrowToType.IMPURE_ZEROONE(IMPURE\040ZEROONE\040BOOLEAN) {value {name ""}} {
	my addReference(STRING) [my impure.string $value]
	if {$name ne "" && [string match {[0-9]*} [GetValueName $value]]} {
	    SetValueName $value $name
	}
	return $value
    }
    
    # Builder:narrowToType.INT(STRING) --
    #
    #	Generate code to parse the given STRING and extract an INT. The STRING
    #	is already be known to contain a value of the right type (due to
    #	higher-level quadcode constraints). Quadcode implementation
    #	('narrowToType').
    #
    # Parameters:
    #	value -	The STRING LLVM value reference to parse.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An INT LLVM value reference.

    method narrowToType.INT(STRING) {value {name ""}} {
	my call ${tcl.extractInteger} [list $value] $name
    }

    # Builder:narrowToType.IMPURE_INT(STRING) --
    #
    #	Generate code to extract IMPURE INT from STRING.  This parses the
    #	number in the string and pairs it up with the string, as well as
    #	adding a reference to the string itself.
    #
    # Parameters:
    #	value -	The STRING LLVM value reference to parse.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An IMPURE INT LLVM value reference.

    method narrowToType.IMPURE_INT(STRING) {value {name ""}} {
	set nval [my Call tcl.extractInteger $value]
	my addReference(STRING) $value
	return [my impure INT $value $nval $name]
    }

    # Builder:narrowToType.INT(NUMERIC) --
    #
    #	Generate code to narrow a NUMERIC to an INT.
    #
    # Parameters:
    #	value - The NUMERIC LLVM reference to parse
    #	name (optional) -
    #		A name to give to the result value

    method narrowToType.INT(NUMERIC) {value {name ""}} {
	my numeric.int $value $name
    }

    # Builder:narrowToType.IMPURE_INT(IMPURE NUMERIC) --
    #
    #	Generate code to extract IMPURE INT from IMPURE NUMERIC.  This narrows
    #	the number in the string and pairs it up with the string part, as well
    #	as adding a reference to the string itself.
    #
    # Parameters:
    #	value -	The IMPURE NUMERIC LLVM value reference to narrow.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An IMPURE DOUBLE LLVM value reference.

    method {narrowToType.IMPURE_INT(IMPURE NUMERIC)} {value {name ""}} {
	set sval [my impure.string $value]
	my addReference(STRING) $sval
	set nval [my numeric.int [my impure.value $value]]
	return [my impure INT $sval $nval $name]
    }

    # Builder:narrowToType.NUMERIC(STRING) --
    #
    #	Generate code to parse the given STRING and extract a NUMERIC. The
    #	STRING is already be known to contain a value of the right type (due
    #	to higher-level quadcode constraints). Quadcode implementation
    #	('narrowToType').
    #
    # Parameters:
    #	value -	The STRING LLVM value reference to parse.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A NUMERIC LLVM value reference.

    method narrowToType.NUMERIC(STRING) {value {name ""}} {
	my call ${tcl.extractNumeric} [list $value] $name
    }

    # Builder:narrowToType.IMPURE_NUMERIC(STRING) --
    #
    #	Generate code to extract IMPURE NUMERIC from STRING.  This parses the
    #	number in the string and pairs it up with the string, as well as
    #	adding a reference to the string itself.
    #
    # Parameters:
    #	value -	The STRING LLVM value reference to parse.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An IMPURE NUMERIC LLVM value reference.

    method narrowToType.IMPURE_NUMERIC(STRING) {value {name ""}} {
	set nval [my call ${tcl.extractNumeric} [list $value]]
	my addReference(STRING) $value
	return [my impure NUMERIC $value $nval $name]
    }

    # Builder:nothing --
    #
    #	Create a Nothing NEXIST of the given type.
    #
    # Parameters:
    #	type -	The type of the NEXIST.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An LLVM NEXIST value reference containing nothing.

    method nothing {type {name ""}} {
	if {[string match "* NEXIST" $type]} {
	    set type [string range $type 0 end-7]
	} elseif {[string match "NEXIST *" $type]} {
	    set type [string range $type 7 end]
	}
	my insert [my undef $type!] [Const true bool] 0 $name
    }

    # Builder:unmaybe --
    #
    #	Get the value out of a FAIL or NEXIST. NOTE: The FAIL/NEXIST must be a
    #	Just or the result will be an 'undef'; test with the 'maybe' method
    #	first!
    #
    # Parameters:
    #	value -	The FAIL to get the value from.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An LLVM value reference containing nothing.

    method unmaybe {value {name ""}} {
	my extract $value 1 $name
    }

    # Builder:maptoint(STRING) --
    #
    #	Look up a positive integer in a dictionary, or give the not-there
    #	value if the value is not present.
    #
    # Parameters:
    #	value -	The FAIL to examine.
    #	mapping -
    #		The mapping from values to integers. Tcl dictionary
    #	notThere -
    #		A value guaranteed to be not present in the mapping. Tcl int.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An LLVM INT value reference.

    method maptoint(STRING) {value mapping notThere {name ""}} {
	set mapping [my @jumptable.constant $mapping]
	set notThere [Const $notThere int]
	my call ${tcl.maptoint} [list $value $mapping $notThere] $name
    }

    # Builder:maybe --
    #
    #	Test if the FAIL or NEXIST value is a Nothing.
    #
    # Parameters:
    #	type -	The FAIL or NEXIST to examine.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An LLVM int1 value reference that is true when the FAIL is a Nothing
    #	and false when the FAIL is a Just.

    method maybe {value {name ""}} {
	set flag [my extract $value 0 $name]
	if {[TypeOf $flag] eq [Type bool]} {
	    my neq [Const false bool] $flag
	} else {
	    my neq [Const 0] $flag
	}
    }

    # Builder:max --
    #
    #	Determines the maximum of two LLVM int[x] values.
    #
    # Parameters:
    #	x -	The int[x] LLVM value reference for one operand.
    #	y -	The int[x] LLVM value reference for one operand.
    #	name (optional) -
    #		The name of the result value.
    #
    # Results:
    #	LLVM int[x] value that is the maximum of the two arguments.

    method max {x y {name "max"}} {
	my select [my gt $x $y] $x $y $name
    }

    # Builder:min --
    #
    #	Determines the minimum of two LLVM int[x] values.
    #
    # Parameters:
    #	x -	The int[x] LLVM value reference for one operand.
    #	y -	The int[x] LLVM value reference for one operand.
    #	name (optional) -
    #		The name of the result value.
    #
    # Results:
    #	LLVM int[x] value that is the minimum of the two arguments.

    method min {x y {name "min"}} {
	my select [my lt $x $y] $x $y $name
    }

    # Builder:mod(INT,INT) --
    #
    #	Generate code to compute the mod of one INT by another INT. Quadcode
    #	implementation ('mod').
    #
    # Parameters:
    #	left -	The INT LLVM value reference for the left operand.
    #	right -	The INT LLVM value reference for the right operand.
    #	ec -	Where to write the error code if an error happens.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An INT LLVM value reference.

    method mod(INT,INT) {left right ec {name ""}} {
	my call ${tcl.mod} [list $left $right $ec] $name
    }

    # Builder:mult(INT,INT) --
    #
    #	Generate code to multiply two INTs. Quadcode implementation ('mult').
    #
    # Parameters:
    #	left -	The INT LLVM value reference for the left operand.
    #	right -	The INT LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An INT LLVM value reference.

    method mult(INT,INT) {left right {name ""}} {
	my call ${tcl.mul} [list $left $right] $name
    }

    # Builder:mult(DOUBLE,DOUBLE) --
    #
    #	Generate code to multiply two DOUBLEs. Quadcode implementation
    #	('mult').
    #
    # Parameters:
    #	left -	The DOUBLE LLVM value reference for the left operand.
    #	right -	The DOUBLE LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A DOUBLE LLVM value reference.

    method mult(DOUBLE,DOUBLE) {left right {name ""}} {
	my mult $left $right $name
    }

    # Builder:mult(DOUBLE,NUMERIC) --
    #
    #	Generate code to multiply a DOUBLE by a NUMERIC. Quadcode
    #	implementation ('mult').
    #
    # Parameters:
    #	left -	The DOUBLE LLVM value reference for the left operand.
    #	right -	The NUMERIC LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A DOUBLE LLVM value reference.

    method mult(DOUBLE,NUMERIC) {left right {name ""}} {
	my mult(DOUBLE,DOUBLE) $left [my NumToDbl $right] $name
    }

    # Builder:mult(NUMERIC,DOUBLE) --
    #
    #	Generate code to multiply a NUMERIC by a DOUBLE. Quadcode
    #	implementation ('mult').
    #
    # Parameters:
    #	left -	The NUMERIC LLVM value reference for the left operand.
    #	right -	The DOUBLE LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A DOUBLE LLVM value reference.

    method mult(NUMERIC,DOUBLE) {left right {name ""}} {
	my mult(DOUBLE,DOUBLE) [my NumToDbl $left] $right $name
    }

    # Builder:mult(INT,NUMERIC) --
    #
    #	Generate code to multiply an INT and a NUMERIC. Quadcode
    #	implementation ('mult').
    #
    # Parameters:
    #	left -	The INT LLVM value reference for the left operand.
    #	right -	The NUMERIC LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A NUMERIC LLVM value reference.

    method mult(INT,NUMERIC) {left right {name ""}} {
	my mult(NUMERIC,NUMERIC) [my packNumericInt $left] $right $name
    }

    # Builder:mult(NUMERIC,INT) --
    #
    #	Generate code to multiply a NUMERIC and an INT. Quadcode
    #	implementation ('mult').
    #
    # Parameters:
    #	left -	The NUMERIC LLVM value reference for the left operand.
    #	right -	The INT LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A NUMERIC LLVM value reference.

    method mult(NUMERIC,INT) {left right {name ""}} {
	my mult(NUMERIC,NUMERIC) $left [my packNumericInt $right] $name
    }

    # Builder:mult(NUMERIC,NUMERIC) --
    #
    #	Generate code to multiply two NUMERICs. Quadcode implementation
    #	('mult').
    #
    # Parameters:
    #	left -	The NUMERIC LLVM value reference for the left operand.
    #	right -	The NUMERIC LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A NUMERIC LLVM value reference.

    method mult(NUMERIC,NUMERIC) {left right {name ""}} {
	my call ${tcl.mult.numeric} [list $left $right] $name
    }

    # Builder:neq --
    #
    #	Generate code to compare two integers of the same bit width *or* two
    #	pointers to see if the first is not equal to the second.
    #
    # Parameters:
    #	left -	The int[X] or pointer LLVM value reference for the left
    #		operand. (X is any width supported by LLVM.)
    #	right -	The int[X] or pointer LLVM value reference for the right
    #		operand. (X is the same as for the 'left' parameter.)
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An int1 LLVM value reference.

    method neq {left right {name ""}} {
	if {[GetTypeKind [TypeOf $left]] eq "LLVMIntegerTypeKind"} {
	    my cmpInt $left NE $right $name
	} else {
	    my cmpPtr $left NE $right $name
	}
    }

    # Builder:neq(INT,INT) --
    #
    #	Generate code to see if two INTs are not equal. Quadcode
    #	implementation ('neq').
    #
    # Parameters:
    #	left -	The INT LLVM value reference for the left operand.
    #	right -	The INT LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A ZEROONE LLVM value reference.

    method neq(INT,INT) {left right {name ""}} {
	my call ${tcl.ne} [list $left $right] $name
    }

    # Builder:neq(DOUBLE,DOUBLE) --
    #
    #	Generate code to compare two DOUBLEs for inequalty. Quadcode
    #	implementation ('eq').
    #
    # Parameters:
    #	left -	The DOUBLE LLVM value reference for the left operand.
    #	right -	The DOUBLE LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A ZEROONE LLVM value reference.

    method neq(DOUBLE,DOUBLE) {left right {name ""}} {
	my cmpDbl $left NE $right $name
    }

    # Builder:neq(NUMERIC,NUMERIC) --
    #
    #	Generate code to compare two NUMERICs for being not equal. Quadcode
    #	implementation ('neq').
    #
    # Parameters:
    #	left -	The NUMERIC LLVM value reference for the left operand.
    #	right -	The NUMERIC LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A ZEROONE LLVM value reference.

    method neq(NUMERIC,NUMERIC) {left right {name ""}} {
	my call ${tcl.ne.numeric} [list $left $right] $name
    }

    # Builder:neq(STRING,NUMERIC) --
    #
    #	Generate code to compare a STRING and a NUMERIC for inequalty.
    #	Quadcode implementation ('neq').
    #
    # Parameters:
    #	left -	The STRING LLVM value reference for the left operand.
    #	right -	The NUMERIC LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A ZEROONE LLVM value reference.

    method neq(STRING,NUMERIC) {left right {name ""}} {
	my neq [my Call tcl.cmp.strnum $left $right] [Const 0] $name
    }
    method neq(NUMERIC,STRING) {left right {name ""}} {
	my neq [my Call tcl.cmp.strnum $right $left] [Const 0] $name
    }

    # Builder:neq(STRING,STRING) --
    #
    #	Generate code to compare two STRINGs for inequalty. Quadcode
    #	implementation ('neq').
    #
    # Parameters:
    #	left -	The STRING LLVM value reference for the left operand.
    #	right -	The STRING LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A ZEROONE LLVM value reference.

    method neq(STRING,STRING) {left right {name ""}} {
	my neq [my Call tcl.cmp.strstr $left $right] [Const 0] $name
    }

    # Builder:not(DOUBLE) --
    #
    #	Generate code to create the logical not of a DOUBLE. Quadcode
    #	implementation ('not').
    #
    # Parameters:
    #	value -	The DOUBLE LLVM value reference for the operand.
    #	errVar -
    #		Location to write the Tcl return code into, as an LLVM int*
    #		reference. (unused)
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A ZEROONE LLVM value reference.

    method not(DOUBLE) {value errVar {name ""}} {
	my eq(DOUBLE,DOUBLE) $value [Const 0.0 double] $name
    }

    # Builder:not(INT) --
    #
    #	Generate code to create the logical not of an INT. Quadcode
    #	implementation ('not').
    #
    # Parameters:
    #	value -	The INT LLVM value reference for the operand.
    #	errVar -
    #		Location to write the Tcl return code into, as an LLVM int*
    #		reference. (unused)
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A ZEROONE LLVM value reference.

    method not(INT) {value errVar {name ""}} {
	my eq(INT,INT) $value [my int 0] $name
    }

    # Builder:not(NUMERIC) --
    #
    #	Generate code to create the logical not of a NUMERIC. Quadcode
    #	implementation ('not').
    #
    # Parameters:
    #	value -	The NUMERIC LLVM value reference for the operand.
    #	errVar -
    #		Location to write the Tcl return code into, as an LLVM int*
    #		reference. (unused)
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A NUMERIC LLVM value reference.

    method not(NUMERIC) {value errVar {name ""}} {
	my call ${tcl.not.numeric} [list $value] $name
    }

    # Builder:not(STRING) --
    #
    #	Generate code to create the logical not of a STRING. Quadcode
    #	implementation ('not').
    #
    # Parameters:
    #	value -	The NUMERIC LLVM value reference for the operand.
    #	errVar -
    #		Location to write the Tcl return code into, as an LLVM int*
    #		reference.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A NUMERIC LLVM value reference.

    method not(STRING) {value errVar {name ""}} {
	my call ${tcl.not.string} [list $value $errVar] $name
    }

    # Builder:not(ZEROONE) --
    #
    #	Generate code to create the logical not of a ZEROONE. Quadcode
    #	implementation ('not').
    #
    # Parameters:
    #	value -	The ZEROONE LLVM value reference for the operand.
    #	errVar -
    #		Location to write the Tcl return code into, as an LLVM int*
    #		reference. (unused)
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A ZEROONE LLVM value reference.

    method not(ZEROONE) {value errVar {name ""}} {
	my not $value $name
    }

    # Builder:ok --
    #
    #	Package a value as a Just FAIL.
    #
    # Parameters:
    #	value -	The value to put inside the FAIL.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An LLVM FAIL value reference containing the other value.

    method ok {value {name ""}} {
	my insert [my insert [my undef [TypeOf $value]?] \
		       [Const 0] 0] $value 1 $name
    }

    # Builder:packImpure(DOUBLE) --
    #
    #	Convert a DOUBLE to an IMPURE DOUBLE
    #
    # Parameters:
    #	value -	LLVM Value to pack into the 'impure' structure
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	Returns an LLVM IMPURE DOUBLE value

    method packImpure(DOUBLE) {value {name ""}} {
	set sval [my stringify(DOUBLE) $value]
	my addReference(STRING) $sval
	return [my impure DOUBLE $sval $value $name]
    }

    # Builder:packImpure(INT) --
    #
    #	Convert a INT to an IMPURE INT
    #
    # Parameters:
    #	value -	LLVM Value to pack into the 'impure' structure
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	Returns an LLVM IMPURE INT value

    method packImpure(INT) {value {name ""}} {
	set sval [my stringify(INT) $value]
	my addReference(STRING) $sval
	return [my impure INT $sval $value $name]
    }

    # Builder:packImpure(NUMERIC) --
    #
    #	Convert a NUMERIC to an IMPURE NUMERIC
    #
    # Parameters:
    #	value -	LLVM Value to pack into the 'impure' structure
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	Returns an LLVM IMPURE NUMERIC value

    method packImpure(NUMERIC) {value {name ""}} {
	set sval [my stringify(NUMERIC) $value]
	my addReference(STRING) $sval
	return [my impure NUMERIC $sval $value $name]
    }

    # Builder:packImpure(ZEROONE BOOLEAN) --
    #
    #	Convert a ZEROONE BOOLEAN to an IMPURE ZEROONE BOOLEAN
    #
    # Parameters:
    #	value -	LLVM Value to pack into the 'impure' structure
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	Returns an LLVM IMPURE NUMERIC value

    method {packImpure(ZEROONE BOOLEAN)} {value {name ""}} {
	set sval [my stringify(NUMERIC) $value]
	my addReference(STRING) $sval
	return [my impure ZEROONE $sval $value $name]
    }

    # Builder:proc.return --
    #
    #	Convert a return code in the way the end of a procedure does.
    #
    # Parameters:
    #	value -	LLVM Value to pack into the 'impure' structure
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	Returns an LLVM IMPURE NUMERIC value

    method proc.return {value procName} {
	set name [Const $procName STRING]
	return [my call ${tcl.procedure.return} [list $value $name] "code"]
    }

    # Builder:regexp(INT,STRING,STRING) --
    #
    #	Match a string against a regular expression. NOTE: this operation can
    #	fail (e.g., because it can be given an invalid regexp) so it produces
    #	an INT FAIL. Quadcode implementation ('regexp').
    #
    # Parameters:
    #	opts -	Flags that control the match, in an LLVM INT reference.
    #	regexpr -
    #		Regular expression, in an LLVM STRING reference.
    #	value -	Value to match against, in an LLVM STRING reference.
    #	errVar -
    #		Location to write the Tcl return code into, as an LLVM int*
    #		reference.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	Whether any/how many matches occurred, as an LLVM ZEROONE FAIL
    #	reference.

    method regexp(INT,STRING,STRING) {opts regexpr value errVar {name ""}} {
	my call ${tcl.regexp} [list $opts $regexpr $value $errVar] $name
    }

    # Builder:resolveCmd(STRING) --
    #
    #	Resolve the given command. Quadcode implementation ('resolveCmd').
    #
    # Parameters:
    #	cmdName - Name of the command being resolved
    #	name (optional) - A name to give to the result value
    #
    # Results:
    #	Returns an LLVM STRING value giving the resolved command name
    #   or an empty string if the command cannot be resolved.

    method resolveCmd(STRING) {cmdName {name ""}} {
	my call ${tcl.resolveCmd} [list $cmdName] $name
    }

    # Builder:originCmd(STRING) --
    #
    #	Resolve the original name of the given command.
    #   Quadcode implementation ('originCmd').
    #
    # Parameters:
    #	cmdName - Name of the command being resolved
    #	ec - Where to store the error code
    #	name (optional) - A name to give to the result value
    #
    # Results:
    #	Returns an LLVM STRING value giving the resolved command name
    #   or an empty string if the command cannot be resolved.

    method originCmd(STRING) {cmdName ec {name ""}} {
	my call ${tcl.originCmd} [list $cmdName $ec] $name
    }

    # Builder:result() --
    #
    #	Get the Tcl result. Quadcode implementation ('result').
    #
    # Parameters:
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An LLVM STRING reference.

    method result() {{name ""}} {
	my call ${tcl.getresult} {} $name
    }

    # Builder:returnOptions(INT) --
    #
    #	Get the Tcl exception dictionary. Quadcode implementation
    #	('returnOptions').
    #
    # Parameters:
    #	value -	The Tcl result code, as an LLVM INT value reference.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An LLVM STRING reference.

    method returnOptions(INT) {value {name ""}} {
	my call ${tcl.getreturnopts} [list $value] $name
    }

    # Builder:rshift(INT,INT) --
    #
    #	Generate code to shift an INT right (divide by powers of 2). Quadcode
    #	implementation ('rshift').
    #
    # Parameters:
    #	left -	The INT LLVM value reference for the left operand.
    #	right -	The INT LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An INT LLVM value reference.

    method rshift(INT,INT) {left right {name ""}} {
	my call ${tcl.shr} [list $left $right] $name
    }

    # Builder:logCommandInfo --
    #
    #	Generate code to log information about a command in the exception
    #	trace.
    #
    # Parameters:
    #	errorCode -
    #		The int32 LLVM value reference for the Tcl error code.
    #	command -
    #		The Tcl string containing the text of the command script
    #		(i.e., sourced before substitutions are performed).
    #
    # Results:
    #	None.

    method logCommandInfo {errorCode command} {
	set limit 150
	set overflow [expr {[string length $command] > $limit}]
	set length [Const [expr {$overflow ? $limit : [string length $command]}]]
	set cmd [my constString $command]
	set ellipsis [my constString [if {$overflow} {string cat "..."}]]
	my Call tcl.logCommandInfo $errorCode $length $cmd $ellipsis
	return
    }

    # Builder:setErrorLine --
    #
    #	Generate code to log information about a command in the exception
    #	trace if that command happens to have generated an error.
    #
    # Parameters:
    #	test -	The bool LLVM value reference that says whether the command
    #		this is talking about generated a non-TCL_OK result.
    #	errorCode -
    #		The int32 LLVM value reference for the Tcl error code.
    #	line -	The int32 LLVM value reference for the source line number for
    #		the (start of) the command.
    #	command -
    #		The Tcl string containing the text of the command script
    #		(i.e., sourced before substitutions are performed).
    #
    # Results:
    #	None.

    method setErrorLine {test errorCode line command} {
	set limit 150
	set overflow [expr {[string length $command] > $limit}]
	set length [Const [expr {$overflow ? $limit : [string length $command]}]]
	set cmd [my constString $command]
	set ellipsis [my constString [if {$overflow} {string cat "..."}]]
	my Call tcl.setErrorLine $test $errorCode $line $length $cmd $ellipsis
	return
    }

    method storeInStruct {structPointer fieldOffset value} {
	set field [my gep $structPointer 0 $fieldOffset]
	set fieldName [regsub {.*\.} $fieldOffset ""]
	SetValueName $field [GetValueName $structPointer].$fieldName
	my store $value $field
    }

    # Builder:stringify(DOUBLE) --
    #
    #	Generate a STRING representation of a DOUBLE. WARNING: caller is
    #	entirely responsible for reference count management; this method does
    #	not handle that. This method is used by the type promotion code.
    #
    # Parameters:
    #	value -	The DOUBLE LLVM value reference to convert.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A STRING LLVM value reference.

    method stringify(DOUBLE) {value {name ""}} {
	my call ${tcl.stringify.double} [list $value] $name
    }

    # Builder:stringify(IMPURE DOUBLE) --
    #
    #	Generate a STRING representation of an IMPURE DOUBLE. WARNING: caller
    #	is entirely responsible for reference count management; this method
    #	does not handle that. This method is used by the type promotion code.
    #
    # Parameters:
    #	value -	The IMPURE DOUBLE LLVM value reference to convert.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A STRING LLVM value reference.

    method stringify(IMPURE\040DOUBLE) {value {name ""}} {
	my stringifyImpure $value $name
    }

    # Builder:stringify(INT) --
    #
    #	Generate a STRING representation of an INT. WARNING: caller is
    #	entirely responsible for reference count management; this method does
    #	not handle that. This method is used by the type promotion code.
    #
    # Parameters:
    #	value -	The INT LLVM value reference to convert.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A STRING LLVM value reference.

    method stringify(INT) {value {name ""}} {
	my call ${tcl.stringify.int} [list $value] $name
    }

    # Builder:stringify(IMPURE INT) --
    #
    #	Generate a STRING representation of an IMPURE INT. WARNING: caller is
    #	entirely responsible for reference count management; this method does
    #	not handle that. This method is used by the type promotion code.
    #
    # Parameters:
    #	value -	The IMPURE INT LLVM value reference to convert.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A STRING LLVM value reference.

    method stringify(IMPURE\040INT) {value {name ""}} {
	my stringifyImpure $value $name
    }

    # Builder:stringify(NUMERIC) --
    #
    #	Generate a STRING representation of a NUMERIC. WARNING: caller is
    #	entirely responsible for reference count management; this method does
    #	not handle that. This method is used by the type promotion code.
    #
    # Parameters:
    #	value -	The NUMERIC LLVM value reference for the operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A STRING LLVM value reference.

    method stringify(NUMERIC) {value {name ""}} {
	my call ${tcl.stringify.numeric} [list $value] $name
    }

    # Builder:stringify(IMPURE NUMERIC) --
    #
    #	Generate a STRING representation of an IMPURE NUMERIC. WARNING: caller
    #	is entirely responsible for reference count management; this method
    #	does not handle that. This method is used by the type promotion code.
    #
    # Parameters:
    #	value -	The IMPURE NUMERIC LLVM value reference for the operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A STRING LLVM value reference.

    method stringify(IMPURE\040NUMERIC) {value {name ""}} {
	my stringifyImpure $value $name
    }

    # Builder:stringify(STRING) --
    #
    #	Do-nothing pass through.
    #
    # Parameters:
    #	value -	The INT LLVM value reference to convert.
    #	name (optional) -
    #		A name to give to the result value. Ignored.
    #
    # Results:
    #	A STRING LLVM value reference.

    method stringify(STRING) {value {name ""}} {
	return $value
    }

    # Builder:stringifyImpure --
    #
    #	Extract the string value of an impure object
    #
    # Parameters:
    #	value - The LLVM value to convert
    #	name (optional) -
    #		A name to give the result value
    #
    # Results:
    #	The string value is extracted. No refcount management is performed.

    method stringifyImpure {value {name ""}} {
	set v [my impure.string $value]
	if {$name ne ""} {
	    SetValueName $v $name
	}
	return $v
    }

    # Builder:strcase(STRING,INT) --
    #
    #	Generate a STRING that is a copy of an input STRING with a case
    #	transformation applied to it; the case transformation is described by
    #	an INT (0 means convert to upper case, 1 means convert to lower case,
    #	and 2 means convert to title case) which is expected to be a literal
    #	for performance reasons. This is the implementation of the 'strcase'
    #	quadcode.
    #
    # Parameters:
    #	value -	The STRING LLVM value reference to convert.
    #	kind -	The INT LLVM value reference that says what conversion to
    #		apply.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A STRING LLVM value reference. This will have a non-zero reference
    #	count.

    method strcase(STRING,INT) {value kind {name ""}} {
	my call ${tcl.strcase} [list $value [my getInt32 $kind]] $name
    }

    # Builder:strclass(STRING,INT) --
    #
    #	Generate an INT (0/1) that says whether all characters in an input
    #	STRING are members of a particular character class; the class is
    #	described by an INT (0 for 'alnum', 1 for 'alpha', 2 for 'ascii', 3
    #	for 'control', 4 for 'digit', 5 for 'graph', 6 for 'lower', 7 for
    #	'print', 8 for 'punct', 9 for 'space', 10 for 'upper', 11 for 'word',
    #	and 12 for 'xdigit') which is expected to be a literal for performance
    #	reasons. This is the implementation of the 'strclass' quadcode.
    #
    # Parameters:
    #	value -	The STRING LLVM value reference to convert.
    #	class -	The INT LLVM value reference that says what class to check
    #		for.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A ZEROONE LLVM value reference.

    method strclass(STRING,INT) {value class {name ""}} {
	my call ${tcl.strclass} [list $value [my getInt32 $class]] $name
    }

    # Builder:strcmp(STRING,STRING) --
    #
    #	Generate an INT that is whether an input STRING is smaller, equal to,
    #	or greater than another input STRING. This is the implementation of
    #	the 'strcmp' quadcode.
    #
    # Parameters:
    #	left -	The first STRING LLVM value reference to compare.
    #	right -	The second STRING LLVM value reference to compare.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An INT LLVM value reference; -1 for 'left' greater, 0 for equal, 1 for
    #	'right' greater.

    method strcmp(STRING,STRING) {left right {name ""}} {
	set val [my Call tcl.strcmp $left $right]
	my select [my lt $val [Const 0]] [my int -1] [
		my select [my gt $val [Const 0]] [my int 1] [my int 0]] \
	    $name
    }

    # Builder:streq(STRING,STRING) --
    #
    #	Generate an INT that contains whether two input STRINGs are equal.
    #	This is the implementation of the 'streq' quadcode.
    #
    # Parameters:
    #	left -	The first STRING LLVM value reference to compare.
    #	right -	The second STRING LLVM value reference to compare.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A boolean-coded INT LLVM value reference.

    method streq(STRING,STRING) {left right {name ""}} {
	my call ${tcl.streq} [list $left $right] $name
    }

    # Builder:strfind(STRING,STRING) --
    #
    #	Generate an INT that describes the first index in the second input
    #	STRING where the first input STRING is located; if the 'needle' is
    #	absent (including if it is larger than the 'haystack') then the result
    #	is -1.  This is the implementation of the 'strfind' quadcode.
    #
    # Parameters:
    #	needle -
    #		The STRING LLVM value reference to search for.
    #	haystack -
    #		The STRING LLVM value reference to search within.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An INT LLVM value reference.

    method strfind(STRING,STRING) {needle haystack {name ""}} {
	my call ${tcl.strfind.fwd} [list $needle $haystack] $name
    }

    # Builder:strindex(STRING,INT) --
    #
    #	Generate a STRING (of length 1) that describes the character in the
    #	input STRING located at the index given by the input INT, or the empty
    #	STRING if that index does not indicate a character in the STRING.
    #	This is the implementation of the 'strindex' quadcode.
    #
    # Parameters:
    #	str -	The STRING LLVM value reference to index into.
    #	idx -	The INT LLVM value reference to use as the index.
    #	ecvar -	Location to write the Tcl return code into, as an LLVM int*
    #		reference. (Ignored.)
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A STRING FAIL LLVM value reference (never a nothing). This will have a
    #	non-zero reference count.

    method strindex(STRING,INT) {str idx ecvar {name ""}} {
	my ok [my Call tcl.stridx $str $idx] $name
    }

    # Builder:strindex(STRING,STRING) --
    #
    #	Generate a STRING (of length 1) that describes the character in the
    #	input STRING located at the index given by the input STRING, or the
    #	empty STRING if that index does not indicate a character in the
    #	STRING. This is the implementation of the 'strindex' quadcode.
    #
    # Parameters:
    #	str -	The STRING LLVM value reference to index into.
    #	idx -	The STRING LLVM value reference to use as the index.
    #	ecvar -	Location to write the Tcl return code into, as an LLVM int*
    #		reference.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A STRING LLVM value reference. This will have a non-zero reference
    #	count.

    method strindex(STRING,STRING) {str idx ecvar {name ""}} {
	my call ${tcl.stridx.idx} [list $str $idx $ecvar] $name
    }

    # Builder:strlen(STRING) --
    #
    #	Generate an INT that describes the length of the input STRING. This is
    #	the implementation of the 'strlen' quadcode.
    #
    # Parameters:
    #	value -	The STRING LLVM value reference to get the length of.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An INT LLVM value reference.

    method strlen(STRING) {value {name ""}} {
	my call ${tcl.strlen} [list $value] $name
    }

    # Builder:strmap(STRING,STRING,STRING) --
    #
    #	Generate a STRING that contains a copy of an input STRING with each
    #	instance of a source STRING replaced with a target STRING. This is the
    #	implementation of the 'strmap' quadcode.
    #
    # Parameters:
    #	source -
    #		The STRING LLVM value reference containing the string to be
    #		replaced.
    #	target -
    #		The STRING LLVM value reference holding the string to use as a
    #		replacement.
    #	string -
    #		The STRING LLVM value reference holding the string to have the
    #		replacements applied to.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A STRING LLVM value reference. This will have a non-zero reference
    #	count.

    method strmap(STRING,STRING,STRING) {source target string {name ""}} {
	my call ${tcl.strmap} [list $source $target $string] $name
    }

    # Builder:strmatch(INT,STRING,STRING) --
    #
    #	Generate an INT that contains whether an input STRING matches a glob
    #	pattern in an input STRING. The INT 'flag' (holding a boolean,
    #	expected to be literal) states whether to apply case-sensitive
    #	matching. This is the implementation of the 'strmatch' quadcode.
    #
    # Parameters:
    #	flag -	The INT LLVM value reference to compare stating whether to
    #		match case-sensitively.
    #	pattern -
    #		The STRING LLVM value reference holding the glob pattern.
    #	string -
    #		The STRING LLVM value reference holding the string to test.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A boolean-coded INT LLVM value reference.

    method strmatch(INT,STRING,STRING) {flag pattern string {name ""}} {
	my call ${tcl.strmatch} [list $flag $pattern $string] $name
    }

    # Builder:strrange(STRING,INT,INT) --
    #
    #	Generate a STRING that describes the substring of the input STRING
    #	located from the index given by the input INT 'from' to the index
    #	given by the input INT 'to', or the empty STRING if those indices
    #	(which will be clamped to the STRING's valid indices) does not
    #	indicate a valid substring. This is the implementation of the
    #	'strrange' quadcode.
    #
    # Parameters:
    #	str -	The STRING LLVM value reference to index into.
    #	from -	The INT LLVM value reference to use as the start index.
    #	to -	The INT LLVM value reference to use as the finish index.
    #	ecvar -	Location to write the Tcl return code into, as an LLVM int*
    #		reference. (Ignored.)
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A STRING FAIL LLVM value reference (never a nothing). This will have a
    #	non-zero reference count.

    method strrange(STRING,INT,INT) {str from to ecvar {name ""}} {
	my ok [my Call tcl.strrange $str $from $to] $name
    }

    # Builder:strrange(STRING,STRING,STRING) --
    #
    #	Generate a STRING that describes the substring of the input STRING
    #	located from the index given by the input STRING 'from' to the index
    #	given by the input STRING 'to', or the empty STRING if those indices
    #	(which will be clamped to the STRING's valid indices) does not
    #	indicate a valid substring. This is the implementation of the
    #	'strrange' quadcode.
    #
    # Parameters:
    #	str -	The STRING LLVM value reference to index into.
    #	from -	The STRING LLVM value reference to use as the start index.
    #	to -	The STRING LLVM value reference to use as the finish index.
    #	ecvar -	Location to write the Tcl return code into, as an LLVM int*
    #		reference.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A STRING FAIL LLVM value reference. This will have a non-zero
    #	reference count.

    method strrange(STRING,STRING,STRING) {str from to ecvar {name ""}} {
	my call ${tcl.strrange.idx} [list $str $from $to $ecvar] $name
    }

    # Builder:strreplace(STRING,INT,INT,STRING) --
    #
    #	Generate a STRING that is the input STRING 'str' with the substring
    #	from the index given by the input INT 'from' to the index given by the
    #	input INT 'to' replaced with the input STRING 'substr'. This is the
    #	implementation of the 'strreplace' quadcode.
    #
    # Parameters:
    #	str -	The STRING LLVM value reference to index into.
    #	from -	The INT LLVM value reference to use as the start index.
    #	to -	The INT LLVM value reference to use as the finish index.
    #	substr -
    #		The STRING LLVM value reference to insert.
    #	ecvar -	Location to write the Tcl return code into, as an LLVM int*
    #		reference. (Ignored.)
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A STRING FAIL LLVM value reference (never a nothing). This will have a
    #	non-zero reference count.

    method strreplace(STRING,INT,INT,STRING) {str from to substr ecvar {name ""}} {
	my ok [my Call tcl.strreplace $str $from $to $substr] $name
    }

    # Builder:strreplace(STRING,STRING,STRING,STRING) --
    #
    #	Generate a STRING that is the input STRING 'str' with the substring
    #	from the index given by the input STRING 'from' to the index given by
    #	the input STRING 'to' replaced with the input STRING 'substr'. This is
    #	the implementation of the 'strreplace' quadcode.
    #
    # Parameters:
    #	str -	The STRING LLVM value reference to index into.
    #	from -	The STRING LLVM value reference to use as the start index.
    #	to -	The STRING LLVM value reference to use as the finish index.
    #	substr -
    #		The STRING LLVM value reference to insert.
    #	ecvar -	Location to write the Tcl return code into, as an LLVM int*
    #		reference.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A STRING FAIL LLVM value reference. This will have a non-zero
    #	reference count.

    method strreplace(STRING,STRING,STRING,STRING) {str from to substr ecvar {name ""}} {
	my call ${tcl.strreplace.idx} [list $str $from $to $substr $ecvar] $name
    }

    # Builder:strrfind(STRING,STRING) --
    #
    #	Generate an INT that describes the last index in the second input
    #	STRING where the first input STRING is located; if the 'needle' is
    #	absent (including if it is larger than the 'haystack') then the result
    #	is -1.  This is the implementation of the 'strrfind' quadcode.
    #
    # Parameters:
    #	needle -
    #		The STRING LLVM value reference to search for.
    #	haystack -
    #		The STRING LLVM value reference to search within.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An INT LLVM value reference.

    method strrfind(STRING,STRING) {needle haystack {name ""}} {
	my call ${tcl.strfind.rev} [list $needle $haystack] $name
    }

    # Builder:strtrim(STRING,STRING,INT) --
    #
    #	Generate a STRING that is the input STRING 'str' with the characters
    #	in the input STRING 'chars' removed from the front and/or the tail,
    #	according to what the input INT 'which' (expected to be a literal)
    #	describes. If 'which' is less than 1, the front will be trimmed, and
    #	of 'which' is greater than -1, the tail will be trimmed (i.e., 0
    #	causes both to be trimmed). This is the implementation of the
    #	'strtrim' quadcode.
    #
    # Parameters:
    #	str -	The STRING LLVM value reference to trim.
    #	chars -	The STRING LLVM value reference holding the characters to
    #		remove.
    #	which -	The INT LLVM value reference indicating which end(s) to trim.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A STRING LLVM value reference. This will have a non-zero reference
    #	count.

    method strtrim(STRING,STRING,INT) {str chars which {name ""}} {
	my call ${tcl.strtrim} [list $str $chars [my getInt32 $which]] $name
    }

    # Builder:sub(INT,INT) --
    #
    #	Generate code to subtract two INTs. Quadcode implementation ('sub').
    #
    # Parameters:
    #	left -	The INT LLVM value reference for the left operand.
    #	right -	The INT LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An INT LLVM value reference.

    method sub(INT,INT) {left right {name ""}} {
	my call ${tcl.sub} [list $left $right] $name
    }

    # Builder:sub(DOUBLE,DOUBLE) --
    #
    #	Generate code to subtract two DOUBLEs. Quadcode implementation
    #	('sub').
    #
    # Parameters:
    #	left -	The DOUBLE LLVM value reference for the left operand.
    #	right -	The DOUBLE LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A DOUBLE LLVM value reference.

    method sub(DOUBLE,DOUBLE) {left right {name ""}} {
	my sub $left $right $name
    }

    # Builder:sub(DOUBLE,NUMERIC) --
    #
    #	Generate code to subtract a NUMERIC from a DOUBLE. Quadcode
    #	implementation ('sub').
    #
    # Parameters:
    #	left -	The DOUBLE LLVM value reference for the left operand.
    #	right -	The NUMERIC LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A DOUBLE LLVM value reference.

    method sub(DOUBLE,NUMERIC) {left right {name ""}} {
	my sub(DOUBLE,DOUBLE) $left [my NumToDbl $right] $name
    }

    # Builder:sub(NUMERIC,DOUBLE) --
    #
    #	Generate code to subtract a DOUBLE from a NUMERIC. Quadcode
    #	implementation ('sub').
    #
    # Parameters:
    #	left -	The NUMERIC LLVM value reference for the left operand.
    #	right -	The DOUBLE LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A DOUBLE LLVM value reference.

    method sub(NUMERIC,DOUBLE) {left right {name ""}} {
	my sub(DOUBLE,DOUBLE) [my NumToDbl $left] $right $name
    }

    # Builder:sub(INT,NUMERIC) --
    #
    #	Generate code to subtract a NUMERIC from an INT. Quadcode
    #	implementation ('sub').
    #
    # Parameters:
    #	left -	The INT LLVM value reference for the left operand.
    #	right -	The NUMERIC LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A NUMERIC LLVM value reference.

    method sub(INT,NUMERIC) {left right {name ""}} {
	my sub(NUMERIC,NUMERIC) [my packNumericInt $left] $right $name
    }

    # Builder:sub(NUMERIC,INT) --
    #
    #	Generate code to subtract an INT from a NUMERIC. Quadcode
    #	implementation ('sub').
    #
    # Parameters:
    #	left -	The NUMERIC LLVM value reference for the left operand.
    #	right -	The DOUBLE LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A NUMERIC LLVM value reference.

    method sub(NUMERIC,INT) {left right {name ""}} {
	my sub(NUMERIC,NUMERIC) $left [my packNumericInt $right] $name
    }

    # Builder:sub(NUMERIC,NUMERIC) --
    #
    #	Generate code to subtract two NUMERICs. Quadcode implementation
    #	('sub').
    #
    # Parameters:
    #	left -	The NUMERIC LLVM value reference for the left operand.
    #	right -	The NUMERIC LLVM value reference for the right operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A NUMERIC LLVM value reference.

    method sub(NUMERIC,NUMERIC) {left right {name ""}} {
	my call ${tcl.sub.numeric} [list $left $right] $name
    }

    # Builder:uminus(INT) --
    #
    #	Generate code to create the negation of an INT. Quadcode
    #	implementation ('uminus').
    #
    # Parameters:
    #	value -	The INT LLVM value reference for the operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An INT LLVM value reference.

    method uminus(INT) {value {name ""}} {
	my call ${tcl.neg} [list $value] $name
    }

    # Builder:uminus(DOUBLE) --
    #
    #	Generate code to create the negation of a DOUBLE. Quadcode
    #	implementation ('uminus').
    #
    # Parameters:
    #	value -	The DOUBLE LLVM value reference for the operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A DOUBLE LLVM value reference.

    method uminus(DOUBLE) {value {name ""}} {
	if {[GetTypeKind [TypeOf $value]] ne "LLVMDoubleTypeKind"} {
	    return -code error "value must be double"
	}
	my neg $value $name
    }

    # Builder:uminus(NUMERIC) --
    #
    #	Generate code to create the negation of a NUMERIC. Quadcode
    #	implementation ('uminus').
    #
    # Parameters:
    #	value -	The NUMERIC LLVM value reference for the operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A NUMERIC LLVM value reference.

    method uminus(NUMERIC) {value {name ""}} {
	my call ${tcl.neg.numeric} [list $value] $name
    }

    # Builder:uniqueUndef --
    #
    #	Create a unique undefined value. This is designed so that it can be
    #	replaced later on when fixing up a loop's back-references at a phi
    #	node.
    #
    # Parameters:
    #	type -	Type (LLVM or name) of undef to create.
    #	name (optional) -
    #		The name of the result value.
    #
    # Results:
    #	LLVM undef value that is guaranteed distinct from all others.

    method uniqueUndef {type {name ""}} {
	set type [Type $type]
	set n2 $name
	if {$n2 ne ""} {
	    set n2 &$n2
	}
	my load [my alloc $type $n2] $name
    }

    # Builder:unshare(STRING) --
    #
    #	Generate a writable buffer by "unsharing" a STRING. This examines the
    #	reference counts and applies Tcl_DuplicateObj if required; the result
    #	*may* be the original value.
    #
    # Parameters:
    #	value -	The STRING LLVM value reference to unshare.
    #
    # Results:
    #	A writable Tcl_Obj* in an LLVM value reference.

    method unshare(STRING) {value {name ""}} {
	if {[string match unshare(*) [lindex [info level -1] 1]]} {
	    my addReference(STRING) $value
	    return $value
	}
	my call ${tcl.unshare} [list $value] $name
    }

    # Builder:unshareCopy(STRING) --
    #
    #	Generate a writable buffer by "unsharing" a STRING by calling
    #	Tcl_DuplicateObj; the result is *always* a new Tcl_Obj*.
    #
    # Parameters:
    #	value -	The STRING LLVM value reference to unshare.
    #
    # Results:
    #	A writable Tcl_Obj* in an LLVM value reference.

    method unshareCopy(STRING) {value {name ""}} {
	my call ${tcl.unshare.copy} [list $value] $name
    }

    # Builder:upcastImpure.INT(ZEROONE) --
    #
    #	Generate code to create the conversion of an IMPURE ZEROONE to an
    #	IMPURE INT.
    #
    # Parameters:
    #	value -	The IMPURE ZEROONE LLVM value reference for the operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An IMPURE INT LLVM value reference. *NOTE* that this does not do
    #	reference management of the string part!

    method upcastImpure.INT(ZEROONE) {value {name ""}} {
	set str [my impure.string $value]
	set num [my cast(BOOLEAN) [my impure.value $value]]
	return [my impure INT $str $num $name]
    }

    # Builder:upcastImpure.NUMERIC(DOUBLE) --
    #
    #	Generate code to create the conversion of an IMPURE DOUBLE to an
    #	IMPURE NUMERIC.
    #
    # Parameters:
    #	value -	The IMPURE DOUBLE LLVM value reference for the operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An IMPURE NUMERIC LLVM value reference. *NOTE* that this does not do
    #	reference management of the string part!

    method upcastImpure.NUMERIC(DOUBLE) {value {name ""}} {
	set str [my impure.string $value]
	set num [my packNumericDouble [my impure.value $value]]
	return [my impure NUMERIC $str $num $name]
    }

    # Builder:upcastImpure.NUMERIC(INT) --
    #
    #	Generate code to create the conversion of an IMPURE INT to an
    #	IMPURE NUMERIC.
    #
    # Parameters:
    #	value -	The IMPURE INT LLVM value reference for the operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An IMPURE NUMERIC LLVM value reference. *NOTE* that this does not do
    #	reference management of the string part!

    method upcastImpure.NUMERIC(INT) {value {name ""}} {
	set str [my impure.string $value]
	set num [my packNumericInt [my impure.value $value]]
	return [my impure NUMERIC $str $num $name]
    }

    # Builder:upcastImpure.INT(ZEROONE) --
    #
    #	Generate code to create the conversion of an IMPURE ZEROONE to an
    #	IMPURE NUMERIC.
    #
    # Parameters:
    #	value -	The IMPURE ZEROONE LLVM value reference for the operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An IMPURE NUMERIC LLVM value reference. *NOTE* that this does not do
    #	reference management of the string part!

    method upcastImpure.NUMERIC(ZEROONE) {value {name ""}} {
	set str [my impure.string $value]
	set num [my packNumericInt [my cast(BOOLEAN) [my impure.value $value]]]
	return [my impure NUMERIC $str $num $name]
    }

    # Builder:uplus(INT) --
    #
    #	Generate code to create the negation of an INT. Quadcode
    #	implementation ('uplus').
    #
    # Parameters:
    #	value -	The INT LLVM value reference for the operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	An INT LLVM value reference.

    method uplus(INT) {value {name ""}} {
	return $value
    }

    # Builder:uplus(DOUBLE) --
    #
    #	Generate code to create the negation of a DOUBLE. Quadcode
    #	implementation ('uplus').
    #
    # Parameters:
    #	value -	The DOUBLE LLVM value reference for the operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A DOUBLE LLVM value reference.

    method uplus(DOUBLE) {value {name ""}} {
	if {[GetTypeKind [TypeOf $value]] ne "LLVMDoubleTypeKind"} {
	    return -code error "value must be double"
	}
	return $value
    }

    # Builder:uplus(NUMERIC) --
    #
    #	Generate code to create the negation of a NUMERIC. Quadcode
    #	implementation ('uplus').
    #
    # Parameters:
    #	value -	The NUMERIC LLVM value reference for the operand.
    #	name (optional) -
    #		A name to give to the result value.
    #
    # Results:
    #	A NUMERIC LLVM value reference.

    method uplus(NUMERIC) {value {name ""}} {
	return $value
    }
}

# Local Variables:
# mode: tcl
# fill-column: 78
# auto-fill-function: nil
# buffer-file-coding-system: utf-8-unix
# End:
